1755731b05c3335240bb6c4c7c9f22a7361eb833
[WebKit-https.git] / JavaScriptCore / VM / Machine.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "Machine.h"
32
33 #include "BatchedTransitionOptimizer.h"
34 #include "CodeBlock.h"
35 #include "DebuggerCallFrame.h"
36 #include "ExceptionHelpers.h"
37 #include "ExecState.h"
38 #include "GlobalEvalFunction.h"
39 #include "JSActivation.h"
40 #include "JSArray.h"
41 #include "JSFunction.h"
42 #include "JSNotAnObject.h"
43 #include "JSPropertyNameIterator.h"
44 #include "JSStaticScopeObject.h"
45 #include "JSString.h"
46 #include "ObjectPrototype.h"
47 #include "Parser.h"
48 #include "Profiler.h"
49 #include "RegExpObject.h"
50 #include "RegExpPrototype.h"
51 #include "Register.h"
52 #include "collector.h"
53 #include "debugger.h"
54 #include "operations.h"
55 #include "SamplingTool.h"
56 #include <stdio.h>
57
58 #if PLATFORM(DARWIN)
59 #include <mach/mach.h>
60 #endif
61
62 #if HAVE(SYS_TIME_H)
63 #include <sys/time.h>
64 #endif
65
66 #if PLATFORM(WIN_OS)
67 #include <windows.h>
68 #endif
69
70 #if PLATFORM(QT)
71 #include <QDateTime>
72 #endif
73
74 using namespace std;
75
76 namespace JSC {
77
78 // Preferred number of milliseconds between each timeout check
79 static const int preferredScriptCheckTimeInterval = 1000;
80
81 #if HAVE(COMPUTED_GOTO)
82 static void* op_throw_end_indirect;
83 static void* op_call_indirect;
84 #endif
85
86 // Returns the depth of the scope chain within a given call frame.
87 static int depth(CodeBlock* codeBlock, ScopeChain& sc)
88 {
89     if (!codeBlock->needsFullScopeChain)
90         return 0;
91     int scopeDepth = 0;
92     ScopeChainIterator iter = sc.begin();
93     ScopeChainIterator end = sc.end();
94     while (!(*iter)->isActivationObject()) {
95         ++iter;
96         if (iter == end)
97             break;
98         ++scopeDepth;
99     }
100     return scopeDepth;
101 }
102
103 // FIXME: This operation should be called "getNumber", not "isNumber" (as it is in JSValue.h).
104 // FIXME: There's no need to have a "slow" version of this. All versions should be fast.
105 static bool fastIsNumber(JSValue* value, double& arg)
106 {
107     if (JSImmediate::isNumber(value))
108         arg = JSImmediate::getTruncatedInt32(value);
109     else if (Heap::isNumber(static_cast<JSCell*>(value)))
110         arg = static_cast<JSNumberCell*>(value)->value();
111     else
112         return false;
113     return true;
114 }
115
116 // FIXME: Why doesn't JSValue::toInt32 have the Heap::isNumber optimization?
117 static bool fastToInt32(JSValue* value, int32_t& arg)
118 {
119     if (JSImmediate::isNumber(value))
120         arg = JSImmediate::getTruncatedInt32(value);
121     else if (Heap::isNumber(static_cast<JSCell*>(value)))
122         arg = static_cast<JSNumberCell*>(value)->toInt32();
123     else
124         return false;
125     return true;
126 }
127
128 static ALWAYS_INLINE bool fastToUInt32(JSValue* value, uint32_t& arg)
129 {
130     if (JSImmediate::isNumber(value)) {
131         if (JSImmediate::getTruncatedUInt32(value, arg))
132             return true;
133         bool scratch;
134         arg = JSValue::toUInt32SlowCase(JSImmediate::getTruncatedInt32(value), scratch);
135         return true;
136     } else if (Heap::isNumber(static_cast<JSCell*>(value)))
137         arg = static_cast<JSNumberCell*>(value)->toUInt32();
138     else
139         return false;
140     return true;
141 }
142
143 static inline bool jsLess(ExecState* exec, JSValue* v1, JSValue* v2)
144 {
145     if (JSImmediate::areBothImmediateNumbers(v1, v2))
146         return JSImmediate::getTruncatedInt32(v1) < JSImmediate::getTruncatedInt32(v2);
147
148     double n1;
149     double n2;
150     if (fastIsNumber(v1, n1) && fastIsNumber(v2, n2))
151         return n1 < n2;
152
153     JSValue* p1;
154     JSValue* p2;
155     bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
156     bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
157
158     if (wasNotString1 | wasNotString2)
159         return n1 < n2;
160
161     return static_cast<const JSString*>(p1)->value() < static_cast<const JSString*>(p2)->value();
162 }
163
164 static inline bool jsLessEq(ExecState* exec, JSValue* v1, JSValue* v2)
165 {
166     if (JSImmediate::areBothImmediateNumbers(v1, v2))
167         return JSImmediate::getTruncatedInt32(v1) <= JSImmediate::getTruncatedInt32(v2);
168
169     double n1;
170     double n2;
171     if (fastIsNumber(v1, n1) && fastIsNumber(v2, n2))
172         return n1 <= n2;
173
174     JSValue* p1;
175     JSValue* p2;
176     bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
177     bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
178
179     if (wasNotString1 | wasNotString2)
180         return n1 <= n2;
181
182     return !(static_cast<const JSString*>(p2)->value() < static_cast<const JSString*>(p1)->value());
183 }
184
185 static JSValue* jsAddSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
186 {
187     // exception for the Date exception in defaultValue()
188     JSValue* p1 = v1->toPrimitive(exec);
189     JSValue* p2 = v2->toPrimitive(exec);
190
191     if (p1->isString() || p2->isString()) {
192         RefPtr<UString::Rep> value = concatenate(p1->toString(exec).rep(), p2->toString(exec).rep());
193         if (!value)
194             return throwOutOfMemoryError(exec);
195         return jsString(exec, value.release());
196     }
197
198     return jsNumber(exec, p1->toNumber(exec) + p2->toNumber(exec));
199 }
200
201 // Fast-path choices here are based on frequency data from SunSpider:
202 //    <times> Add case: <t1> <t2>
203 //    ---------------------------
204 //    5626160 Add case: 3 3 (of these, 3637690 are for immediate values)
205 //    247412  Add case: 5 5
206 //    20900   Add case: 5 6
207 //    13962   Add case: 5 3
208 //    4000    Add case: 3 5
209
210 static inline JSValue* jsAdd(ExecState* exec, JSValue* v1, JSValue* v2)
211 {
212     double left;
213     double right;
214     if (fastIsNumber(v1, left) && fastIsNumber(v2, right))
215         return jsNumber(exec, left + right);
216     
217     if (v1->isString() && v2->isString()) {
218         RefPtr<UString::Rep> value = concatenate(static_cast<JSString*>(v1)->value().rep(), static_cast<JSString*>(v2)->value().rep());
219         if (!value)
220             return throwOutOfMemoryError(exec);
221         return jsString(exec, value.release());
222     }
223
224     // All other cases are pretty uncommon
225     return jsAddSlowCase(exec, v1, v2);
226 }
227
228 static JSValue* jsTypeStringForValue(ExecState* exec, JSValue* v)
229 {
230     if (v->isUndefined())
231         return jsNontrivialString(exec, "undefined");
232     if (v->isBoolean())
233         return jsNontrivialString(exec, "boolean");
234     if (v->isNumber())
235         return jsNontrivialString(exec, "number");
236     if (v->isString())
237         return jsNontrivialString(exec, "string");
238     if (v->isObject()) {
239         // Return "undefined" for objects that should be treated
240         // as null when doing comparisons.
241         if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
242             return jsNontrivialString(exec, "undefined");
243         CallData callData;
244         if (static_cast<JSObject*>(v)->getCallData(callData) != CallTypeNone)
245             return jsNontrivialString(exec, "function");
246     }
247     return jsNontrivialString(exec, "object");
248 }
249
250 static bool NEVER_INLINE resolve(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
251 {
252     int dst = (vPC + 1)->u.operand;
253     int property = (vPC + 2)->u.operand;
254
255     ScopeChainIterator iter = scopeChain->begin();
256     ScopeChainIterator end = scopeChain->end();
257     ASSERT(iter != end);
258
259     Identifier& ident = codeBlock->identifiers[property];
260     do {
261         JSObject* o = *iter;
262         PropertySlot slot(o);
263         if (o->getPropertySlot(exec, ident, slot)) {
264             JSValue* result = slot.getValue(exec, ident);
265             exceptionValue = exec->exception();
266             if (exceptionValue)
267                 return false;
268             r[dst] = result;
269             return true;
270         }
271     } while (++iter != end);
272     exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
273     return false;
274 }
275
276 static bool NEVER_INLINE resolve_skip(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
277 {
278     int dst = (vPC + 1)->u.operand;
279     int property = (vPC + 2)->u.operand;
280     int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain;
281
282     ScopeChainIterator iter = scopeChain->begin();
283     ScopeChainIterator end = scopeChain->end();
284     ASSERT(iter != end);
285     while (skip--) {
286         ++iter;
287         ASSERT(iter != end);
288     }
289     Identifier& ident = codeBlock->identifiers[property];
290     do {
291         JSObject* o = *iter;
292         PropertySlot slot(o);
293         if (o->getPropertySlot(exec, ident, slot)) {
294             JSValue* result = slot.getValue(exec, ident);
295             exceptionValue = exec->exception();
296             if (exceptionValue)
297                 return false;
298             r[dst] = result;
299             return true;
300         }
301     } while (++iter != end);
302     exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
303     return false;
304 }
305
306 ALWAYS_INLINE static JSValue* inlineResolveBase(ExecState* exec, Identifier& property, ScopeChainNode* scopeChain)
307 {
308     ScopeChainIterator iter = scopeChain->begin();
309     ScopeChainIterator next = iter;
310     ++next;
311     ScopeChainIterator end = scopeChain->end();
312     ASSERT(iter != end);
313
314     PropertySlot slot;
315     JSObject* base;
316     while (true) {
317         base = *iter;
318         if (next == end || base->getPropertySlot(exec, property, slot))
319             return base;
320
321         iter = next;
322         ++next;
323     }
324
325     ASSERT_NOT_REACHED();
326     return 0;
327 }
328
329 NEVER_INLINE static void resolveBase(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock)
330 {
331     int dst = (vPC + 1)->u.operand;
332     int property = (vPC + 2)->u.operand;
333     r[dst] = inlineResolveBase(exec, codeBlock->identifiers[property], scopeChain);
334 }
335
336 static bool NEVER_INLINE resolveBaseAndProperty(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
337 {
338     int baseDst = (vPC + 1)->u.operand;
339     int propDst = (vPC + 2)->u.operand;
340     int property = (vPC + 3)->u.operand;
341
342     ScopeChainIterator iter = scopeChain->begin();
343     ScopeChainIterator end = scopeChain->end();
344
345     // FIXME: add scopeDepthIsZero optimization
346
347     ASSERT(iter != end);
348
349     Identifier& ident = codeBlock->identifiers[property];
350     JSObject* base;
351     do {
352         base = *iter;
353         PropertySlot slot(base);
354         if (base->getPropertySlot(exec, ident, slot)) {
355             JSValue* result = slot.getValue(exec, ident);
356             exceptionValue = exec->exception();
357             if (exceptionValue)
358                 return false;
359             r[propDst] = result;
360             r[baseDst] = base;
361             return true;
362         }
363         ++iter;
364     } while (iter != end);
365
366     exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
367     return false;
368 }
369
370 static bool NEVER_INLINE resolveBaseAndFunc(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
371 {
372     int baseDst = (vPC + 1)->u.operand;
373     int funcDst = (vPC + 2)->u.operand;
374     int property = (vPC + 3)->u.operand;
375
376     ScopeChainIterator iter = scopeChain->begin();
377     ScopeChainIterator end = scopeChain->end();
378
379     // FIXME: add scopeDepthIsZero optimization
380
381     ASSERT(iter != end);
382
383     Identifier& ident = codeBlock->identifiers[property];
384     JSObject* base;
385     do {
386         base = *iter;
387         PropertySlot slot(base);
388         if (base->getPropertySlot(exec, ident, slot)) {            
389             // ECMA 11.2.3 says that if we hit an activation the this value should be null.
390             // However, section 10.2.3 says that in the case where the value provided
391             // by the caller is null, the global object should be used. It also says
392             // that the section does not apply to internal functions, but for simplicity
393             // of implementation we use the global object anyway here. This guarantees
394             // that in host objects you always get a valid object for this.
395             // We also handle wrapper substitution for the global object at the same time.
396             JSObject* thisObj = base->toThisObject(exec);
397             JSValue* result = slot.getValue(exec, ident);
398             exceptionValue = exec->exception();
399             if (exceptionValue)
400                 return false;
401
402             r[baseDst] = thisObj;
403             r[funcDst] = result;
404             return true;
405         }
406         ++iter;
407     } while (iter != end);
408
409     exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
410     return false;
411 }
412
413 ALWAYS_INLINE void Machine::initializeCallFrame(Register* callFrame, CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, Register* r, int returnValueRegister, int argv, int argc, int calledAsConstructor, JSValue* function)
414 {
415     callFrame[RegisterFile::CallerCodeBlock] = codeBlock;
416     callFrame[RegisterFile::ReturnVPC] = vPC + 1;
417     callFrame[RegisterFile::CallerScopeChain] = scopeChain;
418     callFrame[RegisterFile::CallerRegisters] = r;
419     callFrame[RegisterFile::ReturnValueRegister] = returnValueRegister;
420     callFrame[RegisterFile::ArgumentStartRegister] = argv; // original argument vector (for the sake of the "arguments" object)
421     callFrame[RegisterFile::ArgumentCount] = argc; // original argument count (for the sake of the "arguments" object)
422     callFrame[RegisterFile::CalledAsConstructor] = calledAsConstructor;
423     callFrame[RegisterFile::Callee] = function;
424     callFrame[RegisterFile::OptionalCalleeActivation] = nullJSValue;
425 }
426
427 ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* newCodeBlock, RegisterFile* registerFile, Register* registerBase, Register* r, int argv, int argc, JSValue*& exceptionValue)
428 {
429     size_t registerOffset = argv + newCodeBlock->numLocals;
430     size_t size = r - registerBase + registerOffset + newCodeBlock->numConstants + newCodeBlock->numTemporaries;
431
432     if (argc == newCodeBlock->numParameters) { // correct number of arguments
433         if (!registerFile->grow(size)) {
434             exceptionValue = createStackOverflowError(exec);
435             return r;
436         }
437         r += registerOffset;
438     } else if (argc < newCodeBlock->numParameters) { // too few arguments -- fill in the blanks
439         if (!registerFile->grow(size)) {
440             exceptionValue = createStackOverflowError(exec);
441             return r;
442         }
443         r += registerOffset;
444
445         int omittedArgCount = newCodeBlock->numParameters - argc;
446         Register* endOfParams = r - newCodeBlock->numVars;
447         for (Register* it = endOfParams - omittedArgCount; it != endOfParams; ++it)
448             (*it) = jsUndefined();
449     } else { // too many arguments -- copy return info and expected arguments, leaving the extra arguments behind
450         int shift = argc + RegisterFile::CallFrameHeaderSize;
451         registerOffset += shift;
452         size += shift;
453
454         if (!registerFile->grow(size)) {
455             exceptionValue = createStackOverflowError(exec);
456             return r;
457         }
458         r += registerOffset;
459
460         Register* it = r - newCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize - shift;
461         Register* end = it + RegisterFile::CallFrameHeaderSize + newCodeBlock->numParameters;
462         for ( ; it != end; ++it)
463             *(it + shift) = *it;
464     }
465     
466     // initialize local variable slots
467     for (Register* it = r - newCodeBlock->numVars; it != r; ++it)
468         (*it) = jsUndefined();
469
470     for (size_t i = 0; i < newCodeBlock->constantRegisters.size(); ++i)
471         r[i] = newCodeBlock->constantRegisters[i];
472
473     return r;
474 }
475
476 ALWAYS_INLINE ScopeChainNode* scopeChainForCall(ExecState* exec, FunctionBodyNode* functionBodyNode, CodeBlock* newCodeBlock, ScopeChainNode* callDataScopeChain, Register* r)
477 {
478     if (newCodeBlock->needsFullScopeChain) {
479         JSActivation* activation = new (exec) JSActivation(exec, functionBodyNode, r);
480         r[RegisterFile::OptionalCalleeActivation - RegisterFile::CallFrameHeaderSize - newCodeBlock->numLocals] = activation;
481
482         return callDataScopeChain->copy()->push(activation);
483     }
484
485     return callDataScopeChain;
486 }
487
488 static NEVER_INLINE bool isNotObject(ExecState* exec, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValue* value, JSValue*& exceptionData)
489 {
490     if (value->isObject())
491         return false;
492     exceptionData = createInvalidParamError(exec, forInstanceOf ? "instanceof" : "in" , value, vPC, codeBlock);
493     return true;
494 }
495
496 NEVER_INLINE JSValue* Machine::callEval(ExecState* exec, CodeBlock* callingCodeBlock, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, Register* r, int argv, int argc, JSValue*& exceptionValue)
497 {
498     if (argc < 2)
499         return jsUndefined();
500
501     JSValue* program = r[argv + 1].jsValue(exec);
502
503     if (!program->isString())
504         return program;
505
506     Profiler** profiler = Profiler::enabledProfilerReference();
507     if (*profiler)
508         (*profiler)->willExecute(exec, scopeChain->globalObject()->evalFunction());
509
510     UString programSource = static_cast<JSString*>(program)->value();
511
512     RefPtr<EvalNode> evalNode = callingCodeBlock->evalCodeCache.get(exec, programSource, scopeChain, exceptionValue);
513
514     JSValue* result = 0;
515     if (evalNode)
516         result = exec->globalData().machine->execute(evalNode.get(), exec, thisObj, r - registerFile->base() + argv + argc, scopeChain, &exceptionValue);
517
518     if (*profiler)
519         (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
520
521     return result;
522 }
523
524 Machine::Machine()
525     : m_sampler(0)
526 #if ENABLE(CTI)
527     , m_ctiArrayLengthTrampoline(0)
528     , m_ctiStringLengthTrampoline(0)
529     , m_jitCodeBuffer(new JITCodeBuffer(1024 * 1024))
530 #endif
531     , m_reentryDepth(0)
532     , m_timeoutTime(0)
533     , m_timeAtLastCheckTimeout(0)
534     , m_timeExecuting(0)
535     , m_timeoutCheckCount(0)
536     , m_ticksUntilNextTimeoutCheck(initialTickCountThreshold)
537 {
538     privateExecute(InitializeAndReturn);
539     
540     // Bizarrely, calling fastMalloc here is faster than allocating space on the stack.
541     void* storage = fastMalloc(sizeof(CollectorBlock));
542
543     JSArray* jsArray = new (storage) JSArray(StructureID::create(jsNull()));
544     m_jsArrayVptr = jsArray->vptr();
545     static_cast<JSCell*>(jsArray)->~JSCell();
546
547     JSString* jsString = new (storage) JSString(JSString::VPtrStealingHack);
548     m_jsStringVptr = jsString->vptr();
549     static_cast<JSCell*>(jsString)->~JSCell();
550
551     JSFunction* jsFunction = new (storage) JSFunction(StructureID::create(jsNull()));
552     m_jsFunctionVptr = jsFunction->vptr();
553     static_cast<JSCell*>(jsFunction)->~JSCell();
554     
555     fastFree(storage);
556 }
557
558 Machine::~Machine()
559 {
560 #if ENABLE(CTI)
561     if (m_ctiArrayLengthTrampoline)
562         fastFree(m_ctiArrayLengthTrampoline);
563     if (m_ctiStringLengthTrampoline)
564         fastFree(m_ctiStringLengthTrampoline);
565 #endif
566 }
567
568 #ifndef NDEBUG
569
570 void Machine::dumpCallFrame(const CodeBlock* codeBlock, ScopeChainNode* scopeChain, RegisterFile* registerFile, const Register* r)
571 {
572     ScopeChain sc(scopeChain);
573     JSGlobalObject* globalObject = sc.globalObject();
574     codeBlock->dump(globalObject->globalExec());
575     dumpRegisters(codeBlock, registerFile, r);
576 }
577
578 void Machine::dumpRegisters(const CodeBlock* codeBlock, RegisterFile* registerFile, const Register* r)
579 {
580     printf("Register frame: \n\n");
581     printf("----------------------------------------------------\n");
582     printf("            use            |   address  |   value   \n");
583     printf("----------------------------------------------------\n");
584
585     const Register* it;
586     const Register* end;
587
588     if (codeBlock->codeType == GlobalCode) {
589         it = registerFile->lastGlobal();
590         end = it + registerFile->numGlobals();
591         while (it != end) {
592             printf("[global var]               | %10p | %10p \n", it, (*it).v());
593             ++it;
594         }
595         printf("----------------------------------------------------\n");
596     }
597     
598     it = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
599     printf("[CallerCodeBlock]          | %10p | %10p \n", it, (*it).v()); ++it;
600     printf("[ReturnVPC]                | %10p | %10p \n", it, (*it).v()); ++it;
601     printf("[CallerScopeChain]         | %10p | %10p \n", it, (*it).v()); ++it;
602     printf("[CallerRegisterOffset]     | %10p | %10p \n", it, (*it).v()); ++it;
603     printf("[ReturnValueRegister]      | %10p | %10p \n", it, (*it).v()); ++it;
604     printf("[ArgumentStartRegister]    | %10p | %10p \n", it, (*it).v()); ++it;
605     printf("[ArgumentCount]            | %10p | %10p \n", it, (*it).v()); ++it;
606     printf("[CalledAsConstructor]      | %10p | %10p \n", it, (*it).v()); ++it;
607     printf("[Callee]                   | %10p | %10p \n", it, (*it).v()); ++it;
608     printf("[OptionalCalleeActivation] | %10p | %10p \n", it, (*it).v()); ++it;
609     printf("----------------------------------------------------\n");
610
611     printf("[this]                     | %10p | %10p \n", it, (*it).v()); ++it;
612     end = it + max(codeBlock->numParameters - 1, 0); // - 1 to skip "this"
613     if (it != end) {
614         do {
615             printf("[param]                    | %10p | %10p \n", it, (*it).v());
616             ++it;
617         } while (it != end);
618     }
619     printf("----------------------------------------------------\n");
620
621     if (codeBlock->codeType != GlobalCode) {
622         end = it + codeBlock->numVars;
623         if (it != end) {
624             do {
625                 printf("[var]                      | %10p | %10p \n", it, (*it).v());
626                 ++it;
627             } while (it != end);
628         printf("----------------------------------------------------\n");
629         }
630     }
631
632     end = it + codeBlock->numTemporaries;
633     if (it != end) {
634         do {
635             printf("[temp]                     | %10p | %10p \n", it, (*it).v());
636             ++it;
637         } while (it != end);
638     }
639 }
640
641 #endif
642
643 //#if !defined(NDEBUG) || ENABLE(SAMPLING_TOOL)
644
645 bool Machine::isOpcode(Opcode opcode)
646 {
647 #if HAVE(COMPUTED_GOTO)
648     return opcode != HashTraits<Opcode>::emptyValue()
649         && !HashTraits<Opcode>::isDeletedValue(opcode)
650         && m_opcodeIDTable.contains(opcode);
651 #else
652     return opcode >= 0 && opcode <= op_end;
653 #endif
654 }
655
656 //#endif
657
658 NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, const Instruction*& vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r)
659 {
660     CodeBlock* oldCodeBlock = codeBlock;
661     Register* callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
662
663     if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
664         DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
665         if (callFrame[RegisterFile::Callee].jsValue(exec))
666             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
667         else
668             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
669     }
670
671     if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
672         if (callFrame[RegisterFile::Callee].jsValue(exec))
673             profiler->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
674         else
675             profiler->didExecute(exec, codeBlock->ownerNode->sourceURL(), codeBlock->ownerNode->lineNo());
676     }
677
678     if (oldCodeBlock->needsFullScopeChain)
679         scopeChain->deref();
680
681     // If this call frame created an activation, tear it off.
682     if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
683         ASSERT(activation->isActivationObject());
684         activation->copyRegisters();
685     }
686     
687     codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
688     if (!codeBlock)
689         return false;
690
691     scopeChain = callFrame[RegisterFile::CallerScopeChain].scopeChain();
692     r = callFrame[RegisterFile::CallerRegisters].r();
693     exec->m_callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
694     vPC = callFrame[RegisterFile::ReturnVPC].vPC();
695
696     return true;
697 }
698
699 NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue*& exceptionValue, const Instruction* vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r, bool explicitThrow)
700 {
701     // Set up the exception object
702     
703     if (exceptionValue->isObject()) {
704         JSObject* exception = static_cast<JSObject*>(exceptionValue);
705         if (exception->isNotAnObjectErrorStub()) {
706             exception = createNotAnObjectError(exec, static_cast<JSNotAnObjectErrorStub*>(exception), vPC, codeBlock);
707             exceptionValue = exception;
708         } else {
709             if (!exception->hasProperty(exec, Identifier(exec, "line")) && 
710                 !exception->hasProperty(exec, Identifier(exec, "sourceId")) && 
711                 !exception->hasProperty(exec, Identifier(exec, "sourceURL")) && 
712                 !exception->hasProperty(exec, Identifier(exec, expressionBeginOffsetPropertyName)) && 
713                 !exception->hasProperty(exec, Identifier(exec, expressionCaretOffsetPropertyName)) && 
714                 !exception->hasProperty(exec, Identifier(exec, expressionEndOffsetPropertyName))) {
715                 if (explicitThrow) {
716                     int startOffset = 0;
717                     int endOffset = 0;
718                     int divotPoint = 0;
719                     int line = codeBlock->expressionRangeForVPC(vPC, divotPoint, startOffset, endOffset);
720                     exception->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, line), ReadOnly | DontDelete);
721                     
722                     // We only hit this path for error messages and throw statements, which don't have a specific failure position
723                     // So we just give the full range of the error/throw statement.
724                     exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
725                     exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
726                 } else
727                     exception->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, codeBlock->lineNumberForVPC(vPC)), ReadOnly | DontDelete);
728                 exception->putWithAttributes(exec, Identifier(exec, "sourceId"), jsNumber(exec, codeBlock->ownerNode->sourceId()), ReadOnly | DontDelete);
729                 exception->putWithAttributes(exec, Identifier(exec, "sourceURL"), jsOwnedString(exec, codeBlock->ownerNode->sourceURL()), ReadOnly | DontDelete);
730             }
731             
732             if (exception->isWatchdogException()) {
733                 while (unwindCallFrame(exec, exceptionValue, vPC, codeBlock, scopeChain, r)) {
734                     // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
735                 }
736                 return 0;
737             }
738         }
739     }
740
741     if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
742         DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
743         debugger->exception(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->lineNumberForVPC(vPC));
744     }
745
746     // Calculate an exception handler vPC, unwinding call frames as necessary.
747
748     int scopeDepth;
749     Instruction* handlerVPC;
750
751     while (!codeBlock->getHandlerForVPC(vPC, handlerVPC, scopeDepth)) {
752         if (!unwindCallFrame(exec, exceptionValue, vPC, codeBlock, scopeChain, r))
753             return 0;
754     }
755
756     // Now unwind the scope chain within the exception handler's call frame.
757
758     ScopeChain sc(scopeChain);
759     int scopeDelta = depth(codeBlock, sc) - scopeDepth;
760     ASSERT(scopeDelta >= 0);
761     while (scopeDelta--)
762         sc.pop();
763     setScopeChain(exec, scopeChain, sc.node());
764
765     return handlerVPC;
766 }
767
768 JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue** exception)
769 {
770     if (m_reentryDepth >= MaxReentryDepth) {
771         *exception = createStackOverflowError(exec);
772         return 0;
773     }
774
775     CodeBlock* codeBlock = &programNode->byteCode(scopeChain);
776
777     size_t oldSize = m_registerFile.size();
778     size_t newSize = oldSize + RegisterFile::CallFrameHeaderSize + codeBlock->numVars + codeBlock->numConstants + codeBlock->numTemporaries;
779     if (!m_registerFile.grow(newSize)) {
780         *exception = createStackOverflowError(exec);
781         return 0;
782     }
783
784     JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
785     JSGlobalObject* globalObject = exec->dynamicGlobalObject();
786     globalObject->copyGlobalsTo(m_registerFile);
787
788     Register* callFrame = m_registerFile.base() + oldSize;
789
790     // a 0 codeBlock indicates a built-in caller
791     initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0, 0);
792
793     Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
794     r[codeBlock->thisRegister] = thisObj;
795
796     for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
797         r[i] = codeBlock->constantRegisters[i];
798
799     if (codeBlock->needsFullScopeChain)
800         scopeChain = scopeChain->copy();
801
802     ExecState newExec(exec, &m_registerFile, scopeChain, 0);
803
804     Profiler** profiler = Profiler::enabledProfilerReference();
805     if (*profiler)
806         (*profiler)->willExecute(exec, programNode->sourceURL(), programNode->lineNo());
807
808     m_reentryDepth++;
809 #if ENABLE(CTI)
810     if (!codeBlock->ctiCode)
811         CTI::compile(this, exec, codeBlock);
812     JSValue* result = CTI::execute(codeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
813 #else
814     JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
815 #endif
816     m_reentryDepth--;
817
818     MACHINE_SAMPLING_privateExecuteReturned();
819
820     if (*profiler)
821         (*profiler)->didExecute(exec, programNode->sourceURL(), programNode->lineNo());
822
823     if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
824         lastGlobalObject->copyGlobalsTo(m_registerFile);
825
826     m_registerFile.shrink(oldSize);
827     return result;
828 }
829
830 JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue** exception)
831 {
832     if (m_reentryDepth >= MaxReentryDepth) {
833         *exception = createStackOverflowError(exec);
834         return 0;
835     }
836
837     int argv = RegisterFile::CallFrameHeaderSize;
838     int argc = args.size() + 1; // implicit "this" parameter
839
840     size_t oldSize = m_registerFile.size();
841     if (!m_registerFile.grow(oldSize + RegisterFile::CallFrameHeaderSize + argc)) {
842         *exception = createStackOverflowError(exec);
843         return 0;
844     }
845
846     Register* callFrame = m_registerFile.base() + oldSize;
847
848     // put args in place, including "this"
849     Register* dst = callFrame + RegisterFile::CallFrameHeaderSize;
850     (*dst) = thisObj;
851
852     ArgList::const_iterator end = args.end();
853     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
854         (*++dst) = *it;
855
856     // a 0 codeBlock indicates a built-in caller
857     initializeCallFrame(callFrame, 0, 0, 0, callFrame, 0, argv, argc, 0, function);
858
859     CodeBlock* newCodeBlock = &functionBodyNode->byteCode(scopeChain);
860     Register* r = slideRegisterWindowForCall(exec, newCodeBlock, &m_registerFile, m_registerFile.base(), callFrame, argv, argc, *exception);
861     if (*exception) {
862         m_registerFile.shrink(oldSize);
863         return 0;
864     }
865
866     scopeChain = scopeChainForCall(exec, functionBodyNode, newCodeBlock, scopeChain, r);
867
868     ExecState newExec(exec, &m_registerFile, scopeChain, callFrame);
869
870     Profiler** profiler = Profiler::enabledProfilerReference();
871     if (*profiler)
872         (*profiler)->willExecute(exec, function);
873
874     m_reentryDepth++;
875 #if ENABLE(CTI)
876     if (!newCodeBlock->ctiCode)
877         CTI::compile(this, exec, newCodeBlock);
878     JSValue* result = CTI::execute(newCodeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, newCodeBlock, exception);
879 #else
880     JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, newCodeBlock, exception);
881 #endif
882     m_reentryDepth--;
883
884     MACHINE_SAMPLING_privateExecuteReturned();
885
886     m_registerFile.shrink(oldSize);
887     return result;
888 }
889
890 JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)
891 {
892     if (m_reentryDepth >= MaxReentryDepth) {
893         *exception = createStackOverflowError(exec);
894         return 0;
895     }
896
897     EvalCodeBlock* codeBlock = &evalNode->byteCode(scopeChain);
898
899     JSVariableObject* variableObject;
900     for (ScopeChainNode* node = scopeChain; ; node = node->next) {
901         ASSERT(node);
902         if (node->object->isVariableObject()) {
903             variableObject = static_cast<JSVariableObject*>(node->object);
904             break;
905         }
906     }
907
908     { // Scope for BatchedTransitionOptimizer
909
910         BatchedTransitionOptimizer optimizer(variableObject);
911
912         const Node::VarStack& varStack = codeBlock->ownerNode->varStack();
913         Node::VarStack::const_iterator varStackEnd = varStack.end();
914         for (Node::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) {
915             const Identifier& ident = (*it).first;
916             if (!variableObject->hasProperty(exec, ident)) {
917                 PutPropertySlot slot;
918                 variableObject->put(exec, ident, jsUndefined(), slot);
919             }
920         }
921
922         const Node::FunctionStack& functionStack = codeBlock->ownerNode->functionStack();
923         Node::FunctionStack::const_iterator functionStackEnd = functionStack.end();
924         for (Node::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it) {
925             PutPropertySlot slot;
926             variableObject->put(exec, (*it)->m_ident, (*it)->makeFunction(exec, scopeChain), slot);
927         }
928
929     }
930
931     size_t oldSize = m_registerFile.size();
932     size_t newSize = registerOffset + codeBlock->numVars + codeBlock->numConstants + codeBlock->numTemporaries + RegisterFile::CallFrameHeaderSize;
933     if (!m_registerFile.grow(newSize)) {
934         *exception = createStackOverflowError(exec);
935         return 0;
936     }
937
938     Register* callFrame = m_registerFile.base() + registerOffset;
939
940     // a 0 codeBlock indicates a built-in caller
941     initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0, 0);
942
943     Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
944     r[codeBlock->thisRegister] = thisObj;
945
946     for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
947         r[i] = codeBlock->constantRegisters[i];
948
949     if (codeBlock->needsFullScopeChain)
950         scopeChain = scopeChain->copy();
951
952     ExecState newExec(exec, &m_registerFile, scopeChain, 0);
953
954     Profiler** profiler = Profiler::enabledProfilerReference();
955     if (*profiler)
956         (*profiler)->willExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
957
958     m_reentryDepth++;
959 #if ENABLE(CTI)
960     if (!codeBlock->ctiCode)
961         CTI::compile(this, exec, codeBlock);
962     JSValue* result = CTI::execute(codeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
963 #else
964     JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
965 #endif
966     m_reentryDepth--;
967
968     MACHINE_SAMPLING_privateExecuteReturned();
969
970     if (*profiler)
971         (*profiler)->didExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
972
973     m_registerFile.shrink(oldSize);
974     return result;
975 }
976
977 ALWAYS_INLINE void Machine::setScopeChain(ExecState* exec, ScopeChainNode*& scopeChain, ScopeChainNode* newScopeChain)
978 {
979     scopeChain = newScopeChain;
980     exec->m_scopeChain = newScopeChain;
981 }
982
983 NEVER_INLINE void Machine::debug(ExecState* exec, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register* r, DebugHookID debugHookID, int firstLine, int lastLine)
984 {
985     Debugger* debugger = exec->dynamicGlobalObject()->debugger();
986     if (!debugger)
987         return;
988
989     DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, 0);
990
991     switch (debugHookID) {
992         case DidEnterCallFrame:
993             debugger->callEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
994             return;
995         case WillLeaveCallFrame:
996             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
997             return;
998         case WillExecuteStatement:
999             debugger->atStatement(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
1000             return;
1001         case WillExecuteProgram:
1002             debugger->willExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
1003             return;
1004         case DidExecuteProgram:
1005             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
1006             return;
1007         case DidReachBreakpoint:
1008             debugger->didReachBreakpoint(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
1009             return;
1010     }
1011 }
1012
1013 void Machine::resetTimeoutCheck()
1014 {
1015     m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
1016     m_timeAtLastCheckTimeout = 0;
1017     m_timeExecuting = 0;
1018 }
1019
1020 // Returns the time the current thread has spent executing, in milliseconds.
1021 static inline unsigned getCPUTime()
1022 {
1023 #if PLATFORM(DARWIN)
1024     mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
1025     thread_basic_info_data_t info;
1026
1027     // Get thread information
1028     thread_info(mach_thread_self(), THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &infoCount);
1029     
1030     unsigned time = info.user_time.seconds * 1000 + info.user_time.microseconds / 1000;
1031     time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000;
1032     
1033     return time;
1034 #elif HAVE(SYS_TIME_H)
1035     // FIXME: This should probably use getrusage with the RUSAGE_THREAD flag.
1036     struct timeval tv;
1037     gettimeofday(&tv, 0);
1038     return tv.tv_sec * 1000 + tv.tv_usec / 1000;
1039 #elif PLATFORM(QT)
1040     QDateTime t = QDateTime::currentDateTime();
1041     return t.toTime_t() * 1000 + t.time().msec();
1042 #elif PLATFORM(WIN_OS)
1043     union {
1044         FILETIME fileTime;
1045         unsigned long long fileTimeAsLong;
1046     } userTime, kernelTime;
1047     
1048     // GetThreadTimes won't accept NULL arguments so we pass these even though
1049     // they're not used.
1050     FILETIME creationTime, exitTime;
1051     
1052     GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime);
1053     
1054     return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000;
1055 #else
1056 #error Platform does not have getCurrentTime function
1057 #endif
1058 }
1059
1060 // We have to return a JSValue here, gcc seems to produce worse code if 
1061 // we attempt to return a bool
1062 ALWAYS_INLINE JSValue* Machine::checkTimeout(JSGlobalObject* globalObject)
1063 {
1064     unsigned currentTime = getCPUTime();
1065     
1066     if (!m_timeAtLastCheckTimeout) {
1067         // Suspicious amount of looping in a script -- start timing it
1068         m_timeAtLastCheckTimeout = currentTime;
1069         return 0;
1070     }
1071     
1072     unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout;
1073     
1074     if (timeDiff == 0)
1075         timeDiff = 1;
1076     
1077     m_timeExecuting += timeDiff;
1078     m_timeAtLastCheckTimeout = currentTime;
1079     
1080     // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in 
1081     // preferredScriptCheckTimeInterval
1082     m_ticksUntilNextTimeoutCheck = static_cast<unsigned>((static_cast<float>(preferredScriptCheckTimeInterval) / timeDiff) * m_ticksUntilNextTimeoutCheck);
1083     // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
1084     // preferred script check time interval.
1085     if (m_ticksUntilNextTimeoutCheck == 0)
1086         m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
1087     
1088     if (m_timeoutTime && m_timeExecuting > m_timeoutTime) {
1089         if (globalObject->shouldInterruptScript())
1090             return jsNull(); // Appeasing GCC, all we need is a non-null js value.
1091         
1092         resetTimeoutCheck();
1093     }
1094     
1095     return 0;
1096 }
1097
1098 static NEVER_INLINE ScopeChainNode* createExceptionScope(ExecState* exec, CodeBlock* codeBlock, const Instruction* vPC, Register* r, ScopeChainNode* scopeChain)
1099 {
1100     int dst = (++vPC)->u.operand;
1101     Identifier& property = codeBlock->identifiers[(++vPC)->u.operand];
1102     JSValue* value = r[(++vPC)->u.operand].jsValue(exec);
1103     JSObject* scope = new (exec) JSStaticScopeObject(exec, property, value, DontDelete);
1104     r[dst] = scope;
1105     return scopeChain->push(scope);
1106 }
1107
1108 static StructureIDChain* cachePrototypeChain(ExecState* exec, StructureID* structureID)
1109 {
1110     RefPtr<StructureIDChain> chain = StructureIDChain::create(static_cast<JSObject*>(structureID->prototypeForLookup(exec))->structureID());
1111     structureID->setCachedPrototypeChain(chain.release());
1112     return structureID->cachedPrototypeChain();
1113 }
1114
1115 NEVER_INLINE void Machine::tryCachePutByID(CodeBlock* codeBlock, Instruction* vPC, JSValue* baseValue, const PutPropertySlot& slot)
1116 {
1117     // Recursive invocation may already have specialized this instruction.
1118     if (vPC[0].u.opcode != getOpcode(op_put_by_id))
1119         return;
1120
1121     if (JSImmediate::isImmediate(baseValue))
1122         return;
1123
1124     // Uncacheable: give up.
1125     if (!slot.isCacheable()) {
1126         vPC[0] = getOpcode(op_put_by_id_generic);
1127         return;
1128     }
1129
1130     // FIXME: Cache new property transitions, too.
1131     if (slot.type() == PutPropertySlot::NewProperty) {
1132         vPC[0] = getOpcode(op_put_by_id_generic);
1133         return;
1134     }
1135     
1136     JSCell* baseCell = static_cast<JSCell*>(baseValue);
1137     StructureID* structureID = baseCell->structureID();
1138
1139     if (structureID->isDictionary()) {
1140         vPC[0] = getOpcode(op_put_by_id_generic);
1141         return;
1142     }
1143
1144     // Cache miss: record StructureID to compare against next time.
1145     StructureID* lastStructureID = vPC[4].u.structureID;
1146     if (structureID != lastStructureID) {
1147         // First miss: record StructureID to compare against next time.
1148         if (!lastStructureID) {
1149             vPC[4] = structureID;
1150             return;
1151         }
1152
1153         // Second miss: give up.
1154         vPC[0] = getOpcode(op_put_by_id_generic);
1155         return;
1156     }
1157
1158     // Cache hit: Specialize instruction and ref StructureIDs.
1159
1160     // If baseCell != slot.base(), then baseCell must be a proxy for another object.
1161     if (baseCell != slot.base()) {
1162         vPC[0] = getOpcode(op_put_by_id_generic);
1163         return;
1164     }
1165     vPC[0] = getOpcode(op_put_by_id_replace);
1166     vPC[5] = slot.cachedOffset();
1167     codeBlock->refStructureIDs(vPC);
1168 }
1169
1170 NEVER_INLINE void Machine::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC)
1171 {
1172     codeBlock->derefStructureIDs(vPC);
1173     vPC[0] = getOpcode(op_put_by_id);
1174     vPC[4] = 0;
1175 }
1176
1177 NEVER_INLINE void Machine::tryCacheGetByID(ExecState* exec, CodeBlock* codeBlock, Instruction* vPC, JSValue* baseValue, const Identifier& propertyName, const PropertySlot& slot)
1178 {
1179     // Recursive invocation may already have specialized this instruction.
1180     if (vPC[0].u.opcode != getOpcode(op_get_by_id))
1181         return;
1182         
1183     if (isJSArray(baseValue) && propertyName == exec->propertyNames().length) {
1184         vPC[0] = getOpcode(op_get_array_length);
1185         return;
1186     }
1187
1188     if (isJSString(baseValue) && propertyName == exec->propertyNames().length) {
1189         vPC[0] = getOpcode(op_get_string_length);
1190         return;
1191     }
1192
1193     // Uncacheable: give up.
1194     if (!slot.isCacheable()) {
1195         vPC[0] = getOpcode(op_get_by_id_generic);
1196         return;
1197     }
1198
1199     // FIXME: Cache property access for immediates.
1200     if (JSImmediate::isImmediate(baseValue)) {
1201         vPC[0] = getOpcode(op_get_by_id_generic);
1202         return;
1203     }
1204
1205     StructureID* structureID = static_cast<JSCell*>(baseValue)->structureID();
1206
1207     if (structureID->isDictionary()) {
1208         vPC[0] = getOpcode(op_get_by_id_generic);
1209         return;
1210     }
1211
1212     // Cache miss
1213     StructureID* lastStructureID = vPC[4].u.structureID;
1214     if (structureID != lastStructureID) {
1215         // First miss: record StructureID to compare against next time.
1216         if (!lastStructureID) {
1217             vPC[4] = structureID;
1218             return;
1219         }
1220
1221         // Second miss: give up.
1222         vPC[0] = getOpcode(op_get_by_id_generic);
1223         return;
1224     }
1225
1226     // Cache hit: Specialize instruction and ref StructureIDs.
1227
1228     if (slot.slotBase() == baseValue) {
1229         vPC[0] = getOpcode(op_get_by_id_self);
1230         vPC[5] = slot.cachedOffset();
1231
1232         codeBlock->refStructureIDs(vPC);
1233         return;
1234     }
1235
1236     if (slot.slotBase() == structureID->prototypeForLookup(exec)) {
1237         ASSERT(slot.slotBase()->isObject());
1238
1239         JSObject* baseObject = static_cast<JSObject*>(slot.slotBase());
1240
1241         // Heavy access to a prototype is a good indication that it's not being
1242         // used as a dictionary.
1243         if (baseObject->structureID()->isDictionary()) {
1244             RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(baseObject->structureID());
1245             baseObject->setStructureID(transition.release());
1246             static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
1247         }
1248
1249         vPC[0] = getOpcode(op_get_by_id_proto);
1250         vPC[5] = baseObject->structureID();
1251         vPC[6] = slot.cachedOffset();
1252
1253         codeBlock->refStructureIDs(vPC);
1254         return;
1255     }
1256
1257     size_t count = 0;
1258     JSObject* o = static_cast<JSObject*>(baseValue);
1259     while (slot.slotBase() != o) {
1260         JSValue* v = o->structureID()->prototypeForLookup(exec);
1261
1262         // If we didn't find base in baseValue's prototype chain, then baseValue
1263         // must be a proxy for another object.
1264         if (v->isNull()) {
1265             vPC[0] = getOpcode(op_get_by_id_generic);
1266             return;
1267         }
1268
1269         o = static_cast<JSObject*>(v);
1270
1271         // Heavy access to a prototype is a good indication that it's not being
1272         // used as a dictionary.
1273         if (o->structureID()->isDictionary()) {
1274             RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(o->structureID());
1275             o->setStructureID(transition.release());
1276             static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
1277         }
1278
1279         ++count;
1280     }
1281
1282     StructureIDChain* chain = structureID->cachedPrototypeChain();
1283     if (!chain)
1284         chain = cachePrototypeChain(exec, structureID);
1285
1286     vPC[0] = getOpcode(op_get_by_id_chain);
1287     vPC[4] = structureID;
1288     vPC[5] = chain;
1289     vPC[6] = count;
1290     vPC[7] = slot.cachedOffset();
1291     codeBlock->refStructureIDs(vPC);
1292 }
1293
1294 NEVER_INLINE void Machine::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC)
1295 {
1296     codeBlock->derefStructureIDs(vPC);
1297     vPC[0] = getOpcode(op_get_by_id);
1298     vPC[4] = 0;
1299 }
1300
1301 JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception)
1302 {
1303     // One-time initialization of our address tables. We have to put this code
1304     // here because our labels are only in scope inside this function.
1305     if (flag == InitializeAndReturn) {
1306         #if HAVE(COMPUTED_GOTO)
1307             #define ADD_OPCODE(id) m_opcodeTable[id] = &&id;
1308                 FOR_EACH_OPCODE_ID(ADD_OPCODE);
1309             #undef ADD_OPCODE
1310
1311             #define ADD_OPCODE_ID(id) m_opcodeIDTable.add(&&id, id);
1312                 FOR_EACH_OPCODE_ID(ADD_OPCODE_ID);
1313             #undef ADD_OPCODE_ID
1314             ASSERT(m_opcodeIDTable.size() == numOpcodeIDs);
1315             op_throw_end_indirect = &&op_throw_end;
1316             op_call_indirect = &&op_call;
1317         #endif // HAVE(COMPUTED_GOTO)
1318         return 0;
1319     }
1320
1321 #if ENABLE(CTI)
1322     // Currently with CTI enabled we never interpret functions
1323     ASSERT_NOT_REACHED();
1324 #endif
1325
1326     JSValue* exceptionValue = 0;
1327     Instruction* handlerVPC = 0;
1328
1329     Register* registerBase = registerFile->base();
1330     Instruction* vPC = codeBlock->instructions.begin();
1331     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
1332     unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1;
1333
1334 #define VM_CHECK_EXCEPTION() \
1335     do { \
1336         if (UNLIKELY(exec->hadException())) { \
1337             exceptionValue = exec->exception(); \
1338             goto vm_throw; \
1339         } \
1340     } while (0)
1341
1342 #if DUMP_OPCODE_STATS
1343     OpcodeStats::resetLastInstruction();
1344 #endif
1345
1346 #define CHECK_FOR_TIMEOUT() \
1347     if (!--tickCount) { \
1348         if ((exceptionValue = checkTimeout(exec->dynamicGlobalObject()))) \
1349             goto vm_throw; \
1350         tickCount = m_ticksUntilNextTimeoutCheck; \
1351     }
1352
1353 #if HAVE(COMPUTED_GOTO)
1354     #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); goto *vPC->u.opcode
1355 #if DUMP_OPCODE_STATS
1356     #define BEGIN_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
1357 #else
1358     #define BEGIN_OPCODE(opcode) opcode:
1359 #endif
1360     NEXT_OPCODE;
1361 #else
1362     #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); continue
1363 #if DUMP_OPCODE_STATS
1364     #define BEGIN_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
1365 #else
1366     #define BEGIN_OPCODE(opcode) case opcode:
1367 #endif
1368     while (1) // iterator loop begins
1369     switch (vPC->u.opcode)
1370 #endif
1371     {
1372     BEGIN_OPCODE(op_new_object) {
1373         /* new_object dst(r)
1374
1375            Constructs a new empty Object instance using the original
1376            constructor, and puts the result in register dst.
1377         */
1378         int dst = (++vPC)->u.operand;
1379         r[dst] = constructEmptyObject(exec);
1380
1381         ++vPC;
1382         NEXT_OPCODE;
1383     }
1384     BEGIN_OPCODE(op_new_array) {
1385         /* new_array dst(r) firstArg(r) argCount(n)
1386
1387            Constructs a new Array instance using the original
1388            constructor, and puts the result in register dst.
1389            The array will contain argCount elements with values
1390            taken from registers starting at register firstArg.
1391         */
1392         int dst = (++vPC)->u.operand;
1393         int firstArg = (++vPC)->u.operand;
1394         int argCount = (++vPC)->u.operand;
1395         ArgList args(r + firstArg, argCount);
1396         r[dst] = constructArray(exec, args);
1397
1398         ++vPC;
1399         NEXT_OPCODE;
1400     }
1401     BEGIN_OPCODE(op_new_regexp) {
1402         /* new_regexp dst(r) regExp(re)
1403
1404            Constructs a new RegExp instance using the original
1405            constructor from regexp regExp, and puts the result in
1406            register dst.
1407         */
1408         int dst = (++vPC)->u.operand;
1409         int regExp = (++vPC)->u.operand;
1410         r[dst] = new (exec) RegExpObject(scopeChain->globalObject()->regExpPrototype(), codeBlock->regexps[regExp]);
1411
1412         ++vPC;
1413         NEXT_OPCODE;
1414     }
1415     BEGIN_OPCODE(op_mov) {
1416         /* mov dst(r) src(r)
1417
1418            Copies register src to register dst.
1419         */
1420         int dst = (++vPC)->u.operand;
1421         int src = (++vPC)->u.operand;
1422         r[dst] = r[src];
1423
1424         ++vPC;
1425         NEXT_OPCODE;
1426     }
1427     BEGIN_OPCODE(op_eq) {
1428         /* eq dst(r) src1(r) src2(r)
1429
1430            Checks whether register src1 and register src2 are equal,
1431            as with the ECMAScript '==' operator, and puts the result
1432            as a boolean in register dst.
1433         */
1434         int dst = (++vPC)->u.operand;
1435         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1436         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1437         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1438             r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1439         else {
1440             JSValue* result = jsBoolean(equal(exec, src1, src2));
1441             VM_CHECK_EXCEPTION();
1442             r[dst] = result;
1443         }
1444
1445         ++vPC;
1446         NEXT_OPCODE;
1447     }
1448     BEGIN_OPCODE(op_eq_null) {
1449         /* neq dst(r) src(r)
1450
1451            Checks whether register src is null, as with the ECMAScript '!='
1452            operator, and puts the result as a boolean in register dst.
1453         */
1454         int dst = (++vPC)->u.operand;
1455         JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1456
1457         if (src->isUndefinedOrNull()) {
1458             r[dst] = jsBoolean(true);
1459             ++vPC;
1460             NEXT_OPCODE;
1461         }
1462         
1463         r[dst] = jsBoolean(!JSImmediate::isImmediate(src) && static_cast<JSCell*>(src)->masqueradeAsUndefined());
1464         ++vPC;
1465         NEXT_OPCODE;
1466     }
1467     BEGIN_OPCODE(op_neq) {
1468         /* neq dst(r) src1(r) src2(r)
1469
1470            Checks whether register src1 and register src2 are not
1471            equal, as with the ECMAScript '!=' operator, and puts the
1472            result as a boolean in register dst.
1473         */
1474         int dst = (++vPC)->u.operand;
1475         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1476         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1477         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1478             r[dst] = jsBoolean(src1 != src2);
1479         else {
1480             JSValue* result = jsBoolean(!equal(exec, src1, src2));
1481             VM_CHECK_EXCEPTION();
1482             r[dst] = result;
1483         }
1484
1485         ++vPC;
1486         NEXT_OPCODE;
1487     }
1488     BEGIN_OPCODE(op_neq_null) {
1489         /* neq dst(r) src(r)
1490
1491            Checks whether register src is not null, as with the ECMAScript '!='
1492            operator, and puts the result as a boolean in register dst.
1493         */
1494         int dst = (++vPC)->u.operand;
1495         JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1496
1497         if (src->isUndefinedOrNull()) {
1498             r[dst] = jsBoolean(false);
1499             ++vPC;
1500             NEXT_OPCODE;
1501         }
1502         
1503         r[dst] = jsBoolean(JSImmediate::isImmediate(src) || !static_cast<JSCell*>(src)->masqueradeAsUndefined());
1504         ++vPC;
1505         NEXT_OPCODE;
1506     }
1507     BEGIN_OPCODE(op_stricteq) {
1508         /* stricteq dst(r) src1(r) src2(r)
1509
1510            Checks whether register src1 and register src2 are strictly
1511            equal, as with the ECMAScript '===' operator, and puts the
1512            result as a boolean in register dst.
1513         */
1514         int dst = (++vPC)->u.operand;
1515         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1516         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1517         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1518             r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1519         else
1520             r[dst] = jsBoolean(strictEqual(src1, src2));
1521
1522         ++vPC;
1523         NEXT_OPCODE;
1524     }
1525     BEGIN_OPCODE(op_nstricteq) {
1526         /* nstricteq dst(r) src1(r) src2(r)
1527
1528            Checks whether register src1 and register src2 are not
1529            strictly equal, as with the ECMAScript '!==' operator, and
1530            puts the result as a boolean in register dst.
1531         */
1532         int dst = (++vPC)->u.operand;
1533         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1534         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1535         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1536             r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
1537         else
1538             r[dst] = jsBoolean(!strictEqual(src1, src2));
1539
1540         ++vPC;
1541         NEXT_OPCODE;
1542     }
1543     BEGIN_OPCODE(op_less) {
1544         /* less dst(r) src1(r) src2(r)
1545
1546            Checks whether register src1 is less than register src2, as
1547            with the ECMAScript '<' operator, and puts the result as
1548            a boolean in register dst.
1549         */
1550         int dst = (++vPC)->u.operand;
1551         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1552         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1553         JSValue* result = jsBoolean(jsLess(exec, src1, src2));
1554         VM_CHECK_EXCEPTION();
1555         r[dst] = result;
1556
1557         ++vPC;
1558         NEXT_OPCODE;
1559     }
1560     BEGIN_OPCODE(op_lesseq) {
1561         /* lesseq dst(r) src1(r) src2(r)
1562
1563            Checks whether register src1 is less than or equal to
1564            register src2, as with the ECMAScript '<=' operator, and
1565            puts the result as a boolean in register dst.
1566         */
1567         int dst = (++vPC)->u.operand;
1568         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1569         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1570         JSValue* result = jsBoolean(jsLessEq(exec, src1, src2));
1571         VM_CHECK_EXCEPTION();
1572         r[dst] = result;
1573
1574         ++vPC;
1575         NEXT_OPCODE;
1576     }
1577     BEGIN_OPCODE(op_pre_inc) {
1578         /* pre_inc srcDst(r)
1579
1580            Converts register srcDst to number, adds one, and puts the result
1581            back in register srcDst.
1582         */
1583         int srcDst = (++vPC)->u.operand;
1584         JSValue* v = r[srcDst].jsValue(exec);
1585         if (JSImmediate::canDoFastAdditiveOperations(v))
1586             r[srcDst] = JSImmediate::incImmediateNumber(v);
1587         else {
1588             JSValue* result = jsNumber(exec, v->toNumber(exec) + 1);
1589             VM_CHECK_EXCEPTION();
1590             r[srcDst] = result;
1591         }
1592
1593         ++vPC;
1594         NEXT_OPCODE;
1595     }
1596     BEGIN_OPCODE(op_pre_dec) {
1597         /* pre_dec srcDst(r)
1598
1599            Converts register srcDst to number, subtracts one, and puts the result
1600            back in register srcDst.
1601         */
1602         int srcDst = (++vPC)->u.operand;
1603         JSValue* v = r[srcDst].jsValue(exec);
1604         if (JSImmediate::canDoFastAdditiveOperations(v))
1605             r[srcDst] = JSImmediate::decImmediateNumber(v);
1606         else {
1607             JSValue* result = jsNumber(exec, v->toNumber(exec) - 1);
1608             VM_CHECK_EXCEPTION();
1609             r[srcDst] = result;
1610         }
1611
1612         ++vPC;
1613         NEXT_OPCODE;
1614     }
1615     BEGIN_OPCODE(op_post_inc) {
1616         /* post_inc dst(r) srcDst(r)
1617
1618            Converts register srcDst to number. The number itself is
1619            written to register dst, and the number plus one is written
1620            back to register srcDst.
1621         */
1622         int dst = (++vPC)->u.operand;
1623         int srcDst = (++vPC)->u.operand;
1624         JSValue* v = r[srcDst].jsValue(exec);
1625         if (JSImmediate::canDoFastAdditiveOperations(v)) {
1626             r[dst] = v;
1627             r[srcDst] = JSImmediate::incImmediateNumber(v);
1628         } else {
1629             JSValue* number = r[srcDst].jsValue(exec)->toJSNumber(exec);
1630             VM_CHECK_EXCEPTION();
1631             r[dst] = number;
1632             r[srcDst] = jsNumber(exec, number->uncheckedGetNumber() + 1);
1633         }
1634
1635         ++vPC;
1636         NEXT_OPCODE;
1637     }
1638     BEGIN_OPCODE(op_post_dec) {
1639         /* post_dec dst(r) srcDst(r)
1640
1641            Converts register srcDst to number. The number itself is
1642            written to register dst, and the number minus one is written
1643            back to register srcDst.
1644         */
1645         int dst = (++vPC)->u.operand;
1646         int srcDst = (++vPC)->u.operand;
1647         JSValue* v = r[srcDst].jsValue(exec);
1648         if (JSImmediate::canDoFastAdditiveOperations(v)) {
1649             r[dst] = v;
1650             r[srcDst] = JSImmediate::decImmediateNumber(v);
1651         } else {
1652             JSValue* number = r[srcDst].jsValue(exec)->toJSNumber(exec);
1653             VM_CHECK_EXCEPTION();
1654             r[dst] = number;
1655             r[srcDst] = jsNumber(exec, number->uncheckedGetNumber() - 1);
1656         }
1657
1658         ++vPC;
1659         NEXT_OPCODE;
1660     }
1661     BEGIN_OPCODE(op_to_jsnumber) {
1662         /* to_jsnumber dst(r) src(r)
1663
1664            Converts register src to number, and puts the result
1665            in register dst.
1666         */
1667         int dst = (++vPC)->u.operand;
1668         int src = (++vPC)->u.operand;
1669         JSValue* result = r[src].jsValue(exec)->toJSNumber(exec);
1670         VM_CHECK_EXCEPTION();
1671
1672         r[dst] = result;
1673
1674         ++vPC;
1675         NEXT_OPCODE;
1676     }
1677     BEGIN_OPCODE(op_negate) {
1678         /* negate dst(r) src(r)
1679
1680            Converts register src to number, negates it, and puts the
1681            result in register dst.
1682         */
1683         int dst = (++vPC)->u.operand;
1684         JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1685         double v;
1686         if (fastIsNumber(src, v))
1687             r[dst] = jsNumber(exec, -v);
1688         else {
1689             JSValue* result = jsNumber(exec, -src->toNumber(exec));
1690             VM_CHECK_EXCEPTION();
1691             r[dst] = result;
1692         }
1693
1694         ++vPC;
1695         NEXT_OPCODE;
1696     }
1697     BEGIN_OPCODE(op_add) {
1698         /* add dst(r) src1(r) src2(r)
1699
1700            Adds register src1 and register src2, and puts the result
1701            in register dst. (JS add may be string concatenation or
1702            numeric add, depending on the types of the operands.)
1703         */
1704         int dst = (++vPC)->u.operand;
1705         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1706         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1707         if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1708             r[dst] = JSImmediate::addImmediateNumbers(src1, src2);
1709         else {
1710             JSValue* result = jsAdd(exec, src1, src2);
1711             VM_CHECK_EXCEPTION();
1712             r[dst] = result;
1713         }
1714         ++vPC;
1715         NEXT_OPCODE;
1716     }
1717     BEGIN_OPCODE(op_mul) {
1718         /* mul dst(r) src1(r) src2(r)
1719
1720            Multiplies register src1 and register src2 (converted to
1721            numbers), and puts the product in register dst.
1722         */
1723         int dst = (++vPC)->u.operand;
1724         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1725         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1726         double left;
1727         double right;
1728         if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
1729             r[dst] = jsNumber(exec, left * right);
1730         else {
1731             JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
1732             VM_CHECK_EXCEPTION();
1733             r[dst] = result;
1734         }
1735
1736         ++vPC;
1737         NEXT_OPCODE;
1738     }
1739     BEGIN_OPCODE(op_div) {
1740         /* div dst(r) dividend(r) divisor(r)
1741
1742            Divides register dividend (converted to number) by the
1743            register divisor (converted to number), and puts the
1744            quotient in register dst.
1745         */
1746         int dst = (++vPC)->u.operand;
1747         JSValue* dividend = r[(++vPC)->u.operand].jsValue(exec);
1748         JSValue* divisor = r[(++vPC)->u.operand].jsValue(exec);
1749         double left;
1750         double right;
1751         if (fastIsNumber(dividend, left) && fastIsNumber(divisor, right))
1752             r[dst] = jsNumber(exec, left / right);
1753         else {
1754             JSValue* result = jsNumber(exec, dividend->toNumber(exec) / divisor->toNumber(exec));
1755             VM_CHECK_EXCEPTION();
1756             r[dst] = result;
1757         }
1758         ++vPC;
1759         NEXT_OPCODE;
1760     }
1761     BEGIN_OPCODE(op_mod) {
1762         /* mod dst(r) dividend(r) divisor(r)
1763
1764            Divides register dividend (converted to number) by
1765            register divisor (converted to number), and puts the
1766            remainder in register dst.
1767         */
1768         int dst = (++vPC)->u.operand;
1769         int dividend = (++vPC)->u.operand;
1770         int divisor = (++vPC)->u.operand;
1771
1772         JSValue* dividendValue = r[dividend].jsValue(exec);
1773         JSValue* divisorValue = r[divisor].jsValue(exec);
1774
1775         if (JSImmediate::areBothImmediateNumbers(dividendValue, divisorValue) && divisorValue != JSImmediate::from(0)) {
1776             r[dst] = JSImmediate::from(JSImmediate::getTruncatedInt32(dividendValue) % JSImmediate::getTruncatedInt32(divisorValue));
1777             ++vPC;
1778             NEXT_OPCODE;
1779         }
1780
1781         double d = dividendValue->toNumber(exec);
1782         JSValue* result = jsNumber(exec, fmod(d, divisorValue->toNumber(exec)));
1783         VM_CHECK_EXCEPTION();
1784         r[dst] = result;
1785         ++vPC;
1786         NEXT_OPCODE;
1787     }
1788     BEGIN_OPCODE(op_sub) {
1789         /* sub dst(r) src1(r) src2(r)
1790
1791            Subtracts register src2 (converted to number) from register
1792            src1 (converted to number), and puts the difference in
1793            register dst.
1794         */
1795         int dst = (++vPC)->u.operand;
1796         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1797         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1798         double left;
1799         double right;
1800         if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1801             r[dst] = JSImmediate::subImmediateNumbers(src1, src2);
1802         else if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
1803             r[dst] = jsNumber(exec, left - right);
1804         else {
1805             JSValue* result = jsNumber(exec, src1->toNumber(exec) - src2->toNumber(exec));
1806             VM_CHECK_EXCEPTION();
1807             r[dst] = result;
1808         }
1809         ++vPC;
1810         NEXT_OPCODE;
1811     }
1812     BEGIN_OPCODE(op_lshift) {
1813         /* lshift dst(r) val(r) shift(r)
1814
1815            Performs left shift of register val (converted to int32) by
1816            register shift (converted to uint32), and puts the result
1817            in register dst.
1818         */
1819         int dst = (++vPC)->u.operand;
1820         JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1821         JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1822         int32_t left;
1823         uint32_t right;
1824         if (JSImmediate::areBothImmediateNumbers(val, shift))
1825             r[dst] = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::getTruncatedUInt32(shift) & 0x1f));
1826         else if (fastToInt32(val, left) && fastToUInt32(shift, right))
1827             r[dst] = jsNumber(exec, left << (right & 0x1f));
1828         else {
1829             JSValue* result = jsNumber(exec, (val->toInt32(exec)) << (shift->toUInt32(exec) & 0x1f));
1830             VM_CHECK_EXCEPTION();
1831             r[dst] = result;
1832         }
1833
1834         ++vPC;
1835         NEXT_OPCODE;
1836     }
1837     BEGIN_OPCODE(op_rshift) {
1838         /* rshift dst(r) val(r) shift(r)
1839
1840            Performs arithmetic right shift of register val (converted
1841            to int32) by register shift (converted to
1842            uint32), and puts the result in register dst.
1843         */
1844         int dst = (++vPC)->u.operand;
1845         JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1846         JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1847         int32_t left;
1848         uint32_t right;
1849         if (JSImmediate::areBothImmediateNumbers(val, shift))
1850             r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
1851         else if (fastToInt32(val, left) && fastToUInt32(shift, right))
1852             r[dst] = jsNumber(exec, left >> (right & 0x1f));
1853         else {
1854             JSValue* result = jsNumber(exec, (val->toInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1855             VM_CHECK_EXCEPTION();
1856             r[dst] = result;
1857         }
1858
1859         ++vPC;
1860         NEXT_OPCODE;
1861     }
1862     BEGIN_OPCODE(op_urshift) {
1863         /* rshift dst(r) val(r) shift(r)
1864
1865            Performs logical right shift of register val (converted
1866            to uint32) by register shift (converted to
1867            uint32), and puts the result in register dst.
1868         */
1869         int dst = (++vPC)->u.operand;
1870         JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1871         JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1872         if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val))
1873             r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
1874         else {
1875             JSValue* result = jsNumber(exec, (val->toUInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1876             VM_CHECK_EXCEPTION();
1877             r[dst] = result;
1878         }
1879
1880         ++vPC;
1881         NEXT_OPCODE;
1882     }
1883     BEGIN_OPCODE(op_bitand) {
1884         /* bitand dst(r) src1(r) src2(r)
1885
1886            Computes bitwise AND of register src1 (converted to int32)
1887            and register src2 (converted to int32), and puts the result
1888            in register dst.
1889         */
1890         int dst = (++vPC)->u.operand;
1891         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1892         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1893         int32_t left;
1894         int32_t right;
1895         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1896             r[dst] = JSImmediate::andImmediateNumbers(src1, src2);
1897         else if (fastToInt32(src1, left) && fastToInt32(src2, right))
1898             r[dst] = jsNumber(exec, left & right);
1899         else {
1900             JSValue* result = jsNumber(exec, src1->toInt32(exec) & src2->toInt32(exec));
1901             VM_CHECK_EXCEPTION();
1902             r[dst] = result;
1903         }
1904
1905         ++vPC;
1906         NEXT_OPCODE;
1907     }
1908     BEGIN_OPCODE(op_bitxor) {
1909         /* bitxor dst(r) src1(r) src2(r)
1910
1911            Computes bitwise XOR of register src1 (converted to int32)
1912            and register src2 (converted to int32), and puts the result
1913            in register dst.
1914         */
1915         int dst = (++vPC)->u.operand;
1916         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1917         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1918         int32_t left;
1919         int32_t right;
1920         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1921             r[dst] = JSImmediate::xorImmediateNumbers(src1, src2);
1922         else if (fastToInt32(src1, left) && fastToInt32(src2, right))
1923             r[dst] = jsNumber(exec, left ^ right);
1924         else {
1925             JSValue* result = jsNumber(exec, src1->toInt32(exec) ^ src2->toInt32(exec));
1926             VM_CHECK_EXCEPTION();
1927             r[dst] = result;
1928         }
1929
1930         ++vPC;
1931         NEXT_OPCODE;
1932     }
1933     BEGIN_OPCODE(op_bitor) {
1934         /* bitor dst(r) src1(r) src2(r)
1935
1936            Computes bitwise OR of register src1 (converted to int32)
1937            and register src2 (converted to int32), and puts the
1938            result in register dst.
1939         */
1940         int dst = (++vPC)->u.operand;
1941         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1942         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1943         int32_t left;
1944         int32_t right;
1945         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1946             r[dst] = JSImmediate::orImmediateNumbers(src1, src2);
1947         else if (fastToInt32(src1, left) && fastToInt32(src2, right))
1948             r[dst] = jsNumber(exec, left | right);
1949         else {
1950             JSValue* result = jsNumber(exec, src1->toInt32(exec) | src2->toInt32(exec));
1951             VM_CHECK_EXCEPTION();
1952             r[dst] = result;
1953         }
1954
1955         ++vPC;
1956         NEXT_OPCODE;
1957     }
1958     BEGIN_OPCODE(op_bitnot) {
1959         /* bitnot dst(r) src(r)
1960
1961            Computes bitwise NOT of register src1 (converted to int32),
1962            and puts the result in register dst.
1963         */
1964         int dst = (++vPC)->u.operand;
1965         JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1966         int32_t value;
1967         if (fastToInt32(src, value))
1968             r[dst] = jsNumber(exec, ~value);
1969         else {
1970             JSValue* result = jsNumber(exec, ~src->toInt32(exec));
1971             VM_CHECK_EXCEPTION();
1972             r[dst] = result;
1973         }
1974         ++vPC;
1975         NEXT_OPCODE;
1976     }
1977     BEGIN_OPCODE(op_not) {
1978         /* not dst(r) src(r)
1979
1980            Computes logical NOT of register src (converted to
1981            boolean), and puts the result in register dst.
1982         */
1983         int dst = (++vPC)->u.operand;
1984         int src = (++vPC)->u.operand;
1985         JSValue* result = jsBoolean(!r[src].jsValue(exec)->toBoolean(exec));
1986         VM_CHECK_EXCEPTION();
1987         r[dst] = result;
1988
1989         ++vPC;
1990         NEXT_OPCODE;
1991     }
1992     BEGIN_OPCODE(op_instanceof) {
1993         /* instanceof dst(r) value(r) constructor(r)
1994
1995            Tests whether register value is an instance of register
1996            constructor, and puts the boolean result in register dst.
1997
1998            Raises an exception if register constructor is not an
1999            object.
2000         */
2001         int dst = (++vPC)->u.operand;
2002         int value = (++vPC)->u.operand;
2003         int base = (++vPC)->u.operand;
2004
2005         JSValue* baseVal = r[base].jsValue(exec);
2006
2007         if (isNotObject(exec, true, codeBlock, vPC, baseVal, exceptionValue))
2008             goto vm_throw;
2009
2010         JSObject* baseObj = static_cast<JSObject*>(baseVal);
2011         r[dst] = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, r[value].jsValue(exec)) : false);
2012
2013         ++vPC;
2014         NEXT_OPCODE;
2015     }
2016     BEGIN_OPCODE(op_typeof) {
2017         /* typeof dst(r) src(r)
2018
2019            Determines the type string for src according to ECMAScript
2020            rules, and puts the result in register dst.
2021         */
2022         int dst = (++vPC)->u.operand;
2023         int src = (++vPC)->u.operand;
2024         r[dst] = jsTypeStringForValue(exec, r[src].jsValue(exec));
2025
2026         ++vPC;
2027         NEXT_OPCODE;
2028     }
2029     BEGIN_OPCODE(op_in) {
2030         /* in dst(r) property(r) base(r)
2031
2032            Tests whether register base has a property named register
2033            property, and puts the boolean result in register dst.
2034
2035            Raises an exception if register constructor is not an
2036            object.
2037         */
2038         int dst = (++vPC)->u.operand;
2039         int property = (++vPC)->u.operand;
2040         int base = (++vPC)->u.operand;
2041
2042         JSValue* baseVal = r[base].jsValue(exec);
2043         if (isNotObject(exec, false, codeBlock, vPC, baseVal, exceptionValue))
2044             goto vm_throw;
2045
2046         JSObject* baseObj = static_cast<JSObject*>(baseVal);
2047
2048         JSValue* propName = r[property].jsValue(exec);
2049
2050         uint32_t i;
2051         if (propName->getUInt32(i))
2052             r[dst] = jsBoolean(baseObj->hasProperty(exec, i));
2053         else {
2054             Identifier property(exec, propName->toString(exec));
2055             VM_CHECK_EXCEPTION();
2056             r[dst] = jsBoolean(baseObj->hasProperty(exec, property));
2057         }
2058
2059         ++vPC;
2060         NEXT_OPCODE;
2061     }
2062     BEGIN_OPCODE(op_resolve) {
2063         /* resolve dst(r) property(id)
2064
2065            Looks up the property named by identifier property in the
2066            scope chain, and writes the resulting value to register
2067            dst. If the property is not found, raises an exception.
2068         */
2069         if (UNLIKELY(!resolve(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
2070             goto vm_throw;
2071
2072         vPC += 3;
2073         NEXT_OPCODE;
2074     }
2075     BEGIN_OPCODE(op_resolve_skip) {
2076         /* resolve_skip dst(r) property(id) skip(n)
2077
2078          Looks up the property named by identifier property in the
2079          scope chain skipping the top 'skip' levels, and writes the resulting
2080          value to register dst. If the property is not found, raises an exception.
2081          */
2082         if (UNLIKELY(!resolve_skip(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
2083             goto vm_throw;
2084
2085         vPC += 4;
2086
2087         NEXT_OPCODE;
2088     }
2089     BEGIN_OPCODE(op_get_global_var) {
2090         /* get_global_var dst(r) index(n)
2091
2092            Gets the global var at global slot index and places it in register dst.
2093          */
2094         int dst = (++vPC)->u.operand;
2095         JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
2096         ASSERT(scope->isGlobalObject());
2097         int index = (++vPC)->u.operand;
2098
2099         r[dst] = scope->registerAt(index);
2100         ++vPC;
2101         NEXT_OPCODE;
2102     }
2103     BEGIN_OPCODE(op_put_global_var) {
2104         /* put_global_var globalObject(c) index(n) value(r)
2105          
2106            Puts value into global slot index.
2107          */
2108         JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
2109         ASSERT(scope->isGlobalObject());
2110         int index = (++vPC)->u.operand;
2111         int value = (++vPC)->u.operand;
2112         
2113         scope->registerAt(index) = r[value].jsValue(exec);
2114         ++vPC;
2115         NEXT_OPCODE;
2116     }            
2117     BEGIN_OPCODE(op_get_scoped_var) {
2118         /* get_scoped_var dst(r) index(n) skip(n)
2119
2120          Loads the contents of the index-th local from the scope skip nodes from
2121          the top of the scope chain, and places it in register dst
2122          */
2123         int dst = (++vPC)->u.operand;
2124         int index = (++vPC)->u.operand;
2125         int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
2126
2127         ScopeChainIterator iter = scopeChain->begin();
2128         ScopeChainIterator end = scopeChain->end();
2129         ASSERT(iter != end);
2130         while (skip--) {
2131             ++iter;
2132             ASSERT(iter != end);
2133         }
2134
2135         ASSERT((*iter)->isVariableObject());
2136         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
2137         r[dst] = scope->registerAt(index);
2138         ++vPC;
2139         NEXT_OPCODE;
2140     }
2141     BEGIN_OPCODE(op_put_scoped_var) {
2142         /* put_scoped_var index(n) skip(n) value(r)
2143
2144          */
2145         int index = (++vPC)->u.operand;
2146         int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
2147         int value = (++vPC)->u.operand;
2148
2149         ScopeChainIterator iter = scopeChain->begin();
2150         ScopeChainIterator end = scopeChain->end();
2151         ASSERT(iter != end);
2152         while (skip--) {
2153             ++iter;
2154             ASSERT(iter != end);
2155         }
2156
2157         ASSERT((*iter)->isVariableObject());
2158         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
2159         scope->registerAt(index) = r[value].jsValue(exec);
2160         ++vPC;
2161         NEXT_OPCODE;
2162     }
2163     BEGIN_OPCODE(op_resolve_base) {
2164         /* resolve_base dst(r) property(id)
2165
2166            Searches the scope chain for an object containing
2167            identifier property, and if one is found, writes it to
2168            register dst. If none is found, the outermost scope (which
2169            will be the global object) is stored in register dst.
2170         */
2171         resolveBase(exec, vPC, r, scopeChain, codeBlock);
2172
2173         vPC += 3;
2174         NEXT_OPCODE;
2175     }
2176     BEGIN_OPCODE(op_resolve_with_base) {
2177         /* resolve_with_base baseDst(r) propDst(r) property(id)
2178
2179            Searches the scope chain for an object containing
2180            identifier property, and if one is found, writes it to
2181            register srcDst, and the retrieved property value to register
2182            propDst. If the property is not found, raises an exception.
2183
2184            This is more efficient than doing resolve_base followed by
2185            resolve, or resolve_base followed by get_by_id, as it
2186            avoids duplicate hash lookups.
2187         */
2188         if (UNLIKELY(!resolveBaseAndProperty(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
2189             goto vm_throw;
2190
2191         vPC += 4;
2192         NEXT_OPCODE;
2193     }
2194     BEGIN_OPCODE(op_resolve_func) {
2195         /* resolve_func baseDst(r) funcDst(r) property(id)
2196
2197            Searches the scope chain for an object containing
2198            identifier property, and if one is found, writes the
2199            appropriate object to use as "this" when calling its
2200            properties to register baseDst; and the retrieved property
2201            value to register propDst. If the property is not found,
2202            raises an exception.
2203
2204            This differs from resolve_with_base, because the
2205            global this value will be substituted for activations or
2206            the global object, which is the right behavior for function
2207            calls but not for other property lookup.
2208         */
2209         if (UNLIKELY(!resolveBaseAndFunc(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
2210             goto vm_throw;
2211
2212         vPC += 4;
2213         NEXT_OPCODE;
2214     }
2215     BEGIN_OPCODE(op_get_by_id) {
2216         /* get_by_id dst(r) base(r) property(id) structureID(sID) nop(n) nop(n) nop(n)
2217
2218            Generic property access: Gets the property named by identifier
2219            property from the value base, and puts the result in register dst.
2220         */
2221         int dst = vPC[1].u.operand;
2222         int base = vPC[2].u.operand;
2223         int property = vPC[3].u.operand;
2224
2225         Identifier& ident = codeBlock->identifiers[property];
2226         JSValue* baseValue = r[base].jsValue(exec);
2227         PropertySlot slot(baseValue);
2228         JSValue* result = baseValue->get(exec, ident, slot);
2229         VM_CHECK_EXCEPTION();
2230
2231         tryCacheGetByID(exec, codeBlock, vPC, baseValue, ident, slot);
2232
2233         r[dst] = result;
2234         vPC += 8;
2235         NEXT_OPCODE;
2236     }
2237     BEGIN_OPCODE(op_get_by_id_self) {
2238         /* op_get_by_id_self dst(r) base(r) property(id) structureID(sID) offset(n) nop(n) nop(n)
2239
2240            Cached property access: Attempts to get a cached property from the
2241            value base. If the cache misses, op_get_by_id_self reverts to
2242            op_get_by_id.
2243         */
2244         int base = vPC[2].u.operand;
2245         JSValue* baseValue = r[base].jsValue(exec);
2246
2247         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2248             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2249             StructureID* structureID = vPC[4].u.structureID;
2250
2251             if (LIKELY(baseCell->structureID() == structureID)) {
2252                 ASSERT(baseCell->isObject());
2253                 JSObject* baseObject = static_cast<JSObject*>(baseCell);
2254                 int dst = vPC[1].u.operand;
2255                 int offset = vPC[5].u.operand;
2256
2257                 ASSERT(baseObject->get(exec, codeBlock->identifiers[vPC[3].u.operand]) == baseObject->getDirectOffset(offset));
2258                 r[dst] = baseObject->getDirectOffset(offset);
2259
2260                 vPC += 8;
2261                 NEXT_OPCODE;
2262             }
2263         }
2264
2265         uncacheGetByID(codeBlock, vPC);
2266         NEXT_OPCODE;
2267     }
2268     BEGIN_OPCODE(op_get_by_id_proto) {
2269         /* op_get_by_id_proto dst(r) base(r) property(id) structureID(sID) protoStructureID(sID) offset(n) nop(n)
2270
2271            Cached property access: Attempts to get a cached property from the
2272            value base's prototype. If the cache misses, op_get_by_id_proto
2273            reverts to op_get_by_id.
2274         */
2275         int base = vPC[2].u.operand;
2276         JSValue* baseValue = r[base].jsValue(exec);
2277
2278         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2279             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2280             StructureID* structureID = vPC[4].u.structureID;
2281
2282             if (LIKELY(baseCell->structureID() == structureID)) {
2283                 ASSERT(structureID->prototypeForLookup(exec)->isObject());
2284                 JSObject* protoObject = static_cast<JSObject*>(structureID->prototypeForLookup(exec));
2285                 StructureID* protoStructureID = vPC[5].u.structureID;
2286
2287                 if (LIKELY(protoObject->structureID() == protoStructureID)) {
2288                     int dst = vPC[1].u.operand;
2289                     int offset = vPC[6].u.operand;
2290
2291                     ASSERT(protoObject->get(exec, codeBlock->identifiers[vPC[3].u.operand]) == protoObject->getDirectOffset(offset));
2292                     r[dst] = protoObject->getDirectOffset(offset);
2293
2294                     vPC += 8;
2295                     NEXT_OPCODE;
2296                 }
2297             }
2298         }
2299
2300         uncacheGetByID(codeBlock, vPC);
2301         NEXT_OPCODE;
2302     }
2303     BEGIN_OPCODE(op_get_by_id_chain) {
2304         /* op_get_by_id_chain dst(r) base(r) property(id) structureID(sID) structureIDChain(sIDc) count(n) offset(n)
2305
2306            Cached property access: Attempts to get a cached property from the
2307            value base's prototype chain. If the cache misses, op_get_by_id_chain
2308            reverts to op_get_by_id.
2309         */
2310         int base = vPC[2].u.operand;
2311         JSValue* baseValue = r[base].jsValue(exec);
2312
2313         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2314             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2315             StructureID* structureID = vPC[4].u.structureID;
2316
2317             if (LIKELY(baseCell->structureID() == structureID)) {
2318                 RefPtr<StructureID>* it = vPC[5].u.structureIDChain->head();
2319                 size_t count = vPC[6].u.operand;
2320                 RefPtr<StructureID>* end = it + count;
2321
2322                 while (1) {
2323                     ASSERT(baseCell->isObject());
2324                     JSObject* baseObject = static_cast<JSObject*>(baseCell->structureID()->prototypeForLookup(exec));
2325                     if (UNLIKELY(baseObject->structureID() != (*it).get()))
2326                         break;
2327
2328                     if (++it == end) {
2329                         int dst = vPC[1].u.operand;
2330                         int offset = vPC[7].u.operand;
2331
2332                         ASSERT(baseObject->get(exec, codeBlock->identifiers[vPC[3].u.operand]) == baseObject->getDirectOffset(offset));
2333                         r[dst] = baseObject->getDirectOffset(offset);
2334
2335                         vPC += 8;
2336                         NEXT_OPCODE;
2337                     }
2338                 }
2339             }
2340         }
2341
2342         uncacheGetByID(codeBlock, vPC);
2343         NEXT_OPCODE;
2344     }
2345     BEGIN_OPCODE(op_get_by_id_generic) {
2346         /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2347
2348            Generic property access: Gets the property named by identifier
2349            property from the value base, and puts the result in register dst.
2350         */
2351         int dst = vPC[1].u.operand;
2352         int base = vPC[2].u.operand;
2353         int property = vPC[3].u.operand;
2354
2355         Identifier& ident = codeBlock->identifiers[property];
2356
2357         JSValue* baseValue = r[base].jsValue(exec);
2358         PropertySlot slot(baseValue);
2359         JSValue* result = baseValue->get(exec, ident, slot);
2360         VM_CHECK_EXCEPTION();
2361
2362         r[dst] = result;
2363         vPC += 8;
2364         NEXT_OPCODE;
2365     }
2366     BEGIN_OPCODE(op_get_array_length) {
2367         /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2368
2369            Cached property access: Gets the length of the array in register base,
2370            and puts the result in register dst. If register base does not hold
2371            an array, op_get_array_length reverts to op_get_by_id.
2372         */
2373
2374         int base = vPC[2].u.operand;
2375         JSValue* baseValue = r[base].jsValue(exec);
2376         if (LIKELY(isJSArray(baseValue))) {
2377             int dst = vPC[1].u.operand;
2378             r[dst] = jsNumber(exec, static_cast<JSArray*>(baseValue)->length());
2379             vPC += 8;
2380             NEXT_OPCODE;
2381         }
2382
2383         uncacheGetByID(codeBlock, vPC);
2384         NEXT_OPCODE;
2385     }
2386     BEGIN_OPCODE(op_get_string_length) {
2387         /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2388
2389            Cached property access: Gets the length of the string in register base,
2390            and puts the result in register dst. If register base does not hold
2391            a string, op_get_string_length reverts to op_get_by_id.
2392         */
2393
2394         int base = vPC[2].u.operand;
2395         JSValue* baseValue = r[base].jsValue(exec);
2396         if (LIKELY(isJSString(baseValue))) {
2397             int dst = vPC[1].u.operand;
2398             r[dst] = jsNumber(exec, static_cast<JSString*>(baseValue)->value().size());
2399             vPC += 8;
2400             NEXT_OPCODE;
2401         }
2402
2403         uncacheGetByID(codeBlock, vPC);
2404         NEXT_OPCODE;
2405     }
2406     BEGIN_OPCODE(op_put_by_id) {
2407         /* put_by_id base(r) property(id) value(r) nop(n) nop(n)
2408
2409            Generic property access: Sets the property named by identifier
2410            property, belonging to register base, to register value.
2411
2412            Unlike many opcodes, this one does not write any output to
2413            the register file.
2414         */
2415
2416         int base = vPC[1].u.operand;
2417         int property = vPC[2].u.operand;
2418         int value = vPC[3].u.operand;
2419
2420         JSValue* baseValue = r[base].jsValue(exec);
2421
2422         PutPropertySlot slot;
2423         Identifier& ident = codeBlock->identifiers[property];
2424         baseValue->put(exec, ident, r[value].jsValue(exec), slot);
2425         VM_CHECK_EXCEPTION();
2426
2427         tryCachePutByID(codeBlock, vPC, baseValue, slot);
2428
2429         vPC += 6;
2430         NEXT_OPCODE;
2431     }
2432     BEGIN_OPCODE(op_put_by_id_replace) {
2433         /* op_put_by_id_replace base(r) property(id) value(r) structureID(sID) offset(n)
2434
2435            Cached property access: Attempts to set a pre-existing, cached
2436            property named by identifier property, belonging to register base,
2437            to register value. If the cache misses, op_put_by_id_replace
2438            reverts to op_put_by_id.
2439
2440            Unlike many opcodes, this one does not write any output to
2441            the register file.
2442         */
2443         int base = vPC[1].u.operand;
2444         JSValue* baseValue = r[base].jsValue(exec);
2445
2446         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2447             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2448             StructureID* structureID = vPC[4].u.structureID;
2449
2450             if (LIKELY(baseCell->structureID() == structureID)) {
2451                 ASSERT(baseCell->isObject());
2452                 JSObject* baseObject = static_cast<JSObject*>(baseCell);
2453                 int value = vPC[3].u.operand;
2454                 unsigned offset = vPC[5].u.operand;
2455                 
2456                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(codeBlock->identifiers[vPC[2].u.operand])) == offset);
2457                 baseObject->putDirectOffset(offset, r[value].jsValue(exec));
2458
2459                 vPC += 6;
2460                 NEXT_OPCODE;
2461             }
2462         }
2463
2464         uncachePutByID(codeBlock, vPC);
2465         NEXT_OPCODE;
2466     }
2467     BEGIN_OPCODE(op_put_by_id_generic) {
2468         /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n)
2469
2470            Generic property access: Sets the property named by identifier
2471            property, belonging to register base, to register value.
2472
2473            Unlike many opcodes, this one does not write any output to
2474            the register file.
2475         */
2476         int base = vPC[1].u.operand;
2477         int property = vPC[2].u.operand;
2478         int value = vPC[3].u.operand;
2479
2480         JSValue* baseValue = r[base].jsValue(exec);
2481
2482         PutPropertySlot slot;
2483         Identifier& ident = codeBlock->identifiers[property];
2484         baseValue->put(exec, ident, r[value].jsValue(exec), slot);
2485         VM_CHECK_EXCEPTION();
2486
2487         vPC += 6;
2488         NEXT_OPCODE;
2489     }
2490     BEGIN_OPCODE(op_del_by_id) {
2491         /* del_by_id dst(r) base(r) property(id)
2492
2493            Converts register base to Object, deletes the property
2494            named by identifier property from the object, and writes a
2495            boolean indicating success (if true) or failure (if false)
2496            to register dst.
2497         */
2498         int dst = (++vPC)->u.operand;
2499         int base = (++vPC)->u.operand;
2500         int property = (++vPC)->u.operand;
2501
2502         JSObject* baseObj = r[base].jsValue(exec)->toObject(exec);
2503
2504         Identifier& ident = codeBlock->identifiers[property];
2505         JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
2506         VM_CHECK_EXCEPTION();
2507         r[dst] = result;
2508         ++vPC;
2509         NEXT_OPCODE;
2510     }
2511     BEGIN_OPCODE(op_get_by_val) {
2512         /* get_by_val dst(r) base(r) property(r)
2513
2514            Converts register base to Object, gets the property named
2515            by register property from the object, and puts the result
2516            in register dst. property is nominally converted to string
2517            but numbers are treated more efficiently.
2518         */
2519         int dst = (++vPC)->u.operand;
2520         int base = (++vPC)->u.operand;
2521         int property = (++vPC)->u.operand;
2522         
2523         JSValue* baseValue = r[base].jsValue(exec);
2524         JSValue* subscript = r[property].jsValue(exec);
2525
2526         JSValue* result;
2527         unsigned i;
2528
2529         bool isUInt32 = JSImmediate::getUInt32(subscript, i);
2530         if (LIKELY(isUInt32)) {
2531             if (isJSArray(baseValue)) {
2532                 JSArray* jsArray = static_cast<JSArray*>(baseValue);
2533                 if (jsArray->canGetIndex(i))
2534                     result = jsArray->getIndex(i);
2535                 else
2536                     result = jsArray->JSArray::get(exec, i);
2537             } else if (isJSString(baseValue) && static_cast<JSString*>(baseValue)->canGetIndex(i))
2538                 result = static_cast<JSString*>(baseValue)->getIndex(exec, i);
2539             else
2540                 result = baseValue->get(exec, i);
2541         } else {
2542             Identifier property(exec, subscript->toString(exec));
2543             result = baseValue->get(exec, property);
2544         }
2545
2546         VM_CHECK_EXCEPTION();
2547         r[dst] = result;
2548         ++vPC;
2549         NEXT_OPCODE;
2550     }
2551     BEGIN_OPCODE(op_put_by_val) {
2552         /* put_by_val base(r) property(r) value(r)
2553
2554            Sets register value on register base as the property named
2555            by register property. Base is converted to object
2556            first. register property is nominally converted to string
2557            but numbers are treated more efficiently.
2558
2559            Unlike many opcodes, this one does not write any output to
2560            the register file.
2561         */
2562         int base = (++vPC)->u.operand;
2563         int property = (++vPC)->u.operand;
2564         int value = (++vPC)->u.operand;
2565
2566         JSValue* baseValue = r[base].jsValue(exec);
2567         JSValue* subscript = r[property].jsValue(exec);
2568
2569         unsigned i;
2570
2571         bool isUInt32 = JSImmediate::getUInt32(subscript, i);
2572         if (LIKELY(isUInt32)) {
2573             if (isJSArray(baseValue)) {
2574                 JSArray* jsArray = static_cast<JSArray*>(baseValue);
2575                 if (jsArray->canSetIndex(i))
2576                     jsArray->setIndex(i, r[value].jsValue(exec));
2577                 else
2578                     jsArray->JSArray::put(exec, i, r[value].jsValue(exec));
2579             } else
2580                 baseValue->put(exec, i, r[value].jsValue(exec));
2581         } else {
2582             Identifier property(exec, subscript->toString(exec));
2583             if (!exec->hadException()) { // Don't put to an object if toString threw an exception.
2584                 PutPropertySlot slot;
2585                 baseValue->put(exec, property, r[value].jsValue(exec), slot);
2586             }
2587         }
2588
2589         VM_CHECK_EXCEPTION();
2590         ++vPC;
2591         NEXT_OPCODE;
2592     }
2593     BEGIN_OPCODE(op_del_by_val) {
2594         /* del_by_val dst(r) base(r) property(r)
2595
2596            Converts register base to Object, deletes the property
2597            named by register property from the object, and writes a
2598            boolean indicating success (if true) or failure (if false)
2599            to register dst.
2600         */
2601         int dst = (++vPC)->u.operand;
2602         int base = (++vPC)->u.operand;
2603         int property = (++vPC)->u.operand;
2604
2605         JSObject* baseObj = r[base].jsValue(exec)->toObject(exec); // may throw
2606
2607         JSValue* subscript = r[property].jsValue(exec);
2608         JSValue* result;
2609         uint32_t i;
2610         if (subscript->getUInt32(i))
2611             result = jsBoolean(baseObj->deleteProperty(exec, i));
2612         else {
2613             VM_CHECK_EXCEPTION();
2614             Identifier property(exec, subscript->toString(exec));
2615             VM_CHECK_EXCEPTION();
2616             result = jsBoolean(baseObj->deleteProperty(exec, property));
2617         }
2618
2619         VM_CHECK_EXCEPTION();
2620         r[dst] = result;
2621         ++vPC;
2622         NEXT_OPCODE;
2623     }
2624     BEGIN_OPCODE(op_put_by_index) {
2625         /* put_by_index base(r) property(n) value(r)
2626
2627            Sets register value on register base as the property named
2628            by the immediate number property. Base is converted to
2629            object first.
2630
2631            Unlike many opcodes, this one does not write any output to
2632            the register file.
2633
2634            This opcode is mainly used to initialize array literals.
2635         */
2636         int base = (++vPC)->u.operand;
2637         unsigned property = (++vPC)->u.operand;
2638         int value = (++vPC)->u.operand;
2639
2640         r[base].jsValue(exec)->put(exec, property, r[value].jsValue(exec));
2641
2642         ++vPC;
2643         NEXT_OPCODE;
2644     }
2645     BEGIN_OPCODE(op_loop) {
2646         /* loop target(offset)
2647          
2648            Jumps unconditionally to offset target from the current
2649            instruction.
2650
2651            Additionally this loop instruction may terminate JS execution is
2652            the JS timeout is reached.
2653          */
2654 #if DUMP_OPCODE_STATS
2655         OpcodeStats::resetLastInstruction();
2656 #endif
2657         int target = (++vPC)->u.operand;
2658         CHECK_FOR_TIMEOUT();
2659         vPC += target;
2660         NEXT_OPCODE;
2661     }
2662     BEGIN_OPCODE(op_jmp) {
2663         /* jmp target(offset)
2664
2665            Jumps unconditionally to offset target from the current
2666            instruction.
2667         */
2668 #if DUMP_OPCODE_STATS
2669         OpcodeStats::resetLastInstruction();
2670 #endif
2671         int target = (++vPC)->u.operand;
2672
2673         vPC += target;
2674         NEXT_OPCODE;
2675     }
2676     BEGIN_OPCODE(op_loop_if_true) {
2677         /* loop_if_true cond(r) target(offset)
2678          
2679            Jumps to offset target from the current instruction, if and
2680            only if register cond converts to boolean as true.
2681
2682            Additionally this loop instruction may terminate JS execution is
2683            the JS timeout is reached.
2684          */
2685         int cond = (++vPC)->u.operand;
2686         int target = (++vPC)->u.operand;
2687         if (r[cond].jsValue(exec)->toBoolean(exec)) {
2688             vPC += target;
2689             CHECK_FOR_TIMEOUT();
2690             NEXT_OPCODE;
2691         }
2692         
2693         ++vPC;
2694         NEXT_OPCODE;
2695     }
2696     BEGIN_OPCODE(op_jtrue) {
2697         /* jtrue cond(r) target(offset)
2698
2699            Jumps to offset target from the current instruction, if and
2700            only if register cond converts to boolean as true.
2701         */
2702         int cond = (++vPC)->u.operand;
2703         int target = (++vPC)->u.operand;
2704         if (r[cond].jsValue(exec)->toBoolean(exec)) {
2705             vPC += target;
2706             NEXT_OPCODE;
2707         }
2708
2709         ++vPC;
2710         NEXT_OPCODE;
2711     }
2712     BEGIN_OPCODE(op_jfalse) {
2713         /* jfalse cond(r) target(offset)
2714
2715            Jumps to offset target from the current instruction, if and
2716            only if register cond converts to boolean as false.
2717         */
2718         int cond = (++vPC)->u.operand;
2719         int target = (++vPC)->u.operand;
2720         if (!r[cond].jsValue(exec)->toBoolean(exec)) {
2721             vPC += target;
2722             NEXT_OPCODE;
2723         }
2724
2725         ++vPC;
2726         NEXT_OPCODE;
2727     }
2728     BEGIN_OPCODE(op_loop_if_less) {
2729         /* loop_if_less src1(r) src2(r) target(offset)
2730
2731            Checks whether register src1 is less than register src2, as
2732            with the ECMAScript '<' operator, and then jumps to offset
2733            target from the current instruction, if and only if the 
2734            result of the comparison is true.
2735
2736            Additionally this loop instruction may terminate JS execution is
2737            the JS timeout is reached.
2738          */
2739         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2740         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2741         int target = (++vPC)->u.operand;
2742         
2743         bool result = jsLess(exec, src1, src2);
2744         VM_CHECK_EXCEPTION();
2745         
2746         if (result) {
2747             vPC += target;
2748             CHECK_FOR_TIMEOUT();
2749             NEXT_OPCODE;
2750         }
2751         
2752         ++vPC;
2753         NEXT_OPCODE;
2754     }
2755     BEGIN_OPCODE(op_jnless) {
2756         /* jnless src1(r) src2(r) target(offset)
2757
2758            Checks whether register src1 is less than register src2, as
2759            with the ECMAScript '<' operator, and then jumps to offset
2760            target from the current instruction, if and only if the 
2761            result of the comparison is false.
2762         */
2763         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2764         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2765         int target = (++vPC)->u.operand;
2766
2767         bool result = jsLess(exec, src1, src2);
2768         VM_CHECK_EXCEPTION();
2769         
2770         if (!result) {
2771             vPC += target;
2772             NEXT_OPCODE;
2773         }
2774
2775         ++vPC;
2776         NEXT_OPCODE;
2777     }
2778     BEGIN_OPCODE(op_switch_imm) {
2779         /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
2780
2781            Performs a range checked switch on the scrutinee value, using
2782            the tableIndex-th immediate switch jump table.  If the scrutinee value
2783            is an immediate number in the range covered by the referenced jump
2784            table, and the value at jumpTable[scrutinee value] is non-zero, then
2785            that value is used as the jump offset, otherwise defaultOffset is used.
2786          */
2787         int tableIndex = (++vPC)->u.operand;
2788         int defaultOffset = (++vPC)->u.operand;
2789         JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2790         if (!JSImmediate::isNumber(scrutinee))
2791             vPC += defaultOffset;
2792         else {
2793             int32_t value = JSImmediate::getTruncatedInt32(scrutinee);
2794             vPC += codeBlock->immediateSwitchJumpTables[tableIndex].offsetForValue(value, defaultOffset);
2795         }
2796         NEXT_OPCODE;
2797     }
2798     BEGIN_OPCODE(op_switch_char) {
2799         /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
2800
2801            Performs a range checked switch on the scrutinee value, using
2802            the tableIndex-th character switch jump table.  If the scrutinee value
2803            is a single character string in the range covered by the referenced jump
2804            table, and the value at jumpTable[scrutinee value] is non-zero, then
2805            that value is used as the jump offset, otherwise defaultOffset is used.
2806          */
2807         int tableIndex = (++vPC)->u.operand;
2808         int defaultOffset = (++vPC)->u.operand;
2809         JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2810         if (!scrutinee->isString())
2811             vPC += defaultOffset;
2812         else {
2813             UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
2814             if (value->size() != 1)
2815                 vPC += defaultOffset;
2816             else
2817                 vPC += codeBlock->characterSwitchJumpTables[tableIndex].offsetForValue(value->data()[0], defaultOffset);
2818         }
2819         NEXT_OPCODE;
2820     }
2821     BEGIN_OPCODE(op_switch_string) {
2822         /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
2823
2824            Performs a sparse hashmap based switch on the value in the scrutinee
2825            register, using the tableIndex-th string switch jump table.  If the 
2826            scrutinee value is a string that exists as a key in the referenced 
2827            jump table, then the value associated with the string is used as the 
2828            jump offset, otherwise defaultOffset is used.
2829          */
2830         int tableIndex = (++vPC)->u.operand;
2831         int defaultOffset = (++vPC)->u.operand;
2832         JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2833         if (!scrutinee->isString())
2834             vPC += defaultOffset;
2835         else 
2836             vPC += codeBlock->stringSwitchJumpTables[tableIndex].offsetForValue(static_cast<JSString*>(scrutinee)->value().rep(), defaultOffset);
2837         NEXT_OPCODE;
2838     }
2839     BEGIN_OPCODE(op_new_func) {
2840         /* new_func dst(r) func(f)
2841
2842            Constructs a new Function instance from function func and
2843            the current scope chain using the original Function
2844            constructor, using the rules for function declarations, and
2845            puts the result in register dst.
2846         */
2847         int dst = (++vPC)->u.operand;
2848         int func = (++vPC)->u.operand;
2849
2850         r[dst] = codeBlock->functions[func]->makeFunction(exec, scopeChain);
2851
2852         ++vPC;
2853         NEXT_OPCODE;
2854     }
2855     BEGIN_OPCODE(op_new_func_exp) {
2856         /* new_func_exp dst(r) func(f)
2857
2858            Constructs a new Function instance from function func and
2859            the current scope chain using the original Function
2860            constructor, using the rules for function expressions, and
2861            puts the result in register dst.
2862         */
2863         int dst = (++vPC)->u.operand;
2864         int func = (++vPC)->u.operand;
2865
2866         r[dst] = codeBlock->functionExpressions[func]->makeFunction(exec, scopeChain);
2867
2868         ++vPC;
2869         NEXT_OPCODE;
2870     }
2871     BEGIN_OPCODE(op_call_eval) {
2872         /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2873
2874            Call a function named "eval" with no explicit "this" value
2875            (which may therefore be the eval operator). If register
2876            thisVal is the global object, and register func contains
2877            that global object's original global eval function, then
2878            perform the eval operator in local scope (interpreting
2879            the argument registers as for the "call"
2880            opcode). Otherwise, act exactly as the "call" opcode would.
2881          */
2882
2883         int dst = (++vPC)->u.operand;
2884         int func = (++vPC)->u.operand;
2885         int thisVal = (++vPC)->u.operand;
2886         int firstArg = (++vPC)->u.operand;
2887         int argCount = (++vPC)->u.operand;
2888
2889         JSValue* funcVal = r[func].jsValue(exec);
2890         JSValue* baseVal = r[thisVal].jsValue(exec);
2891
2892         if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
2893             JSObject* thisObject = static_cast<JSObject*>(r[codeBlock->thisRegister].jsValue(exec));
2894             JSValue* result = callEval(exec, codeBlock, thisObject, scopeChain, registerFile, r, firstArg, argCount, exceptionValue);
2895             if (exceptionValue)
2896                 goto vm_throw;
2897
2898             r[dst] = result;
2899
2900             ++vPC;
2901             NEXT_OPCODE;
2902         }
2903
2904         // We didn't find the blessed version of eval, so reset vPC and process
2905         // this instruction as a normal function call, supplying the proper 'this'
2906         // value.
2907         vPC -= 5;
2908         r[thisVal] = baseVal->toThisObject(exec);
2909
2910 #if HAVE(COMPUTED_GOTO)
2911         // Hack around gcc performance quirk by performing an indirect goto
2912         // in order to set the vPC -- attempting to do so directly results in a
2913         // significant regression.
2914         goto *op_call_indirect; // indirect goto -> op_call
2915 #endif
2916         // fall through to op_call
2917     }
2918     BEGIN_OPCODE(op_call) {
2919         /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2920
2921            Perform a function call. Specifically, call register func
2922            with a "this" value of register thisVal, and put the result
2923            in register dst.
2924
2925            The arguments start at register firstArg and go up to
2926            argCount, but the "this" value is considered an implicit
2927            first argument, so the argCount should be one greater than
2928            the number of explicit arguments passed, and the register
2929            after firstArg should contain the actual first
2930            argument. This opcode will copy from the thisVal register
2931            to the firstArg register, unless the register index of
2932            thisVal is the special missing this object marker, which is
2933            2^31-1; in that case, the global object will be used as the
2934            "this" value.
2935
2936            If func is a native code function, then this opcode calls
2937            it and returns the value immediately. 
2938
2939            But if it is a JS function, then the current scope chain
2940            and code block is set to the function's, and we slide the
2941            register window so that the arguments would form the first
2942            few local registers of the called function's register
2943            window. In addition, a call frame header is written
2944            immediately before the arguments; see the call frame
2945            documentation for an explanation of how many registers a
2946            call frame takes and what they contain. That many registers
2947            before the firstArg register will be overwritten by the
2948            call. In addition, any registers higher than firstArg +
2949            argCount may be overwritten. Once this setup is complete,
2950            execution continues from the called function's first
2951            argument, and does not return until a "ret" opcode is
2952            encountered.
2953          */
2954
2955         int dst = (++vPC)->u.operand;
2956         int func = (++vPC)->u.operand;
2957         int thisVal = (++vPC)->u.operand;
2958         int firstArg = (++vPC)->u.operand;
2959         int argCount = (++vPC)->u.operand;
2960
2961         JSValue* v = r[func].jsValue(exec);
2962
2963         CallData callData;
2964         CallType callType = v->getCallData(callData);
2965
2966         if (*enabledProfilerReference)
2967             (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
2968
2969         Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
2970         initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, 0, v);
2971         exec->m_callFrame = callFrame;
2972
2973         if (callType == CallTypeJS) {
2974
2975             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
2976             FunctionBodyNode* functionBodyNode = callData.js.functionBody;
2977             CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
2978
2979             r[firstArg] = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
2980
2981             r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
2982             if (UNLIKELY(exceptionValue != 0))
2983                 goto vm_throw;
2984
2985             codeBlock = newCodeBlock;
2986             setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
2987             vPC = codeBlock->instructions.begin();
2988
2989 #if DUMP_OPCODE_STATS
2990             OpcodeStats::resetLastInstruction();
2991 #endif
2992             
2993             NEXT_OPCODE;
2994         }
2995
2996         if (callType == CallTypeHost) {
2997             JSValue* thisValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
2998             ArgList args(r + firstArg + 1, argCount - 1);
2999
3000             MACHINE_SAMPLING_callingHostFunction();
3001
3002             JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(v), thisValue, args);
3003             exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3004             VM_CHECK_EXCEPTION();
3005
3006             r[dst] = returnValue;
3007
3008             if (*enabledProfilerReference)
3009                 (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(v));
3010
3011             ++vPC;
3012             NEXT_OPCODE;
3013         }
3014
3015         ASSERT(callType == CallTypeNone);
3016
3017         exceptionValue = createNotAFunctionError(exec, v, vPC, codeBlock);
3018         exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3019         goto vm_throw;
3020     }
3021     BEGIN_OPCODE(op_ret) {
3022         /* ret result(r)
3023            
3024            Return register result as the return value of the current
3025            function call, writing it into the caller's expected return
3026            value register. In addition, unwind one call frame and
3027            restore the scope chain, code block instruction pointer and
3028            register base to those of the calling function.
3029         */
3030            
3031         int result = (++vPC)->u.operand;
3032
3033         Register* callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3034         if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
3035             ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
3036             ASSERT(activation->isActivationObject());
3037             activation->copyRegisters();
3038         }
3039
3040         if (*enabledProfilerReference)
3041             (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
3042
3043         if (codeBlock->needsFullScopeChain)
3044             scopeChain->deref();
3045
3046         JSValue* returnValue = r[result].jsValue(exec);
3047         if (callFrame[RegisterFile::CalledAsConstructor].i() && !returnValue->isObject()) {
3048             JSValue* thisObject = callFrame[RegisterFile::CallFrameHeaderSize].jsValue(exec);
3049             returnValue = thisObject;
3050         }
3051
3052         codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
3053         if (!codeBlock)
3054             return returnValue;
3055
3056         vPC = callFrame[RegisterFile::ReturnVPC].vPC();
3057         setScopeChain(exec, scopeChain, callFrame[RegisterFile::CallerScopeChain].scopeChain());
3058         r = callFrame[RegisterFile::CallerRegisters].r();
3059         exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3060         int dst = callFrame[RegisterFile::ReturnValueRegister].i();
3061         r[dst] = returnValue;
3062
3063         NEXT_OPCODE;
3064     }
3065     BEGIN_OPCODE(op_construct) {
3066         /* construct dst(r) constr(r) firstArg(r) argCount(n)
3067
3068            Invoke register "constr" as a constructor. For JS
3069            functions, the calling convention is exactly as for the
3070            "call" opcode, except that the "this" value is a newly
3071            created Object. For native constructors, a null "this"
3072            value is passed. In either case, the firstArg and argCount
3073            registers are interpreted as for the "call" opcode.
3074         */
3075
3076         int dst = (++vPC)->u.operand;
3077         int constr = (++vPC)->u.operand;
3078         int firstArg = (++vPC)->u.operand;
3079         int argCount = (++vPC)->u.operand;
3080
3081         JSValue* constrVal = r[constr].jsValue(exec);
3082
3083         ConstructData constructData;
3084         ConstructType constructType = constrVal->getConstructData(constructData);
3085
3086         // Removing this line of code causes a measurable regression on squirrelfish.
3087         JSObject* constructor = static_cast<JSObject*>(constrVal);
3088
3089         if (constructType == ConstructTypeJS) {
3090             if (*enabledProfilerReference)
3091                 (*enabledProfilerReference)->willExecute(exec, constructor);
3092
3093             JSObject* prototype;
3094             JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
3095             if (p->isObject())
3096                 prototype = static_cast<JSObject*>(p);
3097             else
3098                 prototype = scopeChain->globalObject()->objectPrototype();
3099             JSObject* newObject = new (exec) JSObject(prototype);
3100
3101             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
3102             FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
3103             CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
3104
3105             r[firstArg] = newObject; // "this" value
3106
3107             Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
3108             initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, 1, constructor);
3109             exec->m_callFrame = callFrame;
3110
3111             r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
3112             if (exceptionValue)
3113                 goto vm_throw;
3114
3115             codeBlock = newCodeBlock;
3116             setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
3117             vPC = codeBlock->instructions.begin();
3118
3119             NEXT_OPCODE;
3120         }
3121
3122         if (constructType == ConstructTypeHost) {
3123             if (*enabledProfilerReference)
3124                 (*enabledProfilerReference)->willExecute(exec, constructor);
3125
3126             ArgList args(r + firstArg + 1, argCount - 1);
3127
3128             MACHINE_SAMPLING_callingHostFunction();
3129
3130             JSValue* returnValue = constructData.native.function(exec, constructor, args);
3131
3132             VM_CHECK_EXCEPTION();
3133             r[dst] = returnValue;
3134
3135             if (*enabledProfilerReference)
3136                 (*enabledProfilerReference)->didExecute(exec, constructor);
3137
3138             ++vPC;
3139             NEXT_OPCODE;
3140         }
3141
3142         ASSERT(constructType == ConstructTypeNone);
3143
3144         exceptionValue = createNotAConstructorError(exec, constrVal, vPC, codeBlock);
3145         goto vm_throw;
3146     }
3147     BEGIN_OPCODE(op_push_scope) {
3148         /* push_scope scope(r)
3149
3150            Converts register scope to object, and pushes it onto the top
3151            of the current scope chain.
3152         */
3153         int scope = (++vPC)->u.operand;
3154         JSValue* v = r[scope].jsValue(exec);
3155         JSObject* o = v->toObject(exec);
3156         VM_CHECK_EXCEPTION();
3157
3158         setScopeChain(exec, scopeChain, scopeChain->push(o));
3159
3160         ++vPC;
3161         NEXT_OPCODE;
3162     }
3163     BEGIN_OPCODE(op_pop_scope) {
3164         /* pop_scope
3165
3166            Removes the top item from the current scope chain.
3167         */
3168         setScopeChain(exec, scopeChain, scopeChain->pop());
3169
3170         ++vPC;
3171         NEXT_OPCODE;
3172     }
3173     BEGIN_OPCODE(op_get_pnames) {
3174         /* get_pnames dst(r) base(r)
3175
3176            Creates a property name list for register base and puts it
3177            in register dst. This is not a true JavaScript value, just
3178            a synthetic value used to keep the iteration state in a
3179            register.
3180         */
3181         int dst = (++vPC)->u.operand;
3182         int base = (++vPC)->u.operand;
3183
3184         r[dst] = JSPropertyNameIterator::create(exec, r[base].jsValue(exec));
3185         ++vPC;
3186         NEXT_OPCODE;
3187     }
3188     BEGIN_OPCODE(op_next_pname) {
3189         /* next_pname dst(r) iter(r) target(offset)
3190
3191            Tries to copies the next name from property name list in
3192            register iter. If there are names left, then copies one to
3193            register dst, and jumps to offset target. If there are none
3194            left, invalidates the iterator and continues to the next
3195            instruction.
3196         */
3197         int dst = (++vPC)->u.operand;
3198         int iter = (++vPC)->u.operand;
3199         int target = (++vPC)->u.operand;
3200
3201         JSPropertyNameIterator* it = r[iter].jsPropertyNameIterator();
3202         if (JSValue* temp = it->next(exec)) {
3203             CHECK_FOR_TIMEOUT();
3204             r[dst] = temp;
3205             vPC += target;
3206             NEXT_OPCODE;
3207         }
3208         it->invalidate();
3209
3210         ++vPC;
3211         NEXT_OPCODE;
3212     }
3213     BEGIN_OPCODE(op_jmp_scopes) {
3214         /* jmp_scopes count(n) target(offset)
3215
3216            Removes the a number of items from the current scope chain
3217            specified by immediate number count, then jumps to offset
3218            target.
3219         */
3220         int count = (++vPC)->u.operand;
3221         int target = (++vPC)->u.operand;
3222
3223         ScopeChainNode* tmp = scopeChain;
3224         while (count--)
3225             tmp = tmp->pop();
3226         setScopeChain(exec, scopeChain, tmp);
3227
3228         vPC += target;
3229         NEXT_OPCODE;
3230     }
3231 #if HAVE(COMPUTED_GOTO)
3232     // Appease GCC
3233     goto *(&&skip_new_scope);
3234 #endif
3235     BEGIN_OPCODE(op_push_new_scope) {
3236         /* new_scope dst(r) property(id) value(r)
3237          
3238            Constructs a new StaticScopeObject with property set to value.  That scope
3239            object is then pushed onto the ScopeChain.  The scope object is then stored
3240            in dst for GC.
3241          */
3242         setScopeChain(exec, scopeChain, createExceptionScope(exec, codeBlock, vPC, r, scopeChain));
3243         vPC += 4;
3244         NEXT_OPCODE;
3245     }
3246 #if HAVE(COMPUTED_GOTO)
3247     skip_new_scope:
3248 #endif
3249     BEGIN_OPCODE(op_catch) {
3250         /* catch ex(r)
3251
3252            Retrieves the VMs current exception and puts it in register
3253            ex. This is only valid after an exception has been raised,
3254            and usually forms the beginning of an exception handler.
3255         */
3256         ASSERT(exceptionValue);
3257         ASSERT(!exec->hadException());
3258         int ex = (++vPC)->u.operand;
3259         r[ex] = exceptionValue;
3260         exceptionValue = 0;
3261
3262         ++vPC;
3263         NEXT_OPCODE;
3264     }
3265     BEGIN_OPCODE(op_throw) {
3266         /* throw ex(r)
3267
3268            Throws register ex as an exception. This involves three
3269            steps: first, it is set as the current exception in the
3270            VM's internal state, then the stack is unwound until an
3271            exception handler or a native code boundary is found, and
3272            then control resumes at the exception handler if any or
3273            else the script returns control to the nearest native caller.
3274         */
3275
3276         int ex = (++vPC)->u.operand;
3277         exceptionValue = r[ex].jsValue(exec);
3278
3279         handlerVPC = throwException(exec, exceptionValue, vPC, codeBlock, scopeChain, r, true);
3280         if (!handlerVPC) {
3281             *exception = exceptionValue;
3282             return jsNull();
3283         }
3284
3285 #if HAVE(COMPUTED_GOTO)
3286         // Hack around gcc performance quirk by performing an indirect goto
3287         // in order to set the vPC -- attempting to do so directly results in a
3288         // significant regression.
3289         goto *op_throw_end_indirect; // indirect goto -> op_throw_end
3290     }
3291     op_throw_end: {
3292 #endif
3293
3294         vPC = handlerVPC;
3295         NEXT_OPCODE;
3296     }
3297     BEGIN_OPCODE(op_unexpected_load) {
3298         /* unexpected_load load dst(r) src(k)
3299
3300            Copies constant src to register dst.
3301         */
3302         int dst = (++vPC)->u.operand;
3303         int src = (++vPC)->u.operand;
3304         r[dst] = codeBlock->unexpectedConstants[src];
3305
3306         ++vPC;
3307         NEXT_OPCODE;
3308     }
3309     BEGIN_OPCODE(op_new_error) {
3310         /* new_error dst(r) type(n) message(k)
3311
3312            Constructs a new Error instance using the original
3313            constructor, using immediate number n as the type and
3314            constant message as the message string. The result is
3315            written to register dst.
3316         */
3317         int dst = (++vPC)->u.operand;
3318         int type = (++vPC)->u.operand;
3319         int message = (++vPC)->u.operand;
3320
3321         r[dst] = Error::create(exec, (ErrorType)type, codeBlock->unexpectedConstants[message]->toString(exec), codeBlock->lineNumberForVPC(vPC), codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->sourceURL());
3322
3323         ++vPC;
3324         NEXT_OPCODE;
3325     }
3326     BEGIN_OPCODE(op_end) {
3327         /* end result(r)
3328            
3329            Return register result as the value of a global or eval
3330            program. Return control to the calling native code.
3331         */
3332
3333         if (codeBlock->needsFullScopeChain) {
3334             ASSERT(scopeChain->refCount > 1);
3335             scopeChain->deref();
3336         }
3337         int result = (++vPC)->u.operand;
3338         return r[result].jsValue(exec);
3339     }
3340     BEGIN_OPCODE(op_put_getter) {
3341         /* put_getter base(r) property(id) function(r)
3342
3343            Sets register function on register base as the getter named
3344            by identifier property. Base and function are assumed to be
3345            objects as this op should only be used for getters defined
3346            in object literal form.
3347
3348            Unlike many opcodes, this one does not write any output to
3349            the register file.
3350         */
3351         int base = (++vPC)->u.operand;
3352         int property = (++vPC)->u.operand;
3353         int function = (++vPC)->u.operand;
3354
3355         ASSERT(r[base].jsValue(exec)->isObject());
3356         JSObject* baseObj = static_cast<JSObject*>(r[base].jsValue(exec));
3357         Identifier& ident = codeBlock->identifiers[property];
3358         ASSERT(r[function].jsValue(exec)->isObject());
3359         baseObj->defineGetter(exec, ident, static_cast<JSObject*>(r[function].jsValue(exec)));
3360
3361         ++vPC;
3362         NEXT_OPCODE;
3363     }
3364     BEGIN_OPCODE(op_put_setter) {
3365         /* put_setter base(r) property(id) function(r)
3366
3367            Sets register function on register base as the setter named
3368            by identifier property. Base and function are assumed to be
3369            objects as this op should only be used for setters defined
3370            in object literal form.
3371
3372            Unlike many opcodes, this one does not write any output to
3373            the register file.
3374         */
3375         int base = (++vPC)->u.operand;
3376         int property = (++vPC)->u.operand;
3377         int function = (++vPC)->u.operand;
3378
3379         ASSERT(r[base].jsValue(exec)->isObject());
3380         JSObject* baseObj = static_cast<JSObject*>(r[base].jsValue(exec));
3381         Identifier& ident = codeBlock->identifiers[property];
3382         ASSERT(r[function].jsValue(exec)->isObject());
3383         baseObj->defineSetter(exec, ident, static_cast<JSObject*>(r[function].jsValue(exec)));
3384
3385         ++vPC;
3386         NEXT_OPCODE;
3387     }
3388     BEGIN_OPCODE(op_jsr) {
3389         /* jsr retAddrDst(r) target(offset)
3390
3391            Places the address of the next instruction into the retAddrDst
3392            register and jumps to offset target from the current instruction.
3393         */
3394         int retAddrDst = (++vPC)->u.operand;
3395         int target = (++vPC)->u.operand;
3396         r[retAddrDst] = vPC + 1;
3397
3398         vPC += target;
3399         NEXT_OPCODE;
3400     }
3401     BEGIN_OPCODE(op_sret) {
3402         /* sret retAddrSrc(r)
3403
3404          Jumps to the address stored in the retAddrSrc register. This
3405          differs from op_jmp because the target address is stored in a
3406          register, not as an immediate.
3407         */
3408         int retAddrSrc = (++vPC)->u.operand;
3409         vPC = r[retAddrSrc].vPC();
3410         NEXT_OPCODE;
3411     }
3412     BEGIN_OPCODE(op_debug) {
3413         /* debug debugHookID(n) firstLine(n) lastLine(n)
3414
3415          Notifies the debugger of the current state of execution. This opcode
3416          is only generated while the debugger is attached.
3417         */
3418         int debugHookID = (++vPC)->u.operand;
3419         int firstLine = (++vPC)->u.operand;
3420         int lastLine = (++vPC)->u.operand;
3421
3422         debug(exec, codeBlock, scopeChain, r, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
3423
3424         ++vPC;
3425         NEXT_OPCODE;
3426     }
3427     vm_throw: {
3428         exec->clearException();
3429         if (!tickCount) {
3430             // The exceptionValue is a lie! (GCC produces bad code for reasons I 
3431             // cannot fathom if we don't assign to the exceptionValue before branching)
3432             exceptionValue = createInterruptedExecutionException(exec);
3433         }
3434         handlerVPC = throwException(exec, exceptionValue, vPC, codeBlock, scopeChain, r, false);
3435         if (!handlerVPC) {
3436             *exception = exceptionValue;
3437             return jsNull();
3438         }
3439         vPC = handlerVPC;
3440         NEXT_OPCODE;
3441     }
3442     }
3443     #undef NEXT_OPCODE
3444     #undef BEGIN_OPCODE
3445     #undef VM_CHECK_EXCEPTION
3446     #undef CHECK_FOR_TIMEOUT
3447 }
3448
3449 JSValue* Machine::retrieveArguments(ExecState* exec, JSFunction* function) const
3450 {
3451     Register* callFrame = this->callFrame(exec, function);
3452     if (!callFrame)
3453         return jsNull();
3454
3455     JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec));
3456     if (!activation) {
3457         CodeBlock* codeBlock = &function->m_body->generatedByteCode();
3458         activation = new (exec) JSActivation(exec, function->m_body, callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numLocals);
3459         callFrame[RegisterFile::OptionalCalleeActivation] = activation;
3460     }
3461
3462     return activation->get(exec, exec->propertyNames().arguments);
3463 }
3464
3465 JSValue* Machine::retrieveCaller(ExecState* exec, InternalFunction* function) const
3466 {
3467     Register* callFrame = this->callFrame(exec, function);
3468     if (!callFrame)
3469         return jsNull();
3470
3471     CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
3472     if (!callerCodeBlock)
3473         return jsNull();
3474
3475     Register* callerCallFrame = callFrame[RegisterFile::CallerRegisters].r() - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3476     if (JSValue* caller = callerCallFrame[RegisterFile::Callee].jsValue(exec))
3477         return caller;
3478
3479     return jsNull();
3480 }
3481
3482 void Machine::retrieveLastCaller(ExecState* exec, int& lineNumber, int& sourceId, UString& sourceURL, JSValue*& function) const
3483 {
3484     function = 0;
3485     lineNumber = -1;
3486     sourceURL = UString();
3487
3488     Register* callFrame = exec->m_callFrame;
3489     if (!callFrame)
3490         return;
3491
3492     CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
3493     if (!callerCodeBlock)
3494         return;
3495
3496     Instruction* vPC = callFrame[RegisterFile::ReturnVPC].vPC();
3497     lineNumber = callerCodeBlock->lineNumberForVPC(vPC - 1);
3498     sourceId = callerCodeBlock->ownerNode->sourceId();
3499     sourceURL = callerCodeBlock->ownerNode->sourceURL();
3500
3501     JSValue* callee = callFrame[RegisterFile::Callee].getJSValue();
3502     if (callee->toThisObject(exec)->inherits(&InternalFunction::info))
3503         function = retrieveCaller(exec, static_cast<InternalFunction*>(callee));
3504 }
3505
3506 Register* Machine::callFrame(ExecState* exec, InternalFunction* function) const
3507 {
3508     Register* callFrame = exec->m_callFrame;
3509
3510     while (1) {
3511         while (!callFrame) {
3512             exec = exec->m_prev;
3513             if (!exec)
3514                 return 0;
3515             callFrame = exec->m_callFrame;
3516         }
3517
3518         if (callFrame[RegisterFile::Callee].jsValue(exec) == function)
3519             return callFrame;
3520
3521         CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
3522         if (!callerCodeBlock) {
3523             callFrame = 0;
3524             continue;
3525         }
3526         
3527         callFrame = callFrame[RegisterFile::CallerRegisters].r() - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3528     }
3529 }
3530
3531 void Machine::getArgumentsData(Register* callFrame, JSFunction*& function, Register*& argv, int& argc)
3532 {
3533     function = static_cast<JSFunction*>(callFrame[RegisterFile::Callee].getJSValue());
3534     ASSERT(function->inherits(&JSFunction::info));
3535
3536     argv = callFrame[RegisterFile::CallerRegisters].r() + callFrame[RegisterFile::ArgumentStartRegister].i() + 1; //  + 1 to skip "this"
3537     argc = callFrame[RegisterFile::ArgumentCount].i() - 1; // - 1 to skip "this"
3538 }
3539
3540 #if ENABLE(CTI)
3541
3542 NEVER_INLINE static void doSetReturnAddressVMThrowTrampoline(void** returnAddress)
3543 {
3544     ctiSetReturnAddress(returnAddress, (void*)ctiVMThrowTrampoline);
3545 }
3546
3547 NEVER_INLINE void Machine::tryCTICachePutByID(ExecState* exec, CodeBlock* codeBlock, void* returnAddress, JSValue* baseValue, const PutPropertySlot& slot)
3548 {
3549     // The interpreter checks for recursion here; I do not believe this can occur in CTI.
3550
3551     if (JSImmediate::isImmediate(baseValue))
3552         return;
3553
3554     // Uncacheable: give up.
3555     if (!slot.isCacheable()) {
3556         ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
3557         return;
3558     }
3559
3560     // FIXME: Cache new property transitions, too.
3561     if (slot.type() == PutPropertySlot::NewProperty) {
3562         ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
3563         return;
3564     }
3565     
3566     JSCell* baseCell = static_cast<JSCell*>(baseValue);
3567     StructureID* structureID = baseCell->structureID();
3568
3569     if (structureID->isDictionary()) {
3570         ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
3571         return;
3572     }
3573
3574     // In the interpreter the last structure is trapped here; in CTI we use the
3575     // *_second method to achieve a similar (but not quite the same) effect.
3576
3577     unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(returnAddress);
3578     Instruction* vPC = codeBlock->instructions.begin() + vPCIndex;
3579
3580     // Cache hit: Specialize instruction and ref StructureIDs.
3581
3582     // If baseCell != base, then baseCell must be a proxy for another object.
3583     if (baseCell != slot.base()) {
3584         ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
3585         return;
3586     }
3587     vPC[0] = getOpcode(op_put_by_id_replace);
3588     vPC[4] = structureID;
3589     vPC[5] = slot.cachedOffset();
3590     codeBlock->refStructureIDs(vPC);
3591
3592     ctiRepatchCallByReturnAddress(returnAddress, CTI::compilePutByIdReplace(this, exec, codeBlock, structureID, slot.cachedOffset()));
3593 }
3594
3595 void* Machine::getCTIArrayLengthTrampoline(ExecState* exec, CodeBlock* codeBlock)
3596 {
3597     if (!m_ctiArrayLengthTrampoline)
3598         m_ctiArrayLengthTrampoline = CTI::compileArrayLengthTrampoline(this, exec, codeBlock);
3599         
3600     return m_ctiArrayLengthTrampoline;
3601 }
3602
3603 void* Machine::getCTIStringLengthTrampoline(ExecState* exec, CodeBlock* codeBlock)
3604 {
3605     if (!m_ctiStringLengthTrampoline)
3606         m_ctiStringLengthTrampoline = CTI::compileStringLengthTrampoline(this, exec, codeBlock);
3607         
3608     return m_ctiStringLengthTrampoline;
3609 }
3610
3611 NEVER_INLINE void Machine::tryCTICacheGetByID(ExecState* exec, CodeBlock* codeBlock, void* returnAddress, JSValue* baseValue, const Identifier& propertyName, const PropertySlot& slot)
3612 {
3613     // The interpreter checks for recursion here; I do not believe this can occur in CTI.
3614
3615     if (isJSArray(baseValue) && propertyName == exec->propertyNames().length) {
3616         ctiRepatchCallByReturnAddress(returnAddress, getCTIArrayLengthTrampoline(exec, codeBlock));
3617         return;
3618     }
3619     if (isJSString(baseValue) && propertyName == exec->propertyNames().length) {
3620         ctiRepatchCallByReturnAddress(returnAddress, getCTIStringLengthTrampoline(exec, codeBlock));
3621         return;
3622     }
3623
3624     // Uncacheable: give up.
3625     if (!slot.isCacheable()) {
3626         ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
3627         return;
3628     }
3629
3630     // FIXME: Cache property access for immediates.
3631     if (JSImmediate::isImmediate(baseValue)) {
3632         ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
3633         return;
3634     }
3635
3636     JSCell* baseCell = static_cast<JSCell*>(baseValue);
3637     StructureID* structureID = baseCell->structureID();
3638
3639     if (structureID->isDictionary()) {
3640         ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
3641         return;
3642     }
3643
3644     // In the interpreter the last structure is trapped here; in CTI we use the
3645     // *_second method to achieve a similar (but not quite the same) effect.
3646
3647     unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(returnAddress);
3648     Instruction* vPC = codeBlock->instructions.begin() + vPCIndex;
3649
3650     // Cache hit: Specialize instruction and ref StructureIDs.
3651
3652     if (slot.slotBase() == baseValue) {
3653         // set this up, so derefStructureIDs can do it's job.
3654         vPC[0] = getOpcode(op_get_by_id_self);
3655         vPC[4] = structureID;
3656         vPC[5] = slot.cachedOffset();
3657         codeBlock->refStructureIDs(vPC);
3658         
3659         ctiRepatchCallByReturnAddress(returnAddress, CTI::compileGetByIdSelf(this, exec, codeBlock, structureID, slot.cachedOffset()));
3660         return;
3661     }
3662
3663     if (slot.slotBase() == structureID->prototypeForLookup(exec)) {
3664         ASSERT(slot.slotBase()->isObject());
3665
3666         JSObject* slotBaseObject = static_cast<JSObject*>(slot.slotBase());
3667
3668         // Heavy access to a prototype is a good indication that it's not being
3669         // used as a dictionary.
3670         if (slotBaseObject->structureID()->isDictionary()) {
3671             RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(slotBaseObject->structureID());
3672             slotBaseObject->setStructureID(transition.release());
3673             static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
3674         }
3675
3676         vPC[0] = getOpcode(op_get_by_id_proto);
3677         vPC[4] = structureID;
3678         vPC[5] = slotBaseObject->structureID();
3679         vPC[6] = slot.cachedOffset();
3680         codeBlock->refStructureIDs(vPC);
3681
3682         ctiRepatchCallByReturnAddress(returnAddress, CTI::compileGetByIdProto(this, exec, codeBlock, structureID, slotBaseObject->structureID(), slot.cachedOffset()));
3683         return;
3684     }
3685
3686     size_t count = 0;
3687     JSObject* o = static_cast<JSObject*>(baseValue);
3688     while (slot.slotBase() != o) {
3689         JSValue* v = o->structureID()->prototypeForLookup(exec);
3690
3691         // If we didn't find slotBase in baseValue's prototype chain, then baseValue
3692         // must be a proxy for another object.
3693
3694         if (v->isNull()) {
3695             vPC[0] = getOpcode(op_get_by_id_generic);
3696             return;
3697         }
3698
3699         o = static_cast<JSObject*>(v);
3700
3701         // Heavy access to a prototype is a good indication that it's not being
3702         // used as a dictionary.
3703         if (o->structureID()->isDictionary()) {
3704             RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(o->structureID());
3705             o->setStructureID(transition.release());
3706             static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
3707         }
3708
3709         ++count;
3710     }
3711
3712     StructureIDChain* chain = structureID->cachedPrototypeChain();
3713     if (!chain)
3714         chain = cachePrototypeChain(exec, structureID);
3715
3716     vPC[0] = getOpcode(op_get_by_id_chain);
3717     vPC[4] = structureID;
3718     vPC[5] = chain;
3719     vPC[6] = count;
3720     vPC[7] = slot.cachedOffset();
3721     codeBlock->refStructureIDs(vPC);
3722
3723     ctiRepatchCallByReturnAddress(returnAddress, CTI::compileGetByIdChain(this, exec, codeBlock, structureID, chain, count, slot.cachedOffset()));
3724 }
3725
3726
3727 #define JSVALUE_VM_CHECK_EXCEPTION_ARG(exception) \
3728     do { \
3729         if (UNLIKELY(exception != 0)) { \
3730             exec->setException(exception); \
3731             exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
3732             doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
3733             return 0; \
3734         } \
3735     } while (0)
3736 #define VM_CHECK_EXCEPTION_v() \
3737     do { \
3738         if (UNLIKELY(exec->hadException())) { \
3739             exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
3740             doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
3741             return; \
3742         } \
3743     } while (0)
3744 #define VM_CHECK_EXCEPTION(type) \
3745     do { \
3746         if (UNLIKELY(exec->hadException())) { \
3747             exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
3748             doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
3749             return (type)0; \
3750         } \
3751     } while (0)
3752 #define VM_CHECK_EXCEPTION_AT_END() \
3753     do { \
3754         if (UNLIKELY(exec->hadException())) { \
3755             /*printf("VM_CHECK_EXCEPTION_AT_END()\n");*/ \
3756             exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
3757             doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
3758         } \
3759     } while (0)
3760
3761 void Machine::cti_op_end(CTI_ARGS)
3762 {
3763     ASSERT(ARG_scopeChain->refCount > 1);
3764     ARG_scopeChain->deref();
3765 }
3766
3767 JSValue* Machine::cti_op_add(CTI_ARGS)
3768 {
3769     JSValue* src1 = ARG_src1;
3770     JSValue* src2 = ARG_src2;
3771
3772     ExecState* exec = ARG_exec;
3773     JSValue* result = jsAdd(exec, src1, src2);
3774     VM_CHECK_EXCEPTION_AT_END();
3775     return result;
3776 }
3777
3778 JSValue* Machine::cti_op_pre_inc(CTI_ARGS)
3779 {
3780     JSValue* v = ARG_src1;
3781
3782     ExecState* exec = ARG_exec;
3783     JSValue* result = jsNumber(exec, v->toNumber(exec) + 1);
3784     VM_CHECK_EXCEPTION_AT_END();
3785     return result;
3786 }
3787
3788 void Machine::cti_timeout_check(CTI_ARGS)
3789 {
3790     ExecState* exec = ARG_exec;
3791
3792     if (exec->machine()->checkTimeout(exec->dynamicGlobalObject()))
3793         exec->setException(createInterruptedExecutionException(exec));
3794
3795     VM_CHECK_EXCEPTION_AT_END();
3796 }
3797
3798
3799 int Machine::cti_op_loop_if_less(CTI_ARGS)
3800 {
3801     JSValue* src1 = ARG_src1;
3802     JSValue* src2 = ARG_src2;
3803     ExecState* exec = ARG_exec;
3804
3805     bool result = jsLess(exec, src1, src2);
3806     VM_CHECK_EXCEPTION_AT_END();
3807     return result;
3808 }
3809
3810 JSValue* Machine::cti_op_new_object(CTI_ARGS)
3811 {
3812     return constructEmptyObject(ARG_exec);;
3813 }
3814
3815 void Machine::cti_op_put_by_id(CTI_ARGS)
3816 {
3817     ExecState* exec = ARG_exec;
3818     Identifier& ident = *ARG_id2;
3819
3820     PutPropertySlot slot;
3821     ARG_src1->put(exec, ident, ARG_src3, slot);
3822
3823     ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_put_by_id_second);
3824
3825     VM_CHECK_EXCEPTION_AT_END();
3826 }
3827
3828 void Machine::cti_op_put_by_id_second(CTI_ARGS)
3829 {
3830     ExecState* exec = ARG_exec;
3831     Identifier& ident = *ARG_id2;
3832
3833     JSValue* baseValue = ARG_src1;
3834     PutPropertySlot slot;
3835     baseValue->put(exec, ident, ARG_src3, slot);
3836
3837     exec->machine()->tryCTICachePutByID(exec, ARG_codeBlock, CTI_RETURN_ADDRESS, baseValue, slot);
3838
3839     VM_CHECK_EXCEPTION_AT_END();
3840 }
3841
3842 void Machine::cti_op_put_by_id_generic(CTI_ARGS)
3843 {
3844     ExecState* exec = ARG_exec;
3845     Identifier& ident = *ARG_id2;
3846
3847     PutPropertySlot slot;
3848     ARG_src1->put(exec, ident, ARG_src3, slot);
3849
3850     VM_CHECK_EXCEPTION_AT_END();
3851 }
3852
3853 void Machine::cti_op_put_by_id_fail(CTI_ARGS)
3854 {
3855     ExecState* exec = ARG_exec;
3856     Identifier& ident = *ARG_id2;
3857
3858     PutPropertySlot slot;
3859     ARG_src1->put(exec, ident, ARG_src3, slot);
3860
3861     // should probably uncachePutByID() ... this would mean doing a vPC lookup - might be worth just bleeding this until the end.
3862     ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_put_by_id_generic);
3863
3864     VM_CHECK_EXCEPTION_AT_END();
3865 }
3866
3867 JSValue* Machine::cti_op_get_by_id(CTI_ARGS)
3868 {
3869     ExecState* exec = ARG_exec;
3870     Identifier& ident = *ARG_id2;
3871
3872     JSValue* baseValue = ARG_src1;
3873     PropertySlot slot(baseValue);
3874     JSValue* result = baseValue->get(exec, ident, slot);
3875
3876     ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_get_by_id_second);
3877
3878     VM_CHECK_EXCEPTION_AT_END();
3879     return result;
3880 }
3881
3882 JSValue* Machine::cti_op_get_by_id_second(CTI_ARGS)
3883 {
3884     ExecState* exec = ARG_exec;
3885     Identifier& ident = *ARG_id2;
3886
3887     JSValue* baseValue = ARG_src1;
3888     PropertySlot slot(baseValue);
3889     JSValue* result = baseValue->get(exec, ident, slot);
3890
3891     exec->machine()->tryCTICacheGetByID(exec, ARG_codeBlock, CTI_RETURN_ADDRESS, baseValue, ident, slot);
3892
3893     VM_CHECK_EXCEPTION_AT_END();
3894     return result;
3895 }
3896
3897 JSValue* Machine::cti_op_get_by_id_generic(CTI_ARGS)
3898 {
3899     ExecState* exec = ARG_exec;
3900     Identifier& ident = *ARG_id2;
3901
3902     JSValue* baseValue = ARG_src1;
3903     PropertySlot slot(baseValue);
3904     JSValue* result = baseValue->get(exec, ident, slot);
3905
3906     VM_CHECK_EXCEPTION_AT_END();
3907     return result;
3908 }
3909
3910 JSValue* Machine::cti_op_get_by_id_fail(CTI_ARGS)
3911 {
3912     ExecState* exec = ARG_exec;
3913     Identifier& ident = *ARG_id2;
3914
3915     JSValue* baseValue = ARG_src1;
3916     PropertySlot slot(baseValue);
3917     JSValue* result = baseValue->get(exec, ident, slot);
3918
3919     // should probably uncacheGetByID() ... this would mean doing a vPC lookup - might be worth just bleeding this until the end.
3920     ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_get_by_id_generic);
3921
3922     VM_CHECK_EXCEPTION_AT_END();
3923     return result;
3924 }
3925
3926 JSValue* Machine::cti_op_instanceof(CTI_ARGS)
3927 {
3928     ExecState* exec = ARG_exec;
3929     JSValue* baseVal = ARG_src2;
3930
3931     if (!baseVal->isObject()) {
3932         CodeBlock* codeBlock = ARG_codeBlock;
3933         ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
3934         unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
3935         exec->setException(createInvalidParamError(exec, "instanceof", baseVal, codeBlock->instructions.begin() + vPCIndex, codeBlock));
3936         VM_CHECK_EXCEPTION(JSValue*);
3937     }
3938
3939     JSObject* baseObj = static_cast<JSObject*>(baseVal);
3940     JSValue* result = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec,  ARG_src1) : false);
3941     VM_CHECK_EXCEPTION_AT_END();
3942     return result;
3943 }
3944
3945 JSValue* Machine::cti_op_del_by_id(CTI_ARGS)
3946 {
3947     ExecState* exec = ARG_exec;
3948     Identifier& ident = *ARG_id2;
3949     
3950     JSObject* baseObj = ARG_src1->toObject(exec);
3951
3952     JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
3953     VM_CHECK_EXCEPTION_AT_END();
3954     return result;
3955 }
3956
3957 JSValue* Machine::cti_op_mul(CTI_ARGS)
3958 {
3959     ExecState* exec = ARG_exec;
3960     JSValue* src1 = ARG_src1;
3961     JSValue* src2 = ARG_src2;
3962
3963     double left;
3964     double right;
3965     if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
3966         return jsNumber(exec, left * right);
3967     else {
3968         JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
3969         VM_CHECK_EXCEPTION_AT_END();
3970         return result;
3971     }
3972 }
3973
3974 JSValue* Machine::cti_op_new_func(CTI_ARGS)
3975 {
3976     return ARG_func1->makeFunction(ARG_exec, ARG_scopeChain);
3977 }
3978
3979 void* Machine::cti_op_call_JSFunction(CTI_ARGS)
3980 {
3981     ExecState* exec = ARG_exec;
3982     RegisterFile* registerFile = ARG_registerFile;
3983     Register* r = ARG_r;
3984     CodeBlock* codeBlock = ARG_codeBlock;
3985     ScopeChainNode* scopeChain = ARG_scopeChain;
3986
3987     Machine* machine = exec->machine();
3988     JSValue* exceptionValue = 0;
3989     Register* registerBase = registerFile->base();
3990     
3991     JSValue* funcVal = ARG_src1;
3992     JSValue* thisValue = ARG_src2;
3993     int firstArg = ARG_int3;
3994     int argCount = ARG_int4;
3995
3996     CallData callData;
3997 #ifndef NDEBUG
3998     CallType callType =
3999 #endif
4000         funcVal->getCallData(callData);
4001
4002     ASSERT(callType == CallTypeJS);
4003
4004     if (*ARG_profilerReference)
4005         (*ARG_profilerReference)->willExecute(exec, static_cast<JSObject*>(funcVal));
4006
4007     ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
4008     FunctionBodyNode* functionBodyNode = callData.js.functionBody;
4009     CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
4010
4011     r[firstArg] = thisValue;
4012
4013     Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
4014     machine->initializeCallFrame(callFrame, codeBlock, ARG_instr5, scopeChain, r, 0/*dst*/, firstArg, argCount, 0, funcVal);
4015     exec->m_callFrame = callFrame;
4016
4017     r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
4018     JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
4019     
4020     codeBlock = newCodeBlock;
4021     machine->setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
4022
4023     if (!codeBlock->ctiCode)
4024         CTI::compile(machine, exec, codeBlock);
4025
4026     ARG_setScopeChain(scopeChain);
4027     ARG_setCodeBlock(codeBlock);
4028     ARG_setR(r);
4029     return codeBlock->ctiCode;
4030 }
4031
4032 JSValue* Machine::cti_op_call_NotJSFunction(CTI_ARGS)
4033 {
4034     ExecState* exec = ARG_exec;
4035     Register* r = ARG_r;
4036
4037     JSValue* funcVal = ARG_src1;
4038     JSValue* thisValue = ARG_src2;
4039     int firstArg = ARG_int3;
4040     int argCount = ARG_int4;
4041
4042     CallData callData;
4043     CallType callType = funcVal->getCallData(callData);
4044
4045     ASSERT(callType != CallTypeJS);
4046
4047     if (callType == CallTypeHost) {
4048         CodeBlock* codeBlock = ARG_codeBlock;
4049         ScopeChainNode* scopeChain = ARG_scopeChain;
4050         Machine* machine = exec->machine();
4051
4052         Register* oldCallFrame = exec->m_callFrame;
4053         Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
4054         machine->initializeCallFrame(callFrame, codeBlock, ARG_instr5, scopeChain, r, 0/*dst*/, firstArg, argCount, 0, funcVal);
4055         exec->m_callFrame = callFrame;
4056
4057         if (*ARG_profilerReference)
4058             (*ARG_profilerReference)->willExecute(exec, static_cast<JSObject*>(funcVal));
4059
4060         ArgList argList(r + firstArg + 1, argCount - 1);
4061
4062         CTI_MACHINE_SAMPLING_callingHostFunction();
4063
4064         JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(funcVal), thisValue, argList);
4065         exec->m_callFrame = oldCallFrame;
4066         VM_CHECK_EXCEPTION(JSValue*);
4067
4068         if (*ARG_profilerReference)
4069             (*ARG_profilerReference)->didExecute(exec, static_cast<JSObject*>(funcVal));
4070
4071         return returnValue;
4072
4073     }
4074
4075     ASSERT(callType == CallTypeNone);
4076
4077     exec->setException(createNotAFunctionError(exec, funcVal, ARG_instr5, ARG_codeBlock));
4078     VM_CHECK_EXCEPTION_AT_END();
4079     return 0;
4080 }
4081
4082 JSValue* Machine::cti_op_ret(CTI_ARGS)
4083 {
4084     ExecState* exec = ARG_exec;
4085     Register* r = ARG_r;
4086     CodeBlock* codeBlock = ARG_codeBlock;
4087     ScopeChainNode* scopeChain = ARG_scopeChain;
4088
4089     Machine* machine = exec->machine();