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