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