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