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