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