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