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