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