initial import
[vuplus_webkit] / Source / JavaScriptCore / interpreter / Interpreter.cpp
1 /*
2  * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "Interpreter.h"
32
33 #include "Arguments.h"
34 #include "BatchedTransitionOptimizer.h"
35 #include "CallFrame.h"
36 #include "CallFrameClosure.h"
37 #include "CodeBlock.h"
38 #include "Heap.h"
39 #include "Debugger.h"
40 #include "DebuggerCallFrame.h"
41 #include "ErrorInstance.h"
42 #include "EvalCodeCache.h"
43 #include "ExceptionHelpers.h"
44 #include "GetterSetter.h"
45 #include "JSActivation.h"
46 #include "JSArray.h"
47 #include "JSByteArray.h"
48 #include "JSFunction.h"
49 #include "JSNotAnObject.h"
50 #include "JSPropertyNameIterator.h"
51 #include "LiteralParser.h"
52 #include "JSStaticScopeObject.h"
53 #include "JSString.h"
54 #include "ObjectPrototype.h"
55 #include "Operations.h"
56 #include "Parser.h"
57 #include "Profiler.h"
58 #include "RegExpObject.h"
59 #include "RegExpPrototype.h"
60 #include "Register.h"
61 #include "SamplingTool.h"
62 #include "StrictEvalActivation.h"
63 #include "UStringConcatenate.h"
64 #include <limits.h>
65 #include <stdio.h>
66 #include <wtf/Threading.h>
67
68 #if ENABLE(JIT)
69 #include "JIT.h"
70 #endif
71
72 #define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (ENABLE(COMPUTED_GOTO_INTERPRETER) && !defined(__llvm__))
73
74 using namespace std;
75
76 namespace JSC {
77
78 // Returns the depth of the scope chain within a given call frame.
79 static int depth(CodeBlock* codeBlock, ScopeChainNode* sc)
80 {
81     if (!codeBlock->needsFullScopeChain())
82         return 0;
83     return sc->localDepth();
84 }
85
86 #if ENABLE(INTERPRETER) 
87 static NEVER_INLINE JSValue concatenateStrings(ExecState* exec, Register* strings, unsigned count)
88 {
89     return jsString(exec, strings, count);
90 }
91
92 NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
93 {
94     int dst = vPC[1].u.operand;
95     int property = vPC[2].u.operand;
96
97     ScopeChainNode* scopeChain = callFrame->scopeChain();
98     ScopeChainIterator iter = scopeChain->begin();
99     ScopeChainIterator end = scopeChain->end();
100     ASSERT(iter != end);
101
102     CodeBlock* codeBlock = callFrame->codeBlock();
103     Identifier& ident = codeBlock->identifier(property);
104     do {
105         JSObject* o = iter->get();
106         PropertySlot slot(o);
107         if (o->getPropertySlot(callFrame, ident, slot)) {
108             JSValue result = slot.getValue(callFrame, ident);
109             exceptionValue = callFrame->globalData().exception;
110             if (exceptionValue)
111                 return false;
112             callFrame->uncheckedR(dst) = JSValue(result);
113             return true;
114         }
115     } while (++iter != end);
116     exceptionValue = createUndefinedVariableError(callFrame, ident);
117     return false;
118 }
119
120 NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
121 {
122     CodeBlock* codeBlock = callFrame->codeBlock();
123
124     int dst = vPC[1].u.operand;
125     int property = vPC[2].u.operand;
126     int skip = vPC[3].u.operand;
127
128     ScopeChainNode* scopeChain = callFrame->scopeChain();
129     ScopeChainIterator iter = scopeChain->begin();
130     ScopeChainIterator end = scopeChain->end();
131     ASSERT(iter != end);
132     bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
133     ASSERT(skip || !checkTopLevel);
134     if (checkTopLevel && skip--) {
135         if (callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
136             ++iter;
137     }
138     while (skip--) {
139         ++iter;
140         ASSERT(iter != end);
141     }
142     Identifier& ident = codeBlock->identifier(property);
143     do {
144         JSObject* o = iter->get();
145         PropertySlot slot(o);
146         if (o->getPropertySlot(callFrame, ident, slot)) {
147             JSValue result = slot.getValue(callFrame, ident);
148             exceptionValue = callFrame->globalData().exception;
149             if (exceptionValue)
150                 return false;
151             ASSERT(result);
152             callFrame->uncheckedR(dst) = JSValue(result);
153             return true;
154         }
155     } while (++iter != end);
156     exceptionValue = createUndefinedVariableError(callFrame, ident);
157     return false;
158 }
159
160 NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
161 {
162     int dst = vPC[1].u.operand;
163     CodeBlock* codeBlock = callFrame->codeBlock();
164     JSGlobalObject* globalObject = codeBlock->globalObject();
165     ASSERT(globalObject->isGlobalObject());
166     int property = vPC[2].u.operand;
167     Structure* structure = vPC[3].u.structure.get();
168     int offset = vPC[4].u.operand;
169
170     if (structure == globalObject->structure()) {
171         callFrame->uncheckedR(dst) = JSValue(globalObject->getDirectOffset(offset));
172         return true;
173     }
174
175     Identifier& ident = codeBlock->identifier(property);
176     PropertySlot slot(globalObject);
177     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
178         JSValue result = slot.getValue(callFrame, ident);
179         if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
180             vPC[3].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
181             vPC[4] = slot.cachedOffset();
182             callFrame->uncheckedR(dst) = JSValue(result);
183             return true;
184         }
185
186         exceptionValue = callFrame->globalData().exception;
187         if (exceptionValue)
188             return false;
189         callFrame->uncheckedR(dst) = JSValue(result);
190         return true;
191     }
192
193     exceptionValue = createUndefinedVariableError(callFrame, ident);
194     return false;
195 }
196
197 NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
198 {
199     int dst = vPC[1].u.operand;
200     CodeBlock* codeBlock = callFrame->codeBlock();
201     JSGlobalObject* globalObject = codeBlock->globalObject();
202     ASSERT(globalObject->isGlobalObject());
203     int property = vPC[2].u.operand;
204     Structure* structure = vPC[3].u.structure.get();
205     int offset = vPC[4].u.operand;
206     int skip = vPC[5].u.operand;
207     
208     ScopeChainNode* scopeChain = callFrame->scopeChain();
209     ScopeChainIterator iter = scopeChain->begin();
210     ScopeChainIterator end = scopeChain->end();
211     ASSERT(iter != end);
212     bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
213     ASSERT(skip || !checkTopLevel);
214     if (checkTopLevel && skip--) {
215         if (callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
216             ++iter;
217     }
218     while (skip--) {
219         JSObject* o = iter->get();
220         if (o->hasCustomProperties()) {
221             Identifier& ident = codeBlock->identifier(property);
222             do {
223                 PropertySlot slot(o);
224                 if (o->getPropertySlot(callFrame, ident, slot)) {
225                     JSValue result = slot.getValue(callFrame, ident);
226                     exceptionValue = callFrame->globalData().exception;
227                     if (exceptionValue)
228                         return false;
229                     ASSERT(result);
230                     callFrame->uncheckedR(dst) = JSValue(result);
231                     return true;
232                 }
233                 if (iter == end)
234                     break;
235                 o = iter->get();
236                 ++iter;
237             } while (true);
238             exceptionValue = createUndefinedVariableError(callFrame, ident);
239             return false;
240         }
241         ++iter;
242     }
243     
244     if (structure == globalObject->structure()) {
245         callFrame->uncheckedR(dst) = JSValue(globalObject->getDirectOffset(offset));
246         ASSERT(callFrame->uncheckedR(dst).jsValue());
247         return true;
248     }
249
250     Identifier& ident = codeBlock->identifier(property);
251     PropertySlot slot(globalObject);
252     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
253         JSValue result = slot.getValue(callFrame, ident);
254         if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
255             vPC[3].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
256             vPC[4] = slot.cachedOffset();
257             ASSERT(result);
258             callFrame->uncheckedR(dst) = JSValue(result);
259             return true;
260         }
261         
262         exceptionValue = callFrame->globalData().exception;
263         if (exceptionValue)
264             return false;
265         ASSERT(result);
266         callFrame->uncheckedR(dst) = JSValue(result);
267         return true;
268     }
269     
270     exceptionValue = createUndefinedVariableError(callFrame, ident);
271     return false;
272 }
273
274 NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC)
275 {
276     int dst = vPC[1].u.operand;
277     int property = vPC[2].u.operand;
278     bool isStrictPut = vPC[3].u.operand;
279     Identifier ident = callFrame->codeBlock()->identifier(property);
280     JSValue result = JSC::resolveBase(callFrame, ident, callFrame->scopeChain(), isStrictPut);
281     if (result) {
282         callFrame->uncheckedR(dst) = result;
283         ASSERT(callFrame->uncheckedR(dst).jsValue());
284     } else
285         callFrame->globalData().exception = createErrorForInvalidGlobalAssignment(callFrame, ident.ustring());
286 }
287
288 NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
289 {
290     int baseDst = vPC[1].u.operand;
291     int propDst = vPC[2].u.operand;
292     int property = vPC[3].u.operand;
293
294     ScopeChainNode* scopeChain = callFrame->scopeChain();
295     ScopeChainIterator iter = scopeChain->begin();
296     ScopeChainIterator end = scopeChain->end();
297
298     // FIXME: add scopeDepthIsZero optimization
299
300     ASSERT(iter != end);
301
302     CodeBlock* codeBlock = callFrame->codeBlock();
303     Identifier& ident = codeBlock->identifier(property);
304     JSObject* base;
305     do {
306         base = iter->get();
307         PropertySlot slot(base);
308         if (base->getPropertySlot(callFrame, ident, slot)) {
309             JSValue result = slot.getValue(callFrame, ident);
310             exceptionValue = callFrame->globalData().exception;
311             if (exceptionValue)
312                 return false;
313             callFrame->uncheckedR(propDst) = JSValue(result);
314             callFrame->uncheckedR(baseDst) = JSValue(base);
315             return true;
316         }
317         ++iter;
318     } while (iter != end);
319
320     exceptionValue = createUndefinedVariableError(callFrame, ident);
321     return false;
322 }
323
324 NEVER_INLINE bool Interpreter::resolveThisAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
325 {
326     int thisDst = vPC[1].u.operand;
327     int propDst = vPC[2].u.operand;
328     int property = vPC[3].u.operand;
329
330     ScopeChainNode* scopeChain = callFrame->scopeChain();
331     ScopeChainIterator iter = scopeChain->begin();
332     ScopeChainIterator end = scopeChain->end();
333
334     // FIXME: add scopeDepthIsZero optimization
335
336     ASSERT(iter != end);
337
338     CodeBlock* codeBlock = callFrame->codeBlock();
339     Identifier& ident = codeBlock->identifier(property);
340     JSObject* base;
341     do {
342         base = iter->get();
343         ++iter;
344         PropertySlot slot(base);
345         if (base->getPropertySlot(callFrame, ident, slot)) {
346             JSValue result = slot.getValue(callFrame, ident);
347             exceptionValue = callFrame->globalData().exception;
348             if (exceptionValue)
349                 return false;
350             callFrame->uncheckedR(propDst) = JSValue(result);
351             // All entries on the scope chain should be EnvironmentRecords (activations etc),
352             // other then 'with' object, which are directly referenced from the scope chain,
353             // and the global object. If we hit either an EnvironmentRecord or a global
354             // object at the end of the scope chain, this is undefined. If we hit a non-
355             // EnvironmentRecord within the scope chain, pass the base as the this value.
356             if (iter == end || base->structure()->typeInfo().isEnvironmentRecord())
357                 callFrame->uncheckedR(thisDst) = jsUndefined();
358             else
359                 callFrame->uncheckedR(thisDst) = JSValue(base);
360             return true;
361         }
362     } while (iter != end);
363
364     exceptionValue = createUndefinedVariableError(callFrame, ident);
365     return false;
366 }
367
368 #endif // ENABLE(INTERPRETER)
369
370 ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
371 {
372     Register* r = callFrame->registers();
373     Register* newEnd = r + registerOffset + newCodeBlock->m_numCalleeRegisters;
374
375     if (LIKELY(argc == newCodeBlock->m_numParameters)) { // correct number of arguments
376         if (UNLIKELY(!registerFile->grow(newEnd)))
377             return 0;
378         r += registerOffset;
379     } else if (argc < newCodeBlock->m_numParameters) { // too few arguments -- fill in the blanks
380         size_t omittedArgCount = newCodeBlock->m_numParameters - argc;
381         registerOffset += omittedArgCount;
382         newEnd += omittedArgCount;
383         if (!registerFile->grow(newEnd))
384             return 0;
385         r += registerOffset;
386
387         Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
388         for (size_t i = 0; i < omittedArgCount; ++i)
389             argv[i] = jsUndefined();
390     } else { // too many arguments -- copy expected arguments, leaving the extra arguments behind
391         size_t numParameters = newCodeBlock->m_numParameters;
392         registerOffset += numParameters;
393         newEnd += numParameters;
394
395         if (!registerFile->grow(newEnd))
396             return 0;
397         r += registerOffset;
398
399         Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argc;
400         for (size_t i = 0; i < numParameters; ++i)
401             argv[i + argc] = argv[i];
402     }
403
404     return CallFrame::create(r);
405 }
406
407 #if ENABLE(INTERPRETER)
408 static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, JSValue value, JSValue& exceptionData)
409 {
410     if (value.isObject())
411         return false;
412     exceptionData = createInvalidParamError(callFrame, "in" , value);
413     return true;
414 }
415
416 static NEVER_INLINE bool isInvalidParamForInstanceOf(CallFrame* callFrame, JSValue value, JSValue& exceptionData)
417 {
418     if (value.isObject() && asObject(value)->structure()->typeInfo().implementsHasInstance())
419         return false;
420     exceptionData = createInvalidParamError(callFrame, "instanceof" , value);
421     return true;
422 }
423 #endif
424
425 NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset)
426 {
427     if (argc < 2)
428         return jsUndefined();
429
430     JSValue program = argv[1].jsValue();
431
432     if (!program.isString())
433         return program;
434
435     UString programSource = asString(program)->value(callFrame);
436     if (callFrame->hadException())
437         return JSValue();
438     
439     CodeBlock* codeBlock = callFrame->codeBlock();
440     
441     ScopeChainNode* scopeChain = callFrame->scopeChain();
442     EvalExecutable* eval = codeBlock->evalCodeCache().tryGet(codeBlock->isStrictMode(), programSource, scopeChain);
443
444     if (!eval) {
445         if (!codeBlock->isStrictMode()) {
446             // FIXME: We can use the preparser in strict mode, we just need additional logic
447             // to prevent duplicates.
448             LiteralParser preparser(callFrame, programSource.characters(), programSource.length(), LiteralParser::NonStrictJSON);
449             if (JSValue parsedObject = preparser.tryLiteralParse())
450                 return parsedObject;
451         }
452
453         JSValue exceptionValue;
454         eval = codeBlock->evalCodeCache().getSlow(callFrame, codeBlock->ownerExecutable(), codeBlock->isStrictMode(), programSource, scopeChain, exceptionValue);
455         
456         ASSERT(!eval == exceptionValue);
457         if (UNLIKELY(!eval))
458             return throwError(callFrame, exceptionValue);
459     }
460
461     JSValue thisValue = callFrame->uncheckedR(codeBlock->thisRegister()).jsValue();
462     ASSERT(isValidThisObject(thisValue, callFrame));
463     return callFrame->globalData().interpreter->execute(eval, callFrame, thisValue, callFrame->registers() - registerFile->begin() + registerOffset, scopeChain);
464 }
465
466 Interpreter::Interpreter()
467     : m_sampleEntryDepth(0)
468     , m_reentryDepth(0)
469 {
470 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
471     privateExecute(InitializeAndReturn, 0, 0);
472
473     for (int i = 0; i < numOpcodeIDs; ++i)
474         m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
475 #endif // ENABLE(COMPUTED_GOTO_INTERPRETER)
476
477 #if ENABLE(OPCODE_SAMPLING)
478     enableSampler();
479 #endif
480 }
481
482 #ifndef NDEBUG
483
484 void Interpreter::dumpCallFrame(CallFrame* callFrame)
485 {
486     callFrame->codeBlock()->dump(callFrame);
487     dumpRegisters(callFrame);
488 }
489
490 void Interpreter::dumpRegisters(CallFrame* callFrame)
491 {
492     printf("Register frame: \n\n");
493     printf("-----------------------------------------------------------------------------\n");
494     printf("            use            |   address  |                value               \n");
495     printf("-----------------------------------------------------------------------------\n");
496
497     CodeBlock* codeBlock = callFrame->codeBlock();
498     const Register* it;
499     const Register* end;
500     JSValue v;
501
502     it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->m_numParameters;
503     v = (*it).jsValue();
504 #if USE(JSVALUE32_64)
505     printf("[this]                     | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); ++it;
506 #else
507     printf("[this]                     | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); ++it;
508 #endif
509     end = it + max(codeBlock->m_numParameters - 1, 0); // - 1 to skip "this"
510     if (it != end) {
511         do {
512             v = (*it).jsValue();
513 #if USE(JSVALUE32_64)
514             printf("[param]                    | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
515 #else
516             printf("[param]                    | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
517 #endif
518             ++it;
519         } while (it != end);
520     }
521     printf("-----------------------------------------------------------------------------\n");
522     printf("[CodeBlock]                | %10p | %p \n", it, (*it).codeBlock()); ++it;
523     printf("[ScopeChain]               | %10p | %p \n", it, (*it).scopeChain()); ++it;
524     printf("[CallerRegisters]          | %10p | %d \n", it, (*it).i()); ++it;
525     printf("[ReturnPC]                 | %10p | %p \n", it, (*it).vPC()); ++it;
526     printf("[ArgumentCount]            | %10p | %d \n", it, (*it).i()); ++it;
527     printf("[Callee]                   | %10p | %p \n", it, (*it).function()); ++it;
528     printf("-----------------------------------------------------------------------------\n");
529
530     int registerCount = 0;
531
532     end = it + codeBlock->m_numVars;
533     if (it != end) {
534         do {
535             v = (*it).jsValue();
536 #if USE(JSVALUE32_64)
537             printf("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
538 #else
539             printf("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
540 #endif
541             ++it;
542             ++registerCount;
543         } while (it != end);
544     }
545     printf("-----------------------------------------------------------------------------\n");
546
547     end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars;
548     if (it != end) {
549         do {
550             v = (*it).jsValue();
551 #if USE(JSVALUE32_64)
552             printf("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
553 #else
554             printf("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
555 #endif
556             ++it;
557             ++registerCount;
558         } while (it != end);
559     }
560     printf("-----------------------------------------------------------------------------\n");
561 }
562
563 #endif
564
565 bool Interpreter::isOpcode(Opcode opcode)
566 {
567 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
568     return opcode != HashTraits<Opcode>::emptyValue()
569         && !HashTraits<Opcode>::isDeletedValue(opcode)
570         && m_opcodeIDTable.contains(opcode);
571 #else
572     return opcode >= 0 && opcode <= op_end;
573 #endif
574 }
575
576 NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
577 {
578     CodeBlock* oldCodeBlock = codeBlock;
579     ScopeChainNode* scopeChain = callFrame->scopeChain();
580
581     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
582         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
583         if (callFrame->callee())
584             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
585         else
586             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
587     }
588
589     // If this call frame created an activation or an 'arguments' object, tear it off.
590     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
591         if (!callFrame->uncheckedR(oldCodeBlock->activationRegister()).jsValue()) {
592             oldCodeBlock->createActivation(callFrame);
593             scopeChain = callFrame->scopeChain();
594         }
595         while (!scopeChain->object->inherits(&JSActivation::s_info))
596             scopeChain = scopeChain->pop();
597
598         callFrame->setScopeChain(scopeChain);
599         JSActivation* activation = asActivation(scopeChain->object.get());
600         activation->copyRegisters(*scopeChain->globalData);
601         if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) {
602             if (!oldCodeBlock->isStrictMode())
603                 asArguments(arguments)->setActivation(callFrame->globalData(), activation);
604         }
605     } else if (oldCodeBlock->usesArguments() && !oldCodeBlock->isStrictMode()) {
606         if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue())
607             asArguments(arguments)->copyRegisters(callFrame->globalData());
608     }
609
610     CallFrame* callerFrame = callFrame->callerFrame();
611     callFrame->globalData().topCallFrame = callerFrame;
612     if (callerFrame->hasHostCallFrameFlag())
613         return false;
614
615     codeBlock = callerFrame->codeBlock();
616     
617     // Because of how the JIT records call site->bytecode offset
618     // information the JIT reports the bytecodeOffset for the returnPC
619     // to be at the beginning of the opcode that has caused the call.
620     // In the interpreter we have an actual return address, which is
621     // the beginning of next instruction to execute. To get an offset
622     // inside the call instruction that triggered the exception we
623     // have to subtract 1.
624 #if ENABLE(JIT) && ENABLE(INTERPRETER)
625     if (callerFrame->globalData().canUseJIT())
626         bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
627     else
628         bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
629 #elif ENABLE(JIT)
630     bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
631 #else
632     bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
633 #endif
634
635     callFrame = callerFrame;
636     return true;
637 }
638
639 static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception, unsigned bytecodeOffset)
640 {
641     exception->clearAppendSourceToMessage();
642
643     if (!callFrame->codeBlock()->hasExpressionInfo())
644         return;
645
646     int startOffset = 0;
647     int endOffset = 0;
648     int divotPoint = 0;
649
650     CodeBlock* codeBlock = callFrame->codeBlock();
651     codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divotPoint, startOffset, endOffset);
652
653     int expressionStart = divotPoint - startOffset;
654     int expressionStop = divotPoint + endOffset;
655
656     if (!expressionStop || expressionStart > codeBlock->source()->length())
657         return;
658
659     JSGlobalData* globalData = &callFrame->globalData();
660     JSValue jsMessage = exception->getDirect(*globalData, globalData->propertyNames->message);
661     if (!jsMessage || !jsMessage.isString())
662         return;
663
664     UString message = asString(jsMessage)->value(callFrame);
665
666     if (expressionStart < expressionStop)
667         message =  makeUString(message, " (evaluating '", codeBlock->source()->getRange(expressionStart, expressionStop), "')");
668     else {
669         // No range information, so give a few characters of context
670         const UChar* data = codeBlock->source()->data();
671         int dataLength = codeBlock->source()->length();
672         int start = expressionStart;
673         int stop = expressionStart;
674         // Get up to 20 characters of context to the left and right of the divot, clamping to the line.
675         // then strip whitespace.
676         while (start > 0 && (expressionStart - start < 20) && data[start - 1] != '\n')
677             start--;
678         while (start < (expressionStart - 1) && isStrWhiteSpace(data[start]))
679             start++;
680         while (stop < dataLength && (stop - expressionStart < 20) && data[stop] != '\n')
681             stop++;
682         while (stop > expressionStart && isStrWhiteSpace(data[stop - 1]))
683             stop--;
684         message = makeUString(message, " (near '...", codeBlock->source()->getRange(start, stop), "...')");
685     }
686
687     exception->putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message));
688 }
689
690 NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
691 {
692     CodeBlock* codeBlock = callFrame->codeBlock();
693     bool isInterrupt = false;
694
695     // Set up the exception object
696     if (exceptionValue.isObject()) {
697         JSObject* exception = asObject(exceptionValue);
698
699         if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage())
700             appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), bytecodeOffset);
701
702         // Using hasExpressionInfo to imply we are interested in rich exception info.
703         if (codeBlock->hasExpressionInfo() && !hasErrorInfo(callFrame, exception)) {
704             ASSERT(codeBlock->hasLineInfo());
705
706             // FIXME: should only really be adding these properties to VM generated exceptions,
707             // but the inspector currently requires these for all thrown objects.
708             addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source());
709         }
710
711         isInterrupt = isInterruptedExecutionException(exception) || isTerminatedExecutionException(exception);
712     }
713
714     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
715         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
716         bool hasHandler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
717         debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), hasHandler);
718     }
719
720     // Calculate an exception handler vPC, unwinding call frames as necessary.
721     HandlerInfo* handler = 0;
722     while (isInterrupt || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
723         if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
724             if (Profiler* profiler = *Profiler::enabledProfilerReference())
725                 profiler->exceptionUnwind(callFrame);
726             return 0;
727         }
728     }
729
730     if (Profiler* profiler = *Profiler::enabledProfilerReference())
731         profiler->exceptionUnwind(callFrame);
732
733     // Shrink the JS stack, in case stack overflow made it huge.
734     Register* highWaterMark = 0;
735     for (CallFrame* callerFrame = callFrame; callerFrame; callerFrame = callerFrame->callerFrame()->removeHostCallFrameFlag()) {
736         CodeBlock* codeBlock = callerFrame->codeBlock();
737         if (!codeBlock)
738             continue;
739         Register* callerHighWaterMark = callerFrame->registers() + codeBlock->m_numCalleeRegisters;
740         highWaterMark = max(highWaterMark, callerHighWaterMark);
741     }
742     m_registerFile.shrink(highWaterMark);
743
744     // Unwind the scope chain within the exception handler's call frame.
745     ScopeChainNode* scopeChain = callFrame->scopeChain();
746     int scopeDelta = 0;
747     if (!codeBlock->needsFullScopeChain() || codeBlock->codeType() != FunctionCode 
748         || callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
749         scopeDelta = depth(codeBlock, scopeChain) - handler->scopeDepth;
750     ASSERT(scopeDelta >= 0);
751     while (scopeDelta--)
752         scopeChain = scopeChain->pop();
753     callFrame->setScopeChain(scopeChain);
754
755     return handler;
756 }
757
758 static inline JSValue checkedReturn(JSValue returnValue)
759 {
760     ASSERT(returnValue);
761     return returnValue;
762 }
763
764 static inline JSObject* checkedReturn(JSObject* returnValue)
765 {
766     ASSERT(returnValue);
767     return returnValue;
768 }
769
770 JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj)
771 {
772     ASSERT(isValidThisObject(thisObj, callFrame));
773     ASSERT(!scopeChain->globalData->exception);
774     ASSERT(!callFrame->globalData().isCollectorBusy());
775     if (callFrame->globalData().isCollectorBusy())
776         return jsNull();
777
778     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
779         return checkedReturn(throwStackOverflowError(callFrame));
780
781     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
782     LiteralParser literalParser(callFrame, program->source().data(), program->source().length(), LiteralParser::JSONP);
783     Vector<LiteralParser::JSONPData> JSONPData;
784     if (literalParser.tryJSONPParse(JSONPData, scopeChain->globalObject->supportsRichSourceInfo())) {
785         JSGlobalObject* globalObject = scopeChain->globalObject.get();
786         JSValue result;
787         for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
788             Vector<LiteralParser::JSONPPathEntry> JSONPPath;
789             JSONPPath.swap(JSONPData[entry].m_path);
790             JSValue JSONPValue = JSONPData[entry].m_value.get();
791             if (JSONPPath.size() == 1 && JSONPPath[0].m_type == LiteralParser::JSONPPathEntryTypeDeclare) {
792                 if (globalObject->hasProperty(callFrame, JSONPPath[0].m_pathEntryName)) {
793                     PutPropertySlot slot;
794                     globalObject->put(callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
795                 } else
796                     globalObject->putWithAttributes(callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, DontEnum | DontDelete);
797                 // var declarations return undefined
798                 result = jsUndefined();
799                 continue;
800             }
801             JSValue baseObject(globalObject);
802             for (unsigned i = 0; i < JSONPPath.size() - 1; i++) {
803                 ASSERT(JSONPPath[i].m_type != LiteralParser::JSONPPathEntryTypeDeclare);
804                 switch (JSONPPath[i].m_type) {
805                 case LiteralParser::JSONPPathEntryTypeDot: {
806                     if (i == 0) {
807                         PropertySlot slot(globalObject);
808                         if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
809                             if (entry)
810                                 return throwError(callFrame, createUndefinedVariableError(globalObject->globalExec(), JSONPPath[i].m_pathEntryName));
811                             goto failedJSONP;
812                         }
813                         baseObject = slot.getValue(callFrame, JSONPPath[i].m_pathEntryName);
814                     } else
815                         baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathEntryName);
816                     if (callFrame->hadException())
817                         return jsUndefined();
818                     continue;
819                 }
820                 case LiteralParser::JSONPPathEntryTypeLookup: {
821                     baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
822                     if (callFrame->hadException())
823                         return jsUndefined();
824                     continue;
825                 }
826                 default:
827                     ASSERT_NOT_REACHED();
828                     return jsUndefined();
829                 }
830             }
831             PutPropertySlot slot;
832             switch (JSONPPath.last().m_type) {
833             case LiteralParser::JSONPPathEntryTypeCall: {
834                 JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
835                 if (callFrame->hadException())
836                     return jsUndefined();
837                 CallData callData;
838                 CallType callType = getCallData(function, callData);
839                 if (callType == CallTypeNone)
840                     return throwError(callFrame, createNotAFunctionError(callFrame, function));
841                 MarkedArgumentBuffer jsonArg;
842                 jsonArg.append(JSONPValue);
843                 JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined(): baseObject;
844                 JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg);
845                 if (callFrame->hadException())
846                     return jsUndefined();
847                 break;
848             }
849             case LiteralParser::JSONPPathEntryTypeDot: {
850                 baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
851                 if (callFrame->hadException())
852                     return jsUndefined();
853                 break;
854             }
855             case LiteralParser::JSONPPathEntryTypeLookup: {
856                 baseObject.put(callFrame, JSONPPath.last().m_pathIndex, JSONPValue);
857                 if (callFrame->hadException())
858                     return jsUndefined();
859                 break;
860             }
861             default:
862                 ASSERT_NOT_REACHED();
863                     return jsUndefined();
864             }
865             result = JSONPValue;
866         }
867         return result;
868     }
869 failedJSONP:
870     JSObject* error = program->compile(callFrame, scopeChain);
871     if (error)
872         return checkedReturn(throwError(callFrame, error));
873     CodeBlock* codeBlock = &program->generatedBytecode();
874
875     Register* oldEnd = m_registerFile.end();
876     Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
877     if (!m_registerFile.grow(newEnd))
878         return checkedReturn(throwStackOverflowError(callFrame));
879
880     CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize);
881     ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'.
882     newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), codeBlock->m_numParameters, 0);
883     newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = JSValue(thisObj);
884     TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
885
886     Profiler** profiler = Profiler::enabledProfilerReference();
887     if (*profiler)
888         (*profiler)->willExecute(callFrame, program->sourceURL(), program->lineNo());
889
890     JSValue result;
891     {
892         SamplingTool::CallRecord callRecord(m_sampler.get());
893
894         m_reentryDepth++;  
895 #if ENABLE(JIT)
896         if (callFrame->globalData().canUseJIT())
897             result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
898         else
899 #endif
900             result = privateExecute(Normal, &m_registerFile, newCallFrame);
901
902         m_reentryDepth--;
903     }
904
905     if (*profiler)
906         (*profiler)->didExecute(callFrame, program->sourceURL(), program->lineNo());
907
908     m_registerFile.shrink(oldEnd);
909
910     return checkedReturn(result);
911 }
912
913 JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
914 {
915     ASSERT(isValidThisObject(thisValue, callFrame));
916     ASSERT(!callFrame->hadException());
917     ASSERT(!callFrame->globalData().isCollectorBusy());
918     if (callFrame->globalData().isCollectorBusy())
919         return jsNull();
920
921     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
922         return checkedReturn(throwStackOverflowError(callFrame));
923
924     Register* oldEnd = m_registerFile.end();
925     int argCount = 1 + args.size(); // implicit "this" parameter
926     size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
927
928     if (!m_registerFile.grow(oldEnd + registerOffset))
929         return checkedReturn(throwStackOverflowError(callFrame));
930
931     CallFrame* newCallFrame = CallFrame::create(oldEnd);
932     size_t dst = 0;
933     newCallFrame->uncheckedR(0) = thisValue;
934     ArgList::const_iterator end = args.end();
935     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
936         newCallFrame->uncheckedR(++dst) = *it;
937
938     if (callType == CallTypeJS) {
939         ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
940
941         DynamicGlobalObjectScope globalObjectScope(*callDataScopeChain->globalData, callDataScopeChain->globalObject.get());
942
943         JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
944         if (UNLIKELY(!!compileError)) {
945             m_registerFile.shrink(oldEnd);
946             return checkedReturn(throwError(callFrame, compileError));
947         }
948
949         CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
950         newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
951         if (UNLIKELY(!newCallFrame)) {
952             m_registerFile.shrink(oldEnd);
953             return checkedReturn(throwStackOverflowError(callFrame));
954         }
955
956         newCallFrame->init(newCodeBlock, 0, callDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
957
958         TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
959
960         Profiler** profiler = Profiler::enabledProfilerReference();
961         if (*profiler)
962             (*profiler)->willExecute(callFrame, function);
963
964         JSValue result;
965         {
966             SamplingTool::CallRecord callRecord(m_sampler.get());
967
968             m_reentryDepth++;  
969 #if ENABLE(JIT)
970             if (callFrame->globalData().canUseJIT())
971                 result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData);
972             else
973 #endif
974                 result = privateExecute(Normal, &m_registerFile, newCallFrame);
975             m_reentryDepth--;
976         }
977
978         if (*profiler)
979             (*profiler)->didExecute(callFrame, function);
980
981         m_registerFile.shrink(oldEnd);
982         return checkedReturn(result);
983     }
984
985     ASSERT(callType == CallTypeHost);
986     ScopeChainNode* scopeChain = callFrame->scopeChain();
987     newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);
988     newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
989
990     TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
991
992     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
993
994     Profiler** profiler = Profiler::enabledProfilerReference();
995     if (*profiler)
996         (*profiler)->willExecute(callFrame, function);
997
998     JSValue result;
999     {
1000         SamplingTool::HostCallRecord callRecord(m_sampler.get());
1001         result = JSValue::decode(callData.native.function(newCallFrame));
1002     }
1003
1004     if (*profiler)
1005         (*profiler)->didExecute(callFrame, function);
1006
1007     m_registerFile.shrink(oldEnd);
1008     return checkedReturn(result);
1009 }
1010
1011 JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
1012 {
1013     ASSERT(!callFrame->hadException());
1014     ASSERT(!callFrame->globalData().isCollectorBusy());
1015     // We throw in this case because we have to return something "valid" but we're
1016     // already in an invalid state.
1017     if (callFrame->globalData().isCollectorBusy())
1018         return checkedReturn(throwStackOverflowError(callFrame));
1019
1020     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
1021         return checkedReturn(throwStackOverflowError(callFrame));
1022
1023     Register* oldEnd = m_registerFile.end();
1024     int argCount = 1 + args.size(); // implicit "this" parameter
1025     size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
1026
1027     if (!m_registerFile.grow(oldEnd + registerOffset))
1028         return checkedReturn(throwStackOverflowError(callFrame));
1029
1030     CallFrame* newCallFrame = CallFrame::create(oldEnd);
1031     size_t dst = 0;
1032     ArgList::const_iterator end = args.end();
1033     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
1034         newCallFrame->uncheckedR(++dst) = *it;
1035
1036     if (constructType == ConstructTypeJS) {
1037         ScopeChainNode* constructDataScopeChain = constructData.js.scopeChain;
1038
1039         DynamicGlobalObjectScope globalObjectScope(*constructDataScopeChain->globalData, constructDataScopeChain->globalObject.get());
1040
1041         JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, constructDataScopeChain);
1042         if (UNLIKELY(!!compileError)) {
1043             m_registerFile.shrink(oldEnd);
1044             return checkedReturn(throwError(callFrame, compileError));
1045         }
1046
1047         CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
1048         newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
1049         if (UNLIKELY(!newCallFrame)) {
1050             m_registerFile.shrink(oldEnd);
1051             return checkedReturn(throwStackOverflowError(callFrame));
1052         }
1053
1054         newCallFrame->init(newCodeBlock, 0, constructDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
1055
1056         TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
1057
1058         Profiler** profiler = Profiler::enabledProfilerReference();
1059         if (*profiler)
1060             (*profiler)->willExecute(callFrame, constructor);
1061
1062         JSValue result;
1063         {
1064             SamplingTool::CallRecord callRecord(m_sampler.get());
1065
1066             m_reentryDepth++;  
1067 #if ENABLE(JIT)
1068             if (callFrame->globalData().canUseJIT())
1069                 result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData);
1070             else
1071 #endif
1072                 result = privateExecute(Normal, &m_registerFile, newCallFrame);
1073             m_reentryDepth--;
1074         }
1075
1076         if (*profiler)
1077             (*profiler)->didExecute(callFrame, constructor);
1078
1079         m_registerFile.shrink(oldEnd);
1080         if (callFrame->hadException())
1081             return 0;
1082         ASSERT(result.isObject());
1083         return checkedReturn(asObject(result));
1084     }
1085
1086     ASSERT(constructType == ConstructTypeHost);
1087     ScopeChainNode* scopeChain = callFrame->scopeChain();
1088     newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);
1089     newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
1090
1091     TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
1092
1093     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
1094
1095     Profiler** profiler = Profiler::enabledProfilerReference();
1096     if (*profiler)
1097         (*profiler)->willExecute(callFrame, constructor);
1098
1099     JSValue result;
1100     {
1101         SamplingTool::HostCallRecord callRecord(m_sampler.get());
1102         result = JSValue::decode(constructData.native.function(newCallFrame));
1103     }
1104
1105     if (*profiler)
1106         (*profiler)->didExecute(callFrame, constructor);
1107
1108     m_registerFile.shrink(oldEnd);
1109     if (callFrame->hadException())
1110         return 0;
1111     ASSERT(result.isObject());
1112     return checkedReturn(asObject(result));
1113 }
1114
1115 CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionExecutable, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain)
1116 {
1117     ASSERT(!scopeChain->globalData->exception);
1118     
1119     if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
1120         if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
1121             throwStackOverflowError(callFrame);
1122             return CallFrameClosure();
1123         }
1124     }
1125     
1126     Register* oldEnd = m_registerFile.end();
1127     int argc = 1 + argCount; // implicit "this" parameter
1128     
1129     if (!m_registerFile.grow(oldEnd + argc)) {
1130         throwStackOverflowError(callFrame);
1131         return CallFrameClosure();
1132     }
1133
1134     CallFrame* newCallFrame = CallFrame::create(oldEnd);
1135     // We initialise |this| unnecessarily here for the sake of code clarity
1136     size_t dst = 0;
1137     for (int i = 0; i < argc; ++i)
1138         newCallFrame->uncheckedR(dst++) = jsUndefined();
1139     
1140     JSObject* error = FunctionExecutable->compileForCall(callFrame, scopeChain);
1141     if (error) {
1142         throwError(callFrame, error);
1143         m_registerFile.shrink(oldEnd);
1144         return CallFrameClosure();
1145     }
1146     CodeBlock* codeBlock = &FunctionExecutable->generatedBytecodeForCall();
1147
1148     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
1149     if (UNLIKELY(!newCallFrame)) {
1150         throwStackOverflowError(callFrame);
1151         m_registerFile.shrink(oldEnd);
1152         return CallFrameClosure();
1153     }
1154     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), argc, function);  
1155     scopeChain->globalData->topCallFrame = newCallFrame;
1156     CallFrameClosure result = { callFrame, newCallFrame, function, FunctionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
1157     return result;
1158 }
1159
1160 JSValue Interpreter::execute(CallFrameClosure& closure) 
1161 {
1162     ASSERT(!closure.oldCallFrame->globalData().isCollectorBusy());
1163     if (closure.oldCallFrame->globalData().isCollectorBusy())
1164         return jsNull();
1165     closure.resetCallFrame();
1166     Profiler** profiler = Profiler::enabledProfilerReference();
1167     if (*profiler)
1168         (*profiler)->willExecute(closure.oldCallFrame, closure.function);
1169
1170     TopCallFrameSetter topCallFrame(*closure.globalData, closure.newCallFrame);
1171
1172     JSValue result;
1173     {
1174         SamplingTool::CallRecord callRecord(m_sampler.get());
1175         
1176         m_reentryDepth++;  
1177 #if ENABLE(JIT)
1178 #if ENABLE(INTERPRETER)
1179         if (closure.newCallFrame->globalData().canUseJIT())
1180 #endif
1181             result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData);
1182 #if ENABLE(INTERPRETER)
1183         else
1184 #endif
1185 #endif
1186 #if ENABLE(INTERPRETER)
1187             result = privateExecute(Normal, &m_registerFile, closure.newCallFrame);
1188 #endif
1189         m_reentryDepth--;
1190     }
1191
1192     if (*profiler)
1193         (*profiler)->didExecute(closure.oldCallFrame, closure.function);
1194     return checkedReturn(result);
1195 }
1196
1197 void Interpreter::endRepeatCall(CallFrameClosure& closure)
1198 {
1199     closure.globalData->topCallFrame = closure.oldCallFrame;
1200     m_registerFile.shrink(closure.oldEnd);
1201 }
1202
1203 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, ScopeChainNode* scopeChain)
1204 {
1205     JSObject* compileError = eval->compile(callFrame, scopeChain);
1206     if (UNLIKELY(!!compileError))
1207         return checkedReturn(throwError(callFrame, compileError));
1208     return execute(eval, callFrame, thisValue, m_registerFile.size() + eval->generatedBytecode().m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain);
1209 }
1210
1211 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, int globalRegisterOffset, ScopeChainNode* scopeChain)
1212 {
1213     ASSERT(isValidThisObject(thisValue, callFrame));
1214     ASSERT(!scopeChain->globalData->exception);
1215     ASSERT(!callFrame->globalData().isCollectorBusy());
1216     if (callFrame->globalData().isCollectorBusy())
1217         return jsNull();
1218
1219     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
1220
1221     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
1222         return checkedReturn(throwStackOverflowError(callFrame));
1223
1224     JSObject* compileError = eval->compile(callFrame, scopeChain);
1225     if (UNLIKELY(!!compileError))
1226         return checkedReturn(throwError(callFrame, compileError));
1227     EvalCodeBlock* codeBlock = &eval->generatedBytecode();
1228
1229     JSObject* variableObject;
1230     for (ScopeChainNode* node = scopeChain; ; node = node->next.get()) {
1231         ASSERT(node);
1232         if (node->object->isVariableObject()) {
1233             variableObject = static_cast<JSVariableObject*>(node->object.get());
1234             break;
1235         }
1236     }
1237
1238     unsigned numVariables = codeBlock->numVariables();
1239     int numFunctions = codeBlock->numberOfFunctionDecls();
1240     bool pushedScope = false;
1241     if (numVariables || numFunctions) {
1242         if (codeBlock->isStrictMode()) {
1243             variableObject = StrictEvalActivation::create(callFrame);
1244             scopeChain = scopeChain->push(variableObject);
1245             pushedScope = true;
1246         }
1247         // Scope for BatchedTransitionOptimizer
1248         BatchedTransitionOptimizer optimizer(callFrame->globalData(), variableObject);
1249
1250         for (unsigned i = 0; i < numVariables; ++i) {
1251             const Identifier& ident = codeBlock->variable(i);
1252             if (!variableObject->hasProperty(callFrame, ident)) {
1253                 PutPropertySlot slot;
1254                 variableObject->put(callFrame, ident, jsUndefined(), slot);
1255             }
1256         }
1257
1258         for (int i = 0; i < numFunctions; ++i) {
1259             FunctionExecutable* function = codeBlock->functionDecl(i);
1260             PutPropertySlot slot;
1261             variableObject->put(callFrame, function->name(), function->make(callFrame, scopeChain), slot);
1262         }
1263     }
1264
1265     Register* oldEnd = m_registerFile.end();
1266     Register* newEnd = m_registerFile.begin() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
1267     if (!m_registerFile.grow(newEnd)) {
1268         if (pushedScope)
1269             scopeChain->pop();
1270         return checkedReturn(throwStackOverflowError(callFrame));
1271     }
1272
1273     CallFrame* newCallFrame = CallFrame::create(m_registerFile.begin() + globalRegisterOffset);
1274
1275     ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'.
1276     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), codeBlock->m_numParameters, 0);
1277     newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = thisValue;
1278
1279     TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
1280
1281     Profiler** profiler = Profiler::enabledProfilerReference();
1282     if (*profiler)
1283         (*profiler)->willExecute(callFrame, eval->sourceURL(), eval->lineNo());
1284
1285     JSValue result;
1286     {
1287         SamplingTool::CallRecord callRecord(m_sampler.get());
1288
1289         m_reentryDepth++;
1290         
1291 #if ENABLE(JIT)
1292 #if ENABLE(INTERPRETER)
1293         if (callFrame->globalData().canUseJIT())
1294 #endif
1295             result = eval->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
1296 #if ENABLE(INTERPRETER)
1297         else
1298 #endif
1299 #endif
1300 #if ENABLE(INTERPRETER)
1301             result = privateExecute(Normal, &m_registerFile, newCallFrame);
1302 #endif
1303         m_reentryDepth--;
1304     }
1305
1306     if (*profiler)
1307         (*profiler)->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
1308
1309     m_registerFile.shrink(oldEnd);
1310     if (pushedScope)
1311         scopeChain->pop();
1312     return checkedReturn(result);
1313 }
1314
1315 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine)
1316 {
1317     Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
1318     if (!debugger)
1319         return;
1320
1321     switch (debugHookID) {
1322         case DidEnterCallFrame:
1323             debugger->callEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
1324             return;
1325         case WillLeaveCallFrame:
1326             debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
1327             return;
1328         case WillExecuteStatement:
1329             debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
1330             return;
1331         case WillExecuteProgram:
1332             debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
1333             return;
1334         case DidExecuteProgram:
1335             debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
1336             return;
1337         case DidReachBreakpoint:
1338             debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
1339             return;
1340     }
1341 }
1342     
1343 #if ENABLE(INTERPRETER)
1344 NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
1345 {
1346     int dst = vPC[1].u.operand;
1347     CodeBlock* codeBlock = callFrame->codeBlock();
1348     Identifier& property = codeBlock->identifier(vPC[2].u.operand);
1349     JSValue value = callFrame->r(vPC[3].u.operand).jsValue();
1350     JSObject* scope = JSStaticScopeObject::create(callFrame, property, value, DontDelete);
1351     callFrame->uncheckedR(dst) = JSValue(scope);
1352
1353     return callFrame->scopeChain()->push(scope);
1354 }
1355
1356 NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const PutPropertySlot& slot)
1357 {
1358     // Recursive invocation may already have specialized this instruction.
1359     if (vPC[0].u.opcode != getOpcode(op_put_by_id))
1360         return;
1361
1362     if (!baseValue.isCell())
1363         return;
1364
1365     // Uncacheable: give up.
1366     if (!slot.isCacheable()) {
1367         vPC[0] = getOpcode(op_put_by_id_generic);
1368         return;
1369     }
1370     
1371     JSCell* baseCell = baseValue.asCell();
1372     Structure* structure = baseCell->structure();
1373
1374     if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
1375         vPC[0] = getOpcode(op_put_by_id_generic);
1376         return;
1377     }
1378
1379     // Cache miss: record Structure to compare against next time.
1380     Structure* lastStructure = vPC[4].u.structure.get();
1381     if (structure != lastStructure) {
1382         // First miss: record Structure to compare against next time.
1383         if (!lastStructure) {
1384             vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
1385             return;
1386         }
1387
1388         // Second miss: give up.
1389         vPC[0] = getOpcode(op_put_by_id_generic);
1390         return;
1391     }
1392
1393     // Cache hit: Specialize instruction and ref Structures.
1394
1395     // If baseCell != slot.base(), then baseCell must be a proxy for another object.
1396     if (baseCell != slot.base()) {
1397         vPC[0] = getOpcode(op_put_by_id_generic);
1398         return;
1399     }
1400
1401     // Structure transition, cache transition info
1402     if (slot.type() == PutPropertySlot::NewProperty) {
1403         if (structure->isDictionary()) {
1404             vPC[0] = getOpcode(op_put_by_id_generic);
1405             return;
1406         }
1407
1408         // put_by_id_transition checks the prototype chain for setters.
1409         normalizePrototypeChain(callFrame, baseCell);
1410         JSCell* owner = codeBlock->ownerExecutable();
1411         JSGlobalData& globalData = callFrame->globalData();
1412         // Get the prototype here because the call to prototypeChain could cause a 
1413         // GC allocation, which we don't want to happen while we're in the middle of 
1414         // initializing the union.
1415         StructureChain* prototypeChain = structure->prototypeChain(callFrame);
1416         vPC[0] = getOpcode(op_put_by_id_transition);
1417         vPC[4].u.structure.set(globalData, owner, structure->previousID());
1418         vPC[5].u.structure.set(globalData, owner, structure);
1419         vPC[6].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), prototypeChain);
1420         ASSERT(vPC[6].u.structureChain);
1421         vPC[7] = slot.cachedOffset();
1422         return;
1423     }
1424
1425     vPC[0] = getOpcode(op_put_by_id_replace);
1426     vPC[5] = slot.cachedOffset();
1427 }
1428
1429 NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock*, Instruction* vPC)
1430 {
1431     vPC[0] = getOpcode(op_put_by_id);
1432     vPC[4] = 0;
1433 }
1434
1435 NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot)
1436 {
1437     // Recursive invocation may already have specialized this instruction.
1438     if (vPC[0].u.opcode != getOpcode(op_get_by_id))
1439         return;
1440
1441     // FIXME: Cache property access for immediates.
1442     if (!baseValue.isCell()) {
1443         vPC[0] = getOpcode(op_get_by_id_generic);
1444         return;
1445     }
1446
1447     JSGlobalData* globalData = &callFrame->globalData();
1448     if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
1449         vPC[0] = getOpcode(op_get_array_length);
1450         return;
1451     }
1452
1453     if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
1454         vPC[0] = getOpcode(op_get_string_length);
1455         return;
1456     }
1457
1458     // Uncacheable: give up.
1459     if (!slot.isCacheable()) {
1460         vPC[0] = getOpcode(op_get_by_id_generic);
1461         return;
1462     }
1463
1464     Structure* structure = baseValue.asCell()->structure();
1465
1466     if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
1467         vPC[0] = getOpcode(op_get_by_id_generic);
1468         return;
1469     }
1470
1471     // Cache miss
1472     Structure* lastStructure = vPC[4].u.structure.get();
1473     if (structure != lastStructure) {
1474         // First miss: record Structure to compare against next time.
1475         if (!lastStructure) {
1476             vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
1477             return;
1478         }
1479
1480         // Second miss: give up.
1481         vPC[0] = getOpcode(op_get_by_id_generic);
1482         return;
1483     }
1484
1485     // Cache hit: Specialize instruction and ref Structures.
1486
1487     if (slot.slotBase() == baseValue) {
1488         switch (slot.cachedPropertyType()) {
1489         case PropertySlot::Getter:
1490             vPC[0] = getOpcode(op_get_by_id_getter_self);
1491             vPC[5] = slot.cachedOffset();
1492             break;
1493         case PropertySlot::Custom:
1494             vPC[0] = getOpcode(op_get_by_id_custom_self);
1495             vPC[5] = slot.customGetter();
1496             break;
1497         default:
1498             vPC[0] = getOpcode(op_get_by_id_self);
1499             vPC[5] = slot.cachedOffset();
1500             break;
1501         }
1502         return;
1503     }
1504
1505     if (structure->isDictionary()) {
1506         vPC[0] = getOpcode(op_get_by_id_generic);
1507         return;
1508     }
1509
1510     if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
1511         ASSERT(slot.slotBase().isObject());
1512
1513         JSObject* baseObject = asObject(slot.slotBase());
1514         size_t offset = slot.cachedOffset();
1515
1516         // Since we're accessing a prototype in a loop, it's a good bet that it
1517         // should not be treated as a dictionary.
1518         if (baseObject->structure()->isDictionary()) {
1519             baseObject->flattenDictionaryObject(callFrame->globalData());
1520             offset = baseObject->structure()->get(callFrame->globalData(), propertyName);
1521         }
1522
1523         ASSERT(!baseObject->structure()->isUncacheableDictionary());
1524         
1525         switch (slot.cachedPropertyType()) {
1526         case PropertySlot::Getter:
1527             vPC[0] = getOpcode(op_get_by_id_getter_proto);
1528             vPC[6] = offset;
1529             break;
1530         case PropertySlot::Custom:
1531             vPC[0] = getOpcode(op_get_by_id_custom_proto);
1532             vPC[6] = slot.customGetter();
1533             break;
1534         default:
1535             vPC[0] = getOpcode(op_get_by_id_proto);
1536             vPC[6] = offset;
1537             break;
1538         }
1539         vPC[5].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), baseObject->structure());
1540         return;
1541     }
1542
1543     size_t offset = slot.cachedOffset();
1544     size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
1545     if (!count) {
1546         vPC[0] = getOpcode(op_get_by_id_generic);
1547         return;
1548     }
1549
1550     
1551     switch (slot.cachedPropertyType()) {
1552     case PropertySlot::Getter:
1553         vPC[0] = getOpcode(op_get_by_id_getter_chain);
1554         vPC[7] = offset;
1555         break;
1556     case PropertySlot::Custom:
1557         vPC[0] = getOpcode(op_get_by_id_custom_chain);
1558         vPC[7] = slot.customGetter();
1559         break;
1560     default:
1561         vPC[0] = getOpcode(op_get_by_id_chain);
1562         vPC[7] = offset;
1563         break;
1564     }
1565     vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
1566     vPC[5].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure->prototypeChain(callFrame));
1567     vPC[6] = count;
1568 }
1569
1570 NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock*, Instruction* vPC)
1571 {
1572     vPC[0] = getOpcode(op_get_by_id);
1573     vPC[4] = 0;
1574 }
1575
1576 #endif // ENABLE(INTERPRETER)
1577
1578 JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame)
1579 {
1580     // One-time initialization of our address tables. We have to put this code
1581     // here because our labels are only in scope inside this function.
1582     if (UNLIKELY(flag == InitializeAndReturn)) {
1583         #if ENABLE(COMPUTED_GOTO_INTERPRETER)
1584             #define LIST_OPCODE_LABEL(id, length) &&id,
1585                 static Opcode labels[] = { FOR_EACH_OPCODE_ID(LIST_OPCODE_LABEL) };
1586                 for (size_t i = 0; i < WTF_ARRAY_LENGTH(labels); ++i)
1587                     m_opcodeTable[i] = labels[i];
1588             #undef LIST_OPCODE_LABEL
1589         #endif // ENABLE(COMPUTED_GOTO_INTERPRETER)
1590         return JSValue();
1591     }
1592     
1593 #if ENABLE(JIT)
1594 #if ENABLE(INTERPRETER)
1595     // Mixing Interpreter + JIT is not supported.
1596     if (callFrame->globalData().canUseJIT())
1597 #endif
1598         ASSERT_NOT_REACHED();
1599 #endif
1600
1601 #if !ENABLE(INTERPRETER)
1602     UNUSED_PARAM(registerFile);
1603     UNUSED_PARAM(callFrame);
1604     return JSValue();
1605 #else
1606
1607     ASSERT(callFrame->globalData().topCallFrame == callFrame);
1608
1609     JSGlobalData* globalData = &callFrame->globalData();
1610     JSValue exceptionValue;
1611     HandlerInfo* handler = 0;
1612     CallFrame** topCallFrameSlot = &globalData->topCallFrame;
1613
1614     CodeBlock* codeBlock = callFrame->codeBlock();
1615     Instruction* vPC = codeBlock->instructions().begin();
1616     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
1617     unsigned tickCount = globalData->timeoutChecker.ticksUntilNextCheck();
1618     JSValue functionReturnValue;
1619
1620 #define CHECK_FOR_EXCEPTION() \
1621     do { \
1622         if (UNLIKELY(globalData->exception != JSValue())) { \
1623             exceptionValue = globalData->exception; \
1624             goto vm_throw; \
1625         } \
1626     } while (0)
1627
1628 #if ENABLE(OPCODE_STATS)
1629     OpcodeStats::resetLastInstruction();
1630 #endif
1631
1632 #define CHECK_FOR_TIMEOUT() \
1633     if (!--tickCount) { \
1634         if (globalData->terminator.shouldTerminate() || globalData->timeoutChecker.didTimeOut(callFrame)) { \
1635             exceptionValue = jsNull(); \
1636             goto vm_throw; \
1637         } \
1638         tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); \
1639     }
1640     
1641 #if ENABLE(OPCODE_SAMPLING)
1642     #define SAMPLE(codeBlock, vPC) m_sampler->sample(codeBlock, vPC)
1643 #else
1644     #define SAMPLE(codeBlock, vPC)
1645 #endif
1646
1647 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
1648     #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto *vPC->u.opcode
1649 #if ENABLE(OPCODE_STATS)
1650     #define DEFINE_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
1651 #else
1652     #define DEFINE_OPCODE(opcode) opcode:
1653 #endif
1654     NEXT_INSTRUCTION();
1655 #else
1656     #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto interpreterLoopStart
1657 #if ENABLE(OPCODE_STATS)
1658     #define DEFINE_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
1659 #else
1660     #define DEFINE_OPCODE(opcode) case opcode:
1661 #endif
1662     while (1) { // iterator loop begins
1663     interpreterLoopStart:;
1664     switch (vPC->u.opcode)
1665 #endif
1666     {
1667     DEFINE_OPCODE(op_new_object) {
1668         /* new_object dst(r)
1669
1670            Constructs a new empty Object instance using the original
1671            constructor, and puts the result in register dst.
1672         */
1673         int dst = vPC[1].u.operand;
1674         callFrame->uncheckedR(dst) = JSValue(constructEmptyObject(callFrame));
1675
1676         vPC += OPCODE_LENGTH(op_new_object);
1677         NEXT_INSTRUCTION();
1678     }
1679     DEFINE_OPCODE(op_new_array) {
1680         /* new_array dst(r) firstArg(r) argCount(n)
1681
1682            Constructs a new Array instance using the original
1683            constructor, and puts the result in register dst.
1684            The array will contain argCount elements with values
1685            taken from registers starting at register firstArg.
1686         */
1687         int dst = vPC[1].u.operand;
1688         int firstArg = vPC[2].u.operand;
1689         int argCount = vPC[3].u.operand;
1690         ArgList args(callFrame->registers() + firstArg, argCount);
1691         callFrame->uncheckedR(dst) = JSValue(constructArray(callFrame, args));
1692
1693         vPC += OPCODE_LENGTH(op_new_array);
1694         NEXT_INSTRUCTION();
1695     }
1696     DEFINE_OPCODE(op_new_array_buffer) {
1697         /* new_array_buffer dst(r) index(n) argCount(n)
1698          
1699          Constructs a new Array instance using the original
1700          constructor, and puts the result in register dst.
1701          The array be initialized with the values from constantBuffer[index]
1702          */
1703         int dst = vPC[1].u.operand;
1704         int firstArg = vPC[2].u.operand;
1705         int argCount = vPC[3].u.operand;
1706         ArgList args(codeBlock->constantBuffer(firstArg), argCount);
1707         callFrame->uncheckedR(dst) = JSValue(constructArray(callFrame, args));
1708         
1709         vPC += OPCODE_LENGTH(op_new_array);
1710         NEXT_INSTRUCTION();
1711     }
1712     DEFINE_OPCODE(op_new_regexp) {
1713         /* new_regexp dst(r) regExp(re)
1714
1715            Constructs a new RegExp instance using the original
1716            constructor from regexp regExp, and puts the result in
1717            register dst.
1718         */
1719         int dst = vPC[1].u.operand;
1720         RegExp* regExp = codeBlock->regexp(vPC[2].u.operand);
1721         if (!regExp->isValid()) {
1722             exceptionValue = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor.");
1723             goto vm_throw;
1724         }
1725         callFrame->uncheckedR(dst) = JSValue(RegExpObject::create(*globalData, callFrame->lexicalGlobalObject(), callFrame->scopeChain()->globalObject->regExpStructure(), regExp));
1726
1727         vPC += OPCODE_LENGTH(op_new_regexp);
1728         NEXT_INSTRUCTION();
1729     }
1730     DEFINE_OPCODE(op_mov) {
1731         /* mov dst(r) src(r)
1732
1733            Copies register src to register dst.
1734         */
1735         int dst = vPC[1].u.operand;
1736         int src = vPC[2].u.operand;
1737         
1738         callFrame->uncheckedR(dst) = callFrame->r(src);
1739
1740         vPC += OPCODE_LENGTH(op_mov);
1741         NEXT_INSTRUCTION();
1742     }
1743     DEFINE_OPCODE(op_eq) {
1744         /* eq dst(r) src1(r) src2(r)
1745
1746            Checks whether register src1 and register src2 are equal,
1747            as with the ECMAScript '==' operator, and puts the result
1748            as a boolean in register dst.
1749         */
1750         int dst = vPC[1].u.operand;
1751         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1752         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1753         if (src1.isInt32() && src2.isInt32())
1754             callFrame->uncheckedR(dst) = jsBoolean(src1.asInt32() == src2.asInt32());
1755         else {
1756             JSValue result = jsBoolean(JSValue::equalSlowCase(callFrame, src1, src2));
1757             CHECK_FOR_EXCEPTION();
1758             callFrame->uncheckedR(dst) = result;
1759         }
1760
1761         vPC += OPCODE_LENGTH(op_eq);
1762         NEXT_INSTRUCTION();
1763     }
1764     DEFINE_OPCODE(op_eq_null) {
1765         /* eq_null dst(r) src(r)
1766
1767            Checks whether register src is null, as with the ECMAScript '!='
1768            operator, and puts the result as a boolean in register dst.
1769         */
1770         int dst = vPC[1].u.operand;
1771         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
1772
1773         if (src.isUndefinedOrNull()) {
1774             callFrame->uncheckedR(dst) = jsBoolean(true);
1775             vPC += OPCODE_LENGTH(op_eq_null);
1776             NEXT_INSTRUCTION();
1777         }
1778         
1779         callFrame->uncheckedR(dst) = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
1780         vPC += OPCODE_LENGTH(op_eq_null);
1781         NEXT_INSTRUCTION();
1782     }
1783     DEFINE_OPCODE(op_neq) {
1784         /* neq dst(r) src1(r) src2(r)
1785
1786            Checks whether register src1 and register src2 are not
1787            equal, as with the ECMAScript '!=' operator, and puts the
1788            result as a boolean in register dst.
1789         */
1790         int dst = vPC[1].u.operand;
1791         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1792         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1793         if (src1.isInt32() && src2.isInt32())
1794             callFrame->uncheckedR(dst) = jsBoolean(src1.asInt32() != src2.asInt32());
1795         else {
1796             JSValue result = jsBoolean(!JSValue::equalSlowCase(callFrame, src1, src2));
1797             CHECK_FOR_EXCEPTION();
1798             callFrame->uncheckedR(dst) = result;
1799         }
1800
1801         vPC += OPCODE_LENGTH(op_neq);
1802         NEXT_INSTRUCTION();
1803     }
1804     DEFINE_OPCODE(op_neq_null) {
1805         /* neq_null dst(r) src(r)
1806
1807            Checks whether register src is not null, as with the ECMAScript '!='
1808            operator, and puts the result as a boolean in register dst.
1809         */
1810         int dst = vPC[1].u.operand;
1811         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
1812
1813         if (src.isUndefinedOrNull()) {
1814             callFrame->uncheckedR(dst) = jsBoolean(false);
1815             vPC += OPCODE_LENGTH(op_neq_null);
1816             NEXT_INSTRUCTION();
1817         }
1818         
1819         callFrame->uncheckedR(dst) = jsBoolean(!src.isCell() || !src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
1820         vPC += OPCODE_LENGTH(op_neq_null);
1821         NEXT_INSTRUCTION();
1822     }
1823     DEFINE_OPCODE(op_stricteq) {
1824         /* stricteq dst(r) src1(r) src2(r)
1825
1826            Checks whether register src1 and register src2 are strictly
1827            equal, as with the ECMAScript '===' operator, and puts the
1828            result as a boolean in register dst.
1829         */
1830         int dst = vPC[1].u.operand;
1831         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1832         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1833         bool result = JSValue::strictEqual(callFrame, src1, src2);
1834         CHECK_FOR_EXCEPTION();
1835         callFrame->uncheckedR(dst) = jsBoolean(result);
1836
1837         vPC += OPCODE_LENGTH(op_stricteq);
1838         NEXT_INSTRUCTION();
1839     }
1840     DEFINE_OPCODE(op_nstricteq) {
1841         /* nstricteq dst(r) src1(r) src2(r)
1842
1843            Checks whether register src1 and register src2 are not
1844            strictly equal, as with the ECMAScript '!==' operator, and
1845            puts the result as a boolean in register dst.
1846         */
1847         int dst = vPC[1].u.operand;
1848         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1849         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1850         bool result = !JSValue::strictEqual(callFrame, src1, src2);
1851         CHECK_FOR_EXCEPTION();
1852         callFrame->uncheckedR(dst) = jsBoolean(result);
1853
1854         vPC += OPCODE_LENGTH(op_nstricteq);
1855         NEXT_INSTRUCTION();
1856     }
1857     DEFINE_OPCODE(op_less) {
1858         /* less dst(r) src1(r) src2(r)
1859
1860            Checks whether register src1 is less than register src2, as
1861            with the ECMAScript '<' operator, and puts the result as
1862            a boolean in register dst.
1863         */
1864         int dst = vPC[1].u.operand;
1865         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1866         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1867         JSValue result = jsBoolean(jsLess<true>(callFrame, src1, src2));
1868         CHECK_FOR_EXCEPTION();
1869         callFrame->uncheckedR(dst) = result;
1870
1871         vPC += OPCODE_LENGTH(op_less);
1872         NEXT_INSTRUCTION();
1873     }
1874     DEFINE_OPCODE(op_lesseq) {
1875         /* lesseq dst(r) src1(r) src2(r)
1876
1877            Checks whether register src1 is less than or equal to
1878            register src2, as with the ECMAScript '<=' operator, and
1879            puts the result as a boolean in register dst.
1880         */
1881         int dst = vPC[1].u.operand;
1882         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1883         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1884         JSValue result = jsBoolean(jsLessEq<true>(callFrame, src1, src2));
1885         CHECK_FOR_EXCEPTION();
1886         callFrame->uncheckedR(dst) = result;
1887
1888         vPC += OPCODE_LENGTH(op_lesseq);
1889         NEXT_INSTRUCTION();
1890     }
1891     DEFINE_OPCODE(op_greater) {
1892         /* greater dst(r) src1(r) src2(r)
1893
1894            Checks whether register src1 is greater than register src2, as
1895            with the ECMAScript '>' operator, and puts the result as
1896            a boolean in register dst.
1897         */
1898         int dst = vPC[1].u.operand;
1899         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1900         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1901         JSValue result = jsBoolean(jsLess<false>(callFrame, src2, src1));
1902         CHECK_FOR_EXCEPTION();
1903         callFrame->uncheckedR(dst) = result;
1904
1905         vPC += OPCODE_LENGTH(op_greater);
1906         NEXT_INSTRUCTION();
1907     }
1908     DEFINE_OPCODE(op_greatereq) {
1909         /* greatereq dst(r) src1(r) src2(r)
1910
1911            Checks whether register src1 is greater than or equal to
1912            register src2, as with the ECMAScript '>=' operator, and
1913            puts the result as a boolean in register dst.
1914         */
1915         int dst = vPC[1].u.operand;
1916         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1917         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1918         JSValue result = jsBoolean(jsLessEq<false>(callFrame, src2, src1));
1919         CHECK_FOR_EXCEPTION();
1920         callFrame->uncheckedR(dst) = result;
1921
1922         vPC += OPCODE_LENGTH(op_greatereq);
1923         NEXT_INSTRUCTION();
1924     }
1925     DEFINE_OPCODE(op_pre_inc) {
1926         /* pre_inc srcDst(r)
1927
1928            Converts register srcDst to number, adds one, and puts the result
1929            back in register srcDst.
1930         */
1931         int srcDst = vPC[1].u.operand;
1932         JSValue v = callFrame->r(srcDst).jsValue();
1933         if (v.isInt32() && v.asInt32() < INT_MAX)
1934             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() + 1);
1935         else {
1936             JSValue result = jsNumber(v.toNumber(callFrame) + 1);
1937             CHECK_FOR_EXCEPTION();
1938             callFrame->uncheckedR(srcDst) = result;
1939         }
1940
1941         vPC += OPCODE_LENGTH(op_pre_inc);
1942         NEXT_INSTRUCTION();
1943     }
1944     DEFINE_OPCODE(op_pre_dec) {
1945         /* pre_dec srcDst(r)
1946
1947            Converts register srcDst to number, subtracts one, and puts the result
1948            back in register srcDst.
1949         */
1950         int srcDst = vPC[1].u.operand;
1951         JSValue v = callFrame->r(srcDst).jsValue();
1952         if (v.isInt32() && v.asInt32() > INT_MIN)
1953             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() - 1);
1954         else {
1955             JSValue result = jsNumber(v.toNumber(callFrame) - 1);
1956             CHECK_FOR_EXCEPTION();
1957             callFrame->uncheckedR(srcDst) = result;
1958         }
1959
1960         vPC += OPCODE_LENGTH(op_pre_dec);
1961         NEXT_INSTRUCTION();
1962     }
1963     DEFINE_OPCODE(op_post_inc) {
1964         /* post_inc dst(r) srcDst(r)
1965
1966            Converts register srcDst to number. The number itself is
1967            written to register dst, and the number plus one is written
1968            back to register srcDst.
1969         */
1970         int dst = vPC[1].u.operand;
1971         int srcDst = vPC[2].u.operand;
1972         JSValue v = callFrame->r(srcDst).jsValue();
1973         if (v.isInt32() && v.asInt32() < INT_MAX) {
1974             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() + 1);
1975             callFrame->uncheckedR(dst) = v;
1976         } else {
1977             JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
1978             CHECK_FOR_EXCEPTION();
1979             callFrame->uncheckedR(srcDst) = jsNumber(number.uncheckedGetNumber() + 1);
1980             callFrame->uncheckedR(dst) = number;
1981         }
1982
1983         vPC += OPCODE_LENGTH(op_post_inc);
1984         NEXT_INSTRUCTION();
1985     }
1986     DEFINE_OPCODE(op_post_dec) {
1987         /* post_dec dst(r) srcDst(r)
1988
1989            Converts register srcDst to number. The number itself is
1990            written to register dst, and the number minus one is written
1991            back to register srcDst.
1992         */
1993         int dst = vPC[1].u.operand;
1994         int srcDst = vPC[2].u.operand;
1995         JSValue v = callFrame->r(srcDst).jsValue();
1996         if (v.isInt32() && v.asInt32() > INT_MIN) {
1997             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() - 1);
1998             callFrame->uncheckedR(dst) = v;
1999         } else {
2000             JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
2001             CHECK_FOR_EXCEPTION();
2002             callFrame->uncheckedR(srcDst) = jsNumber(number.uncheckedGetNumber() - 1);
2003             callFrame->uncheckedR(dst) = number;
2004         }
2005
2006         vPC += OPCODE_LENGTH(op_post_dec);
2007         NEXT_INSTRUCTION();
2008     }
2009     DEFINE_OPCODE(op_to_jsnumber) {
2010         /* to_jsnumber dst(r) src(r)
2011
2012            Converts register src to number, and puts the result
2013            in register dst.
2014         */
2015         int dst = vPC[1].u.operand;
2016         int src = vPC[2].u.operand;
2017
2018         JSValue srcVal = callFrame->r(src).jsValue();
2019
2020         if (LIKELY(srcVal.isNumber()))
2021             callFrame->uncheckedR(dst) = callFrame->r(src);
2022         else {
2023             JSValue result = srcVal.toJSNumber(callFrame);
2024             CHECK_FOR_EXCEPTION();
2025             callFrame->uncheckedR(dst) = result;
2026         }
2027
2028         vPC += OPCODE_LENGTH(op_to_jsnumber);
2029         NEXT_INSTRUCTION();
2030     }
2031     DEFINE_OPCODE(op_negate) {
2032         /* negate dst(r) src(r)
2033
2034            Converts register src to number, negates it, and puts the
2035            result in register dst.
2036         */
2037         int dst = vPC[1].u.operand;
2038         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
2039         if (src.isInt32() && (src.asInt32() & 0x7fffffff)) // non-zero and no overflow
2040             callFrame->uncheckedR(dst) = jsNumber(-src.asInt32());
2041         else {
2042             JSValue result = jsNumber(-src.toNumber(callFrame));
2043             CHECK_FOR_EXCEPTION();
2044             callFrame->uncheckedR(dst) = result;
2045         }
2046
2047         vPC += OPCODE_LENGTH(op_negate);
2048         NEXT_INSTRUCTION();
2049     }
2050     DEFINE_OPCODE(op_add) {
2051         /* add dst(r) src1(r) src2(r)
2052
2053            Adds register src1 and register src2, and puts the result
2054            in register dst. (JS add may be string concatenation or
2055            numeric add, depending on the types of the operands.)
2056         */
2057         int dst = vPC[1].u.operand;
2058         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2059         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2060         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
2061             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() + src2.asInt32());
2062         else {
2063             JSValue result = jsAdd(callFrame, src1, src2);
2064             CHECK_FOR_EXCEPTION();
2065             callFrame->uncheckedR(dst) = result;
2066         }
2067         vPC += OPCODE_LENGTH(op_add);
2068         NEXT_INSTRUCTION();
2069     }
2070     DEFINE_OPCODE(op_mul) {
2071         /* mul dst(r) src1(r) src2(r)
2072
2073            Multiplies register src1 and register src2 (converted to
2074            numbers), and puts the product in register dst.
2075         */
2076         int dst = vPC[1].u.operand;
2077         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2078         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2079         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() >> 15)) // no overflow
2080                 callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() * src2.asInt32());
2081         else {
2082             JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
2083             CHECK_FOR_EXCEPTION();
2084             callFrame->uncheckedR(dst) = result;
2085         }
2086
2087         vPC += OPCODE_LENGTH(op_mul);
2088         NEXT_INSTRUCTION();
2089     }
2090     DEFINE_OPCODE(op_div) {
2091         /* div dst(r) dividend(r) divisor(r)
2092
2093            Divides register dividend (converted to number) by the
2094            register divisor (converted to number), and puts the
2095            quotient in register dst.
2096         */
2097         int dst = vPC[1].u.operand;
2098         JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
2099         JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
2100
2101         JSValue result = jsNumber(dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
2102         CHECK_FOR_EXCEPTION();
2103         callFrame->uncheckedR(dst) = result;
2104
2105         vPC += OPCODE_LENGTH(op_div);
2106         NEXT_INSTRUCTION();
2107     }
2108     DEFINE_OPCODE(op_mod) {
2109         /* mod dst(r) dividend(r) divisor(r)
2110
2111            Divides register dividend (converted to number) by
2112            register divisor (converted to number), and puts the
2113            remainder in register dst.
2114         */
2115         int dst = vPC[1].u.operand;
2116         JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
2117         JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
2118
2119         if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0) {
2120             JSValue result = jsNumber(dividend.asInt32() % divisor.asInt32());
2121             ASSERT(result);
2122             callFrame->uncheckedR(dst) = result;
2123             vPC += OPCODE_LENGTH(op_mod);
2124             NEXT_INSTRUCTION();
2125         }
2126
2127         // Conversion to double must happen outside the call to fmod since the
2128         // order of argument evaluation is not guaranteed.
2129         double d1 = dividend.toNumber(callFrame);
2130         double d2 = divisor.toNumber(callFrame);
2131         JSValue result = jsNumber(fmod(d1, d2));
2132         CHECK_FOR_EXCEPTION();
2133         callFrame->uncheckedR(dst) = result;
2134         vPC += OPCODE_LENGTH(op_mod);
2135         NEXT_INSTRUCTION();
2136     }
2137     DEFINE_OPCODE(op_sub) {
2138         /* sub dst(r) src1(r) src2(r)
2139
2140            Subtracts register src2 (converted to number) from register
2141            src1 (converted to number), and puts the difference in
2142            register dst.
2143         */
2144         int dst = vPC[1].u.operand;
2145         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2146         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2147         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
2148             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() - src2.asInt32());
2149         else {
2150             JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
2151             CHECK_FOR_EXCEPTION();
2152             callFrame->uncheckedR(dst) = result;
2153         }
2154         vPC += OPCODE_LENGTH(op_sub);
2155         NEXT_INSTRUCTION();
2156     }
2157     DEFINE_OPCODE(op_lshift) {
2158         /* lshift dst(r) val(r) shift(r)
2159
2160            Performs left shift of register val (converted to int32) by
2161            register shift (converted to uint32), and puts the result
2162            in register dst.
2163         */
2164         int dst = vPC[1].u.operand;
2165         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
2166         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
2167
2168         if (val.isInt32() && shift.isInt32())
2169             callFrame->uncheckedR(dst) = jsNumber(val.asInt32() << (shift.asInt32() & 0x1f));
2170         else {
2171             JSValue result = jsNumber((val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
2172             CHECK_FOR_EXCEPTION();
2173             callFrame->uncheckedR(dst) = result;
2174         }
2175
2176         vPC += OPCODE_LENGTH(op_lshift);
2177         NEXT_INSTRUCTION();
2178     }
2179     DEFINE_OPCODE(op_rshift) {
2180         /* rshift dst(r) val(r) shift(r)
2181
2182            Performs arithmetic right shift of register val (converted
2183            to int32) by register shift (converted to
2184            uint32), and puts the result in register dst.
2185         */
2186         int dst = vPC[1].u.operand;
2187         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
2188         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
2189
2190         if (val.isInt32() && shift.isInt32())
2191             callFrame->uncheckedR(dst) = jsNumber(val.asInt32() >> (shift.asInt32() & 0x1f));
2192         else {
2193             JSValue result = jsNumber((val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
2194             CHECK_FOR_EXCEPTION();
2195             callFrame->uncheckedR(dst) = result;
2196         }
2197
2198         vPC += OPCODE_LENGTH(op_rshift);
2199         NEXT_INSTRUCTION();
2200     }
2201     DEFINE_OPCODE(op_urshift) {
2202         /* rshift dst(r) val(r) shift(r)
2203
2204            Performs logical right shift of register val (converted
2205            to uint32) by register shift (converted to
2206            uint32), and puts the result in register dst.
2207         */
2208         int dst = vPC[1].u.operand;
2209         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
2210         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
2211         if (val.isUInt32() && shift.isInt32())
2212             callFrame->uncheckedR(dst) = jsNumber(val.asInt32() >> (shift.asInt32() & 0x1f));
2213         else {
2214             JSValue result = jsNumber((val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
2215             CHECK_FOR_EXCEPTION();
2216             callFrame->uncheckedR(dst) = result;
2217         }
2218
2219         vPC += OPCODE_LENGTH(op_urshift);
2220         NEXT_INSTRUCTION();
2221     }
2222     DEFINE_OPCODE(op_bitand) {
2223         /* bitand dst(r) src1(r) src2(r)
2224
2225            Computes bitwise AND of register src1 (converted to int32)
2226            and register src2 (converted to int32), and puts the result
2227            in register dst.
2228         */
2229         int dst = vPC[1].u.operand;
2230         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2231         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2232         if (src1.isInt32() && src2.isInt32())
2233             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() & src2.asInt32());
2234         else {
2235             JSValue result = jsNumber(src1.toInt32(callFrame) & src2.toInt32(callFrame));
2236             CHECK_FOR_EXCEPTION();
2237             callFrame->uncheckedR(dst) = result;
2238         }
2239
2240         vPC += OPCODE_LENGTH(op_bitand);
2241         NEXT_INSTRUCTION();
2242     }
2243     DEFINE_OPCODE(op_bitxor) {
2244         /* bitxor dst(r) src1(r) src2(r)
2245
2246            Computes bitwise XOR of register src1 (converted to int32)
2247            and register src2 (converted to int32), and puts the result
2248            in register dst.
2249         */
2250         int dst = vPC[1].u.operand;
2251         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2252         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2253         if (src1.isInt32() && src2.isInt32())
2254             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() ^ src2.asInt32());
2255         else {
2256             JSValue result = jsNumber(src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
2257             CHECK_FOR_EXCEPTION();
2258             callFrame->uncheckedR(dst) = result;
2259         }
2260
2261         vPC += OPCODE_LENGTH(op_bitxor);
2262         NEXT_INSTRUCTION();
2263     }
2264     DEFINE_OPCODE(op_bitor) {
2265         /* bitor dst(r) src1(r) src2(r)
2266
2267            Computes bitwise OR of register src1 (converted to int32)
2268            and register src2 (converted to int32), and puts the
2269            result in register dst.
2270         */
2271         int dst = vPC[1].u.operand;
2272         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2273         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2274         if (src1.isInt32() && src2.isInt32())
2275             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() | src2.asInt32());
2276         else {
2277             JSValue result = jsNumber(src1.toInt32(callFrame) | src2.toInt32(callFrame));
2278             CHECK_FOR_EXCEPTION();
2279             callFrame->uncheckedR(dst) = result;
2280         }
2281
2282         vPC += OPCODE_LENGTH(op_bitor);
2283         NEXT_INSTRUCTION();
2284     }
2285     DEFINE_OPCODE(op_bitnot) {
2286         /* bitnot dst(r) src(r)
2287
2288            Computes bitwise NOT of register src1 (converted to int32),
2289            and puts the result in register dst.
2290         */
2291         int dst = vPC[1].u.operand;
2292         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
2293         if (src.isInt32())
2294             callFrame->uncheckedR(dst) = jsNumber(~src.asInt32());
2295         else {
2296             JSValue result = jsNumber(~src.toInt32(callFrame));
2297             CHECK_FOR_EXCEPTION();
2298             callFrame->uncheckedR(dst) = result;
2299         }
2300         vPC += OPCODE_LENGTH(op_bitnot);
2301         NEXT_INSTRUCTION();
2302     }
2303     DEFINE_OPCODE(op_not) {
2304         /* not dst(r) src(r)
2305
2306            Computes logical NOT of register src (converted to
2307            boolean), and puts the result in register dst.
2308         */
2309         int dst = vPC[1].u.operand;
2310         int src = vPC[2].u.operand;
2311         JSValue result = jsBoolean(!callFrame->r(src).jsValue().toBoolean(callFrame));
2312         CHECK_FOR_EXCEPTION();
2313         callFrame->uncheckedR(dst) = result;
2314
2315         vPC += OPCODE_LENGTH(op_not);
2316         NEXT_INSTRUCTION();
2317     }
2318     DEFINE_OPCODE(op_check_has_instance) {
2319         /* check_has_instance constructor(r)
2320
2321            Check 'constructor' is an object with the internal property
2322            [HasInstance] (i.e. is a function ... *shakes head sadly at
2323            JSC API*). Raises an exception if register constructor is not
2324            an valid parameter for instanceof.
2325         */
2326         int base = vPC[1].u.operand;
2327         JSValue baseVal = callFrame->r(base).jsValue();
2328
2329         if (isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue))
2330             goto vm_throw;
2331
2332         vPC += OPCODE_LENGTH(op_check_has_instance);
2333         NEXT_INSTRUCTION();
2334     }
2335     DEFINE_OPCODE(op_instanceof) {
2336         /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
2337
2338            Tests whether register value is an instance of register
2339            constructor, and puts the boolean result in register
2340            dst. Register constructorProto must contain the "prototype"
2341            property (not the actual prototype) of the object in
2342            register constructor. This lookup is separated so that
2343            polymorphic inline caching can apply.
2344
2345            Raises an exception if register constructor is not an
2346            object.
2347         */
2348         int dst = vPC[1].u.operand;
2349         int value = vPC[2].u.operand;
2350         int base = vPC[3].u.operand;
2351         int baseProto = vPC[4].u.operand;
2352
2353         JSValue baseVal = callFrame->r(base).jsValue();
2354
2355         ASSERT(!isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue));
2356
2357         bool result = asObject(baseVal)->hasInstance(callFrame, callFrame->r(value).jsValue(), callFrame->r(baseProto).jsValue());
2358         CHECK_FOR_EXCEPTION();
2359         callFrame->uncheckedR(dst) = jsBoolean(result);
2360
2361         vPC += OPCODE_LENGTH(op_instanceof);
2362         NEXT_INSTRUCTION();
2363     }
2364     DEFINE_OPCODE(op_typeof) {
2365         /* typeof dst(r) src(r)
2366
2367            Determines the type string for src according to ECMAScript
2368            rules, and puts the result in register dst.
2369         */
2370         int dst = vPC[1].u.operand;
2371         int src = vPC[2].u.operand;
2372         callFrame->uncheckedR(dst) = JSValue(jsTypeStringForValue(callFrame, callFrame->r(src).jsValue()));
2373
2374         vPC += OPCODE_LENGTH(op_typeof);
2375         NEXT_INSTRUCTION();
2376     }
2377     DEFINE_OPCODE(op_is_undefined) {
2378         /* is_undefined dst(r) src(r)
2379
2380            Determines whether the type string for src according to
2381            the ECMAScript rules is "undefined", and puts the result
2382            in register dst.
2383         */
2384         int dst = vPC[1].u.operand;
2385         int src = vPC[2].u.operand;
2386         JSValue v = callFrame->r(src).jsValue();
2387         callFrame->uncheckedR(dst) = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined());
2388
2389         vPC += OPCODE_LENGTH(op_is_undefined);
2390         NEXT_INSTRUCTION();
2391     }
2392     DEFINE_OPCODE(op_is_boolean) {
2393         /* is_boolean dst(r) src(r)
2394
2395            Determines whether the type string for src according to
2396            the ECMAScript rules is "boolean", and puts the result
2397            in register dst.
2398         */
2399         int dst = vPC[1].u.operand;
2400         int src = vPC[2].u.operand;
2401         callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isBoolean());
2402
2403         vPC += OPCODE_LENGTH(op_is_boolean);
2404         NEXT_INSTRUCTION();
2405     }
2406     DEFINE_OPCODE(op_is_number) {
2407         /* is_number dst(r) src(r)
2408
2409            Determines whether the type string for src according to
2410            the ECMAScript rules is "number", and puts the result
2411            in register dst.
2412         */
2413         int dst = vPC[1].u.operand;
2414         int src = vPC[2].u.operand;
2415         callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isNumber());
2416
2417         vPC += OPCODE_LENGTH(op_is_number);
2418         NEXT_INSTRUCTION();
2419     }
2420     DEFINE_OPCODE(op_is_string) {
2421         /* is_string dst(r) src(r)
2422
2423            Determines whether the type string for src according to
2424            the ECMAScript rules is "string", and puts the result
2425            in register dst.
2426         */
2427         int dst = vPC[1].u.operand;
2428         int src = vPC[2].u.operand;
2429         callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isString());
2430
2431         vPC += OPCODE_LENGTH(op_is_string);
2432         NEXT_INSTRUCTION();
2433     }
2434     DEFINE_OPCODE(op_is_object) {
2435         /* is_object dst(r) src(r)
2436
2437            Determines whether the type string for src according to
2438            the ECMAScript rules is "object", and puts the result
2439            in register dst.
2440         */
2441         int dst = vPC[1].u.operand;
2442         int src = vPC[2].u.operand;
2443         callFrame->uncheckedR(dst) = jsBoolean(jsIsObjectType(callFrame->r(src).jsValue()));
2444
2445         vPC += OPCODE_LENGTH(op_is_object);
2446         NEXT_INSTRUCTION();
2447     }
2448     DEFINE_OPCODE(op_is_function) {
2449         /* is_function dst(r) src(r)
2450
2451            Determines whether the type string for src according to
2452            the ECMAScript rules is "function", and puts the result
2453            in register dst.
2454         */
2455         int dst = vPC[1].u.operand;
2456         int src = vPC[2].u.operand;
2457         callFrame->uncheckedR(dst) = jsBoolean(jsIsFunctionType(callFrame->r(src).jsValue()));
2458
2459         vPC += OPCODE_LENGTH(op_is_function);
2460         NEXT_INSTRUCTION();
2461     }
2462     DEFINE_OPCODE(op_in) {
2463         /* in dst(r) property(r) base(r)
2464
2465            Tests whether register base has a property named register
2466            property, and puts the boolean result in register dst.
2467
2468            Raises an exception if register constructor is not an
2469            object.
2470         */
2471         int dst = vPC[1].u.operand;
2472         int property = vPC[2].u.operand;
2473         int base = vPC[3].u.operand;
2474
2475         JSValue baseVal = callFrame->r(base).jsValue();
2476         if (isInvalidParamForIn(callFrame, baseVal, exceptionValue))
2477             goto vm_throw;
2478
2479         JSObject* baseObj = asObject(baseVal);
2480
2481         JSValue propName = callFrame->r(property).jsValue();
2482
2483         uint32_t i;
2484         if (propName.getUInt32(i))
2485             callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, i));
2486         else {
2487             Identifier property(callFrame, propName.toString(callFrame));
2488             CHECK_FOR_EXCEPTION();
2489             callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, property));
2490         }
2491
2492         vPC += OPCODE_LENGTH(op_in);
2493         NEXT_INSTRUCTION();
2494     }
2495     DEFINE_OPCODE(op_resolve) {
2496         /* resolve dst(r) property(id)
2497
2498            Looks up the property named by identifier property in the
2499            scope chain, and writes the resulting value to register
2500            dst. If the property is not found, raises an exception.
2501         */
2502         if (UNLIKELY(!resolve(callFrame, vPC, exceptionValue)))
2503             goto vm_throw;
2504
2505         vPC += OPCODE_LENGTH(op_resolve);
2506         NEXT_INSTRUCTION();
2507     }
2508     DEFINE_OPCODE(op_resolve_skip) {
2509         /* resolve_skip dst(r) property(id) skip(n)
2510
2511          Looks up the property named by identifier property in the
2512          scope chain skipping the top 'skip' levels, and writes the resulting
2513          value to register dst. If the property is not found, raises an exception.
2514          */
2515         if (UNLIKELY(!resolveSkip(callFrame, vPC, exceptionValue)))
2516             goto vm_throw;
2517
2518         vPC += OPCODE_LENGTH(op_resolve_skip);
2519
2520         NEXT_INSTRUCTION();
2521     }
2522     DEFINE_OPCODE(op_resolve_global) {
2523         /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n)
2524          
2525            Performs a dynamic property lookup for the given property, on the provided
2526            global object.  If structure matches the Structure of the global then perform
2527            a fast lookup using the case offset, otherwise fall back to a full resolve and
2528            cache the new structure and offset
2529          */
2530         if (UNLIKELY(!resolveGlobal(callFrame, vPC, exceptionValue)))
2531             goto vm_throw;
2532         
2533         vPC += OPCODE_LENGTH(op_resolve_global);
2534         
2535         NEXT_INSTRUCTION();
2536     }
2537     DEFINE_OPCODE(op_resolve_global_dynamic) {
2538         /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n), depth(n)
2539          
2540          Performs a dynamic property lookup for the given property, on the provided
2541          global object.  If structure matches the Structure of the global then perform
2542          a fast lookup using the case offset, otherwise fall back to a full resolve and
2543          cache the new structure and offset.
2544          
2545          This walks through n levels of the scope chain to verify that none of those levels
2546          in the scope chain include dynamically added properties.
2547          */
2548         if (UNLIKELY(!resolveGlobalDynamic(callFrame, vPC, exceptionValue)))
2549             goto vm_throw;
2550         
2551         vPC += OPCODE_LENGTH(op_resolve_global_dynamic);
2552         
2553         NEXT_INSTRUCTION();
2554     }
2555     DEFINE_OPCODE(op_get_global_var) {
2556         /* get_global_var dst(r) globalObject(c) index(n)
2557
2558            Gets the global var at global slot index and places it in register dst.
2559          */
2560         int dst = vPC[1].u.operand;
2561         JSGlobalObject* scope = codeBlock->globalObject();
2562         ASSERT(scope->isGlobalObject());
2563         int index = vPC[2].u.operand;
2564
2565         callFrame->uncheckedR(dst) = scope->registerAt(index).get();
2566         vPC += OPCODE_LENGTH(op_get_global_var);
2567         NEXT_INSTRUCTION();
2568     }
2569     DEFINE_OPCODE(op_put_global_var) {
2570         /* put_global_var globalObject(c) index(n) value(r)
2571          
2572            Puts value into global slot index.
2573          */
2574         JSGlobalObject* scope = codeBlock->globalObject();
2575         ASSERT(scope->isGlobalObject());
2576         int index = vPC[1].u.operand;
2577         int value = vPC[2].u.operand;
2578         
2579         scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue());
2580         vPC += OPCODE_LENGTH(op_put_global_var);
2581         NEXT_INSTRUCTION();
2582     }
2583     DEFINE_OPCODE(op_get_scoped_var) {
2584         /* get_scoped_var dst(r) index(n) skip(n)
2585
2586          Loads the contents of the index-th local from the scope skip nodes from
2587          the top of the scope chain, and places it in register dst.
2588          */
2589         int dst = vPC[1].u.operand;
2590         int index = vPC[2].u.operand;
2591         int skip = vPC[3].u.operand;
2592
2593         ScopeChainNode* scopeChain = callFrame->scopeChain();
2594         ScopeChainIterator iter = scopeChain->begin();
2595         ScopeChainIterator end = scopeChain->end();
2596         ASSERT(iter != end);
2597         ASSERT(codeBlock == callFrame->codeBlock());
2598         bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
2599         ASSERT(skip || !checkTopLevel);
2600     if (checkTopLevel && skip--) {
2601             if (callFrame->r(codeBlock->activationRegister()).jsValue())
2602                 ++iter;
2603         }
2604         while (skip--) {
2605             ++iter;
2606             ASSERT(iter != end);
2607         }
2608         ASSERT((*iter)->isVariableObject());
2609         JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get());
2610         callFrame->uncheckedR(dst) = scope->registerAt(index).get();
2611         ASSERT(callFrame->r(dst).jsValue());
2612         vPC += OPCODE_LENGTH(op_get_scoped_var);
2613         NEXT_INSTRUCTION();
2614     }
2615     DEFINE_OPCODE(op_put_scoped_var) {
2616         /* put_scoped_var index(n) skip(n) value(r)
2617
2618          */
2619         int index = vPC[1].u.operand;
2620         int skip = vPC[2].u.operand;
2621         int value = vPC[3].u.operand;
2622
2623         ScopeChainNode* scopeChain = callFrame->scopeChain();
2624         ScopeChainIterator iter = scopeChain->begin();
2625         ScopeChainIterator end = scopeChain->end();
2626         ASSERT(codeBlock == callFrame->codeBlock());
2627         ASSERT(iter != end);
2628         bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
2629         ASSERT(skip || !checkTopLevel);
2630     if (checkTopLevel && skip--) {
2631             if (callFrame->r(codeBlock->activationRegister()).jsValue())
2632                 ++iter;
2633         }
2634         while (skip--) {
2635             ++iter;
2636             ASSERT(iter != end);
2637         }
2638
2639         ASSERT((*iter)->isVariableObject());
2640         JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get());
2641         ASSERT(callFrame->r(value).jsValue());
2642         scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue());
2643         vPC += OPCODE_LENGTH(op_put_scoped_var);
2644         NEXT_INSTRUCTION();
2645     }
2646     DEFINE_OPCODE(op_resolve_base) {
2647         /* resolve_base dst(r) property(id) isStrict(bool)
2648
2649            Searches the scope chain for an object containing
2650            identifier property, and if one is found, writes it to
2651            register dst. If none is found and isStrict is false, the
2652            outermost scope (which will be the global object) is
2653            stored in register dst.
2654         */
2655         resolveBase(callFrame, vPC);
2656         CHECK_FOR_EXCEPTION();
2657
2658         vPC += OPCODE_LENGTH(op_resolve_base);
2659         NEXT_INSTRUCTION();
2660     }
2661     DEFINE_OPCODE(op_ensure_property_exists) {
2662         /* ensure_property_exists base(r) property(id)
2663
2664            Throws an exception if property does not exist on base
2665          */
2666         int base = vPC[1].u.operand;
2667         int property = vPC[2].u.operand;
2668         Identifier& ident = codeBlock->identifier(property);
2669         
2670         JSValue baseVal = callFrame->r(base).jsValue();
2671         JSObject* baseObject = asObject(baseVal);
2672         PropertySlot slot(baseVal);
2673         if (!baseObject->getPropertySlot(callFrame, ident, slot)) {
2674             exceptionValue = createErrorForInvalidGlobalAssignment(callFrame, ident.ustring());
2675             goto vm_throw;
2676         }
2677
2678         vPC += OPCODE_LENGTH(op_ensure_property_exists);
2679         NEXT_INSTRUCTION();
2680     }
2681     DEFINE_OPCODE(op_resolve_with_base) {
2682         /* resolve_with_base baseDst(r) propDst(r) property(id)
2683
2684            Searches the scope chain for an object containing
2685            identifier property, and if one is found, writes it to
2686            register srcDst, and the retrieved property value to register
2687            propDst. If the property is not found, raises an exception.
2688
2689            This is more efficient than doing resolve_base followed by
2690            resolve, or resolve_base followed by get_by_id, as it
2691            avoids duplicate hash lookups.
2692         */
2693         if (UNLIKELY(!resolveBaseAndProperty(callFrame, vPC, exceptionValue)))
2694             goto vm_throw;
2695
2696         vPC += OPCODE_LENGTH(op_resolve_with_base);
2697         NEXT_INSTRUCTION();
2698     }
2699     DEFINE_OPCODE(op_resolve_with_this) {
2700         /* resolve_with_this thisDst(r) propDst(r) property(id)
2701
2702            Searches the scope chain for an object containing
2703            identifier property, and if one is found, writes the
2704            retrieved property value to register propDst, and the
2705            this object to pass in a call to thisDst.
2706
2707            If the property is not found, raises an exception.
2708         */
2709         if (UNLIKELY(!resolveThisAndProperty(callFrame, vPC, exceptionValue)))
2710             goto vm_throw;
2711
2712         vPC += OPCODE_LENGTH(op_resolve_with_this);
2713         NEXT_INSTRUCTION();
2714     }
2715     DEFINE_OPCODE(op_get_by_id) {
2716         /* get_by_id dst(r) base(r) property(id) structure(sID) nop(n) nop(n) nop(n)
2717
2718            Generic property access: Gets the property named by identifier
2719            property from the value base, and puts the result in register dst.
2720         */
2721         int dst = vPC[1].u.operand;
2722         int base = vPC[2].u.operand;
2723         int property = vPC[3].u.operand;
2724
2725         Identifier& ident = codeBlock->identifier(property);
2726         JSValue baseValue = callFrame->r(base).jsValue();
2727         PropertySlot slot(baseValue);
2728         JSValue result = baseValue.get(callFrame, ident, slot);
2729         CHECK_FOR_EXCEPTION();
2730
2731         tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
2732
2733         callFrame->uncheckedR(dst) = result;
2734         vPC += OPCODE_LENGTH(op_get_by_id);
2735         NEXT_INSTRUCTION();
2736     }
2737     DEFINE_OPCODE(op_get_by_id_self) {
2738         /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
2739
2740            Cached property access: Attempts to get a cached property from the
2741            value base. If the cache misses, op_get_by_id_self reverts to
2742            op_get_by_id.
2743         */
2744         int base = vPC[2].u.operand;
2745         JSValue baseValue = callFrame->r(base).jsValue();
2746
2747         if (LIKELY(baseValue.isCell())) {
2748             JSCell* baseCell = baseValue.asCell();
2749             Structure* structure = vPC[4].u.structure.get();
2750
2751             if (LIKELY(baseCell->structure() == structure)) {
2752                 ASSERT(baseCell->isObject());
2753                 JSObject* baseObject = asObject(baseCell);
2754                 int dst = vPC[1].u.operand;
2755                 int offset = vPC[5].u.operand;
2756
2757                 ASSERT(baseObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
2758                 callFrame->uncheckedR(dst) = JSValue(baseObject->getDirectOffset(offset));
2759
2760                 vPC += OPCODE_LENGTH(op_get_by_id_self);
2761                 NEXT_INSTRUCTION();
2762             }
2763         }
2764
2765         uncacheGetByID(codeBlock, vPC);
2766         NEXT_INSTRUCTION();
2767     }
2768     DEFINE_OPCODE(op_get_by_id_proto) {
2769         /* op_get_by_id_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
2770
2771            Cached property access: Attempts to get a cached property from the
2772            value base's prototype. If the cache misses, op_get_by_id_proto
2773            reverts to op_get_by_id.
2774         */
2775         int base = vPC[2].u.operand;
2776         JSValue baseValue = callFrame->r(base).jsValue();
2777
2778         if (LIKELY(baseValue.isCell())) {
2779             JSCell* baseCell = baseValue.asCell();
2780             Structure* structure = vPC[4].u.structure.get();
2781
2782             if (LIKELY(baseCell->structure() == structure)) {
2783                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
2784                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
2785                 Structure* prototypeStructure = vPC[5].u.structure.get();
2786
2787                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
2788                     int dst = vPC[1].u.operand;
2789                     int offset = vPC[6].u.operand;
2790
2791                     ASSERT(protoObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
2792                     ASSERT(baseValue.get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
2793                     callFrame->uncheckedR(dst) = JSValue(protoObject->getDirectOffset(offset));
2794
2795                     vPC += OPCODE_LENGTH(op_get_by_id_proto);
2796                     NEXT_INSTRUCTION();
2797                 }
2798             }
2799         }
2800
2801         uncacheGetByID(codeBlock, vPC);
2802         NEXT_INSTRUCTION();
2803     }
2804 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
2805     goto *(&&skip_id_getter_proto);
2806 #endif
2807     DEFINE_OPCODE(op_get_by_id_getter_proto) {
2808         /* op_get_by_id_getter_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
2809          
2810          Cached property access: Attempts to get a cached getter property from the
2811          value base's prototype. If the cache misses, op_get_by_id_getter_proto
2812          reverts to op_get_by_id.
2813          */
2814         int base = vPC[2].u.operand;
2815         JSValue baseValue = callFrame->r(base).jsValue();
2816         
2817         if (LIKELY(baseValue.isCell())) {
2818             JSCell* baseCell = baseValue.asCell();
2819             Structure* structure = vPC[4].u.structure.get();
2820             
2821             if (LIKELY(baseCell->structure() == structure)) {
2822                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
2823                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
2824                 Structure* prototypeStructure = vPC[5].u.structure.get();
2825                 
2826                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
2827                     int dst = vPC[1].u.operand;
2828                     int offset = vPC[6].u.operand;
2829                     if (GetterSetter* getterSetter = asGetterSetter(protoObject->getDirectOffset(offset).asCell())) {
2830                         JSObject* getter = getterSetter->getter();
2831                         CallData callData;
2832                         CallType callType = getter->getCallData(callData);
2833                         JSValue result = call(callFrame, getter, callType, callData, asObject(baseCell), ArgList());
2834                         CHECK_FOR_EXCEPTION();
2835                         callFrame->uncheckedR(dst) = result;
2836                     } else
2837                         callFrame->uncheckedR(dst) = jsUndefined();
2838                     vPC += OPCODE_LENGTH(op_get_by_id_getter_proto);
2839                     NEXT_INSTRUCTION();
2840                 }
2841             }
2842         }
2843         uncacheGetByID(codeBlock, vPC);
2844         NEXT_INSTRUCTION();
2845     }
2846 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
2847     skip_id_getter_proto:
2848 #endif
2849 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
2850     goto *(&&skip_id_custom_proto);
2851 #endif
2852     DEFINE_OPCODE(op_get_by_id_custom_proto) {
2853         /* op_get_by_id_custom_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
2854          
2855          Cached property access: Attempts to use a cached named property getter
2856          from the value base's prototype. If the cache misses, op_get_by_id_custom_proto
2857          reverts to op_get_by_id.
2858          */
2859         int base = vPC[2].u.operand;
2860         JSValue baseValue = callFrame->r(base).jsValue();
2861         
2862         if (LIKELY(baseValue.isCell())) {
2863             JSCell* baseCell = baseValue.asCell();
2864             Structure* structure = vPC[4].u.structure.get();
2865             
2866             if (LIKELY(baseCell->structure() == structure)) {
2867                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
2868                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
2869                 Structure* prototypeStructure = vPC[5].u.structure.get();
2870                 
2871                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
2872                     int dst = vPC[1].u.operand;
2873                     int property = vPC[3].u.operand;
2874                     Identifier& ident = codeBlock->identifier(property);
2875                     
2876                     PropertySlot::GetValueFunc getter = vPC[6].u.getterFunc;
2877                     JSValue result = getter(callFrame, protoObject, ident);
2878                     CHECK_FOR_EXCEPTION();
2879                     callFrame->uncheckedR(dst) = result;
2880                     vPC += OPCODE_LENGTH(op_get_by_id_custom_proto);
2881                     NEXT_INSTRUCTION();
2882                 }
2883             }
2884         }
2885         uncacheGetByID(codeBlock, vPC);
2886         NEXT_INSTRUCTION();
2887     }
2888 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
2889     skip_id_custom_proto:
2890 #endif
2891 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
2892     goto *(&&skip_get_by_id_chain);
2893 #endif
2894     DEFINE_OPCODE(op_get_by_id_chain) {
2895         /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
2896
2897            Cached property access: Attempts to get a cached property from the
2898            value base's prototype chain. If the cache misses, op_get_by_id_chain
2899            reverts to op_get_by_id.
2900         */
2901         int base = vPC[2].u.operand;
2902         JSValue baseValue = callFrame->r(base).jsValue();
2903
2904         if (LIKELY(baseValue.isCell())) {
2905             JSCell* baseCell = baseValue.asCell();
2906             Structure* structure = vPC[4].u.structure.get();
2907
2908             if (LIKELY(baseCell->structure() == structure)) {
2909                 WriteBarrier<Structure>* it = vPC[5].u.structureChain->head();
2910                 size_t count = vPC[6].u.operand;
2911                 WriteBarrier<Structure>* end = it + count;
2912
2913                 while (true) {
2914                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
2915
2916                     if (UNLIKELY(baseObject->structure() != (*it).get()))
2917                         break;
2918
2919                     if (++it == end) {
2920                         int dst = vPC[1].u.operand;
2921                         int offset = vPC[7].u.operand;
2922
2923                         ASSERT(baseObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
2924                         ASSERT(baseValue.get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
2925                         callFrame->uncheckedR(dst) = JSValue(baseObject->getDirectOffset(offset));
2926
2927                         vPC += OPCODE_LENGTH(op_get_by_id_chain);
2928                         NEXT_INSTRUCTION();
2929                     }
2930
2931                     // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
2932                     baseCell = baseObject;
2933                 }
2934             }
2935         }
2936
2937         uncacheGetByID(codeBlock, vPC);
2938         NEXT_INSTRUCTION();
2939     }
2940 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
2941     skip_get_by_id_chain:
2942     goto *(&&skip_id_getter_self);
2943 #endif
2944     DEFINE_OPCODE(op_get_by_id_getter_self) {
2945         /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
2946          
2947          Cached property access: Attempts to get a cached property from the
2948          value base. If the cache misses, op_get_by_id_getter_self reverts to
2949          op_get_by_id.
2950          */
2951         int base = vPC[2].u.operand;
2952         JSValue baseValue = callFrame->r(base).jsValue();
2953         
2954         if (LIKELY(baseValue.isCell())) {
2955             JSCell* baseCell = baseValue.asCell();
2956             Structure* structure = vPC[4].u.structure.get();
2957             
2958             if (LIKELY(baseCell->structure() == structure)) {
2959                 ASSERT(baseCell->isObject());
2960                 JSObject* baseObject = asObject(baseCell);
2961                 int dst = vPC[1].u.operand;
2962                 int offset = vPC[5].u.operand;
2963
2964                 if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) {
2965                     JSObject* getter = getterSetter->getter();
2966                     CallData callData;
2967                     CallType callType = getter->getCallData(callData);
2968                     JSValue result = call(callFrame, getter, callType, callData, baseObject, ArgList());
2969                     CHECK_FOR_EXCEPTION();
2970                     callFrame->uncheckedR(dst) = result;
2971                 } else
2972                     callFrame->uncheckedR(dst) = jsUndefined();
2973
2974                 vPC += OPCODE_LENGTH(op_get_by_id_getter_self);
2975                 NEXT_INSTRUCTION();
2976             }
2977         }
2978         uncacheGetByID(codeBlock, vPC);
2979         NEXT_INSTRUCTION();
2980     }
2981 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
2982     skip_id_getter_self:
2983 #endif
2984 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
2985     goto *(&&skip_id_custom_self);
2986 #endif
2987     DEFINE_OPCODE(op_get_by_id_custom_self) {
2988         /* op_get_by_id_custom_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
2989          
2990          Cached property access: Attempts to use a cached named property getter
2991          from the value base. If the cache misses, op_get_by_id_custom_self reverts to
2992          op_get_by_id.
2993          */
2994         int base = vPC[2].u.operand;
2995         JSValue baseValue = callFrame->r(base).jsValue();
2996         
2997         if (LIKELY(baseValue.isCell())) {
2998             JSCell* baseCell = baseValue.asCell();
2999             Structure* structure = vPC[4].u.structure.get();
3000             
3001             if (LIKELY(baseCell->structure() == structure)) {
3002                 ASSERT(baseCell->isObject());
3003                 int dst = vPC[1].u.operand;
3004                 int property = vPC[3].u.operand;
3005                 Identifier& ident = codeBlock->identifier(property);
3006
3007                 PropertySlot::GetValueFunc getter = vPC[5].u.getterFunc;
3008                 JSValue result = getter(callFrame, baseValue, ident);
3009                 CHECK_FOR_EXCEPTION();
3010                 callFrame->uncheckedR(dst) = result;
3011                 vPC += OPCODE_LENGTH(op_get_by_id_custom_self);
3012                 NEXT_INSTRUCTION();
3013             }
3014         }
3015         uncacheGetByID(codeBlock, vPC);
3016         NEXT_INSTRUCTION();
3017     }
3018 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3019 skip_id_custom_self:
3020 #endif
3021     DEFINE_OPCODE(op_get_by_id_generic) {
3022         /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
3023
3024            Generic property access: Gets the property named by identifier
3025            property from the value base, and puts the result in register dst.
3026         */
3027         int dst = vPC[1].u.operand;
3028         int base = vPC[2].u.operand;
3029         int property = vPC[3].u.operand;
3030
3031         Identifier& ident = codeBlock->identifier(property);
3032         JSValue baseValue = callFrame->r(base).jsValue();
3033         PropertySlot slot(baseValue);
3034         JSValue result = baseValue.get(callFrame, ident, slot);
3035         CHECK_FOR_EXCEPTION();
3036
3037         callFrame->uncheckedR(dst) = result;
3038         vPC += OPCODE_LENGTH(op_get_by_id_generic);
3039         NEXT_INSTRUCTION();
3040     }
3041 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3042     goto *(&&skip_id_getter_chain);
3043 #endif
3044     DEFINE_OPCODE(op_get_by_id_getter_chain) {
3045         /* op_get_by_id_getter_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
3046          
3047          Cached property access: Attempts to get a cached property from the
3048          value base's prototype chain. If the cache misses, op_get_by_id_getter_chain
3049          reverts to op_get_by_id.
3050          */
3051         int base = vPC[2].u.operand;
3052         JSValue baseValue = callFrame->r(base).jsValue();
3053         
3054         if (LIKELY(baseValue.isCell())) {
3055             JSCell* baseCell = baseValue.asCell();
3056             Structure* structure = vPC[4].u.structure.get();
3057             
3058             if (LIKELY(baseCell->structure() == structure)) {
3059                 WriteBarrier<Structure>* it = vPC[5].u.structureChain->head();
3060                 size_t count = vPC[6].u.operand;
3061                 WriteBarrier<Structure>* end = it + count;
3062                 
3063                 while (true) {
3064                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
3065                     
3066                     if (UNLIKELY(baseObject->structure() != (*it).get()))
3067                         break;
3068                     
3069                     if (++it == end) {
3070                         int dst = vPC[1].u.operand;
3071                         int offset = vPC[7].u.operand;
3072                         if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) {
3073                             JSObject* getter = getterSetter->getter();
3074                             CallData callData;
3075                             CallType callType = getter->getCallData(callData);
3076                             JSValue result = call(callFrame, getter, callType, callData, baseValue, ArgList());
3077                             CHECK_FOR_EXCEPTION();
3078                             callFrame->uncheckedR(dst) = result;
3079                         } else
3080                             callFrame->uncheckedR(dst) = jsUndefined();
3081                         vPC += OPCODE_LENGTH(op_get_by_id_getter_chain);
3082                         NEXT_INSTRUCTION();
3083                     }
3084                     
3085                     // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
3086                     baseCell = baseObject;
3087                 }
3088             }
3089         }
3090         uncacheGetByID(codeBlock, vPC);
3091         NEXT_INSTRUCTION();
3092     }
3093 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3094     skip_id_getter_chain:
3095 #endif
3096 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3097     goto *(&&skip_id_custom_chain);
3098 #endif
3099     DEFINE_OPCODE(op_get_by_id_custom_chain) {
3100         /* op_get_by_id_custom_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
3101          
3102          Cached property access: Attempts to use a cached named property getter on the
3103          value base's prototype chain. If the cache misses, op_get_by_id_custom_chain
3104          reverts to op_get_by_id.
3105          */
3106         int base = vPC[2].u.operand;
3107         JSValue baseValue = callFrame->r(base).jsValue();
3108         
3109         if (LIKELY(baseValue.isCell())) {
3110             JSCell* baseCell = baseValue.asCell();
3111             Structure* structure = vPC[4].u.structure.get();
3112             
3113             if (LIKELY(baseCell->structure() == structure)) {
3114                 WriteBarrier<Structure>* it = vPC[5].u.structureChain->head();
3115                 size_t count = vPC[6].u.operand;
3116                 WriteBarrier<Structure>* end = it + count;
3117                 
3118                 while (true) {
3119                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
3120                     
3121                     if (UNLIKELY(baseObject->structure() != (*it).get()))
3122                         break;
3123                     
3124                     if (++it == end) {
3125                         int dst = vPC[1].u.operand;
3126                         int property = vPC[3].u.operand;
3127                         Identifier& ident = codeBlock->identifier(property);
3128                         
3129                         PropertySlot::GetValueFunc getter = vPC[7].u.getterFunc;
3130                         JSValue result = getter(callFrame, baseObject, ident);
3131                         CHECK_FOR_EXCEPTION();
3132                         callFrame->uncheckedR(dst) = result;
3133                         vPC += OPCODE_LENGTH(op_get_by_id_custom_chain);
3134                         NEXT_INSTRUCTION();
3135                     }
3136                     
3137                     // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
3138                     baseCell = baseObject;
3139                 }
3140             }
3141         }
3142         uncacheGetByID(codeBlock, vPC);
3143         NEXT_INSTRUCTION();
3144     }
3145 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3146     skip_id_custom_chain:
3147     goto *(&&skip_get_array_length);
3148 #endif
3149     DEFINE_OPCODE(op_get_array_length) {
3150         /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
3151
3152            Cached property access: Gets the length of the array in register base,
3153            and puts the result in register dst. If register base does not hold
3154            an array, op_get_array_length reverts to op_get_by_id.
3155         */
3156
3157         int base = vPC[2].u.operand;
3158         JSValue baseValue = callFrame->r(base).jsValue();
3159         if (LIKELY(isJSArray(globalData, baseValue))) {
3160             int dst = vPC[1].u.operand;
3161             callFrame->uncheckedR(dst) = jsNumber(asArray(baseValue)->length());
3162             vPC += OPCODE_LENGTH(op_get_array_length);
3163             NEXT_INSTRUCTION();
3164         }
3165
3166         uncacheGetByID(codeBlock, vPC);
3167         NEXT_INSTRUCTION();
3168     }
3169 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3170     skip_get_array_length:
3171     goto *(&&skip_get_string_length);
3172 #endif
3173     DEFINE_OPCODE(op_get_string_length) {
3174         /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
3175
3176            Cached property access: Gets the length of the string in register base,
3177            and puts the result in register dst. If register base does not hold
3178            a string, op_get_string_length reverts to op_get_by_id.
3179         */
3180
3181         int base = vPC[2].u.operand;
3182         JSValue baseValue = callFrame->r(base).jsValue();
3183         if (LIKELY(isJSString(globalData, baseValue))) {
3184             int dst = vPC[1].u.operand;
3185             callFrame->uncheckedR(dst) = jsNumber(asString(baseValue)->length());
3186             vPC += OPCODE_LENGTH(op_get_string_length);
3187             NEXT_INSTRUCTION();
3188         }
3189
3190         uncacheGetByID(codeBlock, vPC);
3191         NEXT_INSTRUCTION();
3192     }
3193 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3194     skip_get_string_length:
3195     goto *(&&skip_put_by_id);
3196 #endif
3197     DEFINE_OPCODE(op_put_by_id) {
3198         /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b)
3199
3200            Generic property access: Sets the property named by identifier
3201            property, belonging to register base, to register value.
3202
3203            Unlike many opcodes, this one does not write any output to
3204            the register file.
3205
3206            The "direct" flag should only be set this put_by_id is to initialize
3207            an object literal.
3208         */
3209
3210         int base = vPC[1].u.operand;
3211         int property = vPC[2].u.operand;
3212         int value = vPC[3].u.operand;
3213         int direct = vPC[8].u.operand;
3214
3215         JSValue baseValue = callFrame->r(base).jsValue();
3216         Identifier& ident = codeBlock->identifier(property);
3217         PutPropertySlot slot(codeBlock->isStrictMode());
3218         if (direct) {
3219             baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
3220             ASSERT(slot.base() == baseValue);
3221         } else
3222             baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
3223         CHECK_FOR_EXCEPTION();
3224
3225         tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
3226
3227         vPC += OPCODE_LENGTH(op_put_by_id);
3228         NEXT_INSTRUCTION();
3229     }
3230 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3231       skip_put_by_id:
3232 #endif
3233     DEFINE_OPCODE(op_put_by_id_transition) {
3234         /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n) direct(b)
3235          
3236            Cached property access: Attempts to set a new property with a cached transition
3237            property named by identifier property, belonging to register base,
3238            to register value. If the cache misses, op_put_by_id_transition
3239            reverts to op_put_by_id_generic.
3240          
3241            Unlike many opcodes, this one does not write any output to
3242            the register file.
3243          */
3244         int base = vPC[1].u.operand;
3245         JSValue baseValue = callFrame->r(base).jsValue();
3246         
3247         if (LIKELY(baseValue.isCell())) {
3248             JSCell* baseCell = baseValue.asCell();
3249             Structure* oldStructure = vPC[4].u.structure.get();
3250             Structure* newStructure = vPC[5].u.structure.get();
3251             
3252             if (LIKELY(baseCell->structure() == oldStructure)) {
3253                 ASSERT(baseCell->isObject());
3254                 JSObject* baseObject = asObject(baseCell);
3255                 int direct = vPC[8].u.operand;
3256                 
3257                 if (!direct) {
3258                     WriteBarrier<Structure>* it = vPC[6].u.structureChain->head();
3259
3260                     JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
3261                     while (!proto.isNull()) {
3262                         if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
3263                             uncachePutByID(codeBlock, vPC);
3264                             NEXT_INSTRUCTION();
3265                         }
3266                         ++it;
3267                         proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
3268                     }
3269                 }
3270                 baseObject->transitionTo(*globalData, newStructure);
3271
3272                 int value = vPC[3].u.operand;
3273                 unsigned offset = vPC[7].u.operand;
3274                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(*globalData, codeBlock->identifier(vPC[2].u.operand))) == offset);
3275                 baseObject->putDirectOffset(callFrame->globalData(), offset, callFrame->r(value).jsValue());
3276
3277                 vPC += OPCODE_LENGTH(op_put_by_id_transition);
3278                 NEXT_INSTRUCTION();
3279             }
3280         }
3281         
3282         uncachePutByID(codeBlock, vPC);
3283         NEXT_INSTRUCTION();
3284     }
3285     DEFINE_OPCODE(op_put_by_id_replace) {
3286         /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n) direct(b)
3287
3288            Cached property access: Attempts to set a pre-existing, cached
3289            property named by identifier property, belonging to register base,
3290            to register value. If the cache misses, op_put_by_id_replace
3291            reverts to op_put_by_id.
3292
3293            Unlike many opcodes, this one does not write any output to
3294            the register file.
3295         */
3296         int base = vPC[1].u.operand;
3297         JSValue baseValue = callFrame->r(base).jsValue();
3298
3299         if (LIKELY(baseValue.isCell())) {
3300             JSCell* baseCell = baseValue.asCell();
3301             Structure* structure = vPC[4].u.structure.get();
3302
3303             if (LIKELY(baseCell->structure() == structure)) {
3304                 ASSERT(baseCell->isObject());
3305                 JSObject* baseObject = asObject(baseCell);
3306                 int value = vPC[3].u.operand;
3307                 unsigned offset = vPC[5].u.operand;
3308                 
3309                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(*globalData, codeBlock->identifier(vPC[2].u.operand))) == offset);
3310                 baseObject->putDirectOffset(callFrame->globalData(), offset, callFrame->r(value).jsValue());
3311
3312                 vPC += OPCODE_LENGTH(op_put_by_id_replace);
3313                 NEXT_INSTRUCTION();
3314             }
3315         }
3316
3317         uncachePutByID(codeBlock, vPC);
3318         NEXT_INSTRUCTION();
3319     }
3320     DEFINE_OPCODE(op_put_by_id_generic) {
3321         /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b)
3322
3323            Generic property access: Sets the property named by identifier
3324            property, belonging to register base, to register value.
3325
3326            Unlike many opcodes, this one does not write any output to
3327            the register file.
3328         */
3329         int base = vPC[1].u.operand;
3330         int property = vPC[2].u.operand;
3331         int value = vPC[3].u.operand;
3332         int direct = vPC[8].u.operand;
3333
3334         JSValue baseValue = callFrame->r(base).jsValue();
3335         Identifier& ident = codeBlock->identifier(property);
3336         PutPropertySlot slot(codeBlock->isStrictMode());
3337         if (direct) {
3338             baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
3339             ASSERT(slot.base() == baseValue);
3340         } else
3341             baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
3342         CHECK_FOR_EXCEPTION();
3343
3344         vPC += OPCODE_LENGTH(op_put_by_id_generic);
3345         NEXT_INSTRUCTION();
3346     }
3347     DEFINE_OPCODE(op_del_by_id) {
3348         /* del_by_id dst(r) base(r) property(id)
3349
3350            Converts register base to Object, deletes the property
3351            named by identifier property from the object, and writes a
3352            boolean indicating success (if true) or failure (if false)
3353            to register dst.
3354         */
3355         int dst = vPC[1].u.operand;
3356         int base = vPC[2].u.operand;
3357         int property = vPC[3].u.operand;
3358
3359         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame);
3360         Identifier& ident = codeBlock->identifier(property);
3361         bool result = baseObj->deleteProperty(callFrame, ident);
3362         if (!result && codeBlock->isStrictMode()) {
3363             exceptionValue = createTypeError(callFrame, "Unable to delete property.");
3364             goto vm_throw;
3365         }
3366         CHECK_FOR_EXCEPTION();
3367         callFrame->uncheckedR(dst) = jsBoolean(result);
3368         vPC += OPCODE_LENGTH(op_del_by_id);
3369         NEXT_INSTRUCTION();
3370     }
3371     DEFINE_OPCODE(op_get_by_pname) {
3372         int dst = vPC[1].u.operand;
3373         int base = vPC[2].u.operand;
3374         int property = vPC[3].u.operand;
3375         int expected = vPC[4].u.operand;
3376         int iter = vPC[5].u.operand;
3377         int i = vPC[6].u.operand;
3378
3379         JSValue baseValue = callFrame->r(base).jsValue();
3380         JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
3381         JSValue subscript = callFrame->r(property).jsValue();
3382         JSValue expectedSubscript = callFrame->r(expected).jsValue();
3383         int index = callFrame->r(i).i() - 1;
3384         JSValue result;
3385         int offset = 0;
3386         if (subscript == expectedSubscript && baseValue.isCell() && (baseValue.asCell()->structure() == it->cachedStructure()) && it->getOffset(index, offset)) {
3387             callFrame->uncheckedR(dst) = JSValue(asObject(baseValue)->getDirectOffset(offset));
3388             vPC += OPCODE_LENGTH(op_get_by_pname);
3389             NEXT_INSTRUCTION();
3390         }
3391         {
3392             Identifier propertyName(callFrame, subscript.toString(callFrame));
3393             result = baseValue.get(callFrame, propertyName);
3394         }
3395         CHECK_FOR_EXCEPTION();
3396         callFrame->uncheckedR(dst) = result;
3397         vPC += OPCODE_LENGTH(op_get_by_pname);
3398         NEXT_INSTRUCTION();
3399     }
3400     DEFINE_OPCODE(op_get_arguments_length) {
3401         int dst = vPC[1].u.operand;
3402         int argumentsRegister = vPC[2].u.operand;
3403         int property = vPC[3].u.operand;
3404         JSValue arguments = callFrame->r(argumentsRegister).jsValue();
3405         if (arguments) {
3406             Identifier& ident = codeBlock->identifier(property);
3407             PropertySlot slot(arguments);
3408             JSValue result = arguments.get(callFrame, ident, slot);
3409             CHECK_FOR_EXCEPTION();
3410             callFrame->uncheckedR(dst) = result;
3411         } else
3412             callFrame->uncheckedR(dst) = jsNumber(callFrame->argumentCount());
3413
3414         vPC += OPCODE_LENGTH(op_get_arguments_length);
3415         NEXT_INSTRUCTION();
3416     }
3417     DEFINE_OPCODE(op_get_argument_by_val) {
3418         int dst = vPC[1].u.operand;
3419         int argumentsRegister = vPC[2].u.operand;
3420         int property = vPC[3].u.operand;
3421         JSValue arguments = callFrame->r(argumentsRegister).jsValue();
3422         JSValue subscript = callFrame->r(property).jsValue();
3423         if (!arguments && subscript.isUInt32() && subscript.asUInt32() < callFrame->argumentCount()) {
3424             unsigned arg = subscript.asUInt32() + 1;
3425             unsigned numParameters = callFrame->codeBlock()->m_numParameters;
3426             if (arg < numParameters)
3427                 callFrame->uncheckedR(dst) = callFrame->r(arg - RegisterFile::CallFrameHeaderSize - numParameters);
3428             else
3429                 callFrame->uncheckedR(dst) = callFrame->r(arg - RegisterFile::CallFrameHeaderSize - numParameters - callFrame->argumentCount() - 1);
3430             vPC += OPCODE_LENGTH(op_get_argument_by_val);
3431             NEXT_INSTRUCTION();
3432         }
3433         if (!arguments) {
3434             Arguments* arguments = Arguments::create(*globalData, callFrame);
3435             callFrame->uncheckedR(argumentsRegister) = JSValue(arguments);
3436             callFrame->uncheckedR(unmodifiedArgumentsRegister(argumentsRegister)) = JSValue(arguments);
3437         }
3438         // fallthrough
3439     }
3440     DEFINE_OPCODE(op_get_by_val) {
3441         /* get_by_val dst(r) base(r) property(r)
3442
3443            Converts register base to Object, gets the property named
3444            by register property from the object, and puts the result
3445            in register dst. property is nominally converted to string
3446            but numbers are treated more efficiently.
3447         */
3448         int dst = vPC[1].u.operand;
3449         int base = vPC[2].u.operand;
3450         int property = vPC[3].u.operand;
3451         
3452         JSValue baseValue = callFrame->r(base).jsValue();
3453         JSValue subscript = callFrame->r(property).jsValue();
3454
3455         JSValue result;
3456
3457         if (LIKELY(subscript.isUInt32())) {
3458             uint32_t i = subscript.asUInt32();
3459             if (isJSArray(globalData, baseValue)) {
3460                 JSArray* jsArray = asArray(baseValue);
3461                 if (jsArray->canGetIndex(i))
3462                     result = jsArray->getIndex(i);
3463                 else
3464                     result = jsArray->JSArray::get(callFrame, i);
3465             } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
3466                 result = asString(baseValue)->getIndex(callFrame, i);
3467             else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i))
3468                 result = asByteArray(baseValue)->getIndex(callFrame, i);
3469             else
3470                 result = baseValue.get(callFrame, i);
3471         } else {
3472             Identifier property(callFrame, subscript.toString(callFrame));
3473             result = baseValue.get(callFrame, property);
3474         }
3475
3476         CHECK_FOR_EXCEPTION();
3477         callFrame->uncheckedR(dst) = result;
3478         vPC += OPCODE_LENGTH(op_get_by_val);
3479         NEXT_INSTRUCTION();
3480     }
3481     DEFINE_OPCODE(op_put_by_val) {
3482         /* put_by_val base(r) property(r) value(r)
3483
3484            Sets register value on register base as the property named
3485            by register property. Base is converted to object
3486            first. register property is nominally converted to string
3487            but numbers are treated more efficiently.
3488
3489            Unlike many opcodes, this one does not write any output to
3490            the register file.
3491         */
3492         int base = vPC[1].u.operand;
3493         int property = vPC[2].u.operand;
3494         int value = vPC[3].u.operand;
3495
3496         JSValue baseValue = callFrame->r(base).jsValue();
3497         JSValue subscript = callFrame->r(property).jsValue();
3498
3499         if (LIKELY(subscript.isUInt32())) {
3500             uint32_t i = subscript.asUInt32();
3501             if (isJSArray(globalData, baseValue)) {
3502                 JSArray* jsArray = asArray(baseValue);
3503                 if (jsArray->canSetIndex(i))
3504                     jsArray->setIndex(*globalData, i, callFrame->r(value).jsValue());
3505                 else
3506                     jsArray->JSArray::put(callFrame, i, callFrame->r(value).jsValue());
3507             } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
3508                 JSByteArray* jsByteArray = asByteArray(baseValue);
3509                 double dValue = 0;
3510                 JSValue jsValue = callFrame->r(value).jsValue();
3511                 if (jsValue.isInt32())
3512                     jsByteArray->setIndex(i, jsValue.asInt32());
3513                 else if (jsValue.getNumber(dValue))
3514                     jsByteArray->setIndex(i, dValue);
3515                 else
3516                     baseValue.put(callFrame, i, jsValue);
3517             } else
3518                 baseValue.put(callFrame, i, callFrame->r(value).jsValue());
3519         } else {
3520             Identifier property(callFrame, subscript.toString(callFrame));
3521             if (!globalData->exception) { // Don't put to an object if toString threw an exception.
3522                 PutPropertySlot slot(codeBlock->isStrictMode());
3523                 baseValue.put(callFrame, property, callFrame->r(value).jsValue(), slot);
3524             }
3525         }
3526
3527         CHECK_FOR_EXCEPTION();
3528         vPC += OPCODE_LENGTH(op_put_by_val);
3529         NEXT_INSTRUCTION();
3530     }
3531     DEFINE_OPCODE(op_del_by_val) {
3532         /* del_by_val dst(r) base(r) property(r)
3533
3534            Converts register base to Object, deletes the property
3535            named by register property from the object, and writes a
3536            boolean indicating success (if true) or failure (if false)
3537            to register dst.
3538         */
3539         int dst = vPC[1].u.operand;
3540         int base = vPC[2].u.operand;
3541         int property = vPC[3].u.operand;
3542
3543         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); // may throw
3544
3545         JSValue subscript = callFrame->r(property).jsValue();
3546         bool result;
3547         uint32_t i;
3548         if (subscript.getUInt32(i))
3549             result = baseObj->deleteProperty(callFrame, i);
3550         else {
3551             CHECK_FOR_EXCEPTION();
3552             Identifier property(callFrame, subscript.toString(callFrame));
3553             CHECK_FOR_EXCEPTION();
3554             result = baseObj->deleteProperty(callFrame, property);
3555         }
3556         if (!result && codeBlock->isStrictMode()) {
3557             exceptionValue = createTypeError(callFrame, "Unable to delete property.");
3558             goto vm_throw;
3559         }
3560         CHECK_FOR_EXCEPTION();
3561         callFrame->uncheckedR(dst) = jsBoolean(result);
3562         vPC += OPCODE_LENGTH(op_del_by_val);
3563         NEXT_INSTRUCTION();
3564     }
3565     DEFINE_OPCODE(op_put_by_index) {
3566         /* put_by_index base(r) property(n) value(r)
3567
3568            Sets register value on register base as the property named
3569            by the immediate number property. Base is converted to
3570            object first.
3571
3572            Unlike many opcodes, this one does not write any output to
3573            the register file.
3574
3575            This opcode is mainly used to initialize array literals.
3576         */
3577         int base = vPC[1].u.operand;
3578         unsigned property = vPC[2].u.operand;
3579         int value = vPC[3].u.operand;
3580
3581         callFrame->r(base).jsValue().put(callFrame, property, callFrame->r(value).jsValue());
3582
3583         vPC += OPCODE_LENGTH(op_put_by_index);
3584         NEXT_INSTRUCTION();
3585     }
3586     DEFINE_OPCODE(op_loop) {
3587         /* loop target(offset)
3588          
3589            Jumps unconditionally to offset target from the current
3590            instruction.
3591
3592            Additionally this loop instruction may terminate JS execution is
3593            the JS timeout is reached.
3594          */
3595 #if ENABLE(OPCODE_STATS)
3596         OpcodeStats::resetLastInstruction();
3597 #endif
3598         int target = vPC[1].u.operand;
3599         CHECK_FOR_TIMEOUT();
3600         vPC += target;
3601         NEXT_INSTRUCTION();
3602     }
3603     DEFINE_OPCODE(op_jmp) {
3604         /* jmp target(offset)
3605
3606            Jumps unconditionally to offset target from the current
3607            instruction.
3608         */
3609 #if ENABLE(OPCODE_STATS)
3610         OpcodeStats::resetLastInstruction();
3611 #endif
3612         int target = vPC[1].u.operand;
3613
3614         vPC += target;
3615         NEXT_INSTRUCTION();
3616     }
3617     DEFINE_OPCODE(op_loop_hint) {
3618         // This is a no-op unless we intend on doing OSR from the interpreter.
3619         NEXT_INSTRUCTION();
3620     }
3621     DEFINE_OPCODE(op_loop_if_true) {
3622         /* loop_if_true cond(r) target(offset)
3623          
3624            Jumps to offset target from the current instruction, if and
3625            only if register cond converts to boolean as true.
3626
3627            Additionally this loop instruction may terminate JS execution is
3628            the JS timeout is reached.
3629          */
3630         int cond = vPC[1].u.operand;
3631         int target = vPC[2].u.operand;
3632         if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
3633             vPC += target;
3634             CHECK_FOR_TIMEOUT();
3635             NEXT_INSTRUCTION();
3636         }
3637         
3638         vPC += OPCODE_LENGTH(op_loop_if_true);
3639         NEXT_INSTRUCTION();
3640     }
3641     DEFINE_OPCODE(op_loop_if_false) {
3642         /* loop_if_true cond(r) target(offset)
3643          
3644            Jumps to offset target from the current instruction, if and
3645            only if register cond converts to boolean as false.
3646
3647            Additionally this loop instruction may terminate JS execution is
3648            the JS timeout is reached.
3649          */
3650         int cond = vPC[1].u.operand;
3651         int target = vPC[2].u.operand;
3652         if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) {
3653             vPC += target;
3654             CHECK_FOR_TIMEOUT();
3655             NEXT_INSTRUCTION();
3656         }
3657         
3658         vPC += OPCODE_LENGTH(op_loop_if_true);
3659         NEXT_INSTRUCTION();
3660     }
3661     DEFINE_OPCODE(op_jtrue) {
3662         /* jtrue cond(r) target(offset)
3663
3664            Jumps to offset target from the current instruction, if and
3665            only if register cond converts to boolean as true.
3666         */
3667         int cond = vPC[1].u.operand;
3668         int target = vPC[2].u.operand;
3669         if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
3670             vPC += target;
3671             NEXT_INSTRUCTION();
3672         }
3673
3674         vPC += OPCODE_LENGTH(op_jtrue);
3675         NEXT_INSTRUCTION();
3676     }
3677     DEFINE_OPCODE(op_jfalse) {
3678         /* jfalse cond(r) target(offset)
3679
3680            Jumps to offset target from the current instruction, if and
3681            only if register cond converts to boolean as false.
3682         */
3683         int cond = vPC[1].u.operand;
3684         int target = vPC[2].u.operand;
3685         if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) {
3686             vPC += target;
3687             NEXT_INSTRUCTION();
3688         }
3689
3690         vPC += OPCODE_LENGTH(op_jfalse);
3691         NEXT_INSTRUCTION();
3692     }
3693     DEFINE_OPCODE(op_jeq_null) {
3694         /* jeq_null src(r) target(offset)
3695
3696            Jumps to offset target from the current instruction, if and
3697            only if register src is null.
3698         */
3699         int src = vPC[1].u.operand;
3700         int target = vPC[2].u.operand;
3701         JSValue srcValue = callFrame->r(src).jsValue();
3702
3703         if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
3704             vPC += target;
3705             NEXT_INSTRUCTION();
3706         }
3707
3708         vPC += OPCODE_LENGTH(op_jeq_null);
3709         NEXT_INSTRUCTION();
3710     }
3711     DEFINE_OPCODE(op_jneq_null) {
3712         /* jneq_null src(r) target(offset)
3713
3714            Jumps to offset target from the current instruction, if and
3715            only if register src is not null.
3716         */
3717         int src = vPC[1].u.operand;
3718         int target = vPC[2].u.operand;
3719         JSValue srcValue = callFrame->r(src).jsValue();
3720
3721         if (!srcValue.isUndefinedOrNull() && (!srcValue.isCell() || !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
3722             vPC += target;
3723             NEXT_INSTRUCTION();
3724         }
3725
3726         vPC += OPCODE_LENGTH(op_jneq_null);
3727         NEXT_INSTRUCTION();
3728     }
3729     DEFINE_OPCODE(op_jneq_ptr) {
3730         /* jneq_ptr src(r) ptr(jsCell) target(offset)
3731          
3732            Jumps to offset target from the current instruction, if the value r is equal
3733            to ptr, using pointer equality.
3734          */
3735         int src = vPC[1].u.operand;
3736         int target = vPC[3].u.operand;
3737         JSValue srcValue = callFrame->r(src).jsValue();
3738         if (srcValue != vPC[2].u.jsCell.get()) {
3739             vPC += target;
3740             NEXT_INSTRUCTION();
3741         }
3742
3743         vPC += OPCODE_LENGTH(op_jneq_ptr);
3744         NEXT_INSTRUCTION();
3745     }
3746     DEFINE_OPCODE(op_loop_if_less) {
3747         /* loop_if_less src1(r) src2(r) target(offset)
3748
3749            Checks whether register src1 is less than register src2, as
3750            with the ECMAScript '<' operator, and then jumps to offset
3751            target from the current instruction, if and only if the 
3752            result of the comparison is true.
3753
3754            Additionally this loop instruction may terminate JS execution is
3755            the JS timeout is reached.
3756          */
3757         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
3758         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
3759         int target = vPC[3].u.operand;
3760         
3761         bool result = jsLess<true>(callFrame, src1, src2);
3762         CHECK_FOR_EXCEPTION();
3763         
3764         if (result) {
3765             vPC += target;
3766             CHECK_FOR_TIMEOUT();
3767             NEXT_INSTRUCTION();
3768         }
3769         
3770         vPC += OPCODE_LENGTH(op_loop_if_less);
3771         NEXT_INSTRUCTION();
3772     }
3773     DEFINE_OPCODE(op_loop_if_lesseq) {
3774         /* loop_if_lesseq src1(r) src2(r) target(offset)
3775
3776            Checks whether register src1 is less than or equal to register
3777            src2, as with the ECMAScript '<=' operator, and then jumps to
3778            offset target from the current instruction, if and only if the 
3779            result of the comparison is true.
3780
3781            Additionally this loop instruction may terminate JS execution is
3782            the JS timeout is reached.
3783         */
3784         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
3785         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
3786         int target = vPC[3].u.operand;
3787         
3788         bool result = jsLessEq<true>(callFrame, src1, src2);
3789         CHECK_FOR_EXCEPTION();
3790         
3791         if (result) {
3792             vPC += target;
3793             CHECK_FOR_TIMEOUT();
3794             NEXT_INSTRUCTION();
3795         }
3796         
3797         vPC += OPCODE_LENGTH(op_loop_if_lesseq);
3798         NEXT_INSTRUCTION();
3799     }
3800     DEFINE_OPCODE(op_loop_if_greater) {
3801         /* loop_if_greater src1(r) src2(r) target(offset)
3802
3803            Checks whether register src1 is greater than register src2, as
3804            with the ECMAScript '>' operator, and then jumps to offset
3805            target from the current instruction, if and only if the 
3806            result of the comparison is true.
3807
3808            Additionally this loop instruction may terminate JS execution is
3809            the JS timeout is reached.
3810          */
3811         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
3812         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
3813         int target = vPC[3].u.operand;
3814         
3815         bool result = jsLess<false>(callFrame, src2, src1);
3816         CHECK_FOR_EXCEPTION();
3817         
3818         if (result) {
3819             vPC += target;
3820             CHECK_FOR_TIMEOUT();
3821             NEXT_INSTRUCTION();
3822         }
3823         
3824         vPC += OPCODE_LENGTH(op_loop_if_greater);
3825         NEXT_INSTRUCTION();
3826     }
3827     DEFINE_OPCODE(op_loop_if_greatereq) {
3828         /* loop_if_greatereq src1(r) src2(r) target(offset)
3829
3830            Checks whether register src1 is greater than or equal to register
3831            src2, as with the ECMAScript '>=' operator, and then jumps to
3832            offset target from the current instruction, if and only if the 
3833            result of the comparison is true.
3834
3835            Additionally this loop instruction may terminate JS execution is
3836            the JS timeout is reached.
3837         */
3838         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
3839         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
3840         int target = vPC[3].u.operand;
3841         
3842         bool result = jsLessEq<false>(callFrame, src2, src1);
3843         CHECK_FOR_EXCEPTION();
3844         
3845         if (result) {
3846             vPC += target;
3847             CHECK_FOR_TIMEOUT();
3848             NEXT_INSTRUCTION();
3849         }
3850         
3851         vPC += OPCODE_LENGTH(op_loop_if_greatereq);
3852         NEXT_INSTRUCTION();
3853     }
3854     DEFINE_OPCODE(op_jless) {
3855         /* jless src1(r) src2(r) target(offset)
3856
3857            Checks whether register src1 is less than register src2, as
3858            with the ECMAScript '<' operator, and then jumps to offset
3859            target from the current instruction, if and only if the 
3860            result of the comparison is true.
3861         */
3862         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
3863         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
3864         int target = vPC[3].u.operand;
3865
3866         bool result = jsLess<true>(callFrame, src1, src2);
3867         CHECK_FOR_EXCEPTION();
3868         
3869         if (result) {
3870             vPC += target;
3871             NEXT_INSTRUCTION();
3872         }
3873
3874         vPC += OPCODE_LENGTH(op_jless);
3875         NEXT_INSTRUCTION();
3876     }
3877     DEFINE_OPCODE(op_jlesseq) {
3878         /* jlesseq src1(r) src2(r) target(offset)
3879          
3880          Checks whether register src1 is less than or equal to
3881          register src2, as with the ECMAScript '<=' operator,
3882          and then jumps to offset target from the current instruction,
3883          if and only if the result of the comparison is true.
3884          */
3885         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
3886         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
3887         int target = vPC[3].u.operand;
3888         
3889         bool result = jsLessEq<true>(callFrame, src1, src2);
3890         CHECK_FOR_EXCEPTION();
3891         
3892         if (result) {
3893             vPC += target;
3894             NEXT_INSTRUCTION();
3895         }
3896         
3897         vPC += OPCODE_LENGTH(op_jlesseq);
3898         NEXT_INSTRUCTION();
3899     }
3900     DEFINE_OPCODE(op_jgreater) {
3901         /* jgreater src1(r) src2(r) target(offset)
3902
3903            Checks whether register src1 is greater than register src2, as
3904            with the ECMAScript '>' operator, and then jumps to offset
3905            target from the current instruction, if and only if the 
3906            result of the comparison is true.
3907         */
3908         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
3909         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
3910         int target = vPC[3].u.operand;
3911
3912         bool result = jsLess<false>(callFrame, src2, src1);
3913         CHECK_FOR_EXCEPTION();
3914         
3915         if (result) {
3916             vPC += target;
3917             NEXT_INSTRUCTION();
3918         }
3919
3920         vPC += OPCODE_LENGTH(op_jgreater);
3921         NEXT_INSTRUCTION();
3922     }
3923     DEFINE_OPCODE(op_jgreatereq) {
3924         /* jgreatereq src1(r) src2(r) target(offset)
3925          
3926          Checks whether register src1 is greater than or equal to
3927          register src2, as with the ECMAScript '>=' operator,
3928          and then jumps to offset target from the current instruction,
3929          if and only if the result of the comparison is true.
3930          */
3931         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
3932         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
3933         int target = vPC[3].u.operand;
3934         
3935         bool result = jsLessEq<false>(callFrame, src2, src1);
3936         CHECK_FOR_EXCEPTION();
3937         
3938         if (result) {
3939             vPC += target;
3940             NEXT_INSTRUCTION();
3941         }
3942         
3943         vPC += OPCODE_LENGTH(op_jgreatereq);
3944         NEXT_INSTRUCTION();
3945     }
3946     DEFINE_OPCODE(op_jnless) {
3947         /* jnless src1(r) src2(r) target(offset)
3948
3949            Checks whether register src1 is less than register src2, as
3950            with the ECMAScript '<' operator, and then jumps to offset
3951            target from the current instruction, if and only if the 
3952            result of the comparison is false.
3953         */
3954         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
3955         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
3956         int target = vPC[3].u.operand;
3957
3958         bool result = jsLess<true>(callFrame, src1, src2);
3959         CHECK_FOR_EXCEPTION();
3960         
3961         if (!result) {
3962             vPC += target;
3963             NEXT_INSTRUCTION();
3964         }
3965
3966         vPC += OPCODE_LENGTH(op_jnless);
3967         NEXT_INSTRUCTION();
3968     }
3969     DEFINE_OPCODE(op_jnlesseq) {
3970         /* jnlesseq src1(r) src2(r) target(offset)
3971
3972            Checks whether register src1 is less than or equal to
3973            register src2, as with the ECMAScript '<=' operator,
3974            and then jumps to offset target from the current instruction,
3975            if and only if theresult of the comparison is false.
3976         */
3977         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
3978         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
3979         int target = vPC[3].u.operand;
3980
3981         bool result = jsLessEq<true>(callFrame, src1, src2);
3982         CHECK_FOR_EXCEPTION();
3983         
3984         if (!result) {
3985             vPC += target;
3986             NEXT_INSTRUCTION();
3987         }
3988
3989         vPC += OPCODE_LENGTH(op_jnlesseq);
3990         NEXT_INSTRUCTION();
3991     }
3992     DEFINE_OPCODE(op_jngreater) {
3993         /* jngreater src1(r) src2(r) target(offset)
3994
3995            Checks whether register src1 is greater than register src2, as
3996            with the ECMAScript '>' operator, and then jumps to offset
3997            target from the current instruction, if and only if the 
3998            result of the comparison is false.
3999         */
4000         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
4001         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
4002         int target = vPC[3].u.operand;
4003
4004         bool result = jsLess<false>(callFrame, src2, src1);
4005         CHECK_FOR_EXCEPTION();
4006         
4007         if (!result) {
4008             vPC += target;
4009             NEXT_INSTRUCTION();
4010         }
4011
4012         vPC += OPCODE_LENGTH(op_jngreater);
4013         NEXT_INSTRUCTION();
4014     }
4015     DEFINE_OPCODE(op_jngreatereq) {
4016         /* jngreatereq src1(r) src2(r) target(offset)
4017
4018            Checks whether register src1 is greater than or equal to
4019            register src2, as with the ECMAScript '>=' operator,
4020            and then jumps to offset target from the current instruction,
4021            if and only if theresult of the comparison is false.
4022         */
4023         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
4024         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
4025         int target = vPC[3].u.operand;
4026
4027         bool result = jsLessEq<false>(callFrame, src2, src1);
4028         CHECK_FOR_EXCEPTION();
4029         
4030         if (!result) {
4031             vPC += target;
4032             NEXT_INSTRUCTION();
4033         }
4034
4035         vPC += OPCODE_LENGTH(op_jngreatereq);
4036         NEXT_INSTRUCTION();
4037     }
4038     DEFINE_OPCODE(op_switch_imm) {
4039         /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
4040
4041            Performs a range checked switch on the scrutinee value, using
4042            the tableIndex-th immediate switch jump table.  If the scrutinee value
4043            is an immediate number in the range covered by the referenced jump
4044            table, and the value at jumpTable[scrutinee value] is non-zero, then
4045            that value is used as the jump offset, otherwise defaultOffset is used.
4046          */
4047         int tableIndex = vPC[1].u.operand;
4048         int defaultOffset = vPC[2].u.operand;
4049         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
4050         if (scrutinee.isInt32())
4051             vPC += codeBlock->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset);
4052         else {
4053             double value;
4054             int32_t intValue;
4055             if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value))
4056                 vPC += codeBlock->immediateSwitchJumpTable(tableIndex).offsetForValue(intValue, defaultOffset);
4057             else
4058                 vPC += defaultOffset;
4059         }
4060         NEXT_INSTRUCTION();
4061     }
4062     DEFINE_OPCODE(op_switch_char) {
4063         /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
4064
4065            Performs a range checked switch on the scrutinee value, using
4066            the tableIndex-th character switch jump table.  If the scrutinee value
4067            is a single character string in the range covered by the referenced jump
4068            table, and the value at jumpTable[scrutinee value] is non-zero, then
4069            that value is used as the jump offset, otherwise defaultOffset is used.
4070          */
4071         int tableIndex = vPC[1].u.operand;
4072         int defaultOffset = vPC[2].u.operand;
4073         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
4074         if (!scrutinee.isString())
4075             vPC += defaultOffset;
4076         else {
4077             StringImpl* value = asString(scrutinee)->value(callFrame).impl();
4078             if (value->length() != 1)
4079                 vPC += defaultOffset;
4080             else
4081                 vPC += codeBlock->characterSwitchJumpTable(tableIndex).offsetForValue((*value)[0], defaultOffset);
4082         }
4083         NEXT_INSTRUCTION();
4084     }
4085     DEFINE_OPCODE(op_switch_string) {
4086         /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
4087
4088            Performs a sparse hashmap based switch on the value in the scrutinee
4089            register, using the tableIndex-th string switch jump table.  If the 
4090            scrutinee value is a string that exists as a key in the referenced 
4091            jump table, then the value associated with the string is used as the 
4092            jump offset, otherwise defaultOffset is used.
4093          */
4094         int tableIndex = vPC[1].u.operand;
4095         int defaultOffset = vPC[2].u.operand;
4096         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
4097         if (!scrutinee.isString())
4098             vPC += defaultOffset;
4099         else 
4100             vPC += codeBlock->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value(callFrame).impl(), defaultOffset);
4101         NEXT_INSTRUCTION();
4102     }
4103     DEFINE_OPCODE(op_new_func) {
4104         /* new_func dst(r) func(f)
4105
4106            Constructs a new Function instance from function func and
4107            the current scope chain using the original Function
4108            constructor, using the rules for function declarations, and
4109            puts the result in register dst.
4110         */
4111         int dst = vPC[1].u.operand;
4112         int func = vPC[2].u.operand;
4113         int shouldCheck = vPC[3].u.operand;
4114         ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
4115         if (!shouldCheck || !callFrame->r(dst).jsValue())
4116             callFrame->uncheckedR(dst) = JSValue(codeBlock->functionDecl(func)->make(callFrame, callFrame->scopeChain()));
4117
4118         vPC += OPCODE_LENGTH(op_new_func);
4119         NEXT_INSTRUCTION();
4120     }
4121     DEFINE_OPCODE(op_new_func_exp) {
4122         /* new_func_exp dst(r) func(f)
4123
4124            Constructs a new Function instance from function func and
4125            the current scope chain using the original Function
4126            constructor, using the rules for function expressions, and
4127            puts the result in register dst.
4128         */
4129         int dst = vPC[1].u.operand;
4130         int funcIndex = vPC[2].u.operand;
4131         
4132         ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
4133         FunctionExecutable* function = codeBlock->functionExpr(funcIndex);
4134         JSFunction* func = function->make(callFrame, callFrame->scopeChain());
4135
4136         /* 
4137             The Identifier in a FunctionExpression can be referenced from inside
4138             the FunctionExpression's FunctionBody to allow the function to call
4139             itself recursively. However, unlike in a FunctionDeclaration, the
4140             Identifier in a FunctionExpression cannot be referenced from and
4141             does not affect the scope enclosing the FunctionExpression.
4142          */
4143         if (!function->name().isNull()) {
4144             JSStaticScopeObject* functionScopeObject = JSStaticScopeObject::create(callFrame, function->name(), func, ReadOnly | DontDelete);
4145             func->setScope(*globalData, func->scope()->push(functionScopeObject));
4146         }
4147
4148         callFrame->uncheckedR(dst) = JSValue(func);
4149
4150         vPC += OPCODE_LENGTH(op_new_func_exp);
4151         NEXT_INSTRUCTION();
4152     }
4153     DEFINE_OPCODE(op_call_eval) {
4154         /* call_eval func(r) argCount(n) registerOffset(n)
4155
4156            Call a function named "eval" with no explicit "this" value
4157            (which may therefore be the eval operator). If register
4158            thisVal is the global object, and register func contains
4159            that global object's original global eval function, then
4160            perform the eval operator in local scope (interpreting
4161            the argument registers as for the "call"
4162            opcode). Otherwise, act exactly as the "call" opcode would.
4163          */
4164
4165         int func = vPC[1].u.operand;
4166         int argCount = vPC[2].u.operand;
4167         int registerOffset = vPC[3].u.operand;
4168         
4169         ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
4170         JSValue funcVal = callFrame->r(func).jsValue();
4171
4172         if (isHostFunction(callFrame->globalData(), funcVal, globalFuncEval)) {
4173             Register* newCallFrame = callFrame->registers() + registerOffset;
4174             Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
4175
4176             JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset);
4177             if ((exceptionValue = globalData->exception))
4178                 goto vm_throw;
4179             functionReturnValue = result;
4180
4181             vPC += OPCODE_LENGTH(op_call_eval);
4182             NEXT_INSTRUCTION();
4183         }
4184
4185         // We didn't find the blessed version of eval, so process this
4186         // instruction as a normal function call.
4187         // fall through to op_call
4188     }
4189     DEFINE_OPCODE(op_call) {
4190         /* call func(r) argCount(n) registerOffset(n)
4191
4192            Perform a function call.
4193            
4194            registerOffset is the distance the callFrame pointer should move
4195            before the VM initializes the new call frame's header.
4196            
4197            dst is where op_ret should store its result.
4198          */
4199
4200         int func = vPC[1].u.operand;
4201         int argCount = vPC[2].u.operand;
4202         int registerOffset = vPC[3].u.operand;
4203
4204         JSValue v = callFrame->r(func).jsValue();
4205
4206         CallData callData;
4207         CallType callType = getCallData(v, callData);
4208
4209         if (callType == CallTypeJS) {
4210             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
4211
4212             JSObject* error = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
4213             if (UNLIKELY(!!error)) {
4214                 exceptionValue = error;
4215                 goto vm_throw;
4216             }
4217
4218             CallFrame* previousCallFrame = callFrame;
4219             CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
4220             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
4221             if (UNLIKELY(!callFrame)) {
4222                 callFrame = previousCallFrame;
4223                 exceptionValue = createStackOverflowError(callFrame);
4224                 goto vm_throw;
4225             }
4226
4227             callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
4228             codeBlock = newCodeBlock;
4229             ASSERT(codeBlock == callFrame->codeBlock());
4230             *topCallFrameSlot = callFrame;
4231             vPC = newCodeBlock->instructions().begin();
4232
4233 #if ENABLE(OPCODE_STATS)
4234             OpcodeStats::resetLastInstruction();
4235 #endif
4236
4237             NEXT_INSTRUCTION();
4238         }
4239
4240         if (callType == CallTypeHost) {
4241             ScopeChainNode* scopeChain = callFrame->scopeChain();
4242             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
4243             if (!registerFile->grow(newCallFrame->registers())) {
4244                 exceptionValue = createStackOverflowError(callFrame);
4245                 goto vm_throw;
4246             }
4247
4248             newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call), scopeChain, callFrame, argCount, asObject(v));
4249             JSValue returnValue;
4250             {
4251                 *topCallFrameSlot = newCallFrame;
4252                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
4253                 returnValue = JSValue::decode(callData.native.function(newCallFrame));
4254                 *topCallFrameSlot = callFrame;
4255             }
4256             CHECK_FOR_EXCEPTION();
4257
4258             functionReturnValue = returnValue;
4259
4260             vPC += OPCODE_LENGTH(op_call);
4261             NEXT_INSTRUCTION();
4262         }
4263
4264         ASSERT(callType == CallTypeNone);
4265
4266         exceptionValue = createNotAFunctionError(callFrame, v);
4267         goto vm_throw;
4268     }
4269     DEFINE_OPCODE(op_load_varargs) {
4270         int argCountDst = vPC[1].u.operand;
4271         int argsOffset = vPC[2].u.operand;
4272         
4273         JSValue arguments = callFrame->r(argsOffset).jsValue();
4274         uint32_t argCount = 0;
4275         if (!arguments) {
4276             argCount = (uint32_t)(callFrame->argumentCount());
4277             if (argCount > Arguments::MaxArguments) {
4278                 exceptionValue = createStackOverflowError(callFrame);
4279                 goto vm_throw;
4280             }
4281             int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
4282             Register* newEnd = callFrame->registers() + sizeDelta;
4283             if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
4284                 exceptionValue = createStackOverflowError(callFrame);
4285                 goto vm_throw;
4286             }
4287             ASSERT(!asFunction(callFrame->callee())->isHostFunction());
4288             int32_t expectedParams = asFunction(callFrame->callee())->jsExecutable()->parameterCount();
4289             int32_t inplaceArgs = min(static_cast<int32_t>(argCount), expectedParams);
4290             int32_t i = 0;
4291             Register* argStore = callFrame->registers() + argsOffset;
4292
4293             // First step is to copy the "expected" parameters from their normal location relative to the callframe
4294             for (; i < inplaceArgs; i++)
4295                 argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams];
4296             // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
4297             for (; i < static_cast<int32_t>(argCount); i++)
4298                 argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - static_cast<int32_t>(argCount) - 1];
4299         } else if (!arguments.isUndefinedOrNull()) {
4300             if (!arguments.isObject()) {
4301                 exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
4302                 goto vm_throw;
4303             }
4304             if (asObject(arguments)->classInfo() == &Arguments::s_info) {
4305                 Arguments* args = asArguments(arguments);
4306                 argCount = args->numProvidedArguments(callFrame);
4307                 if (argCount > Arguments::MaxArguments) {
4308                     exceptionValue = createStackOverflowError(callFrame);
4309                     goto vm_throw;
4310                 }
4311                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
4312                 Register* newEnd = callFrame->registers() + sizeDelta;
4313                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
4314                     exceptionValue = createStackOverflowError(callFrame);
4315                     goto vm_throw;
4316                 }
4317                 args->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
4318             } else if (isJSArray(&callFrame->globalData(), arguments)) {
4319                 JSArray* array = asArray(arguments);
4320                 argCount = array->length();
4321                 if (argCount > Arguments::MaxArguments) {
4322                     exceptionValue = createStackOverflowError(callFrame);
4323                     goto vm_throw;
4324                 }
4325                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
4326                 Register* newEnd = callFrame->registers() + sizeDelta;
4327                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
4328                     exceptionValue = createStackOverflowError(callFrame);
4329                     goto vm_throw;
4330                 }
4331                 array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
4332             } else {
4333                 JSObject* argObject = asObject(arguments);
4334                 argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
4335                 if (argCount > Arguments::MaxArguments) {
4336                     exceptionValue = createStackOverflowError(callFrame);
4337                     goto vm_throw;
4338                 }
4339                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
4340                 Register* newEnd = callFrame->registers() + sizeDelta;
4341                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
4342                     exceptionValue = createStackOverflowError(callFrame);
4343                     goto vm_throw;
4344                 }
4345                 Register* argsBuffer = callFrame->registers() + argsOffset;
4346                 for (uint32_t i = 0; i < argCount; ++i) {
4347                     argsBuffer[i] = asObject(arguments)->get(callFrame, i);
4348                     CHECK_FOR_EXCEPTION();
4349                 }
4350             }
4351         }
4352         CHECK_FOR_EXCEPTION();
4353         callFrame->uncheckedR(argCountDst) = Register::withInt(argCount + 1);
4354         vPC += OPCODE_LENGTH(op_load_varargs);
4355         NEXT_INSTRUCTION();
4356     }
4357     DEFINE_OPCODE(op_call_varargs) {
4358         /* call_varargs func(r) argCountReg(r) baseRegisterOffset(n)
4359          
4360          Perform a function call with a dynamic set of arguments.
4361          
4362          registerOffset is the distance the callFrame pointer should move
4363          before the VM initializes the new call frame's header, excluding
4364          space for arguments.
4365          
4366          dst is where op_ret should store its result.
4367          */
4368         
4369         int func = vPC[1].u.operand;
4370         int argCountReg = vPC[2].u.operand;
4371         int registerOffset = vPC[3].u.operand;
4372         
4373         JSValue v = callFrame->r(func).jsValue();
4374         int argCount = callFrame->r(argCountReg).i();
4375         registerOffset += argCount;
4376         CallData callData;
4377         CallType callType = getCallData(v, callData);
4378         
4379         if (callType == CallTypeJS) {
4380             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
4381
4382             JSObject* error = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
4383             if (UNLIKELY(!!error)) {
4384                 exceptionValue = error;
4385                 goto vm_throw;
4386             }
4387
4388             CallFrame* previousCallFrame = callFrame;
4389             CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
4390             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
4391             if (UNLIKELY(!callFrame)) {
4392                 callFrame = previousCallFrame;
4393                 exceptionValue = createStackOverflowError(callFrame);
4394                 goto vm_throw;
4395             }
4396
4397             callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call_varargs), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
4398             codeBlock = newCodeBlock;
4399             ASSERT(codeBlock == callFrame->codeBlock());
4400             *topCallFrameSlot = callFrame;
4401             vPC = newCodeBlock->instructions().begin();
4402             
4403 #if ENABLE(OPCODE_STATS)
4404             OpcodeStats::resetLastInstruction();
4405 #endif
4406             
4407             NEXT_INSTRUCTION();
4408         }
4409         
4410         if (callType == CallTypeHost) {
4411             ScopeChainNode* scopeChain = callFrame->scopeChain();
4412             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
4413             if (!registerFile->grow(newCallFrame->registers())) {
4414                 exceptionValue = createStackOverflowError(callFrame);
4415                 goto vm_throw;
4416             }
4417             newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call_varargs), scopeChain, callFrame, argCount, asObject(v));
4418             
4419             JSValue returnValue;
4420             {
4421                 *topCallFrameSlot = newCallFrame;
4422                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
4423                 returnValue = JSValue::decode(callData.native.function(newCallFrame));
4424                 *topCallFrameSlot = callFrame;
4425             }
4426             CHECK_FOR_EXCEPTION();
4427             
4428             functionReturnValue = returnValue;
4429             
4430             vPC += OPCODE_LENGTH(op_call_varargs);
4431             NEXT_INSTRUCTION();
4432         }
4433         
4434         ASSERT(callType == CallTypeNone);
4435         
4436         exceptionValue = createNotAFunctionError(callFrame, v);
4437         goto vm_throw;
4438     }
4439     DEFINE_OPCODE(op_tear_off_activation) {
4440         /* tear_off_activation activation(r) arguments(r)
4441
4442            Copy locals and named parameters from the register file to the heap.
4443            Point the bindings in 'activation' and 'arguments' to this new backing
4444            store. (Note that 'arguments' may not have been created. If created,
4445            'arguments' already holds a copy of any extra / unnamed parameters.)
4446
4447            This opcode appears before op_ret in functions that require full scope chains.
4448         */
4449
4450         int activation = vPC[1].u.operand;
4451         int arguments = vPC[2].u.operand;
4452         ASSERT(codeBlock->needsFullScopeChain());
4453         JSValue activationValue = callFrame->r(activation).jsValue();
4454         if (activationValue) {
4455             asActivation(activationValue)->copyRegisters(*globalData);
4456
4457             if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) {
4458                 if (!codeBlock->isStrictMode())
4459                     asArguments(argumentsValue)->setActivation(*globalData, asActivation(activationValue));
4460             }
4461         } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) {
4462             if (!codeBlock->isStrictMode())
4463                 asArguments(argumentsValue)->copyRegisters(*globalData);
4464         }
4465
4466         vPC += OPCODE_LENGTH(op_tear_off_activation);
4467         NEXT_INSTRUCTION();
4468     }
4469     DEFINE_OPCODE(op_tear_off_arguments) {
4470         /* tear_off_arguments arguments(r)
4471
4472            Copy named parameters from the register file to the heap. Point the
4473            bindings in 'arguments' to this new backing store. (Note that
4474            'arguments' may not have been created. If created, 'arguments' already
4475            holds a copy of any extra / unnamed parameters.)
4476
4477            This opcode appears before op_ret in functions that don't require full
4478            scope chains, but do use 'arguments'.
4479         */
4480
4481         int src1 = vPC[1].u.operand;
4482         ASSERT(!codeBlock->needsFullScopeChain() && codeBlock->ownerExecutable()->usesArguments());
4483
4484         if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src1)).jsValue())
4485             asArguments(arguments)->copyRegisters(*globalData);
4486
4487         vPC += OPCODE_LENGTH(op_tear_off_arguments);
4488         NEXT_INSTRUCTION();
4489     }
4490     DEFINE_OPCODE(op_ret) {
4491         /* ret result(r)
4492            
4493            Return register result as the return value of the current
4494            function call, writing it into functionReturnValue.
4495            In addition, unwind one call frame and restore the scope
4496            chain, code block instruction pointer and register base
4497            to those of the calling function.
4498         */
4499
4500         int result = vPC[1].u.operand;
4501
4502         JSValue returnValue = callFrame->r(result).jsValue();
4503
4504         vPC = callFrame->returnVPC();
4505         callFrame = callFrame->callerFrame();
4506
4507         if (callFrame->hasHostCallFrameFlag())
4508             return returnValue;
4509
4510         *topCallFrameSlot = callFrame;
4511         functionReturnValue = returnValue;
4512         codeBlock = callFrame->codeBlock();
4513         ASSERT(codeBlock == callFrame->codeBlock());
4514
4515         NEXT_INSTRUCTION();
4516     }
4517     DEFINE_OPCODE(op_call_put_result) {
4518         /* op_call_put_result result(r)
4519            
4520            Move call result from functionReturnValue to caller's
4521            expected return value register.
4522         */
4523
4524         callFrame->uncheckedR(vPC[1].u.operand) = functionReturnValue;
4525
4526         vPC += OPCODE_LENGTH(op_call_put_result);
4527         NEXT_INSTRUCTION();
4528     }
4529     DEFINE_OPCODE(op_ret_object_or_this) {
4530         /* ret result(r)
4531            
4532            Return register result as the return value of the current
4533            function call, writing it into the caller's expected return
4534            value register. In addition, unwind one call frame and
4535            restore the scope chain, code block instruction pointer and
4536            register base to those of the calling function.
4537         */
4538
4539         int result = vPC[1].u.operand;
4540
4541         JSValue returnValue = callFrame->r(result).jsValue();
4542
4543         if (UNLIKELY(!returnValue.isObject()))
4544             returnValue = callFrame->r(vPC[2].u.operand).jsValue();
4545
4546         vPC = callFrame->returnVPC();
4547         callFrame = callFrame->callerFrame();
4548
4549         if (callFrame->hasHostCallFrameFlag())
4550             return returnValue;
4551
4552         *topCallFrameSlot = callFrame;
4553         functionReturnValue = returnValue;
4554         codeBlock = callFrame->codeBlock();
4555         ASSERT(codeBlock == callFrame->codeBlock());
4556
4557         NEXT_INSTRUCTION();
4558     }
4559     DEFINE_OPCODE(op_enter) {
4560         /* enter
4561
4562            Initializes local variables to undefined. If the code block requires
4563            an activation, enter_with_activation is used instead.
4564
4565            This opcode appears only at the beginning of a code block.
4566         */
4567
4568         size_t i = 0;
4569         for (size_t count = codeBlock->m_numVars; i < count; ++i)
4570             callFrame->uncheckedR(i) = jsUndefined();
4571
4572         vPC += OPCODE_LENGTH(op_enter);
4573         NEXT_INSTRUCTION();
4574     }
4575     DEFINE_OPCODE(op_create_activation) {
4576         /* create_activation dst(r)
4577
4578            If the activation object for this callframe has not yet been created,
4579            this creates it and writes it back to dst.
4580         */
4581
4582         int activationReg = vPC[1].u.operand;
4583         if (!callFrame->r(activationReg).jsValue()) {
4584             JSActivation* activation = JSActivation::create(*globalData, callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable()));
4585             callFrame->r(activationReg) = JSValue(activation);
4586             callFrame->setScopeChain(callFrame->scopeChain()->push(activation));
4587         }
4588         vPC += OPCODE_LENGTH(op_create_activation);
4589         NEXT_INSTRUCTION();
4590     }
4591     DEFINE_OPCODE(op_get_callee) {
4592         /* op_get_callee callee(r)
4593
4594            Move callee into a register.
4595         */
4596
4597         callFrame->uncheckedR(vPC[1].u.operand) = JSValue(callFrame->callee());
4598
4599         vPC += OPCODE_LENGTH(op_get_callee);
4600         NEXT_INSTRUCTION();
4601     }
4602     DEFINE_OPCODE(op_create_this) {
4603         /* op_create_this this(r) proto(r)
4604
4605            Allocate an object as 'this', fr use in construction.
4606
4607            This opcode should only be used at the beginning of a code
4608            block.
4609         */
4610
4611         int thisRegister = vPC[1].u.operand;
4612         int protoRegister = vPC[2].u.operand;
4613
4614         JSFunction* constructor = asFunction(callFrame->callee());
4615 #if !ASSERT_DISABLED
4616         ConstructData constructData;
4617         ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
4618 #endif
4619
4620         Structure* structure;
4621         JSValue proto = callFrame->r(protoRegister).jsValue();
4622         if (proto.isObject())
4623             structure = asObject(proto)->inheritorID(callFrame->globalData());
4624         else
4625             structure = constructor->scope()->globalObject->emptyObjectStructure();
4626         callFrame->uncheckedR(thisRegister) = constructEmptyObject(callFrame, structure);
4627
4628         vPC += OPCODE_LENGTH(op_create_this);
4629         NEXT_INSTRUCTION();
4630     }
4631     DEFINE_OPCODE(op_convert_this) {
4632         /* convert_this this(r)
4633
4634            Takes the value in the 'this' register, converts it to a
4635            value that is suitable for use as the 'this' value, and
4636            stores it in the 'this' register. This opcode is emitted
4637            to avoid doing the conversion in the caller unnecessarily.
4638
4639            This opcode should only be used at the beginning of a code
4640            block.
4641         */
4642
4643         int thisRegister = vPC[1].u.operand;
4644         JSValue thisVal = callFrame->r(thisRegister).jsValue();
4645         if (thisVal.isPrimitive())
4646             callFrame->uncheckedR(thisRegister) = JSValue(thisVal.toThisObject(callFrame));
4647
4648         vPC += OPCODE_LENGTH(op_convert_this);
4649         NEXT_INSTRUCTION();
4650     }
4651     DEFINE_OPCODE(op_init_lazy_reg) {
4652         /* init_lazy_reg dst(r)
4653
4654            Initialises dst(r) to JSValue().
4655
4656            This opcode appears only at the beginning of a code block.
4657          */
4658         int dst = vPC[1].u.operand;
4659
4660         callFrame->uncheckedR(dst) = JSValue();
4661         vPC += OPCODE_LENGTH(op_init_lazy_reg);
4662         NEXT_INSTRUCTION();
4663     }
4664     DEFINE_OPCODE(op_create_arguments) {
4665         /* create_arguments dst(r)
4666
4667            Creates the 'arguments' object and places it in both the
4668            'arguments' call frame slot and the local 'arguments'
4669            register, if it has not already been initialised.
4670          */
4671         
4672         int dst = vPC[1].u.operand;
4673
4674         if (!callFrame->r(dst).jsValue()) {
4675             Arguments* arguments = Arguments::create(*globalData, callFrame);
4676             callFrame->uncheckedR(dst) = JSValue(arguments);
4677             callFrame->uncheckedR(unmodifiedArgumentsRegister(dst)) = JSValue(arguments);
4678         }
4679         vPC += OPCODE_LENGTH(op_create_arguments);
4680         NEXT_INSTRUCTION();
4681     }
4682     DEFINE_OPCODE(op_construct) {
4683         /* construct func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r)
4684
4685            Invoke register "func" as a constructor. For JS
4686            functions, the calling convention is exactly as for the
4687            "call" opcode, except that the "this" value is a newly
4688            created Object. For native constructors, no "this"
4689            value is passed. In either case, the argCount and registerOffset
4690            registers are interpreted as for the "call" opcode.
4691
4692            Register proto must contain the prototype property of
4693            register func. This is to enable polymorphic inline
4694            caching of this lookup.
4695         */
4696
4697         int func = vPC[1].u.operand;
4698         int argCount = vPC[2].u.operand;
4699         int registerOffset = vPC[3].u.operand;
4700
4701         JSValue v = callFrame->r(func).jsValue();
4702
4703         ConstructData constructData;
4704         ConstructType constructType = getConstructData(v, constructData);
4705
4706         if (constructType == ConstructTypeJS) {
4707             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
4708
4709             JSObject* error = constructData.js.functionExecutable->compileForConstruct(callFrame, callDataScopeChain);
4710             if (UNLIKELY(!!error)) {
4711                 exceptionValue = error;
4712                 goto vm_throw;
4713             }
4714
4715             CallFrame* previousCallFrame = callFrame;
4716             CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
4717             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
4718             if (UNLIKELY(!callFrame)) {
4719                 callFrame = previousCallFrame;
4720                 exceptionValue = createStackOverflowError(callFrame);
4721                 goto vm_throw;
4722             }
4723
4724             callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_construct), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
4725             codeBlock = newCodeBlock;
4726             *topCallFrameSlot = callFrame;
4727             vPC = newCodeBlock->instructions().begin();
4728 #if ENABLE(OPCODE_STATS)
4729             OpcodeStats::resetLastInstruction();
4730 #endif
4731
4732             NEXT_INSTRUCTION();
4733         }
4734
4735         if (constructType == ConstructTypeHost) {
4736             ScopeChainNode* scopeChain = callFrame->scopeChain();
4737             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
4738             if (!registerFile->grow(newCallFrame->registers())) {
4739                 exceptionValue = createStackOverflowError(callFrame);
4740                 goto vm_throw;
4741             }
4742             newCallFrame->init(0, vPC + OPCODE_LENGTH(op_construct), scopeChain, callFrame, argCount, asObject(v));
4743
4744             JSValue returnValue;
4745             {
4746                 *topCallFrameSlot = newCallFrame;
4747                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
4748                 returnValue = JSValue::decode(constructData.native.function(newCallFrame));
4749                 *topCallFrameSlot = callFrame;
4750             }
4751             CHECK_FOR_EXCEPTION();
4752             functionReturnValue = returnValue;
4753
4754             vPC += OPCODE_LENGTH(op_construct);
4755             NEXT_INSTRUCTION();
4756         }
4757
4758         ASSERT(constructType == ConstructTypeNone);
4759
4760         exceptionValue = createNotAConstructorError(callFrame, v);
4761         goto vm_throw;
4762     }
4763     DEFINE_OPCODE(op_strcat) {
4764         /* strcat dst(r) src(r) count(n)
4765
4766            Construct a new String instance using the original
4767            constructor, and puts the result in register dst.
4768            The string will be the result of concatenating count
4769            strings with values taken from registers starting at
4770            register src.
4771         */
4772         int dst = vPC[1].u.operand;
4773         int src = vPC[2].u.operand;
4774         int count = vPC[3].u.operand;
4775
4776         callFrame->uncheckedR(dst) = concatenateStrings(callFrame, &callFrame->registers()[src], count);
4777         CHECK_FOR_EXCEPTION();
4778         vPC += OPCODE_LENGTH(op_strcat);
4779
4780         NEXT_INSTRUCTION();
4781     }
4782     DEFINE_OPCODE(op_to_primitive) {
4783         int dst = vPC[1].u.operand;
4784         int src = vPC[2].u.operand;
4785
4786         callFrame->uncheckedR(dst) = callFrame->r(src).jsValue().toPrimitive(callFrame);
4787         vPC += OPCODE_LENGTH(op_to_primitive);
4788
4789         NEXT_INSTRUCTION();
4790     }
4791     DEFINE_OPCODE(op_push_scope) {
4792         /* push_scope scope(r)
4793
4794            Converts register scope to object, and pushes it onto the top
4795            of the current scope chain.  The contents of the register scope
4796            are replaced by the result of toObject conversion of the scope.
4797         */
4798         int scope = vPC[1].u.operand;
4799         JSValue v = callFrame->r(scope).jsValue();
4800         JSObject* o = v.toObject(callFrame);
4801         CHECK_FOR_EXCEPTION();
4802
4803         callFrame->uncheckedR(scope) = JSValue(o);
4804         callFrame->setScopeChain(callFrame->scopeChain()->push(o));
4805
4806         vPC += OPCODE_LENGTH(op_push_scope);
4807         NEXT_INSTRUCTION();
4808     }
4809     DEFINE_OPCODE(op_pop_scope) {
4810         /* pop_scope
4811
4812            Removes the top item from the current scope chain.
4813         */
4814         callFrame->setScopeChain(callFrame->scopeChain()->pop());
4815
4816         vPC += OPCODE_LENGTH(op_pop_scope);
4817         NEXT_INSTRUCTION();
4818     }
4819     DEFINE_OPCODE(op_get_pnames) {
4820         /* get_pnames dst(r) base(r) i(n) size(n) breakTarget(offset)
4821
4822            Creates a property name list for register base and puts it
4823            in register dst, initializing i and size for iteration. If
4824            base is undefined or null, jumps to breakTarget.
4825         */
4826         int dst = vPC[1].u.operand;
4827         int base = vPC[2].u.operand;
4828         int i = vPC[3].u.operand;
4829         int size = vPC[4].u.operand;
4830         int breakTarget = vPC[5].u.operand;
4831
4832         JSValue v = callFrame->r(base).jsValue();
4833         if (v.isUndefinedOrNull()) {
4834             vPC += breakTarget;
4835             NEXT_INSTRUCTION();
4836         }
4837
4838         JSObject* o = v.toObject(callFrame);
4839         Structure* structure = o->structure();
4840         JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
4841         if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
4842             jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
4843
4844         callFrame->uncheckedR(dst) = jsPropertyNameIterator;
4845         callFrame->uncheckedR(base) = JSValue(o);
4846         callFrame->uncheckedR(i) = Register::withInt(0);
4847         callFrame->uncheckedR(size) = Register::withInt(jsPropertyNameIterator->size());
4848         vPC += OPCODE_LENGTH(op_get_pnames);
4849         NEXT_INSTRUCTION();
4850     }
4851     DEFINE_OPCODE(op_next_pname) {
4852         /* next_pname dst(r) base(r) i(n) size(n) iter(r) target(offset)
4853
4854            Copies the next name from the property name list in
4855            register iter to dst, then jumps to offset target. If there are no
4856            names left, invalidates the iterator and continues to the next
4857            instruction.
4858         */
4859         int dst = vPC[1].u.operand;
4860         int base = vPC[2].u.operand;
4861         int i = vPC[3].u.operand;
4862         int size = vPC[4].u.operand;
4863         int iter = vPC[5].u.operand;
4864         int target = vPC[6].u.operand;
4865
4866         JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
4867         while (callFrame->r(i).i() != callFrame->r(size).i()) {
4868             JSValue key = it->get(callFrame, asObject(callFrame->r(base).jsValue()), callFrame->r(i).i());
4869             CHECK_FOR_EXCEPTION();
4870             callFrame->uncheckedR(i) = Register::withInt(callFrame->r(i).i() + 1);
4871             if (key) {
4872                 CHECK_FOR_TIMEOUT();
4873                 callFrame->uncheckedR(dst) = key;
4874                 vPC += target;
4875                 NEXT_INSTRUCTION();
4876             }
4877         }
4878
4879         vPC += OPCODE_LENGTH(op_next_pname);
4880         NEXT_INSTRUCTION();
4881     }
4882     DEFINE_OPCODE(op_jmp_scopes) {
4883         /* jmp_scopes count(n) target(offset)
4884
4885            Removes the a number of items from the current scope chain
4886            specified by immediate number count, then jumps to offset
4887            target.
4888         */
4889         int count = vPC[1].u.operand;
4890         int target = vPC[2].u.operand;
4891
4892         ScopeChainNode* tmp = callFrame->scopeChain();
4893         while (count--)
4894             tmp = tmp->pop();
4895         callFrame->setScopeChain(tmp);
4896
4897         vPC += target;
4898         NEXT_INSTRUCTION();
4899     }
4900 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
4901     // Appease GCC
4902     goto *(&&skip_new_scope);
4903 #endif
4904     DEFINE_OPCODE(op_push_new_scope) {
4905         /* new_scope dst(r) property(id) value(r)
4906          
4907            Constructs a new StaticScopeObject with property set to value.  That scope
4908            object is then pushed onto the ScopeChain.  The scope object is then stored
4909            in dst for GC.
4910          */
4911         callFrame->setScopeChain(createExceptionScope(callFrame, vPC));
4912
4913         vPC += OPCODE_LENGTH(op_push_new_scope);
4914         NEXT_INSTRUCTION();
4915     }
4916 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
4917     skip_new_scope:
4918 #endif
4919     DEFINE_OPCODE(op_catch) {
4920         /* catch ex(r)
4921
4922            Retrieves the VM's current exception and puts it in register
4923            ex. This is only valid after an exception has been raised,
4924            and usually forms the beginning of an exception handler.
4925         */
4926         ASSERT(exceptionValue);
4927         ASSERT(!globalData->exception);
4928         int ex = vPC[1].u.operand;
4929         callFrame->uncheckedR(ex) = exceptionValue;
4930         exceptionValue = JSValue();
4931
4932         vPC += OPCODE_LENGTH(op_catch);
4933         NEXT_INSTRUCTION();
4934     }
4935     DEFINE_OPCODE(op_throw) {
4936         /* throw ex(r)
4937
4938            Throws register ex as an exception. This involves three
4939            steps: first, it is set as the current exception in the
4940            VM's internal state, then the stack is unwound until an
4941            exception handler or a native code boundary is found, and
4942            then control resumes at the exception handler if any or
4943            else the script returns control to the nearest native caller.
4944         */
4945
4946         int ex = vPC[1].u.operand;
4947         exceptionValue = callFrame->r(ex).jsValue();
4948
4949         handler = throwException(callFrame, exceptionValue, vPC - codeBlock->instructions().begin());
4950         if (!handler)
4951             return throwError(callFrame, exceptionValue);
4952
4953         codeBlock = callFrame->codeBlock();
4954         vPC = codeBlock->instructions().begin() + handler->target;
4955         NEXT_INSTRUCTION();
4956     }
4957     DEFINE_OPCODE(op_throw_reference_error) {
4958         /* op_throw_reference_error message(k)
4959
4960            Constructs a new reference Error instance using the
4961            original constructor, using constant message as the
4962            message string. The result is thrown.
4963         */
4964         UString message = callFrame->r(vPC[1].u.operand).jsValue().toString(callFrame);
4965         exceptionValue = JSValue(createReferenceError(callFrame, message));
4966         goto vm_throw;
4967     }
4968     DEFINE_OPCODE(op_end) {
4969         /* end result(r)
4970            
4971            Return register result as the value of a global or eval
4972            program. Return control to the calling native code.
4973         */
4974
4975         int result = vPC[1].u.operand;
4976         return callFrame->r(result).jsValue();
4977     }
4978     DEFINE_OPCODE(op_put_getter) {
4979         /* put_getter base(r) property(id) function(r)
4980
4981            Sets register function on register base as the getter named
4982            by identifier property. Base and function are assumed to be
4983            objects as this op should only be used for getters defined
4984            in object literal form.
4985
4986            Unlike many opcodes, this one does not write any output to
4987            the register file.
4988         */
4989         int base = vPC[1].u.operand;
4990         int property = vPC[2].u.operand;
4991         int function = vPC[3].u.operand;
4992
4993         ASSERT(callFrame->r(base).jsValue().isObject());
4994         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
4995         Identifier& ident = codeBlock->identifier(property);
4996         ASSERT(callFrame->r(function).jsValue().isObject());
4997         baseObj->defineGetter(callFrame, ident, asObject(callFrame->r(function).jsValue()));
4998
4999         vPC += OPCODE_LENGTH(op_put_getter);
5000         NEXT_INSTRUCTION();
5001     }
5002     DEFINE_OPCODE(op_put_setter) {
5003         /* put_setter base(r) property(id) function(r)
5004
5005            Sets register function on register base as the setter named
5006            by identifier property. Base and function are assumed to be
5007            objects as this op should only be used for setters defined
5008            in object literal form.
5009
5010            Unlike many opcodes, this one does not write any output to
5011            the register file.
5012         */
5013         int base = vPC[1].u.operand;
5014         int property = vPC[2].u.operand;
5015         int function = vPC[3].u.operand;
5016
5017         ASSERT(callFrame->r(base).jsValue().isObject());
5018         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
5019         Identifier& ident = codeBlock->identifier(property);
5020         ASSERT(callFrame->r(function).jsValue().isObject());
5021         baseObj->defineSetter(callFrame, ident, asObject(callFrame->r(function).jsValue()), 0);
5022
5023         vPC += OPCODE_LENGTH(op_put_setter);
5024         NEXT_INSTRUCTION();
5025     }
5026     DEFINE_OPCODE(op_method_check) {
5027         vPC++;
5028         NEXT_INSTRUCTION();
5029     }
5030     DEFINE_OPCODE(op_jsr) {
5031         /* jsr retAddrDst(r) target(offset)
5032
5033            Places the address of the next instruction into the retAddrDst
5034            register and jumps to offset target from the current instruction.
5035         */
5036         int retAddrDst = vPC[1].u.operand;
5037         int target = vPC[2].u.operand;
5038         callFrame->r(retAddrDst) = vPC + OPCODE_LENGTH(op_jsr);
5039
5040         vPC += target;
5041         NEXT_INSTRUCTION();
5042     }
5043     DEFINE_OPCODE(op_sret) {
5044         /* sret retAddrSrc(r)
5045
5046          Jumps to the address stored in the retAddrSrc register. This
5047          differs from op_jmp because the target address is stored in a
5048          register, not as an immediate.
5049         */
5050         int retAddrSrc = vPC[1].u.operand;
5051         vPC = callFrame->r(retAddrSrc).vPC();
5052         NEXT_INSTRUCTION();
5053     }
5054     DEFINE_OPCODE(op_debug) {
5055         /* debug debugHookID(n) firstLine(n) lastLine(n)
5056
5057          Notifies the debugger of the current state of execution. This opcode
5058          is only generated while the debugger is attached.
5059         */
5060         int debugHookID = vPC[1].u.operand;
5061         int firstLine = vPC[2].u.operand;
5062         int lastLine = vPC[3].u.operand;
5063
5064         debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
5065
5066         vPC += OPCODE_LENGTH(op_debug);
5067         NEXT_INSTRUCTION();
5068     }
5069     DEFINE_OPCODE(op_profile_will_call) {
5070         /* op_profile_will_call function(r)
5071
5072          Notifies the profiler of the beginning of a function call. This opcode
5073          is only generated if developer tools are enabled.
5074         */
5075         int function = vPC[1].u.operand;
5076
5077         if (*enabledProfilerReference)
5078             (*enabledProfilerReference)->willExecute(callFrame, callFrame->r(function).jsValue());
5079
5080         vPC += OPCODE_LENGTH(op_profile_will_call);
5081         NEXT_INSTRUCTION();
5082     }
5083     DEFINE_OPCODE(op_profile_did_call) {
5084         /* op_profile_did_call function(r)
5085
5086          Notifies the profiler of the end of a function call. This opcode
5087          is only generated if developer tools are enabled.
5088         */
5089         int function = vPC[1].u.operand;
5090
5091         if (*enabledProfilerReference)
5092             (*enabledProfilerReference)->didExecute(callFrame, callFrame->r(function).jsValue());
5093
5094         vPC += OPCODE_LENGTH(op_profile_did_call);
5095         NEXT_INSTRUCTION();
5096     }
5097     vm_throw: {
5098         globalData->exception = JSValue();
5099         if (!tickCount) {
5100             // The exceptionValue is a lie! (GCC produces bad code for reasons I 
5101             // cannot fathom if we don't assign to the exceptionValue before branching)
5102             exceptionValue = createInterruptedExecutionException(globalData);
5103         }
5104         JSGlobalObject* globalObject = callFrame->lexicalGlobalObject();
5105         handler = throwException(callFrame, exceptionValue, vPC - codeBlock->instructions().begin());
5106         if (!handler) {
5107             // Can't use the callframe at this point as the scopechain, etc have
5108             // been released.
5109             return throwError(globalObject->globalExec(), exceptionValue);
5110         }
5111
5112         codeBlock = callFrame->codeBlock();
5113         vPC = codeBlock->instructions().begin() + handler->target;
5114         NEXT_INSTRUCTION();
5115     }
5116     }
5117 #if !ENABLE(COMPUTED_GOTO_INTERPRETER)
5118     } // iterator loop ends
5119 #endif
5120     #undef NEXT_INSTRUCTION
5121     #undef DEFINE_OPCODE
5122     #undef CHECK_FOR_EXCEPTION
5123     #undef CHECK_FOR_TIMEOUT
5124 #endif // ENABLE(INTERPRETER)
5125 }
5126
5127 JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
5128 {
5129     CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
5130     if (!functionCallFrame)
5131         return jsNull();
5132
5133     CodeBlock* codeBlock = functionCallFrame->codeBlock();
5134     if (codeBlock->usesArguments()) {
5135         ASSERT(codeBlock->codeType() == FunctionCode);
5136         int argumentsRegister = codeBlock->argumentsRegister();
5137         int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
5138         if (JSValue arguments = functionCallFrame->uncheckedR(argumentsRegister).jsValue())
5139             return arguments;
5140         JSValue arguments = JSValue(Arguments::create(callFrame->globalData(), functionCallFrame));
5141         functionCallFrame->r(argumentsRegister) = arguments;
5142         functionCallFrame->r(realArgumentsRegister) = arguments;
5143         return arguments;
5144     }
5145
5146     Arguments* arguments = Arguments::create(functionCallFrame->globalData(), functionCallFrame);
5147     arguments->copyRegisters(functionCallFrame->globalData());
5148     return arguments;
5149 }
5150
5151 JSValue Interpreter::retrieveCaller(CallFrame* callFrame, JSFunction* function) const
5152 {
5153     CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
5154     if (!functionCallFrame)
5155         return jsNull();
5156
5157     CallFrame* callerFrame = functionCallFrame->callerFrame();
5158     if (callerFrame->hasHostCallFrameFlag())
5159         return jsNull();
5160
5161     JSValue caller = callerFrame->callee();
5162     if (!caller)
5163         return jsNull();
5164
5165     return caller;
5166 }
5167
5168 void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& function) const
5169 {
5170     function = JSValue();
5171     lineNumber = -1;
5172     sourceURL = UString();
5173
5174     CallFrame* callerFrame = callFrame->callerFrame();
5175     if (callerFrame->hasHostCallFrameFlag())
5176         return;
5177
5178     CodeBlock* callerCodeBlock = callerFrame->codeBlock();
5179     if (!callerCodeBlock)
5180         return;
5181     unsigned bytecodeOffset = 0;
5182 #if ENABLE(INTERPRETER)
5183     if (!callerFrame->globalData().canUseJIT())
5184         bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC());
5185 #if ENABLE(JIT)
5186     else
5187         bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
5188 #endif
5189 #else
5190     bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
5191 #endif
5192     lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
5193     sourceID = callerCodeBlock->ownerExecutable()->sourceID();
5194     sourceURL = callerCodeBlock->ownerExecutable()->sourceURL();
5195     function = callerFrame->callee();
5196 }
5197
5198 CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, JSFunction* function)
5199 {
5200     for (CallFrame* candidate = callFrame; candidate; candidate = candidate->callerFrame()->removeHostCallFrameFlag()) {
5201         if (candidate->callee() == function)
5202             return candidate;
5203     }
5204     return 0;
5205 }
5206
5207 void Interpreter::enableSampler()
5208 {
5209 #if ENABLE(OPCODE_SAMPLING)
5210     if (!m_sampler) {
5211         m_sampler = adoptPtr(new SamplingTool(this));
5212         m_sampler->setup();
5213     }
5214 #endif
5215 }
5216 void Interpreter::dumpSampleData(ExecState* exec)
5217 {
5218 #if ENABLE(OPCODE_SAMPLING)
5219     if (m_sampler)
5220         m_sampler->dump(exec);
5221 #else
5222     UNUSED_PARAM(exec);
5223 #endif
5224 }
5225 void Interpreter::startSampling()
5226 {
5227 #if ENABLE(SAMPLING_THREAD)
5228     if (!m_sampleEntryDepth)
5229         SamplingThread::start();
5230
5231     m_sampleEntryDepth++;
5232 #endif
5233 }
5234 void Interpreter::stopSampling()
5235 {
5236 #if ENABLE(SAMPLING_THREAD)
5237     m_sampleEntryDepth--;
5238     if (!m_sampleEntryDepth)
5239         SamplingThread::stop();
5240 #endif
5241 }
5242
5243 } // namespace JSC