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