Groundwork for reimplementing the slow script dialog
[WebKit-https.git] / JavaScriptCore / VM / Machine.cpp
1 /*
2  * Copyright (C) 2008 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 "Machine.h"
32
33 #include "CodeBlock.h"
34 #include "DebuggerCallFrame.h"
35 #include "ExceptionHelpers.h"
36 #include "ExecState.h"
37 #include "JSActivation.h"
38 #include "JSLock.h"
39 #include "JSPropertyNameIterator.h"
40 #include "Parser.h"
41 #include "Profiler.h"
42 #include "Register.h"
43 #include "ArrayPrototype.h"
44 #include "debugger.h"
45 #include "JSFunction.h"
46 #include "JSString.h"
47 #include "object_object.h"
48 #include "operations.h"
49 #include "operations.h"
50 #include "RegExpObject.h"
51
52 namespace KJS {
53
54 #if HAVE(COMPUTED_GOTO)
55 static void* op_throw_end_indirect;
56 static void* op_call_indirect;
57 #endif
58
59 // Retrieves the offset of a calling function within the current register file.
60 bool getCallerFunctionOffset(Register** registerBase, int callOffset, int& callerOffset)
61 {
62     Register* callFrame = (*registerBase) + callOffset;
63
64     CodeBlock* callerCodeBlock = callFrame[Machine::CallerCodeBlock].u.codeBlock;
65     if (!callerCodeBlock) // test for top frame of re-entrant function call
66         return false;
67     
68     if (callerCodeBlock->codeType == EvalCode)
69         return false;
70     
71     callerOffset = callFrame[Machine::CallerRegisterOffset].u.i - callerCodeBlock->numLocals - Machine::CallFrameHeaderSize;
72     if (callerOffset < 0) // test for global frame
73         return false;
74
75     return true;
76 }
77
78 // Returns the depth of the scope chain within a given call frame.
79 static int depth(ScopeChain& sc)
80 {
81     int scopeDepth = 0;
82     ScopeChainIterator iter = sc.begin();
83     ScopeChainIterator end = sc.end();
84     while (!(*iter)->isVariableObject()) {
85         ++iter;
86         ++scopeDepth;
87     }
88     return scopeDepth;
89 }
90
91 static inline bool jsLess(ExecState* exec, JSValue* v1, JSValue* v2)
92 {
93     if (JSImmediate::areBothImmediateNumbers(v1, v2))
94         return JSImmediate::getTruncatedInt32(v1) < JSImmediate::getTruncatedInt32(v2);
95
96     double n1;
97     double n2;
98     JSValue* p1;
99     JSValue* p2;
100     bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
101     bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
102
103     if (wasNotString1 | wasNotString2)
104         return n1 < n2;
105
106     return static_cast<const JSString*>(p1)->value() < static_cast<const JSString*>(p2)->value();
107 }
108
109 static inline bool jsLessEq(ExecState* exec, JSValue* v1, JSValue* v2)
110 {
111     double n1;
112     double n2;
113     JSValue* p1;
114     JSValue* p2;
115     bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
116     bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
117
118     if (wasNotString1 | wasNotString2)
119         return n1 <= n2;
120
121     return !(static_cast<const JSString*>(p2)->value() < static_cast<const JSString*>(p1)->value());
122 }
123
124 static JSValue* jsAddSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
125 {
126     // exception for the Date exception in defaultValue()
127     JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
128     JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
129
130     if (p1->isString() || p2->isString()) {
131         UString value = p1->toString(exec) + p2->toString(exec);
132         if (value.isNull())
133             return throwOutOfMemoryError(exec);
134         return jsString(exec, value);
135     }
136
137     return jsNumber(exec, p1->toNumber(exec) + p2->toNumber(exec));
138 }
139
140 // Fast-path choices here are based on frequency data from SunSpider:
141 //    <times> Add case: <t1> <t2>
142 //    ---------------------------
143 //    5626160 Add case: 3 3 (of these, 3637690 are for immediate values)
144 //    247412  Add case: 5 5
145 //    20900   Add case: 5 6
146 //    13962   Add case: 5 3
147 //    4000    Add case: 3 5
148
149 static inline JSValue* jsAdd(ExecState* exec, JSValue* v1, JSValue* v2)
150 {
151     JSType t1 = v1->type();
152     JSType t2 = v2->type();
153     const unsigned bothTypes = (t1 << 3) | t2;
154
155     if (bothTypes == ((NumberType << 3) | NumberType))
156         return jsNumber(exec, v1->uncheckedGetNumber() + v2->uncheckedGetNumber());
157     if (bothTypes == ((StringType << 3) | StringType)) {
158         UString value = static_cast<JSString*>(v1)->value() + static_cast<JSString*>(v2)->value();
159         if (value.isNull())
160             return throwOutOfMemoryError(exec);
161         return jsString(exec, value);
162     }
163
164     // All other cases are pretty uncommon
165     return jsAddSlowCase(exec, v1, v2);
166 }
167
168 static JSValue* jsTypeStringForValue(ExecState* exec, JSValue* v)
169 {
170     switch (v->type()) {
171         case UndefinedType:
172             return jsString(exec, "undefined");
173         case NullType:
174             return jsString(exec, "object");
175         case BooleanType:
176             return jsString(exec, "boolean");
177         case NumberType:
178             return jsString(exec, "number");
179         case StringType:
180             return jsString(exec, "string");
181         default:
182             if (v->isObject()) {
183                 // Return "undefined" for objects that should be treated
184                 // as null when doing comparisons.
185                 if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
186                     return jsString(exec, "undefined");
187                 CallData callData;
188                 if (static_cast<JSObject*>(v)->getCallData(callData) != CallTypeNone)
189                     return jsString(exec, "function");
190             }
191
192             return jsString(exec, "object");
193     }
194 }
195
196 static bool NEVER_INLINE resolve(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
197 {
198     int dst = (vPC + 1)->u.operand;
199     int property = (vPC + 2)->u.operand;
200
201     ScopeChainIterator iter = scopeChain->begin();
202     ScopeChainIterator end = scopeChain->end();
203     ASSERT(iter != end);
204
205     Identifier& ident = codeBlock->identifiers[property];
206     do {
207         JSObject* o = *iter;
208         PropertySlot slot(o);
209         if (o->getPropertySlot(exec, ident, slot)) {
210             JSValue* result = slot.getValue(exec, ident);
211             exceptionValue = exec->exception();
212             if (exceptionValue)
213                 return false;
214             r[dst].u.jsValue = result;
215             return true;
216         }
217     } while (++iter != end);
218     exceptionValue = createUndefinedVariableError(exec, ident);
219     return false;
220 }
221
222 static bool NEVER_INLINE resolve_skip(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
223 {
224     int dst = (vPC + 1)->u.operand;
225     int property = (vPC + 2)->u.operand;
226     int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain;
227
228     ScopeChainIterator iter = scopeChain->begin();
229     ScopeChainIterator end = scopeChain->end();
230     ASSERT(iter != end);
231     while (skip--) {
232         ++iter;
233         ASSERT(iter != end);
234     }
235     Identifier& ident = codeBlock->identifiers[property];
236     do {
237         JSObject* o = *iter;
238         PropertySlot slot(o);
239         if (o->getPropertySlot(exec, ident, slot)) {
240             JSValue* result = slot.getValue(exec, ident);
241             exceptionValue = exec->exception();
242             if (exceptionValue)
243                 return false;
244             r[dst].u.jsValue = result;
245             return true;
246         }
247     } while (++iter != end);
248     exceptionValue = createUndefinedVariableError(exec, ident);
249     return false;
250 }
251
252 static void NEVER_INLINE resolveBase(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock)
253 {
254     int dst = (vPC + 1)->u.operand;
255     int property = (vPC + 2)->u.operand;
256
257     ScopeChainIterator iter = scopeChain->begin();
258     ScopeChainIterator next = iter;
259     ++next;
260     ScopeChainIterator end = scopeChain->end();
261     ASSERT(iter != end);
262
263     PropertySlot slot;
264     Identifier& ident = codeBlock->identifiers[property];
265     JSObject* base;
266     while (true) {
267         base = *iter;
268         if (next == end || base->getPropertySlot(exec, ident, slot)) {
269             r[dst].u.jsValue = base;
270             return;
271         }
272         iter = next;
273         ++next;
274     }
275 }
276
277 static bool NEVER_INLINE resolveBaseAndProperty(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
278 {
279     int baseDst = (vPC + 1)->u.operand;
280     int propDst = (vPC + 2)->u.operand;
281     int property = (vPC + 3)->u.operand;
282
283     ScopeChainIterator iter = scopeChain->begin();
284     ScopeChainIterator end = scopeChain->end();
285
286     // FIXME: add scopeDepthIsZero optimization
287
288     ASSERT(iter != end);
289
290     Identifier& ident = codeBlock->identifiers[property];
291     JSObject* base;
292     do {
293         base = *iter;
294         PropertySlot slot(base);
295         if (base->getPropertySlot(exec, ident, slot)) {
296             JSValue* result = slot.getValue(exec, ident);
297             exceptionValue = exec->exception();
298             if (exceptionValue)
299                 return false;
300             r[propDst].u.jsValue = result;
301             r[baseDst].u.jsValue = base;
302             return true;
303         }
304         ++iter;
305     } while (iter != end);
306
307     exceptionValue = createUndefinedVariableError(exec, ident);
308     return false;
309 }
310
311 static bool NEVER_INLINE resolveBaseAndFunc(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
312 {
313     int baseDst = (vPC + 1)->u.operand;
314     int funcDst = (vPC + 2)->u.operand;
315     int property = (vPC + 3)->u.operand;
316
317     ScopeChainIterator iter = scopeChain->begin();
318     ScopeChainIterator end = scopeChain->end();
319
320     // FIXME: add scopeDepthIsZero optimization
321
322     ASSERT(iter != end);
323
324     Identifier& ident = codeBlock->identifiers[property];
325     JSObject* base;
326     do {
327         base = *iter;
328         PropertySlot slot(base);
329         if (base->getPropertySlot(exec, ident, slot)) {            
330             // ECMA 11.2.3 says that if we hit an activation the this value should be null.
331             // However, section 10.2.3 says that in the case where the value provided
332             // by the caller is null, the global object should be used. It also says
333             // that the section does not apply to internal functions, but for simplicity
334             // of implementation we use the global object anyway here. This guarantees
335             // that in host objects you always get a valid object for this.
336             // We also handle wrapper substitution for the global object at the same time.
337             JSObject* thisObj = base->toThisObject(exec);
338             JSValue* result = slot.getValue(exec, ident);
339             exceptionValue = exec->exception();
340             if (exceptionValue)
341                 return false;
342
343             r[baseDst].u.jsValue = thisObj;
344             r[funcDst].u.jsValue = result;
345             return true;
346         }
347         ++iter;
348     } while (iter != end);
349
350     exceptionValue = createUndefinedVariableError(exec, ident);
351     return false;
352 }
353
354 ALWAYS_INLINE void initializeCallFrame(Register* callFrame, CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, int registerOffset, int returnValueRegister, int argv, int argc, int calledAsConstructor, JSValue* function)
355 {
356     callFrame[Machine::CallerCodeBlock].u.codeBlock = codeBlock;
357     callFrame[Machine::ReturnVPC].u.vPC = vPC + 1;
358     callFrame[Machine::CallerScopeChain].u.scopeChain = scopeChain;
359     callFrame[Machine::CallerRegisterOffset].u.i = registerOffset;
360     callFrame[Machine::ReturnValueRegister].u.i = returnValueRegister;
361     callFrame[Machine::ArgumentStartRegister].u.i = argv; // original argument vector (for the sake of the "arguments" object)
362     callFrame[Machine::ArgumentCount].u.i = argc; // original argument count (for the sake of the "arguments" object)
363     callFrame[Machine::CalledAsConstructor].u.i = calledAsConstructor;
364     callFrame[Machine::Callee].u.jsValue = function;
365     callFrame[Machine::OptionalCalleeActivation].u.jsValue = 0;
366 }
367
368 ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* newCodeBlock, RegisterFile* registerFile, Register** registerBase, int registerOffset, int argv, int argc, JSValue*& exceptionValue)
369 {
370     Register* r = 0;
371     int oldOffset = registerOffset;
372     registerOffset += argv + newCodeBlock->numLocals;
373     size_t size = registerOffset + newCodeBlock->numTemporaries;
374
375     if (argc == newCodeBlock->numParameters) { // correct number of arguments
376         if (!registerFile->grow(size)) {
377             exceptionValue = createStackOverflowError(exec);
378             return *registerBase + oldOffset;
379         }
380         r = (*registerBase) + registerOffset;
381     } else if (argc < newCodeBlock->numParameters) { // too few arguments -- fill in the blanks
382         if (!registerFile->grow(size)) {
383             exceptionValue = createStackOverflowError(exec);
384             return *registerBase + oldOffset;
385         }
386         r = (*registerBase) + registerOffset;
387
388         int omittedArgCount = newCodeBlock->numParameters - argc;
389         Register* endOfParams = r - newCodeBlock->numVars;
390         for (Register* it = endOfParams - omittedArgCount; it != endOfParams; ++it)
391             (*it).u.jsValue = jsUndefined();
392     } else { // too many arguments -- copy return info and expected arguments, leaving the extra arguments behind
393         int shift = argc + Machine::CallFrameHeaderSize;
394         registerOffset += shift;
395         size += shift;
396
397         if (!registerFile->grow(size)) {
398             exceptionValue = createStackOverflowError(exec);
399             return *registerBase + oldOffset;
400         }
401         r = (*registerBase) + registerOffset;
402
403         Register* it = r - newCodeBlock->numLocals - Machine::CallFrameHeaderSize - shift;
404         Register* end = it + Machine::CallFrameHeaderSize + newCodeBlock->numParameters;
405         for ( ; it != end; ++it)
406             *(it + shift) = *it;
407     }
408     
409     // initialize local variable slots
410     for (Register* it = r - newCodeBlock->numVars; it != r; ++it)
411         (*it).u.jsValue = jsUndefined();
412
413     return r;
414 }
415
416 ALWAYS_INLINE ScopeChainNode* scopeChainForCall(ExecState* exec, FunctionBodyNode* functionBodyNode, CodeBlock* newCodeBlock, ScopeChainNode* callDataScopeChain, Register** registerBase, Register* r)
417 {
418     if (newCodeBlock->needsFullScopeChain) {
419         JSActivation* activation = new (exec) JSActivation(functionBodyNode, registerBase, r - (*registerBase));
420         r[Machine::OptionalCalleeActivation - Machine::CallFrameHeaderSize - newCodeBlock->numLocals].u.jsValue = activation;
421
422         return callDataScopeChain->copy()->push(activation);
423     }
424
425     return callDataScopeChain;
426 }
427
428 static NEVER_INLINE bool isNotObject(ExecState* exec, bool forInstanceOf, CodeBlock*, JSValue* value, JSValue*& exceptionData)
429 {
430     if (value->isObject())
431         return false;
432     exceptionData = createInvalidParamError(exec, forInstanceOf ? "instanceof" : "in" , value);
433     return true;
434 }
435
436 static NEVER_INLINE JSValue* callEval(ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, Register* r, int argv, int argc, JSValue*& exceptionValue)
437 {
438     if (argc < 2)
439         return jsUndefined();
440
441     JSValue* program = r[argv + 1].u.jsValue;
442
443     if (!program->isString())
444         return program;
445
446     Profiler** profiler = Profiler::enabledProfilerReference();
447     if (*profiler)
448         (*profiler)->willExecute(exec, scopeChain->globalObject()->evalFunction());
449
450     int sourceId;
451     int errLine;
452     UString errMsg;
453     RefPtr<EvalNode> evalNode = exec->parser()->parse<EvalNode>(exec, UString(), 1, UStringSourceProvider::create(static_cast<JSString*>(program)->value()), &sourceId, &errLine, &errMsg);
454
455     if (!evalNode) {
456         exceptionValue = Error::create(exec, SyntaxError, errMsg, errLine, sourceId, NULL);
457         if (*profiler)
458             (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
459         return 0;
460     }
461
462     JSValue* result = exec->machine()->execute(evalNode.get(), exec, thisObj, registerFile, r - (*registerFile->basePointer()) + argv + argc, scopeChain, &exceptionValue);
463
464     if (*profiler)
465         (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
466
467     return result;
468 }
469
470 Machine::Machine()
471     : m_reentryDepth(0)
472 {
473     privateExecute(InitializeAndReturn);
474 }
475
476 void Machine::dumpCallFrame(const CodeBlock* codeBlock, ScopeChainNode* scopeChain, RegisterFile* registerFile, const Register* r)
477 {
478     ScopeChain sc(scopeChain);
479     JSGlobalObject* globalObject = sc.globalObject();
480     codeBlock->dump(globalObject->globalExec());
481     dumpRegisters(codeBlock, registerFile, r);
482 }
483
484 void Machine::dumpRegisters(const CodeBlock* codeBlock, RegisterFile* registerFile, const Register* r)
485 {
486     printf("Register frame: \n\n");
487     printf("----------------------------------------\n");
488     printf("     use      |   address  |    value   \n");
489     printf("----------------------------------------\n");
490
491     const Register* it;
492     const Register* end;
493
494     if (isGlobalCallFrame(registerFile->basePointer(), r)) {
495         it = r - registerFile->numGlobalSlots();
496         end = r;
497         if (it != end) {
498             do {
499                 printf("[global var]  | %10p | %10p \n", it, (*it).u.jsValue);
500                 ++it;
501             } while (it != end);
502             printf("----------------------------------------\n");
503         }
504     } else {
505         it = r - codeBlock->numLocals - CallFrameHeaderSize;
506         end = it + CallFrameHeaderSize;
507         if (it != end) {
508             do {
509                 printf("[call frame]  | %10p | %10p \n", it, (*it).u.jsValue);
510                 ++it;
511             } while (it != end);
512             printf("----------------------------------------\n");
513         }
514
515         end = it + codeBlock->numParameters;
516         if (it != end) {
517             do {
518                 printf("[param]       | %10p | %10p \n", it, (*it).u.jsValue);
519                 ++it;
520             } while (it != end);
521             printf("----------------------------------------\n");
522         }
523
524         end = it + codeBlock->numVars;
525         if (it != end) {
526             do {
527                 printf("[var]         | %10p | %10p \n", it, (*it).u.jsValue);
528                 ++it;
529             } while (it != end);
530             printf("----------------------------------------\n");
531         }
532     }
533
534     end = it + codeBlock->numTemporaries;
535     if (it != end) {
536         do {
537             printf("[temp]        | %10p | %10p \n", it, (*it).u.jsValue);
538             ++it;
539         } while (it != end);
540     }
541 }
542
543 bool Machine::isOpcode(Opcode opcode)
544 {
545 #if HAVE(COMPUTED_GOTO)
546     return opcode != HashTraits<Opcode>::emptyValue()
547         && !HashTraits<Opcode>::isDeletedValue(opcode)
548         && m_opcodeIDTable.contains(opcode);
549 #else
550     return opcode >= 0 && opcode <= op_end;
551 #endif
552 }
553
554 NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, Register** registerBase, const Instruction*& vPC, CodeBlock*& codeBlock, JSValue**& k, ScopeChainNode*& scopeChain, Register*& r)
555 {
556     CodeBlock* oldCodeBlock = codeBlock;
557     Register* callFrame = r - oldCodeBlock->numLocals - CallFrameHeaderSize;
558
559     if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
560         DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, exceptionValue, registerBase, r - *registerBase);
561         if (!isGlobalCallFrame(registerBase, r) && callFrame[Callee].u.jsObject) // Check for global and eval code
562             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
563         else
564             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
565     }
566
567     if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
568         if (!isGlobalCallFrame(registerBase, r) && callFrame[Callee].u.jsObject) // Check for global and eval code
569             profiler->didExecute(exec, callFrame[Callee].u.jsObject);
570         else
571             profiler->didExecute(exec, codeBlock->ownerNode->sourceURL(), codeBlock->ownerNode->lineNo());
572     }
573
574     if (oldCodeBlock->needsFullScopeChain)
575         scopeChain->deref();
576
577     if (isGlobalCallFrame(registerBase, r))
578         return false;
579     
580     // If this call frame created an activation, tear it off.
581     if (JSActivation* activation = static_cast<JSActivation*>(callFrame[OptionalCalleeActivation].u.jsValue)) {
582         ASSERT(activation->isActivationObject());
583         activation->copyRegisters();
584     }
585     
586     codeBlock = callFrame[CallerCodeBlock].u.codeBlock;
587     if (!codeBlock)
588         return false;
589
590     k = codeBlock->jsValues.data();
591     scopeChain = callFrame[CallerScopeChain].u.scopeChain;
592     int callerRegisterOffset = callFrame[CallerRegisterOffset].u.i;
593     r = (*registerBase) + callerRegisterOffset;
594     exec->m_callFrameOffset = callerRegisterOffset - codeBlock->numLocals - CallFrameHeaderSize;
595     vPC = callFrame[ReturnVPC].u.vPC;
596
597     return true;
598 }
599
600 NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue* exceptionValue, Register** registerBase, const Instruction* vPC, CodeBlock*& codeBlock, JSValue**& k, ScopeChainNode*& scopeChain, Register*& r)
601 {
602     // Set up the exception object
603
604     if (exceptionValue->isObject()) {
605         JSObject* exception = static_cast<JSObject*>(exceptionValue);
606         if (!exception->hasProperty(exec, Identifier(exec, "line")) && !exception->hasProperty(exec, Identifier(exec, "sourceURL"))) {
607             exception->put(exec, Identifier(exec, "line"), jsNumber(exec, codeBlock->lineNumberForVPC(vPC)));
608             exception->put(exec, Identifier(exec, "sourceURL"), jsOwnedString(exec, codeBlock->ownerNode->sourceURL()));
609         }
610     }
611
612     if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
613         DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, exceptionValue, registerBase, r - *registerBase);
614         debugger->exception(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->lineNumberForVPC(vPC));
615     }
616
617     // Calculate an exception handler vPC, unwinding call frames as necessary.
618
619     int scopeDepth;
620     Instruction* handlerVPC;
621
622     while (!codeBlock->getHandlerForVPC(vPC, handlerVPC, scopeDepth)) {
623         if (!unwindCallFrame(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r))
624             return 0;
625     }
626
627     // Now unwind the scope chain within the exception handler's call frame.
628
629     ScopeChain sc(scopeChain);
630     int scopeDelta = depth(sc) - scopeDepth;
631     ASSERT(scopeDelta >= 0);
632     while (scopeDelta--)
633         sc.pop();
634     setScopeChain(exec, scopeChain, sc.node());
635
636     return handlerVPC;
637 }
638
639 JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainNode* scopeChain, JSObject* thisObj, RegisterFileStack* registerFileStack, JSValue** exception)
640 {
641     if (m_reentryDepth >= MaxReentryDepth) {
642         *exception = createStackOverflowError(exec);
643         return 0;
644     }
645
646     RegisterFile* registerFile = registerFileStack->pushGlobalRegisterFile();
647     ASSERT(registerFile->numGlobalSlots());
648     CodeBlock* codeBlock = &programNode->code(scopeChain, !registerFileStack->inImplicitCall());
649     registerFile->addGlobalSlots(codeBlock->numVars);
650
651     if (!registerFile->grow(codeBlock->numTemporaries)) {
652         registerFileStack->popGlobalRegisterFile();
653         *exception = createStackOverflowError(exec);
654         return 0;
655     }
656     Register* r = (*registerFile->basePointer());
657
658     r[ProgramCodeThisRegister].u.jsValue = thisObj;
659
660     if (codeBlock->needsFullScopeChain)
661         scopeChain = scopeChain->copy();
662
663     ExecState newExec(exec, registerFile, scopeChain, -1);
664
665     Profiler** profiler = Profiler::enabledProfilerReference();
666     if (*profiler)
667         (*profiler)->willExecute(exec, programNode->sourceURL(), programNode->lineNo());
668
669     m_reentryDepth++;
670     JSValue* result = privateExecute(Normal, &newExec, registerFile, r, scopeChain, codeBlock, exception);
671     m_reentryDepth--;
672
673     registerFileStack->popGlobalRegisterFile();
674
675     if (*profiler) {
676         (*profiler)->didExecute(exec, programNode->sourceURL(), programNode->lineNo());
677         if (!m_reentryDepth)
678             (*profiler)->didFinishAllExecution(exec);
679     }
680
681     return result;
682 }
683
684 JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, JSFunction* function, JSObject* thisObj, const ArgList& args, RegisterFileStack* registerFileStack, ScopeChainNode* scopeChain, JSValue** exception)
685 {
686     if (m_reentryDepth >= MaxReentryDepth) {
687         *exception = createStackOverflowError(exec);
688         return 0;
689     }
690
691     RegisterFile* registerFile = registerFileStack->current();
692
693     int argv = CallFrameHeaderSize;
694     int argc = args.size() + 1; // implicit "this" parameter
695
696     size_t oldSize = registerFile->size();
697     if (!registerFile->grow(oldSize + CallFrameHeaderSize + argc)) {
698         *exception = createStackOverflowError(exec);
699         return 0;
700     }
701
702     Register** registerBase = registerFile->basePointer();
703     int registerOffset = oldSize;
704     int callFrameOffset = registerOffset;
705     Register* callFrame = (*registerBase) + callFrameOffset;
706
707     // put args in place, including "this"
708     Register* dst = callFrame + CallFrameHeaderSize;
709     (*dst).u.jsValue = thisObj;
710
711     ArgList::const_iterator end = args.end();
712     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
713         (*++dst).u.jsValue = *it;
714
715     // put call frame in place, using a 0 codeBlock to indicate a built-in caller
716     initializeCallFrame(callFrame, 0, 0, 0, registerOffset, 0, argv, argc, 0, function);
717
718     CodeBlock* newCodeBlock = &functionBodyNode->code(scopeChain);
719     Register* r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, registerOffset, argv, argc, *exception);
720     if (*exception) {
721         registerFile->shrink(oldSize);
722         return 0;
723     }
724
725     scopeChain = scopeChainForCall(exec, functionBodyNode, newCodeBlock, scopeChain, registerBase, r);
726
727     ExecState newExec(exec, registerFile, scopeChain, callFrameOffset);
728
729     Profiler** profiler = Profiler::enabledProfilerReference();
730     if (*profiler)
731         (*profiler)->willExecute(exec, function);
732
733     m_reentryDepth++;
734     JSValue* result = privateExecute(Normal, &newExec, registerFile, r, scopeChain, newCodeBlock, exception);
735     m_reentryDepth--;
736
737     if (*profiler && !m_reentryDepth)
738         (*profiler)->didFinishAllExecution(exec);
739
740     registerFile->shrink(oldSize);
741     return result;
742 }
743
744 JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, RegisterFile* registerFile, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)
745 {
746     if (m_reentryDepth >= MaxReentryDepth) {
747         *exception = createStackOverflowError(exec);
748         return 0;
749     }
750
751     EvalCodeBlock* codeBlock = &evalNode->code(scopeChain);
752
753     JSVariableObject* variableObject;
754     for (ScopeChainNode* node = scopeChain; ; node = node->next) {
755         ASSERT(node);
756         if (node->object->isVariableObject()) {
757             variableObject = static_cast<JSVariableObject*>(node->object);
758             break;
759         }
760     }
761
762     const Node::VarStack& varStack = codeBlock->ownerNode->varStack();
763     Node::VarStack::const_iterator varStackEnd = varStack.end();
764     for (Node::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) {
765         const Identifier& ident = (*it).first;
766         if (!variableObject->hasProperty(exec, ident))
767             variableObject->put(exec, ident, jsUndefined());
768     }
769
770     const Node::FunctionStack& functionStack = codeBlock->ownerNode->functionStack();
771     Node::FunctionStack::const_iterator functionStackEnd = functionStack.end();
772     for (Node::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it)
773         variableObject->put(exec, (*it)->m_ident, (*it)->makeFunction(exec, scopeChain));
774
775     size_t oldSize = registerFile->size();
776     size_t newSize = registerOffset + codeBlock->numVars + codeBlock->numTemporaries + CallFrameHeaderSize;
777     if (!registerFile->grow(newSize)) {
778         *exception = createStackOverflowError(exec);
779         return 0;
780     }
781
782     Register* callFrame = *registerFile->basePointer() + registerOffset;
783
784     // put call frame in place, using a 0 codeBlock to indicate a built-in caller
785     initializeCallFrame(callFrame, 0, 0, 0, registerOffset, 0, 0, 0, 0, 0);
786
787     Register* r = callFrame + CallFrameHeaderSize + codeBlock->numVars;
788     r[ProgramCodeThisRegister].u.jsValue = thisObj;
789
790     if (codeBlock->needsFullScopeChain)
791         scopeChain = scopeChain->copy();
792
793     ExecState newExec(exec, registerFile, scopeChain, -1);
794
795     Profiler** profiler = Profiler::enabledProfilerReference();
796     if (*profiler)
797         (*profiler)->willExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
798
799     m_reentryDepth++;
800     JSValue* result = privateExecute(Normal, &newExec, registerFile, r, scopeChain, codeBlock, exception);
801     m_reentryDepth--;
802
803     registerFile->shrink(oldSize);
804
805     if (*profiler) {
806         (*profiler)->didExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
807         if (!m_reentryDepth)
808             (*profiler)->didFinishAllExecution(exec);
809     }
810
811     return result;
812 }
813
814 JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, RegisterFileStack* registerFileStack, ScopeChainNode* scopeChain, JSValue** exception)
815 {
816     RegisterFile* registerFile = registerFileStack->current();
817     if (registerFile->safeForReentry())
818         return Machine::execute(evalNode, exec, thisObj, registerFile, registerFile->size(), scopeChain, exception);
819     registerFile = registerFileStack->pushFunctionRegisterFile();
820     JSValue* result = Machine::execute(evalNode, exec, thisObj, registerFile, registerFile->size(), scopeChain, exception);
821     registerFileStack->popFunctionRegisterFile();
822     return result;
823 }
824
825 ALWAYS_INLINE void Machine::setScopeChain(ExecState* exec, ScopeChainNode*& scopeChain, ScopeChainNode* newScopeChain)
826 {
827     scopeChain = newScopeChain;
828     exec->m_scopeChain = newScopeChain;
829 }
830
831 NEVER_INLINE void Machine::debug(ExecState* exec, const Instruction* vPC, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register** registerBase, Register* r)
832 {
833     int debugHookID = (++vPC)->u.operand;
834     int firstLine = (++vPC)->u.operand;
835     int lastLine = (++vPC)->u.operand;
836
837     Debugger* debugger = exec->dynamicGlobalObject()->debugger();
838     if (!debugger)
839         return;
840
841     DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, 0, registerBase, r - *registerBase);
842
843     switch((DebugHookID)debugHookID) {
844     case DidEnterCallFrame: {
845         debugger->callEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
846         return;
847     }
848     case WillLeaveCallFrame: {
849         debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
850         return;
851     }
852     case WillExecuteStatement: {
853         debugger->atStatement(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
854         return;
855     }
856     case WillExecuteProgram: {
857         debugger->willExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
858         return;
859     }
860     case DidExecuteProgram: {
861         debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
862         return;
863     }
864     case DidReachBreakpoint: {
865         debugger->didReachBreakpoint(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
866         return;
867     }
868     }
869 }
870
871 JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception)
872 {
873     // One-time initialization of our address tables. We have to put this code
874     // here because our labels are only in scope inside this function.
875     if (flag == InitializeAndReturn) {
876         #if HAVE(COMPUTED_GOTO)
877             #define ADD_OPCODE(id) m_opcodeTable[id] = &&id;
878                 FOR_EACH_OPCODE_ID(ADD_OPCODE);
879             #undef ADD_OPCODE
880
881             #define ADD_OPCODE_ID(id) m_opcodeIDTable.add(&&id, id);
882                 FOR_EACH_OPCODE_ID(ADD_OPCODE_ID);
883             #undef ADD_OPCODE
884             ASSERT(m_opcodeIDTable.size() == numOpcodeIDs);
885             op_throw_end_indirect = &&op_throw_end;
886             op_call_indirect = &&op_call;
887         #endif // HAVE(COMPUTED_GOTO)
888         return 0;
889     }
890
891     JSValue* exceptionValue = 0;
892     Instruction* handlerVPC = 0;
893
894     Register** registerBase = registerFile->basePointer();
895     Instruction* vPC = codeBlock->instructions.begin();
896     JSValue** k = codeBlock->jsValues.data();
897     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
898     
899     registerFile->setSafeForReentry(false);
900 #define VM_CHECK_EXCEPTION() \
901      do { \
902         if (UNLIKELY(exec->hadException())) { \
903             exceptionValue = exec->exception(); \
904             goto vm_throw; \
905         } \
906     } while (0)
907
908 #if DUMP_OPCODE_STATS
909     OpcodeStats::resetLastInstruction();
910 #endif
911     
912 #define CHECK_FOR_TIMEOUT() 
913     
914 #if HAVE(COMPUTED_GOTO)
915     #define NEXT_OPCODE goto *vPC->u.opcode
916 #if DUMP_OPCODE_STATS
917     #define BEGIN_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
918 #else
919     #define BEGIN_OPCODE(opcode) opcode:
920 #endif
921     NEXT_OPCODE;
922 #else
923     #define NEXT_OPCODE continue
924 #if DUMP_OPCODE_STATS
925     #define BEGIN_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
926 #else
927     #define BEGIN_OPCODE(opcode) case opcode:
928 #endif
929     while (1) // iterator loop begins
930     switch (vPC->u.opcode)
931 #endif
932     {
933     BEGIN_OPCODE(op_load) {
934         /* load dst(r) src(k)
935
936            Copies constant src to register dst.
937         */
938         int dst = (++vPC)->u.operand;
939         int src = (++vPC)->u.operand;
940         r[dst].u.jsValue = k[src];
941
942         ++vPC;
943         NEXT_OPCODE;
944     }
945     BEGIN_OPCODE(op_new_object) {
946         /* new_object dst(r)
947
948            Constructs a new empty Object instance using the original
949            constructor, and puts the result in register dst.
950         */
951         int dst = (++vPC)->u.operand;
952         r[dst].u.jsValue = constructEmptyObject(exec);
953
954         ++vPC;
955         NEXT_OPCODE;
956     }
957     BEGIN_OPCODE(op_new_array) {
958         /* new_array dst(r)
959
960            Constructs a new empty Array instance using the original
961            constructor, and puts the result in register dst.
962         */
963         int dst = (++vPC)->u.operand;
964         r[dst].u.jsValue = constructEmptyArray(exec);
965
966         ++vPC;
967         NEXT_OPCODE;
968     }
969     BEGIN_OPCODE(op_new_regexp) {
970         /* new_regexp dst(r) regExp(re)
971
972            Constructs a new RegExp instance using the original
973            constructor from regexp regExp, and puts the result in
974            register dst.
975         */
976         int dst = (++vPC)->u.operand;
977         int regExp = (++vPC)->u.operand;
978         r[dst].u.jsValue = new (exec) RegExpObject(scopeChain->globalObject()->regExpPrototype(), codeBlock->regexps[regExp]);
979
980         ++vPC;
981         NEXT_OPCODE;
982     }
983     BEGIN_OPCODE(op_mov) {
984         /* mov dst(r) src(r)
985
986            Copies register src to register dst.
987         */
988         int dst = (++vPC)->u.operand;
989         int src = (++vPC)->u.operand;
990         r[dst] = r[src];
991
992         ++vPC;
993         NEXT_OPCODE;
994     }
995     BEGIN_OPCODE(op_eq) {
996         /* eq dst(r) src1(r) src2(r)
997
998            Checks whether register src1 and register src2 are equal,
999            as with the ECMAScript '==' operator, and puts the result
1000            as a boolean in register dst.
1001         */
1002         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1003         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1004         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1005         JSValue* result;
1006         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1007             result = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1008         else {
1009             result = jsBoolean(equal(exec, src1, src2));
1010             VM_CHECK_EXCEPTION();
1011         }
1012         dst = result;
1013
1014         ++vPC;
1015         NEXT_OPCODE;
1016     }
1017     BEGIN_OPCODE(op_neq) {
1018         /* neq dst(r) src1(r) src2(r)
1019
1020            Checks whether register src1 and register src2 are not
1021            equal, as with the ECMAScript '!=' operator, and puts the
1022            result as a boolean in register dst.
1023         */
1024         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1025         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1026         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1027         JSValue* result;
1028         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1029             result = jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
1030         else {
1031             result = jsBoolean(!equal(exec, src1, src2));
1032             VM_CHECK_EXCEPTION();
1033         }
1034         dst = result;
1035
1036         ++vPC;
1037         NEXT_OPCODE;
1038     }
1039     BEGIN_OPCODE(op_stricteq) {
1040         /* stricteq dst(r) src1(r) src2(r)
1041
1042            Checks whether register src1 and register src2 are strictly
1043            equal, as with the ECMAScript '===' operator, and puts the
1044            result as a boolean in register dst.
1045         */
1046         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1047         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1048         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1049         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1050             dst = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1051         else
1052             dst = jsBoolean(strictEqual(src1, src2));
1053
1054         ++vPC;
1055         NEXT_OPCODE;
1056     }
1057     BEGIN_OPCODE(op_nstricteq) {
1058         /* nstricteq dst(r) src1(r) src2(r)
1059
1060            Checks whether register src1 and register src2 are not
1061            strictly equal, as with the ECMAScript '!==' operator, and
1062            puts the result as a boolean in register dst.
1063         */
1064         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1065         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1066         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1067         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1068             dst = jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
1069         else
1070             dst = jsBoolean(!strictEqual(src1, src2));
1071
1072         ++vPC;
1073         NEXT_OPCODE;
1074     }
1075     BEGIN_OPCODE(op_less) {
1076         /* less dst(r) src1(r) src2(r)
1077
1078            Checks whether register src1 is less than register src2, as
1079            with the ECMAScript '<' operator, and puts the result as
1080            a boolean in register dst.
1081         */
1082         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1083         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1084         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1085         JSValue* result = jsBoolean(jsLess(exec, src1, src2));
1086         VM_CHECK_EXCEPTION();
1087         dst = result;
1088
1089         ++vPC;
1090         NEXT_OPCODE;
1091     }
1092     BEGIN_OPCODE(op_lesseq) {
1093         /* lesseq dst(r) src1(r) src2(r)
1094
1095            Checks whether register src1 is less than or equal to
1096            register src2, as with the ECMAScript '<=' operator, and
1097            puts the result as a boolean in register dst.
1098         */
1099         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1100         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1101         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1102         JSValue* result = jsBoolean(jsLessEq(exec, src1, src2));
1103         VM_CHECK_EXCEPTION();
1104         dst = result;
1105
1106         ++vPC;
1107         NEXT_OPCODE;
1108     }
1109     BEGIN_OPCODE(op_pre_inc) {
1110         /* pre_inc srcDst(r)
1111
1112            Converts register srcDst to number, adds one, and puts the result
1113            back in register srcDst.
1114         */
1115         int srcDst = (++vPC)->u.operand;
1116         JSValue* v = r[srcDst].u.jsValue;
1117         JSValue* result;
1118         if (JSImmediate::canDoFastAdditiveOperations(v))
1119             result = JSImmediate::incImmediateNumber(v);
1120         else
1121             result = jsNumber(exec, v->toNumber(exec) + 1);
1122         VM_CHECK_EXCEPTION();
1123         r[srcDst].u.jsValue = result;
1124
1125         ++vPC;
1126         NEXT_OPCODE;
1127     }
1128     BEGIN_OPCODE(op_pre_dec) {
1129         /* pre_dec srcDst(r)
1130
1131            Converts register srcDst to number, subtracts one, and puts the result
1132            back in register srcDst.
1133         */
1134         int srcDst = (++vPC)->u.operand;
1135         JSValue* v = r[srcDst].u.jsValue;
1136         JSValue* result;
1137         if (JSImmediate::canDoFastAdditiveOperations(v))
1138             result = JSImmediate::decImmediateNumber(v);
1139         else
1140             result = jsNumber(exec, v->toNumber(exec) - 1);
1141         VM_CHECK_EXCEPTION();
1142         r[srcDst].u.jsValue = result;
1143
1144         ++vPC;
1145         NEXT_OPCODE;
1146     }
1147     BEGIN_OPCODE(op_post_inc) {
1148         /* post_inc dst(r) srcDst(r)
1149
1150            Converts register srcDst to number. The number itself is
1151            written to register dst, and the number plus one is written
1152            back to register srcDst.
1153         */
1154         int dst = (++vPC)->u.operand;
1155         int srcDst = (++vPC)->u.operand;
1156         JSValue* v = r[srcDst].u.jsValue;
1157         JSValue* result;
1158         JSValue* number;
1159         if (JSImmediate::canDoFastAdditiveOperations(v)) {
1160             number = v;
1161             result = JSImmediate::incImmediateNumber(v);
1162         } else {
1163             number = r[srcDst].u.jsValue->toJSNumber(exec);
1164             result = jsNumber(exec, number->uncheckedGetNumber() + 1);
1165         }
1166         VM_CHECK_EXCEPTION();
1167
1168         r[dst].u.jsValue = number;
1169         r[srcDst].u.jsValue = result;
1170
1171         ++vPC;
1172         NEXT_OPCODE;
1173     }
1174     BEGIN_OPCODE(op_post_dec) {
1175         /* post_dec dst(r) srcDst(r)
1176
1177            Converts register srcDst to number. The number itself is
1178            written to register dst, and the number minus one is written
1179            back to register srcDst.
1180         */
1181         int dst = (++vPC)->u.operand;
1182         int srcDst = (++vPC)->u.operand;
1183         JSValue* v = r[srcDst].u.jsValue;
1184         JSValue* result;
1185         JSValue* number;
1186         if (JSImmediate::canDoFastAdditiveOperations(v)) {
1187             number = v;
1188             result = JSImmediate::decImmediateNumber(v);
1189         } else {
1190             number = r[srcDst].u.jsValue->toJSNumber(exec);
1191             result = jsNumber(exec, number->uncheckedGetNumber() - 1);
1192         }
1193         VM_CHECK_EXCEPTION();
1194
1195         r[dst].u.jsValue = number;
1196         r[srcDst].u.jsValue = result;
1197
1198         ++vPC;
1199         NEXT_OPCODE;
1200     }
1201     BEGIN_OPCODE(op_to_jsnumber) {
1202         /* to_jsnumber dst(r) src(r)
1203
1204            Converts register src to number, and puts the result
1205            in register dst.
1206         */
1207         int dst = (++vPC)->u.operand;
1208         int src = (++vPC)->u.operand;
1209         JSValue* result = r[src].u.jsValue->toJSNumber(exec);
1210         VM_CHECK_EXCEPTION();
1211
1212         r[dst].u.jsValue = result;
1213
1214         ++vPC;
1215         NEXT_OPCODE;
1216     }
1217     BEGIN_OPCODE(op_negate) {
1218         /* negate dst(r) src(r)
1219
1220            Converts register src to number, negates it, and puts the
1221            result in register dst.
1222         */
1223         int dst = (++vPC)->u.operand;
1224         int src = (++vPC)->u.operand;
1225         JSValue* result = jsNumber(exec, -r[src].u.jsValue->toNumber(exec));
1226         VM_CHECK_EXCEPTION();
1227         r[dst].u.jsValue = result;
1228
1229         ++vPC;
1230         NEXT_OPCODE;
1231     }
1232     BEGIN_OPCODE(op_add) {
1233         /* add dst(r) src1(r) src2(r)
1234
1235            Adds register src1 and register src2, and puts the result
1236            in register dst. (JS add may be string concatenation or
1237            numeric add, depending on the types of the operands.)
1238         */
1239         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1240         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1241         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1242         JSValue* result;
1243         if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1244             result = JSImmediate::addImmediateNumbers(src1, src2);
1245         else {
1246             result = jsAdd(exec, src1, src2);
1247             VM_CHECK_EXCEPTION();
1248         }
1249         dst = result;
1250         ++vPC;
1251         NEXT_OPCODE;
1252     }
1253     BEGIN_OPCODE(op_mul) {
1254         /* mul dst(r) src1(r) src2(r)
1255
1256            Multiplies register src1 and register src2 (converted to
1257            numbers), and puts the product in register dst.
1258         */
1259         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1260         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1261         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1262         JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
1263         VM_CHECK_EXCEPTION();
1264         dst = result;
1265
1266         ++vPC;
1267         NEXT_OPCODE;
1268     }
1269     BEGIN_OPCODE(op_div) {
1270         /* div dst(r) dividend(r) divisor(r)
1271
1272            Divides register dividend (converted to number) by the
1273            register divisor (converted to number), and puts the
1274            quotient in register dst.
1275         */
1276         int dst = (++vPC)->u.operand;
1277         int dividend = (++vPC)->u.operand;
1278         int divisor = (++vPC)->u.operand;
1279         JSValue* result = jsNumber(exec, r[dividend].u.jsValue->toNumber(exec) / r[divisor].u.jsValue->toNumber(exec));
1280         VM_CHECK_EXCEPTION();
1281         r[dst].u.jsValue = result;
1282         ++vPC;
1283         NEXT_OPCODE;
1284     }
1285     BEGIN_OPCODE(op_mod) {
1286         /* mod dst(r) dividend(r) divisor(r)
1287
1288            Divides register dividend (converted to number) by
1289            register divisor (converted to number), and puts the
1290            remainder in register dst.
1291         */
1292         int dst = (++vPC)->u.operand;
1293         int dividend = (++vPC)->u.operand;
1294         int divisor = (++vPC)->u.operand;
1295         double d = r[dividend].u.jsValue->toNumber(exec);
1296         JSValue* result = jsNumber(exec, fmod(d, r[divisor].u.jsValue->toNumber(exec)));
1297         VM_CHECK_EXCEPTION();
1298         r[dst].u.jsValue = result;
1299         ++vPC;
1300         NEXT_OPCODE;
1301     }
1302     BEGIN_OPCODE(op_sub) {
1303         /* sub dst(r) src1(r) src2(r)
1304
1305            Subtracts register src2 (converted to number) from register
1306            src1 (converted to number), and puts the difference in
1307            register dst.
1308         */
1309         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1310         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1311         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1312         JSValue* result;
1313         if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1314             result = JSImmediate::subImmediateNumbers(src1, src2);
1315         else {
1316             result = jsNumber(exec, src1->toNumber(exec) - src2->toNumber(exec));
1317             VM_CHECK_EXCEPTION();
1318         }
1319         dst = result;
1320         ++vPC;
1321         NEXT_OPCODE;
1322     }
1323     BEGIN_OPCODE(op_lshift) {
1324         /* lshift dst(r) val(r) shift(r)
1325
1326            Performs left shift of register val (converted to int32) by
1327            register shift (converted to uint32), and puts the result
1328            in register dst.
1329         */
1330         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1331         JSValue* val = r[(++vPC)->u.operand].u.jsValue;
1332         JSValue* shift = r[(++vPC)->u.operand].u.jsValue;
1333         JSValue* result;
1334         if (JSImmediate::areBothImmediateNumbers(val, shift))
1335             result = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::toTruncatedUInt32(shift) & 0x1f));
1336         else {
1337             result = jsNumber(exec, (val->toInt32(exec)) << (shift->toUInt32(exec) & 0x1f));
1338             VM_CHECK_EXCEPTION();
1339         }
1340         dst = result;
1341
1342         ++vPC;
1343         NEXT_OPCODE;
1344     }
1345     BEGIN_OPCODE(op_rshift) {
1346         /* rshift dst(r) val(r) shift(r)
1347
1348            Performs arithmetic right shift of register val (converted
1349            to int32) by register shift (converted to
1350            uint32), and puts the result in register dst.
1351         */
1352         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1353         JSValue* val = r[(++vPC)->u.operand].u.jsValue;
1354         JSValue* shift = r[(++vPC)->u.operand].u.jsValue;
1355         JSValue* result;
1356         if (JSImmediate::areBothImmediateNumbers(val, shift))
1357             result = JSImmediate::rightShiftImmediateNumbers(val, shift);
1358         else {
1359             result = jsNumber(exec, (val->toInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1360             VM_CHECK_EXCEPTION();
1361         }
1362         dst = result;
1363
1364         ++vPC;
1365         NEXT_OPCODE;
1366     }
1367     BEGIN_OPCODE(op_urshift) {
1368         /* rshift dst(r) val(r) shift(r)
1369
1370            Performs logical right shift of register val (converted
1371            to uint32) by register shift (converted to
1372            uint32), and puts the result in register dst.
1373         */
1374         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1375         JSValue* val = r[(++vPC)->u.operand].u.jsValue;
1376         JSValue* shift = r[(++vPC)->u.operand].u.jsValue;
1377         JSValue* result;
1378         if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val))
1379             result = JSImmediate::rightShiftImmediateNumbers(val, shift);
1380         else {
1381             result = jsNumber(exec, (val->toUInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1382             VM_CHECK_EXCEPTION();
1383         }
1384         dst = result;
1385
1386         ++vPC;
1387         NEXT_OPCODE;
1388     }
1389     BEGIN_OPCODE(op_bitand) {
1390         /* bitand dst(r) src1(r) src2(r)
1391
1392            Computes bitwise AND of register src1 (converted to int32)
1393            and register src2 (converted to int32), and puts the result
1394            in register dst.
1395         */
1396         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1397         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1398         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1399         JSValue* result;
1400         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1401             result = JSImmediate::andImmediateNumbers(src1, src2);
1402         else {
1403             result = jsNumber(exec, src1->toInt32(exec) & src2->toInt32(exec));
1404             VM_CHECK_EXCEPTION();
1405         }
1406         dst = result;
1407
1408         ++vPC;
1409         NEXT_OPCODE;
1410     }
1411     BEGIN_OPCODE(op_bitxor) {
1412         /* bitxor dst(r) src1(r) src2(r)
1413
1414            Computes bitwise XOR of register src1 (converted to int32)
1415            and register src2 (converted to int32), and puts the result
1416            in register dst.
1417         */
1418         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1419         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1420         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1421         JSValue* result;
1422         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1423             result = JSImmediate::xorImmediateNumbers(src1, src2);
1424         else {
1425             result = jsNumber(exec, src1->toInt32(exec) ^ src2->toInt32(exec));
1426             VM_CHECK_EXCEPTION();
1427         }
1428         dst = result;
1429
1430         ++vPC;
1431         NEXT_OPCODE;
1432     }
1433     BEGIN_OPCODE(op_bitor) {
1434         /* bitor dst(r) src1(r) src2(r)
1435
1436            Computes bitwise OR of register src1 (converted to int32)
1437            and register src2 (converted to int32), and puts the
1438            result in register dst.
1439         */
1440         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1441         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1442         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1443         JSValue* result;
1444         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1445             result = JSImmediate::orImmediateNumbers(src1, src2);
1446         else {
1447             result = jsNumber(exec, src1->toInt32(exec) | src2->toInt32(exec));
1448             VM_CHECK_EXCEPTION();
1449         }
1450         dst = result;
1451
1452         ++vPC;
1453         NEXT_OPCODE;
1454     }
1455     BEGIN_OPCODE(op_bitnot) {
1456         /* bitnot dst(r) src(r)
1457
1458            Computes bitwise NOT of register src1 (converted to int32),
1459            and puts the result in register dst.
1460         */
1461         int dst = (++vPC)->u.operand;
1462         int src = (++vPC)->u.operand;
1463         JSValue* result = jsNumber(exec, ~r[src].u.jsValue->toInt32(exec));
1464         VM_CHECK_EXCEPTION();
1465         r[dst].u.jsValue = result;
1466
1467         ++vPC;
1468         NEXT_OPCODE;
1469     }
1470     BEGIN_OPCODE(op_not) {
1471         /* not dst(r) src1(r) src2(r)
1472
1473            Computes logical NOT of register src1 (converted to
1474            boolean), and puts the result in register dst.
1475         */
1476         int dst = (++vPC)->u.operand;
1477         int src = (++vPC)->u.operand;
1478         JSValue* result = jsBoolean(!r[src].u.jsValue->toBoolean(exec));
1479         VM_CHECK_EXCEPTION();
1480         r[dst].u.jsValue = result;
1481
1482         ++vPC;
1483         NEXT_OPCODE;
1484     }
1485     BEGIN_OPCODE(op_instanceof) {
1486         /* instanceof dst(r) value(r) constructor(r)
1487
1488            Tests whether register value is an instance of register
1489            constructor, and puts the boolean result in register dst.
1490
1491            Raises an exception if register constructor is not an
1492            object.
1493         */
1494         int dst = (++vPC)->u.operand;
1495         int value = (++vPC)->u.operand;
1496         int base = (++vPC)->u.operand;
1497
1498         JSValue* baseVal = r[base].u.jsValue;
1499
1500         if (isNotObject(exec, vPC, codeBlock, baseVal, exceptionValue))
1501             goto vm_throw;
1502
1503         JSObject* baseObj = static_cast<JSObject*>(baseVal);
1504         r[dst].u.jsValue = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, r[value].u.jsValue) : false);
1505
1506         ++vPC;
1507         NEXT_OPCODE;
1508     }
1509     BEGIN_OPCODE(op_typeof) {
1510         /* typeof dst(r) src(r)
1511
1512            Determines the type string for src according to ECMAScript
1513            rules, and puts the result in register dst.
1514         */
1515         int dst = (++vPC)->u.operand;
1516         int src = (++vPC)->u.operand;
1517         r[dst].u.jsValue = jsTypeStringForValue(exec, r[src].u.jsValue);
1518
1519         ++vPC;
1520         NEXT_OPCODE;
1521     }
1522     BEGIN_OPCODE(op_in) {
1523         /* in dst(r) property(r) base(r)
1524
1525            Tests whether register base has a property named register
1526            property, and puts the boolean result in register dst.
1527
1528            Raises an exception if register constructor is not an
1529            object.
1530         */
1531         int dst = (++vPC)->u.operand;
1532         int property = (++vPC)->u.operand;
1533         int base = (++vPC)->u.operand;
1534
1535         JSValue* baseVal = r[base].u.jsValue;
1536         if (isNotObject(exec, vPC, codeBlock, baseVal, exceptionValue))
1537             goto vm_throw;
1538
1539         JSObject* baseObj = static_cast<JSObject*>(baseVal);
1540
1541         JSValue* propName = r[property].u.jsValue;
1542
1543         uint32_t i;
1544         if (propName->getUInt32(i))
1545             r[dst].u.jsValue = jsBoolean(baseObj->hasProperty(exec, i));
1546         else {
1547             Identifier property(exec, propName->toString(exec));
1548             VM_CHECK_EXCEPTION();
1549             r[dst].u.jsValue = jsBoolean(baseObj->hasProperty(exec, property));
1550         }
1551
1552         ++vPC;
1553         NEXT_OPCODE;
1554     }
1555     BEGIN_OPCODE(op_resolve) {
1556         /* resolve dst(r) property(id)
1557
1558            Looks up the property named by identifier property in the
1559            scope chain, and writes the resulting value to register
1560            dst. If the property is not found, raises an exception.
1561         */
1562         if (UNLIKELY(!resolve(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1563             goto vm_throw;
1564
1565         vPC += 3;
1566         NEXT_OPCODE;
1567     }
1568     BEGIN_OPCODE(op_resolve_skip) {
1569         /* resolve_skip dst(r) property(id) skip(n)
1570
1571          Looks up the property named by identifier property in the
1572          scope chain skipping the top 'skip' levels, and writes the resulting
1573          value to register dst. If the property is not found, raises an exception.
1574          */
1575         if (UNLIKELY(!resolve_skip(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1576             goto vm_throw;
1577
1578         vPC += 4;
1579
1580         NEXT_OPCODE;
1581     }
1582     BEGIN_OPCODE(op_get_scoped_var) {
1583         /* get_scoped_var dst(r) index(n) skip(n)
1584
1585          Loads the contents of the index-th local from the scope skip nodes from
1586          the top of the scope chain, and places it in register dst
1587          */
1588         int dst = (++vPC)->u.operand;
1589         int index = (++vPC)->u.operand;
1590         int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
1591
1592         ScopeChainIterator iter = scopeChain->begin();
1593         ScopeChainIterator end = scopeChain->end();
1594         ASSERT(iter != end);
1595         while (skip--) {
1596             ++iter;
1597             ASSERT(iter != end);
1598         }
1599
1600         ASSERT((*iter)->isVariableObject());
1601         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1602         r[dst].u.jsValue = scope->valueAt(index);
1603         ++vPC;
1604         NEXT_OPCODE;
1605     }
1606     BEGIN_OPCODE(op_put_scoped_var) {
1607         /* put_scoped_var index(n) skip(n) value(r)
1608
1609          */
1610         int index = (++vPC)->u.operand;
1611         int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
1612         int value = (++vPC)->u.operand;
1613
1614         ScopeChainIterator iter = scopeChain->begin();
1615         ScopeChainIterator end = scopeChain->end();
1616         ASSERT(iter != end);
1617         while (skip--) {
1618             ++iter;
1619             ASSERT(iter != end);
1620         }
1621
1622         ASSERT((*iter)->isVariableObject());
1623         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1624         scope->valueAt(index) = r[value].u.jsValue;
1625         ++vPC;
1626         NEXT_OPCODE;
1627     }
1628     BEGIN_OPCODE(op_resolve_base) {
1629         /* resolve_base dst(r) property(id)
1630
1631            Searches the scope chain for an object containing
1632            identifier property, and if one is found, writes it to
1633            register dst. If none is found, the outermost scope (which
1634            will be the global object) is stored in register dst.
1635         */
1636         resolveBase(exec, vPC, r, scopeChain, codeBlock);
1637
1638         vPC += 3;
1639         NEXT_OPCODE;
1640     }
1641     BEGIN_OPCODE(op_resolve_with_base) {
1642         /* resolve_with_base baseDst(r) propDst(r) property(id)
1643
1644            Searches the scope chain for an object containing
1645            identifier property, and if one is found, writes it to
1646            register srcDst, and the retrieved property value to register
1647            propDst. If the property is not found, raises an exception.
1648
1649            This is more efficient than doing resolve_base followed by
1650            resolve, or resolve_base followed by get_by_id, as it
1651            avoids duplicate hash lookups.
1652         */
1653         if (UNLIKELY(!resolveBaseAndProperty(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1654             goto vm_throw;
1655
1656         vPC += 4;
1657         NEXT_OPCODE;
1658     }
1659     BEGIN_OPCODE(op_resolve_func) {
1660         /* resolve_func baseDst(r) funcDst(r) property(id)
1661
1662            Searches the scope chain for an object containing
1663            identifier property, and if one is found, writes the
1664            appropriate object to use as "this" when calling its
1665            properties to register baseDst; and the retrieved property
1666            value to register propDst. If the property is not found,
1667            raises an exception.
1668
1669            This differs from resolve_with_base, because the
1670            global this value will be substituted for activations or
1671            the global object, which is the right behavior for function
1672            calls but not for other property lookup.
1673         */
1674         if (UNLIKELY(!resolveBaseAndFunc(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1675             goto vm_throw;
1676
1677         vPC += 4;
1678         NEXT_OPCODE;
1679     }
1680     BEGIN_OPCODE(op_get_by_id) {
1681         /* get_by_id dst(r) base(r) property(id)
1682
1683            Converts register base to Object, gets the property
1684            named by identifier property from the object, and puts the
1685            result in register dst.
1686         */
1687         int dst = (++vPC)->u.operand;
1688         int base = (++vPC)->u.operand;
1689         int property = (++vPC)->u.operand;
1690 #ifndef NDEBUG
1691         int registerOffset = r - (*registerBase);
1692 #endif
1693
1694         Identifier& ident = codeBlock->identifiers[property];
1695         JSValue *result = r[base].u.jsValue->get(exec, ident);
1696         ASSERT(registerOffset == (r - (*registerBase)));
1697         VM_CHECK_EXCEPTION();
1698         r[dst].u.jsValue = result;
1699         ++vPC;
1700         NEXT_OPCODE;
1701     }
1702     BEGIN_OPCODE(op_put_by_id) {
1703         /* put_by_id base(r) property(id) value(r)
1704
1705            Sets register value on register base as the property named
1706            by identifier property. Base is converted to object first.
1707
1708            Unlike many opcodes, this one does not write any output to
1709            the register file.
1710         */
1711         int base = (++vPC)->u.operand;
1712         int property = (++vPC)->u.operand;
1713         int value = (++vPC)->u.operand;
1714 #ifndef NDEBUG
1715         int registerOffset = r - (*registerBase);
1716 #endif
1717
1718         Identifier& ident = codeBlock->identifiers[property];
1719         r[base].u.jsValue->put(exec, ident, r[value].u.jsValue);
1720         ASSERT(registerOffset == (r - (*registerBase)));
1721
1722         VM_CHECK_EXCEPTION();
1723         ++vPC;
1724         NEXT_OPCODE;
1725     }
1726     BEGIN_OPCODE(op_del_by_id) {
1727         /* del_by_id dst(r) base(r) property(id)
1728
1729            Converts register base to Object, deletes the property
1730            named by identifier property from the object, and writes a
1731            boolean indicating success (if true) or failure (if false)
1732            to register dst.
1733         */
1734         int dst = (++vPC)->u.operand;
1735         int base = (++vPC)->u.operand;
1736         int property = (++vPC)->u.operand;
1737
1738         JSObject* baseObj = r[base].u.jsValue->toObject(exec);
1739
1740         Identifier& ident = codeBlock->identifiers[property];
1741         JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
1742         VM_CHECK_EXCEPTION();
1743         r[dst].u.jsValue = result;
1744         ++vPC;
1745         NEXT_OPCODE;
1746     }
1747     BEGIN_OPCODE(op_get_by_val) {
1748         /* get_by_val dst(r) base(r) property(r)
1749
1750            Converts register base to Object, gets the property named
1751            by register property from the object, and puts the result
1752            in register dst. property is nominally converted to string
1753            but numbers are treated more efficiently.
1754         */
1755         int dst = (++vPC)->u.operand;
1756         int base = (++vPC)->u.operand;
1757         int property = (++vPC)->u.operand;
1758
1759         JSValue* baseValue = r[base].u.jsValue;
1760
1761         JSValue* subscript = r[property].u.jsValue;
1762         JSValue* result;
1763         uint32_t i;
1764         if (subscript->getUInt32(i))
1765             result = baseValue->get(exec, i);
1766         else {
1767             JSObject* baseObj = baseValue->toObject(exec); // may throw
1768         
1769             Identifier property;
1770             if (subscript->isObject()) {
1771                 VM_CHECK_EXCEPTION(); // If toObject threw, we must not call toString, which may execute arbitrary code
1772                 property = Identifier(exec, subscript->toString(exec));
1773             } else
1774                 property = Identifier(exec, subscript->toString(exec));
1775
1776             VM_CHECK_EXCEPTION(); // This check is needed to prevent us from incorrectly calling a getter after an exception is thrown
1777             result = baseObj->get(exec, property);
1778         }
1779
1780         VM_CHECK_EXCEPTION();
1781         r[dst].u.jsValue = result;
1782         ++vPC;
1783         NEXT_OPCODE;
1784     }
1785     BEGIN_OPCODE(op_put_by_val) {
1786         /* put_by_val base(r) property(r) value(r)
1787
1788            Sets register value on register base as the property named
1789            by register property. Base is converted to object
1790            first. register property is nominally converted to string
1791            but numbers are treated more efficiently.
1792
1793            Unlike many opcodes, this one does not write any output to
1794            the register file.
1795         */
1796         int base = (++vPC)->u.operand;
1797         int property = (++vPC)->u.operand;
1798         int value = (++vPC)->u.operand;
1799
1800         JSValue* baseValue = r[base].u.jsValue;
1801
1802         JSValue* subscript = r[property].u.jsValue;
1803
1804         uint32_t i;
1805         if (subscript->getUInt32(i))
1806             baseValue->put(exec, i, r[value].u.jsValue);
1807         else {
1808             JSObject* baseObj = baseValue->toObject(exec);
1809
1810             Identifier property;
1811             if (subscript->isObject()) {
1812                 VM_CHECK_EXCEPTION(); // If toObject threw, we must not call toString, which may execute arbitrary code
1813                 property = Identifier(exec, subscript->toString(exec));
1814             } else
1815                 property = Identifier(exec, subscript->toString(exec));
1816
1817             VM_CHECK_EXCEPTION(); // This check is needed to prevent us from incorrectly calling a setter after an exception is thrown
1818             baseObj->put(exec, property, r[value].u.jsValue);
1819         }
1820
1821         VM_CHECK_EXCEPTION();
1822         ++vPC;
1823         NEXT_OPCODE;
1824     }
1825     BEGIN_OPCODE(op_del_by_val) {
1826         /* del_by_val dst(r) base(r) property(r)
1827
1828            Converts register base to Object, deletes the property
1829            named by register property from the object, and writes a
1830            boolean indicating success (if true) or failure (if false)
1831            to register dst.
1832         */
1833         int dst = (++vPC)->u.operand;
1834         int base = (++vPC)->u.operand;
1835         int property = (++vPC)->u.operand;
1836
1837         JSObject* baseObj = r[base].u.jsValue->toObject(exec); // may throw
1838
1839         JSValue* subscript = r[property].u.jsValue;
1840         JSValue* result;
1841         uint32_t i;
1842         if (subscript->getUInt32(i))
1843             result = jsBoolean(baseObj->deleteProperty(exec, i));
1844         else {
1845             VM_CHECK_EXCEPTION(); // If toObject threw, we must not call toString, which may execute arbitrary code
1846             Identifier property(exec, subscript->toString(exec));
1847             VM_CHECK_EXCEPTION();
1848             result = jsBoolean(baseObj->deleteProperty(exec, property));
1849         }
1850
1851         VM_CHECK_EXCEPTION();
1852         r[dst].u.jsValue = result;
1853         ++vPC;
1854         NEXT_OPCODE;
1855     }
1856     BEGIN_OPCODE(op_put_by_index) {
1857         /* put_by_index base(r) property(n) value(r)
1858
1859            Sets register value on register base as the property named
1860            by the immediate number property. Base is converted to
1861            object first. register property is nominally converted to
1862            string but numbers are treated more efficiently.
1863
1864            Unlike many opcodes, this one does not write any output to
1865            the register file.
1866
1867            This opcode is mainly used to initialize array literals.
1868         */
1869         int base = (++vPC)->u.operand;
1870         unsigned property = (++vPC)->u.operand;
1871         int value = (++vPC)->u.operand;
1872
1873         r[base].u.jsObject->put(exec, property, r[value].u.jsValue);
1874
1875         ++vPC;
1876         NEXT_OPCODE;
1877     }
1878     BEGIN_OPCODE(op_jmp) {
1879         /* jmp target(offset)
1880
1881            Jumps unconditionally to offset target from the current
1882            instruction.
1883         */
1884 #if DUMP_OPCODE_STATS
1885         OpcodeStats::resetLastInstruction();
1886 #endif
1887         int target = (++vPC)->u.operand;
1888
1889         vPC += target;
1890         NEXT_OPCODE;
1891     }
1892     BEGIN_OPCODE(op_loop_if_true) {
1893         /* loop_if_true cond(r) target(offset)
1894          
1895            Jumps to offset target from the current instruction, if and
1896            only if register cond converts to boolean as true.
1897
1898            Additionally this loop instruction may terminate JS execution is
1899            the JS timeout is reached.
1900          */
1901         int cond = (++vPC)->u.operand;
1902         int target = (++vPC)->u.operand;
1903         if (r[cond].u.jsValue->toBoolean(exec)) {
1904             vPC += target;
1905             CHECK_FOR_TIMEOUT();
1906             NEXT_OPCODE;
1907         }
1908         
1909         ++vPC;
1910         NEXT_OPCODE;
1911     }
1912     BEGIN_OPCODE(op_jtrue) {
1913         /* jtrue cond(r) target(offset)
1914
1915            Jumps to offset target from the current instruction, if and
1916            only if register cond converts to boolean as true.
1917         */
1918         int cond = (++vPC)->u.operand;
1919         int target = (++vPC)->u.operand;
1920         if (r[cond].u.jsValue->toBoolean(exec)) {
1921             vPC += target;
1922             NEXT_OPCODE;
1923         }
1924
1925         ++vPC;
1926         NEXT_OPCODE;
1927     }
1928     BEGIN_OPCODE(op_jfalse) {
1929         /* jfalse cond(r) target(offset)
1930
1931            Jumps to offset target from the current instruction, if and
1932            only if register cond converts to boolean as false.
1933         */
1934         int cond = (++vPC)->u.operand;
1935         int target = (++vPC)->u.operand;
1936         if (!r[cond].u.jsValue->toBoolean(exec)) {
1937             vPC += target;
1938             NEXT_OPCODE;
1939         }
1940
1941         ++vPC;
1942         NEXT_OPCODE;
1943     }
1944     BEGIN_OPCODE(op_loop_if_less) {
1945         /* loop_if_less src1(r) src2(r) target(offset)
1946
1947            Checks whether register src1 is less than register src2, as
1948            with the ECMAScript '<' operator, and then jumps to offset
1949            target from the current instruction, if and only if the 
1950            result of the comparison is true.
1951
1952            Additionally this loop instruction may terminate JS execution is
1953            the JS timeout is reached.
1954          */
1955         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1956         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1957         int target = (++vPC)->u.operand;
1958         
1959         bool result = jsLess(exec, src1, src2);
1960         VM_CHECK_EXCEPTION();
1961         
1962         if (result) {
1963             vPC += target;
1964             CHECK_FOR_TIMEOUT();
1965             NEXT_OPCODE;
1966         }
1967         
1968         ++vPC;
1969         NEXT_OPCODE;
1970     }
1971     BEGIN_OPCODE(op_jless) {
1972         /* jless src1(r) src2(r) target(offset)
1973
1974            Checks whether register src1 is less than register src2, as
1975            with the ECMAScript '<' operator, and then jumps to offset
1976            target from the current instruction, if and only if the 
1977            result of the comparison is true.
1978         */
1979         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1980         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1981         int target = (++vPC)->u.operand;
1982
1983         bool result = jsLess(exec, src1, src2);
1984         VM_CHECK_EXCEPTION();
1985         
1986         if (result) {
1987             vPC += target;
1988             NEXT_OPCODE;
1989         }
1990
1991         ++vPC;
1992         NEXT_OPCODE;
1993     }
1994     BEGIN_OPCODE(op_new_func) {
1995         /* new_func dst(r) func(f)
1996
1997            Constructs a new Function instance from function func and
1998            the current scope chain using the original Function
1999            constructor, using the rules for function declarations, and
2000            puts the result in register dst.
2001         */
2002         int dst = (++vPC)->u.operand;
2003         int func = (++vPC)->u.operand;
2004
2005         r[dst].u.jsValue = codeBlock->functions[func]->makeFunction(exec, scopeChain);
2006
2007         ++vPC;
2008         NEXT_OPCODE;
2009     }
2010     BEGIN_OPCODE(op_new_func_exp) {
2011         /* new_func_exp dst(r) func(f)
2012
2013            Constructs a new Function instance from function func and
2014            the current scope chain using the original Function
2015            constructor, using the rules for function expressions, and
2016            puts the result in register dst.
2017         */
2018         int dst = (++vPC)->u.operand;
2019         int func = (++vPC)->u.operand;
2020
2021         r[dst].u.jsValue = codeBlock->functionExpressions[func]->makeFunction(exec, scopeChain);
2022
2023         ++vPC;
2024         NEXT_OPCODE;
2025     }
2026     BEGIN_OPCODE(op_call_eval) {
2027         /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2028
2029            Call a function named "eval" with no explicit "this" value
2030            (which may therefore be the eval operator). If register
2031            thisVal is the global object, and register func contains
2032            that global object's original global eval function, then
2033            perform the eval operator in local scope (interpreting
2034            the argument registers as for the "call"
2035            opcode). Otherwise, act exacty as the "call" opcode.
2036          */
2037
2038         int dst = (++vPC)->u.operand;
2039         int func = (++vPC)->u.operand;
2040         int thisVal = (++vPC)->u.operand;
2041         int firstArg = (++vPC)->u.operand;
2042         int argCount = (++vPC)->u.operand;
2043
2044         JSValue* funcVal = r[func].u.jsValue;
2045         JSValue* baseVal = r[thisVal].u.jsValue;
2046
2047         if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
2048             int registerOffset = r - (*registerBase);
2049
2050             JSObject* thisObject = r[codeBlock->thisRegister].u.jsObject;
2051
2052             registerFile->setSafeForReentry(true);
2053
2054             JSValue* result = callEval(exec, thisObject, scopeChain, registerFile, r, firstArg, argCount, exceptionValue);
2055
2056             registerFile->setSafeForReentry(false);
2057             r = (*registerBase) + registerOffset;
2058
2059             if (exceptionValue)
2060                 goto vm_throw;
2061
2062             r[dst].u.jsValue = result;
2063
2064             ++vPC;
2065             NEXT_OPCODE;
2066         }
2067
2068         // We didn't find the blessed version of eval, so reset vPC and process
2069         // this instruction as a normal function call, supplying the proper 'this'
2070         // value.
2071         vPC -= 5;
2072         r[thisVal].u.jsValue = baseVal->toThisObject(exec);
2073
2074 #if HAVE(COMPUTED_GOTO)
2075         // Hack around gcc performance quirk by performing an indirect goto
2076         // in order to set the vPC -- attempting to do so directly results in a
2077         // significant regression.
2078         goto *op_call_indirect; // indirect goto -> op_call
2079 #endif
2080         // fall through to op_call
2081     }
2082     BEGIN_OPCODE(op_call) {
2083         /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2084
2085            Perform a function call. Specifically, call register func
2086            with a "this" value of register thisVal, and put the result
2087            in register dst.
2088
2089            The arguments start at register firstArg and go up to
2090            argCount, but the "this" value is considered an implicit
2091            first argument, so the argCount should be one greater than
2092            the number of explicit arguments passed, and the register
2093            after firstArg should contain the actual first
2094            argument. This opcode will copy from the thisVal register
2095            to the firstArg register, unless the register index of
2096            thisVal is the special missing this object marker, which is
2097            2^31-1; in that case, the global object will be used as the
2098            "this" value.
2099
2100            If func is a native code function, then this opcode calls
2101            it and returns the value immediately. 
2102
2103            But if it is a JS function, then the current scope chain
2104            and code block is set to the function's, and we slide the
2105            register window so that the arguments would form the first
2106            few local registers of the called function's register
2107            window. In addition, a call frame header is written
2108            immediately before the arguments; see the call frame
2109            documentation for an explanation of how many registers a
2110            call frame takes and what they contain. That many registers
2111            before the firstArg register will be overwritten by the
2112            call. In addition, any registers higher than firstArg +
2113            argCount may be overwritten. Once this setup is complete,
2114            execution continues from the called function's first
2115            argument, and does not return until a "ret" opcode is
2116            encountered.
2117          */
2118
2119         int dst = (++vPC)->u.operand;
2120         int func = (++vPC)->u.operand;
2121         int thisVal = (++vPC)->u.operand;
2122         int firstArg = (++vPC)->u.operand;
2123         int argCount = (++vPC)->u.operand;
2124
2125         JSValue* v = r[func].u.jsValue;
2126
2127         CallData callData;
2128         CallType callType = v->getCallData(callData);
2129
2130         if (callType == CallTypeJS) {
2131             if (*enabledProfilerReference)
2132                 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
2133             int registerOffset = r - (*registerBase);
2134             Register* callFrame = r + firstArg - CallFrameHeaderSize;
2135             int callFrameOffset = registerOffset + firstArg - CallFrameHeaderSize;
2136
2137             r[firstArg].u.jsValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].u.jsValue;
2138             initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, registerOffset, dst, firstArg, argCount, 0, v);
2139
2140             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
2141             FunctionBodyNode* functionBodyNode = callData.js.functionBody;
2142
2143             CodeBlock* newCodeBlock = &functionBodyNode->code(callDataScopeChain);
2144             r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, registerOffset, firstArg, argCount, exceptionValue);
2145             if (UNLIKELY(exceptionValue != 0))
2146                 goto vm_throw;
2147
2148             codeBlock = newCodeBlock;
2149             exec->m_callFrameOffset = callFrameOffset;
2150             setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, registerBase, r));
2151             k = codeBlock->jsValues.data();
2152             vPC = codeBlock->instructions.begin();
2153
2154 #if DUMP_OPCODE_STATS
2155             OpcodeStats::resetLastInstruction();
2156 #endif
2157             
2158             NEXT_OPCODE;
2159         }
2160
2161         if (callType == CallTypeNative) {
2162             if (*enabledProfilerReference)
2163                 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
2164             int registerOffset = r - (*registerBase);
2165
2166             r[firstArg].u.jsValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : (r[thisVal].u.jsValue)->toObject(exec);
2167             JSValue* thisValue = r[firstArg].u.jsValue;
2168
2169             ArgList args(reinterpret_cast<JSValue***>(registerBase), registerOffset + firstArg + 1, argCount - 1);
2170
2171             registerFile->setSafeForReentry(true);
2172             JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(v), thisValue, args);
2173             registerFile->setSafeForReentry(false);
2174
2175             r = (*registerBase) + registerOffset;
2176             r[dst].u.jsValue = returnValue;
2177
2178             if (*enabledProfilerReference)
2179                 (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(v));
2180             VM_CHECK_EXCEPTION();
2181
2182             ++vPC;
2183             NEXT_OPCODE;
2184         }
2185
2186         ASSERT(callType == CallTypeNone);
2187
2188         exceptionValue = createNotAFunctionError(exec, v, 0);
2189         goto vm_throw;
2190     }
2191     BEGIN_OPCODE(op_ret) {
2192         /* ret result(r)
2193            
2194            Return register result as the return value of the current
2195            function call, writing it into the caller's expected return
2196            value register. In addition, unwind one call frame and
2197            restore the scope chain, code block instruction pointer and
2198            register base to those of the calling function.
2199         */
2200            
2201         int result = (++vPC)->u.operand;
2202
2203         CodeBlock* oldCodeBlock = codeBlock;
2204
2205         Register* callFrame = r - oldCodeBlock->numLocals - CallFrameHeaderSize;
2206         JSValue* returnValue = r[result].u.jsValue;
2207
2208         if (JSActivation* activation = static_cast<JSActivation*>(callFrame[OptionalCalleeActivation].u.jsValue)) {
2209             ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
2210             ASSERT(activation->isActivationObject());
2211             activation->copyRegisters();
2212         }
2213
2214         if (*enabledProfilerReference)
2215             (*enabledProfilerReference)->didExecute(exec, callFrame[Callee].u.jsObject);
2216
2217         if (codeBlock->needsFullScopeChain)
2218             scopeChain->deref();
2219
2220         if (callFrame[CalledAsConstructor].u.i && !returnValue->isObject()) {
2221             JSValue* thisObject = callFrame[CallFrameHeaderSize].u.jsValue;
2222             returnValue = thisObject;
2223         }
2224
2225         codeBlock = callFrame[CallerCodeBlock].u.codeBlock;
2226         if (!codeBlock)
2227             return returnValue;
2228
2229         k = codeBlock->jsValues.data();
2230         vPC = callFrame[ReturnVPC].u.vPC;
2231         setScopeChain(exec, scopeChain, callFrame[CallerScopeChain].u.scopeChain);
2232         int callerRegisterOffset = callFrame[CallerRegisterOffset].u.i;
2233         r = (*registerBase) + callerRegisterOffset;
2234         exec->m_callFrameOffset = callerRegisterOffset - codeBlock->numLocals - CallFrameHeaderSize;
2235         int dst = callFrame[ReturnValueRegister].u.i;
2236         r[dst].u.jsValue = returnValue;
2237
2238         NEXT_OPCODE;
2239     }
2240     BEGIN_OPCODE(op_construct) {
2241         /* construct dst(r) constr(r) firstArg(r) argCount(n)
2242
2243            Invoke register "constr" as a constructor. For JS
2244            functions, the calling convention is exactly as for the
2245            "call" opcode, except that the "this" value is a newly
2246            created Object. For native constructors, a null "this"
2247            value is passed. In either case, the firstArg and argCount
2248            registers are interpreted as for the "call" opcode.
2249         */
2250
2251         int dst = (++vPC)->u.operand;
2252         int constr = (++vPC)->u.operand;
2253         int firstArg = (++vPC)->u.operand;
2254         int argCount = (++vPC)->u.operand;
2255
2256         JSValue* constrVal = r[constr].u.jsValue;
2257
2258         ConstructData constructData;
2259         ConstructType constructType = constrVal->getConstructData(constructData);
2260
2261         // Removing this line of code causes a measurable regression on squirrelfish.
2262         JSObject* constructor = static_cast<JSObject*>(constrVal);
2263
2264         if (constructType == ConstructTypeJS) {
2265             if (*enabledProfilerReference)
2266                 (*enabledProfilerReference)->willExecute(exec, constructor);
2267
2268             int registerOffset = r - (*registerBase);
2269             Register* callFrame = r + firstArg - CallFrameHeaderSize;
2270             int callFrameOffset = registerOffset + firstArg - CallFrameHeaderSize;
2271
2272             JSObject* prototype;
2273             JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
2274             if (p->isObject())
2275                 prototype = static_cast<JSObject*>(p);
2276             else
2277                 prototype = scopeChain->globalObject()->objectPrototype();
2278             JSObject* newObject = new (exec) JSObject(prototype);
2279             r[firstArg].u.jsValue = newObject; // "this" value
2280
2281             initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, registerOffset, dst, firstArg, argCount, 1, constructor);
2282
2283             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
2284             FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
2285
2286             CodeBlock* newCodeBlock = &functionBodyNode->code(callDataScopeChain);
2287             r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, registerOffset, firstArg, argCount, exceptionValue);
2288             if (exceptionValue)
2289                 goto vm_throw;
2290
2291             codeBlock = newCodeBlock;
2292             exec->m_callFrameOffset = callFrameOffset;
2293             setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, registerBase, r));
2294             k = codeBlock->jsValues.data();
2295             vPC = codeBlock->instructions.begin();
2296
2297             NEXT_OPCODE;
2298         }
2299
2300         if (constructType == ConstructTypeNative) {
2301             if (*enabledProfilerReference)
2302                 (*enabledProfilerReference)->willExecute(exec, constructor);
2303
2304             int registerOffset = r - (*registerBase);
2305
2306             ArgList args(reinterpret_cast<JSValue***>(registerBase), registerOffset + firstArg + 1, argCount - 1);
2307
2308             registerFile->setSafeForReentry(true);
2309             JSValue* returnValue = constructData.native.function(exec, constructor, args);
2310             registerFile->setSafeForReentry(false);
2311
2312             r = (*registerBase) + registerOffset;
2313             VM_CHECK_EXCEPTION();
2314             r[dst].u.jsValue = returnValue;
2315
2316             if (*enabledProfilerReference)
2317                 (*enabledProfilerReference)->didExecute(exec, constructor);
2318
2319             ++vPC;
2320             NEXT_OPCODE;
2321         }
2322
2323         ASSERT(constructType == ConstructTypeNone);
2324
2325         exceptionValue = createNotAConstructorError(exec, constrVal, 0);
2326         goto vm_throw;
2327     }
2328     BEGIN_OPCODE(op_push_scope) {
2329         /* push_scope scope(r)
2330
2331            Converts register scope to object, and pushes it onto the top
2332            of the current scope chain.
2333         */
2334         int scope = (++vPC)->u.operand;
2335         JSValue* v = r[scope].u.jsValue;
2336         JSObject* o = v->toObject(exec);
2337         VM_CHECK_EXCEPTION();
2338
2339         setScopeChain(exec, scopeChain, scopeChain->push(o));
2340
2341         ++vPC;
2342         NEXT_OPCODE;
2343     }
2344     BEGIN_OPCODE(op_pop_scope) {
2345         /* pop_scope
2346
2347            Removes the top item from the current scope chain.
2348         */
2349         setScopeChain(exec, scopeChain, scopeChain->pop());
2350
2351         ++vPC;
2352         NEXT_OPCODE;
2353     }
2354     BEGIN_OPCODE(op_get_pnames) {
2355         /* get_pnames dst(r) base(r)
2356
2357            Creates a property name list for register base and puts it
2358            in register dst. This is not a true JavaScript value, just
2359            a synthetic value used to keep the iteration state in a
2360            register.
2361         */
2362         int dst = (++vPC)->u.operand;
2363         int base = (++vPC)->u.operand;
2364
2365         r[dst].u.jsPropertyNameIterator = JSPropertyNameIterator::create(exec, r[base].u.jsValue);
2366         ++vPC;
2367         NEXT_OPCODE;
2368     }
2369     BEGIN_OPCODE(op_next_pname) {
2370         /* next_pname dst(r) iter(r) target(offset)
2371
2372            Tries to copies the next name from property name list in
2373            register iter. If there are names left, then copies one to
2374            register dst, and jumps to offset target. If there are none
2375            left, invalidates the iterator and continues to the next
2376            instruction.
2377         */
2378         int dst = (++vPC)->u.operand;
2379         int iter = (++vPC)->u.operand;
2380         int target = (++vPC)->u.operand;
2381
2382         JSPropertyNameIterator* it = r[iter].u.jsPropertyNameIterator;
2383         if (JSValue* temp = it->next(exec)) {
2384             r[dst].u.jsValue = temp;
2385             vPC += target;
2386             NEXT_OPCODE;
2387         }
2388         it->invalidate();
2389
2390         ++vPC;
2391         NEXT_OPCODE;
2392     }
2393     BEGIN_OPCODE(op_jmp_scopes) {
2394         /* jmp_scopes count(n) target(offset)
2395
2396            Removes the a number of items from the current scope chain
2397            specified by immediate number count, then jumps to offset
2398            target.
2399         */
2400         int count = (++vPC)->u.operand;
2401         int target = (++vPC)->u.operand;
2402
2403         ScopeChainNode* tmp = scopeChain;
2404         while (count--)
2405             tmp = tmp->pop();
2406         setScopeChain(exec, scopeChain, tmp);
2407
2408         vPC += target;
2409         NEXT_OPCODE;
2410     }
2411     BEGIN_OPCODE(op_catch) {
2412         /* catch ex(r)
2413
2414            Retrieves the VMs current exception and puts it in register
2415            ex. This is only valid after an exception has been raised,
2416            and usually forms the beginning of an exception handler.
2417         */
2418         ASSERT(exceptionValue);
2419         ASSERT(!exec->hadException());
2420         int ex = (++vPC)->u.operand;
2421         r[ex].u.jsValue = exceptionValue;
2422         exceptionValue = 0;
2423
2424         ++vPC;
2425         NEXT_OPCODE;
2426     }
2427     BEGIN_OPCODE(op_throw) {
2428         /* throw ex(r)
2429
2430            Throws register ex as an exception. This involves three
2431            steps: first, it is set as the current exception in the
2432            VM's internal state, then the stack is unwound until an
2433            exception handler or a native code boundary is found, and
2434            then control resumes at the exception handler if any or
2435            else the script returns control to the nearest native caller.
2436         */
2437
2438         int ex = (++vPC)->u.operand;
2439         exceptionValue = r[ex].u.jsValue;
2440         handlerVPC = throwException(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r);
2441         if (!handlerVPC) {
2442             *exception = exceptionValue;
2443             return jsNull();
2444         }
2445
2446 #if HAVE(COMPUTED_GOTO)
2447         // Hack around gcc performance quirk by performing an indirect goto
2448         // in order to set the vPC -- attempting to do so directly results in a
2449         // significant regression.
2450         goto *op_throw_end_indirect; // indirect goto -> op_throw_end
2451     }
2452     op_throw_end: {
2453 #endif
2454
2455         vPC = handlerVPC;
2456         NEXT_OPCODE;
2457     }
2458     BEGIN_OPCODE(op_new_error) {
2459         /* new_error dst(r) type(n) message(k)
2460
2461            Constructs a new Error instance using the original
2462            constructor, using immediate number n as the type and
2463            constant message as the message string. The result is
2464            written to register dst.
2465         */
2466         int dst = (++vPC)->u.operand;
2467         int type = (++vPC)->u.operand;
2468         int message = (++vPC)->u.operand;
2469
2470         r[dst].u.jsValue = Error::create(exec, (ErrorType)type, k[message]->toString(exec), codeBlock->lineNumberForVPC(vPC), codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->sourceURL());
2471
2472         ++vPC;
2473         NEXT_OPCODE;
2474     }
2475     BEGIN_OPCODE(op_end) {
2476         /* end result(r)
2477            
2478            Return register result as the value of a global or eval
2479            program. Return control to the calling native code.
2480         */
2481
2482         if (codeBlock->needsFullScopeChain) {
2483             ASSERT(scopeChain->refCount > 1);
2484             scopeChain->deref();
2485         }
2486         int result = (++vPC)->u.operand;
2487         return r[result].u.jsValue;
2488     }
2489     BEGIN_OPCODE(op_put_getter) {
2490         /* put_getter base(r) property(id) function(r)
2491
2492            Sets register function on register base as the getter named
2493            by identifier property. Base and function are assumed to be
2494            objects as this op should only be used for getters defined
2495            in object literal form.
2496
2497            Unlike many opcodes, this one does not write any output to
2498            the register file.
2499         */
2500         int base = (++vPC)->u.operand;
2501         int property = (++vPC)->u.operand;
2502         int function = (++vPC)->u.operand;
2503
2504         ASSERT(r[base].u.jsValue->isObject());
2505         JSObject* baseObj = static_cast<JSObject*>(r[base].u.jsValue);
2506         Identifier& ident = codeBlock->identifiers[property];
2507         ASSERT(r[function].u.jsValue->isObject());
2508         baseObj->defineGetter(exec, ident, static_cast<JSObject* >(r[function].u.jsValue));
2509
2510         ++vPC;
2511         NEXT_OPCODE;
2512     }
2513     BEGIN_OPCODE(op_put_setter) {
2514         /* put_setter base(r) property(id) function(r)
2515
2516            Sets register function on register base as the setter named
2517            by identifier property. Base and function are assumed to be
2518            objects as this op should only be used for setters defined
2519            in object literal form.
2520
2521            Unlike many opcodes, this one does not write any output to
2522            the register file.
2523         */
2524         int base = (++vPC)->u.operand;
2525         int property = (++vPC)->u.operand;
2526         int function = (++vPC)->u.operand;
2527
2528         ASSERT(r[base].u.jsValue->isObject());
2529         JSObject* baseObj = static_cast<JSObject*>(r[base].u.jsValue);
2530         Identifier& ident = codeBlock->identifiers[property];
2531         ASSERT(r[function].u.jsValue->isObject());
2532         baseObj->defineSetter(exec, ident, static_cast<JSObject* >(r[function].u.jsValue));
2533
2534         ++vPC;
2535         NEXT_OPCODE;
2536     }
2537     BEGIN_OPCODE(op_jsr) {
2538         /* jsr retAddrDst(r) target(offset)
2539
2540            Places the address of the next instruction into the retAddrDst
2541            register and jumps to offset target from the current instruction.
2542         */
2543         int retAddrDst = (++vPC)->u.operand;
2544         int target = (++vPC)->u.operand;
2545         r[retAddrDst].u.vPC = vPC + 1;
2546
2547         vPC += target;
2548         NEXT_OPCODE;
2549     }
2550     BEGIN_OPCODE(op_sret) {
2551         /* sret retAddrSrc(r)
2552
2553          Jumps to the address stored in the retAddrSrc register. This
2554          differs from op_jmp because the target address is stored in a
2555          register, not as an immediate.
2556         */
2557         int retAddrSrc = (++vPC)->u.operand;
2558         vPC = r[retAddrSrc].u.vPC;
2559         NEXT_OPCODE;
2560     }
2561     BEGIN_OPCODE(op_debug) {
2562         /* debug debugHookID(n) firstLine(n) lastLine(n)
2563
2564          Notifies the debugger of the current state of execution. This opcode
2565          is only generated while the debugger is attached.
2566         */
2567
2568         int registerOffset = r - (*registerBase);
2569         registerFile->setSafeForReentry(true);
2570         debug(exec, vPC, codeBlock, scopeChain, registerBase, r);
2571         registerFile->setSafeForReentry(false);
2572         r = (*registerBase) + registerOffset;
2573
2574         vPC += 4;
2575         NEXT_OPCODE;
2576     }
2577     vm_throw: {
2578         exec->clearException();
2579         handlerVPC = throwException(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r);
2580         if (!handlerVPC) {
2581             *exception = exceptionValue;
2582             return jsNull();
2583         }
2584         vPC = handlerVPC;
2585         NEXT_OPCODE;
2586     }
2587     }
2588     #undef NEXT_OPCODE
2589     #undef BEGIN_OPCODE
2590     #undef VM_CHECK_EXCEPTION
2591 }
2592
2593 JSValue* Machine::retrieveArguments(ExecState* exec, JSFunction* function) const
2594 {
2595     Register** registerBase;
2596     int callFrameOffset;
2597
2598     if (!getCallFrame(exec, function, registerBase, callFrameOffset))
2599         return jsNull();
2600
2601     Register* callFrame = (*registerBase) + callFrameOffset;
2602     JSActivation* activation = static_cast<JSActivation*>(callFrame[OptionalCalleeActivation].u.jsValue);
2603     if (!activation) {
2604         CodeBlock* codeBlock = &function->body->generatedCode();
2605         activation = new (exec) JSActivation(function->body, registerBase, callFrameOffset + CallFrameHeaderSize + codeBlock->numLocals);
2606         callFrame[OptionalCalleeActivation].u.jsValue = activation;
2607     }
2608
2609     return activation->get(exec, exec->propertyNames().arguments);
2610 }
2611
2612 JSValue* Machine::retrieveCaller(ExecState* exec, JSFunction* function) const
2613 {
2614     Register** registerBase;
2615     int callFrameOffset;
2616
2617     if (!getCallFrame(exec, function, registerBase, callFrameOffset))
2618         return jsNull();
2619
2620     int callerFrameOffset;
2621     if (!getCallerFunctionOffset(registerBase, callFrameOffset, callerFrameOffset))
2622         return jsNull();
2623
2624     Register* callerFrame = (*registerBase) + callerFrameOffset;
2625     ASSERT(callerFrame[Callee].u.jsValue);
2626     return callerFrame[Callee].u.jsValue;
2627 }
2628
2629 bool Machine::getCallFrame(ExecState* exec, JSFunction* function, Register**& registerBase, int& callFrameOffset) const
2630 {
2631     callFrameOffset = exec->m_callFrameOffset;
2632
2633     while (1) {
2634         while (callFrameOffset < 0) {
2635             exec = exec->m_prev;
2636             if (!exec)
2637                 return false;
2638             callFrameOffset = exec->m_callFrameOffset;
2639         }
2640
2641         registerBase = exec->m_registerFile->basePointer();
2642         Register* callFrame = (*registerBase) + callFrameOffset;
2643         if (callFrame[Callee].u.jsValue == function)
2644             return true;
2645
2646         if (!getCallerFunctionOffset(registerBase, callFrameOffset, callFrameOffset))
2647             callFrameOffset = -1;
2648     }
2649 }
2650
2651 void Machine::getFunctionAndArguments(Register** registerBase, Register* callFrame, JSFunction*& function, Register*& argv, int& argc)
2652 {
2653     function = static_cast<JSFunction*>(callFrame[Callee].u.jsValue);
2654     ASSERT(function->inherits(&JSFunction::info));
2655
2656     argv = (*registerBase) + callFrame[CallerRegisterOffset].u.i + callFrame[ArgumentStartRegister].u.i + 1; // skip "this"
2657     argc = callFrame[ArgumentCount].u.i - 1; // skip "this"
2658 }
2659
2660 } // namespace KJS