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