Bug 20874: op_resolve does not do any form of caching
[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 jsIsObjectType(JSValue* v)
251 {
252     if (JSImmediate::isImmediate(v))
253         return v->isNull();
254
255     JSType type = static_cast<JSCell*>(v)->structureID()->type();
256     if (type == NumberType || type == StringType)
257         return false;
258     if (type == ObjectType) {
259         if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
260             return false;
261         CallData callData;
262         if (static_cast<JSObject*>(v)->getCallData(callData) != CallTypeNone)
263             return false;
264     }
265     return true;
266 }
267
268 static bool jsIsFunctionType(JSValue* v)
269 {
270     if (v->isObject()) {
271         CallData callData;
272         if (static_cast<JSObject*>(v)->getCallData(callData) != CallTypeNone)
273             return true;
274     }
275     return false;
276 }
277
278 static bool NEVER_INLINE resolve(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
279 {
280     int dst = (vPC + 1)->u.operand;
281     int property = (vPC + 2)->u.operand;
282
283     ScopeChainIterator iter = scopeChain->begin();
284     ScopeChainIterator end = scopeChain->end();
285     ASSERT(iter != end);
286
287     Identifier& ident = codeBlock->identifiers[property];
288     do {
289         JSObject* o = *iter;
290         PropertySlot slot(o);
291         if (o->getPropertySlot(exec, ident, slot)) {
292             JSValue* result = slot.getValue(exec, ident);
293             exceptionValue = exec->exception();
294             if (exceptionValue)
295                 return false;
296             r[dst] = result;
297             return true;
298         }
299     } while (++iter != end);
300     exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
301     return false;
302 }
303
304 static bool NEVER_INLINE resolve_skip(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
305 {
306     int dst = (vPC + 1)->u.operand;
307     int property = (vPC + 2)->u.operand;
308     int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain;
309
310     ScopeChainIterator iter = scopeChain->begin();
311     ScopeChainIterator end = scopeChain->end();
312     ASSERT(iter != end);
313     while (skip--) {
314         ++iter;
315         ASSERT(iter != end);
316     }
317     Identifier& ident = codeBlock->identifiers[property];
318     do {
319         JSObject* o = *iter;
320         PropertySlot slot(o);
321         if (o->getPropertySlot(exec, ident, slot)) {
322             JSValue* result = slot.getValue(exec, ident);
323             exceptionValue = exec->exception();
324             if (exceptionValue)
325                 return false;
326             r[dst] = result;
327             return true;
328         }
329     } while (++iter != end);
330     exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
331     return false;
332 }
333
334 static bool NEVER_INLINE resolveGlobal(ExecState* exec, Instruction* vPC, Register* r, CodeBlock* codeBlock, JSValue*& exceptionValue)
335 {
336     int dst = (vPC + 1)->u.operand;
337     JSGlobalObject* globalObject = static_cast<JSGlobalObject*>((vPC + 2)->u.jsCell);
338     ASSERT(globalObject->isGlobalObject());
339     int property = (vPC + 3)->u.operand;
340     StructureID* structureID = (vPC + 4)->u.structureID;
341     int offset = (vPC + 5)->u.operand;
342
343     if (structureID == globalObject->structureID()) {
344         r[dst] = globalObject->getDirectOffset(offset);
345         return true;
346     }
347
348     Identifier& ident = codeBlock->identifiers[property];
349     PropertySlot slot(globalObject);
350     if (globalObject->getPropertySlot(exec, ident, slot)) {
351         JSValue* result = slot.getValue(exec, ident);
352         if (slot.isCacheable()) {
353             if (vPC[4].u.structureID)
354                 vPC[4].u.structureID->deref();
355             globalObject->structureID()->ref();
356             vPC[4] = globalObject->structureID();
357             vPC[5] = slot.cachedOffset();
358             r[dst] = result;
359             return true;
360         }
361
362         exceptionValue = exec->exception();
363         if (exceptionValue)
364             return false;
365         r[dst] = result;
366         return true;
367     }
368
369     exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
370     return false;
371 }
372
373 ALWAYS_INLINE static JSValue* inlineResolveBase(ExecState* exec, Identifier& property, ScopeChainNode* scopeChain)
374 {
375     ScopeChainIterator iter = scopeChain->begin();
376     ScopeChainIterator next = iter;
377     ++next;
378     ScopeChainIterator end = scopeChain->end();
379     ASSERT(iter != end);
380
381     PropertySlot slot;
382     JSObject* base;
383     while (true) {
384         base = *iter;
385         if (next == end || base->getPropertySlot(exec, property, slot))
386             return base;
387
388         iter = next;
389         ++next;
390     }
391
392     ASSERT_NOT_REACHED();
393     return 0;
394 }
395
396 NEVER_INLINE static void resolveBase(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock)
397 {
398     int dst = (vPC + 1)->u.operand;
399     int property = (vPC + 2)->u.operand;
400     r[dst] = inlineResolveBase(exec, codeBlock->identifiers[property], scopeChain);
401 }
402
403 static bool NEVER_INLINE resolveBaseAndProperty(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
404 {
405     int baseDst = (vPC + 1)->u.operand;
406     int propDst = (vPC + 2)->u.operand;
407     int property = (vPC + 3)->u.operand;
408
409     ScopeChainIterator iter = scopeChain->begin();
410     ScopeChainIterator end = scopeChain->end();
411
412     // FIXME: add scopeDepthIsZero optimization
413
414     ASSERT(iter != end);
415
416     Identifier& ident = codeBlock->identifiers[property];
417     JSObject* base;
418     do {
419         base = *iter;
420         PropertySlot slot(base);
421         if (base->getPropertySlot(exec, ident, slot)) {
422             JSValue* result = slot.getValue(exec, ident);
423             exceptionValue = exec->exception();
424             if (exceptionValue)
425                 return false;
426             r[propDst] = result;
427             r[baseDst] = base;
428             return true;
429         }
430         ++iter;
431     } while (iter != end);
432
433     exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
434     return false;
435 }
436
437 static bool NEVER_INLINE resolveBaseAndFunc(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
438 {
439     int baseDst = (vPC + 1)->u.operand;
440     int funcDst = (vPC + 2)->u.operand;
441     int property = (vPC + 3)->u.operand;
442
443     ScopeChainIterator iter = scopeChain->begin();
444     ScopeChainIterator end = scopeChain->end();
445
446     // FIXME: add scopeDepthIsZero optimization
447
448     ASSERT(iter != end);
449
450     Identifier& ident = codeBlock->identifiers[property];
451     JSObject* base;
452     do {
453         base = *iter;
454         PropertySlot slot(base);
455         if (base->getPropertySlot(exec, ident, slot)) {            
456             // ECMA 11.2.3 says that if we hit an activation the this value should be null.
457             // However, section 10.2.3 says that in the case where the value provided
458             // by the caller is null, the global object should be used. It also says
459             // that the section does not apply to internal functions, but for simplicity
460             // of implementation we use the global object anyway here. This guarantees
461             // that in host objects you always get a valid object for this.
462             // We also handle wrapper substitution for the global object at the same time.
463             JSObject* thisObj = base->toThisObject(exec);
464             JSValue* result = slot.getValue(exec, ident);
465             exceptionValue = exec->exception();
466             if (exceptionValue)
467                 return false;
468
469             r[baseDst] = thisObj;
470             r[funcDst] = result;
471             return true;
472         }
473         ++iter;
474     } while (iter != end);
475
476     exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
477     return false;
478 }
479
480 ALWAYS_INLINE void Machine::initializeCallFrame(Register* callFrame, CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, Register* r, int returnValueRegister, int argv, int argc, JSValue* function)
481 {
482     callFrame[RegisterFile::CallerCodeBlock] = codeBlock;
483     callFrame[RegisterFile::ReturnVPC] = vPC + 1;
484     callFrame[RegisterFile::CallerScopeChain] = scopeChain;
485     callFrame[RegisterFile::CallerRegisters] = r;
486     callFrame[RegisterFile::ReturnValueRegister] = returnValueRegister;
487     callFrame[RegisterFile::ArgumentStartRegister] = argv; // original argument vector (for the sake of the "arguments" object)
488     callFrame[RegisterFile::ArgumentCount] = argc; // original argument count (for the sake of the "arguments" object)
489     callFrame[RegisterFile::Callee] = function;
490     callFrame[RegisterFile::OptionalCalleeActivation] = nullJSValue;
491 }
492
493 ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* newCodeBlock, RegisterFile* registerFile, Register* registerBase, Register* r, int argv, int argc, JSValue*& exceptionValue)
494 {
495     size_t registerOffset = argv + newCodeBlock->numLocals;
496     size_t size = r - registerBase + registerOffset + newCodeBlock->numConstants + newCodeBlock->numTemporaries;
497
498     if (argc == newCodeBlock->numParameters) { // correct number of arguments
499         if (!registerFile->grow(size)) {
500             exceptionValue = createStackOverflowError(exec);
501             return r;
502         }
503         r += registerOffset;
504     } else if (argc < newCodeBlock->numParameters) { // too few arguments -- fill in the blanks
505         if (!registerFile->grow(size)) {
506             exceptionValue = createStackOverflowError(exec);
507             return r;
508         }
509         r += registerOffset;
510
511         int omittedArgCount = newCodeBlock->numParameters - argc;
512         Register* endOfParams = r - newCodeBlock->numVars;
513         for (Register* it = endOfParams - omittedArgCount; it != endOfParams; ++it)
514             (*it) = jsUndefined();
515     } else { // too many arguments -- copy return info and expected arguments, leaving the extra arguments behind
516         int shift = argc + RegisterFile::CallFrameHeaderSize;
517         registerOffset += shift;
518         size += shift;
519
520         if (!registerFile->grow(size)) {
521             exceptionValue = createStackOverflowError(exec);
522             return r;
523         }
524         r += registerOffset;
525
526         Register* it = r - newCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize - shift;
527         Register* end = it + RegisterFile::CallFrameHeaderSize + newCodeBlock->numParameters;
528         for ( ; it != end; ++it)
529             *(it + shift) = *it;
530     }
531     
532     // initialize local variable slots
533     for (Register* it = r - newCodeBlock->numVars; it != r; ++it)
534         (*it) = jsUndefined();
535
536     for (size_t i = 0; i < newCodeBlock->constantRegisters.size(); ++i)
537         r[i] = newCodeBlock->constantRegisters[i];
538
539     return r;
540 }
541
542 ALWAYS_INLINE ScopeChainNode* scopeChainForCall(ExecState* exec, FunctionBodyNode* functionBodyNode, CodeBlock* newCodeBlock, ScopeChainNode* callDataScopeChain, Register* r)
543 {
544     if (newCodeBlock->needsFullScopeChain) {
545         JSActivation* activation = new (exec) JSActivation(exec, functionBodyNode, r);
546         r[RegisterFile::OptionalCalleeActivation - RegisterFile::CallFrameHeaderSize - newCodeBlock->numLocals] = activation;
547
548         return callDataScopeChain->copy()->push(activation);
549     }
550
551     return callDataScopeChain;
552 }
553
554 static NEVER_INLINE bool isNotObject(ExecState* exec, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValue* value, JSValue*& exceptionData)
555 {
556     if (value->isObject())
557         return false;
558     exceptionData = createInvalidParamError(exec, forInstanceOf ? "instanceof" : "in" , value, vPC, codeBlock);
559     return true;
560 }
561
562 NEVER_INLINE JSValue* Machine::callEval(ExecState* exec, CodeBlock* callingCodeBlock, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, Register* r, int argv, int argc, JSValue*& exceptionValue)
563 {
564     if (argc < 2)
565         return jsUndefined();
566
567     JSValue* program = r[argv + 1].jsValue(exec);
568
569     if (!program->isString())
570         return program;
571
572     Profiler** profiler = Profiler::enabledProfilerReference();
573     if (*profiler)
574         (*profiler)->willExecute(exec, scopeChain->globalObject()->evalFunction());
575
576     UString programSource = static_cast<JSString*>(program)->value();
577
578     RefPtr<EvalNode> evalNode = callingCodeBlock->evalCodeCache.get(exec, programSource, scopeChain, exceptionValue);
579
580     JSValue* result = 0;
581     if (evalNode)
582         result = exec->globalData().machine->execute(evalNode.get(), exec, thisObj, r - registerFile->base() + argv + argc, scopeChain, &exceptionValue);
583
584     if (*profiler)
585         (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
586
587     return result;
588 }
589
590 Machine::Machine()
591     : m_sampler(0)
592 #if ENABLE(CTI)
593     , m_ctiArrayLengthTrampoline(0)
594     , m_ctiStringLengthTrampoline(0)
595     , m_jitCodeBuffer(new JITCodeBuffer(1024 * 1024))
596 #endif
597     , m_reentryDepth(0)
598     , m_timeoutTime(0)
599     , m_timeAtLastCheckTimeout(0)
600     , m_timeExecuting(0)
601     , m_timeoutCheckCount(0)
602     , m_ticksUntilNextTimeoutCheck(initialTickCountThreshold)
603 {
604     privateExecute(InitializeAndReturn);
605     
606     // Bizarrely, calling fastMalloc here is faster than allocating space on the stack.
607     void* storage = fastMalloc(sizeof(CollectorBlock));
608
609     JSArray* jsArray = new (storage) JSArray(StructureID::create(jsNull()));
610     m_jsArrayVptr = jsArray->vptr();
611     static_cast<JSCell*>(jsArray)->~JSCell();
612
613     JSString* jsString = new (storage) JSString(JSString::VPtrStealingHack);
614     m_jsStringVptr = jsString->vptr();
615     static_cast<JSCell*>(jsString)->~JSCell();
616
617     JSFunction* jsFunction = new (storage) JSFunction(StructureID::create(jsNull()));
618     m_jsFunctionVptr = jsFunction->vptr();
619     static_cast<JSCell*>(jsFunction)->~JSCell();
620     
621     fastFree(storage);
622 }
623
624 Machine::~Machine()
625 {
626 #if ENABLE(CTI)
627     if (m_ctiArrayLengthTrampoline)
628         fastFree(m_ctiArrayLengthTrampoline);
629     if (m_ctiStringLengthTrampoline)
630         fastFree(m_ctiStringLengthTrampoline);
631 #endif
632 }
633
634 #ifndef NDEBUG
635
636 void Machine::dumpCallFrame(const CodeBlock* codeBlock, ScopeChainNode* scopeChain, RegisterFile* registerFile, const Register* r)
637 {
638     ScopeChain sc(scopeChain);
639     JSGlobalObject* globalObject = sc.globalObject();
640     codeBlock->dump(globalObject->globalExec());
641     dumpRegisters(codeBlock, registerFile, r);
642 }
643
644 void Machine::dumpRegisters(const CodeBlock* codeBlock, RegisterFile* registerFile, const Register* r)
645 {
646     printf("Register frame: \n\n");
647     printf("----------------------------------------------------\n");
648     printf("            use            |   address  |   value   \n");
649     printf("----------------------------------------------------\n");
650
651     const Register* it;
652     const Register* end;
653
654     if (codeBlock->codeType == GlobalCode) {
655         it = registerFile->lastGlobal();
656         end = it + registerFile->numGlobals();
657         while (it != end) {
658             printf("[global var]               | %10p | %10p \n", it, (*it).v());
659             ++it;
660         }
661         printf("----------------------------------------------------\n");
662     }
663     
664     it = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
665     printf("[CallerCodeBlock]          | %10p | %10p \n", it, (*it).v()); ++it;
666     printf("[ReturnVPC]                | %10p | %10p \n", it, (*it).v()); ++it;
667     printf("[CallerScopeChain]         | %10p | %10p \n", it, (*it).v()); ++it;
668     printf("[CallerRegisterOffset]     | %10p | %10p \n", it, (*it).v()); ++it;
669     printf("[ReturnValueRegister]      | %10p | %10p \n", it, (*it).v()); ++it;
670     printf("[ArgumentStartRegister]    | %10p | %10p \n", it, (*it).v()); ++it;
671     printf("[ArgumentCount]            | %10p | %10p \n", it, (*it).v()); ++it;
672     printf("[Callee]                   | %10p | %10p \n", it, (*it).v()); ++it;
673     printf("[OptionalCalleeActivation] | %10p | %10p \n", it, (*it).v()); ++it;
674     printf("----------------------------------------------------\n");
675
676     printf("[this]                     | %10p | %10p \n", it, (*it).v()); ++it;
677     end = it + max(codeBlock->numParameters - 1, 0); // - 1 to skip "this"
678     if (it != end) {
679         do {
680             printf("[param]                    | %10p | %10p \n", it, (*it).v());
681             ++it;
682         } while (it != end);
683     }
684     printf("----------------------------------------------------\n");
685
686     if (codeBlock->codeType != GlobalCode) {
687         end = it + codeBlock->numVars;
688         if (it != end) {
689             do {
690                 printf("[var]                      | %10p | %10p \n", it, (*it).v());
691                 ++it;
692             } while (it != end);
693         printf("----------------------------------------------------\n");
694         }
695     }
696
697     end = it + codeBlock->numTemporaries;
698     if (it != end) {
699         do {
700             printf("[temp]                     | %10p | %10p \n", it, (*it).v());
701             ++it;
702         } while (it != end);
703     }
704 }
705
706 #endif
707
708 //#if !defined(NDEBUG) || ENABLE(SAMPLING_TOOL)
709
710 bool Machine::isOpcode(Opcode opcode)
711 {
712 #if HAVE(COMPUTED_GOTO)
713     return opcode != HashTraits<Opcode>::emptyValue()
714         && !HashTraits<Opcode>::isDeletedValue(opcode)
715         && m_opcodeIDTable.contains(opcode);
716 #else
717     return opcode >= 0 && opcode <= op_end;
718 #endif
719 }
720
721 //#endif
722
723 NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, const Instruction*& vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r)
724 {
725     CodeBlock* oldCodeBlock = codeBlock;
726     Register* callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
727
728     if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
729         DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
730         if (callFrame[RegisterFile::Callee].jsValue(exec))
731             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
732         else
733             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
734     }
735
736     if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
737         if (callFrame[RegisterFile::Callee].jsValue(exec))
738             profiler->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
739         else
740             profiler->didExecute(exec, codeBlock->ownerNode->sourceURL(), codeBlock->ownerNode->lineNo());
741     }
742
743     if (oldCodeBlock->needsFullScopeChain)
744         scopeChain->deref();
745
746     // If this call frame created an activation, tear it off.
747     if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
748         ASSERT(activation->isActivationObject());
749         activation->copyRegisters();
750     }
751     
752     codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
753     if (!codeBlock)
754         return false;
755
756     scopeChain = callFrame[RegisterFile::CallerScopeChain].scopeChain();
757     r = callFrame[RegisterFile::CallerRegisters].r();
758     exec->m_callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
759     vPC = callFrame[RegisterFile::ReturnVPC].vPC();
760
761     return true;
762 }
763
764 NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue*& exceptionValue, const Instruction* vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r, bool explicitThrow)
765 {
766     // Set up the exception object
767     
768     if (exceptionValue->isObject()) {
769         JSObject* exception = static_cast<JSObject*>(exceptionValue);
770         if (exception->isNotAnObjectErrorStub()) {
771             exception = createNotAnObjectError(exec, static_cast<JSNotAnObjectErrorStub*>(exception), vPC, codeBlock);
772             exceptionValue = exception;
773         } else {
774             if (!exception->hasProperty(exec, Identifier(exec, "line")) && 
775                 !exception->hasProperty(exec, Identifier(exec, "sourceId")) && 
776                 !exception->hasProperty(exec, Identifier(exec, "sourceURL")) && 
777                 !exception->hasProperty(exec, Identifier(exec, expressionBeginOffsetPropertyName)) && 
778                 !exception->hasProperty(exec, Identifier(exec, expressionCaretOffsetPropertyName)) && 
779                 !exception->hasProperty(exec, Identifier(exec, expressionEndOffsetPropertyName))) {
780                 if (explicitThrow) {
781                     int startOffset = 0;
782                     int endOffset = 0;
783                     int divotPoint = 0;
784                     int line = codeBlock->expressionRangeForVPC(vPC, divotPoint, startOffset, endOffset);
785                     exception->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, line), ReadOnly | DontDelete);
786                     
787                     // We only hit this path for error messages and throw statements, which don't have a specific failure position
788                     // So we just give the full range of the error/throw statement.
789                     exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
790                     exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
791                 } else
792                     exception->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, codeBlock->lineNumberForVPC(vPC)), ReadOnly | DontDelete);
793                 exception->putWithAttributes(exec, Identifier(exec, "sourceId"), jsNumber(exec, codeBlock->ownerNode->sourceId()), ReadOnly | DontDelete);
794                 exception->putWithAttributes(exec, Identifier(exec, "sourceURL"), jsOwnedString(exec, codeBlock->ownerNode->sourceURL()), ReadOnly | DontDelete);
795             }
796             
797             if (exception->isWatchdogException()) {
798                 while (unwindCallFrame(exec, exceptionValue, vPC, codeBlock, scopeChain, r)) {
799                     // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
800                 }
801                 return 0;
802             }
803         }
804     }
805
806     if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
807         DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
808         debugger->exception(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->lineNumberForVPC(vPC));
809     }
810
811     // Calculate an exception handler vPC, unwinding call frames as necessary.
812
813     int scopeDepth;
814     Instruction* handlerVPC;
815
816     while (!codeBlock->getHandlerForVPC(vPC, handlerVPC, scopeDepth)) {
817         if (!unwindCallFrame(exec, exceptionValue, vPC, codeBlock, scopeChain, r))
818             return 0;
819     }
820
821     // Now unwind the scope chain within the exception handler's call frame.
822
823     ScopeChain sc(scopeChain);
824     int scopeDelta = depth(codeBlock, sc) - scopeDepth;
825     ASSERT(scopeDelta >= 0);
826     while (scopeDelta--)
827         sc.pop();
828     setScopeChain(exec, scopeChain, sc.node());
829
830     return handlerVPC;
831 }
832
833 JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue** exception)
834 {
835     if (m_reentryDepth >= MaxReentryDepth) {
836         *exception = createStackOverflowError(exec);
837         return 0;
838     }
839
840     CodeBlock* codeBlock = &programNode->byteCode(scopeChain);
841
842     size_t oldSize = m_registerFile.size();
843     size_t newSize = oldSize + RegisterFile::CallFrameHeaderSize + codeBlock->numVars + codeBlock->numConstants + codeBlock->numTemporaries;
844     if (!m_registerFile.grow(newSize)) {
845         *exception = createStackOverflowError(exec);
846         return 0;
847     }
848
849     JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
850     JSGlobalObject* globalObject = exec->dynamicGlobalObject();
851     globalObject->copyGlobalsTo(m_registerFile);
852
853     Register* callFrame = m_registerFile.base() + oldSize;
854
855     // a 0 codeBlock indicates a built-in caller
856     initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0);
857
858     Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
859     r[codeBlock->thisRegister] = thisObj;
860
861     for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
862         r[i] = codeBlock->constantRegisters[i];
863
864     if (codeBlock->needsFullScopeChain)
865         scopeChain = scopeChain->copy();
866
867     ExecState newExec(exec, &m_registerFile, scopeChain, 0);
868
869     Profiler** profiler = Profiler::enabledProfilerReference();
870     if (*profiler)
871         (*profiler)->willExecute(exec, programNode->sourceURL(), programNode->lineNo());
872
873     m_reentryDepth++;
874 #if ENABLE(CTI)
875     if (!codeBlock->ctiCode)
876         CTI::compile(this, exec, codeBlock);
877     JSValue* result = CTI::execute(codeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
878 #else
879     JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
880 #endif
881     m_reentryDepth--;
882
883     MACHINE_SAMPLING_privateExecuteReturned();
884
885     if (*profiler)
886         (*profiler)->didExecute(exec, programNode->sourceURL(), programNode->lineNo());
887
888     if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
889         lastGlobalObject->copyGlobalsTo(m_registerFile);
890
891     m_registerFile.shrink(oldSize);
892     return result;
893 }
894
895 JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue** exception)
896 {
897     if (m_reentryDepth >= MaxReentryDepth) {
898         *exception = createStackOverflowError(exec);
899         return 0;
900     }
901
902     int argv = RegisterFile::CallFrameHeaderSize;
903     int argc = args.size() + 1; // implicit "this" parameter
904
905     size_t oldSize = m_registerFile.size();
906     if (!m_registerFile.grow(oldSize + RegisterFile::CallFrameHeaderSize + argc)) {
907         *exception = createStackOverflowError(exec);
908         return 0;
909     }
910
911     Register* callFrame = m_registerFile.base() + oldSize;
912
913     // put args in place, including "this"
914     Register* dst = callFrame + RegisterFile::CallFrameHeaderSize;
915     (*dst) = thisObj;
916
917     ArgList::const_iterator end = args.end();
918     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
919         (*++dst) = *it;
920
921     // a 0 codeBlock indicates a built-in caller
922     initializeCallFrame(callFrame, 0, 0, 0, callFrame, 0, argv, argc, function);
923
924     CodeBlock* newCodeBlock = &functionBodyNode->byteCode(scopeChain);
925     Register* r = slideRegisterWindowForCall(exec, newCodeBlock, &m_registerFile, m_registerFile.base(), callFrame, argv, argc, *exception);
926     if (*exception) {
927         m_registerFile.shrink(oldSize);
928         return 0;
929     }
930
931     scopeChain = scopeChainForCall(exec, functionBodyNode, newCodeBlock, scopeChain, r);
932
933     ExecState newExec(exec, &m_registerFile, scopeChain, callFrame);
934
935     Profiler** profiler = Profiler::enabledProfilerReference();
936     if (*profiler)
937         (*profiler)->willExecute(exec, function);
938
939     m_reentryDepth++;
940 #if ENABLE(CTI)
941     if (!newCodeBlock->ctiCode)
942         CTI::compile(this, exec, newCodeBlock);
943     JSValue* result = CTI::execute(newCodeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, newCodeBlock, exception);
944 #else
945     JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, newCodeBlock, exception);
946 #endif
947     m_reentryDepth--;
948
949     MACHINE_SAMPLING_privateExecuteReturned();
950
951     m_registerFile.shrink(oldSize);
952     return result;
953 }
954
955 JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)
956 {
957     if (m_reentryDepth >= MaxReentryDepth) {
958         *exception = createStackOverflowError(exec);
959         return 0;
960     }
961
962     EvalCodeBlock* codeBlock = &evalNode->byteCode(scopeChain);
963
964     JSVariableObject* variableObject;
965     for (ScopeChainNode* node = scopeChain; ; node = node->next) {
966         ASSERT(node);
967         if (node->object->isVariableObject()) {
968             variableObject = static_cast<JSVariableObject*>(node->object);
969             break;
970         }
971     }
972
973     { // Scope for BatchedTransitionOptimizer
974
975         BatchedTransitionOptimizer optimizer(variableObject);
976
977         const Node::VarStack& varStack = codeBlock->ownerNode->varStack();
978         Node::VarStack::const_iterator varStackEnd = varStack.end();
979         for (Node::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) {
980             const Identifier& ident = (*it).first;
981             if (!variableObject->hasProperty(exec, ident)) {
982                 PutPropertySlot slot;
983                 variableObject->put(exec, ident, jsUndefined(), slot);
984             }
985         }
986
987         const Node::FunctionStack& functionStack = codeBlock->ownerNode->functionStack();
988         Node::FunctionStack::const_iterator functionStackEnd = functionStack.end();
989         for (Node::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it) {
990             PutPropertySlot slot;
991             variableObject->put(exec, (*it)->m_ident, (*it)->makeFunction(exec, scopeChain), slot);
992         }
993
994     }
995
996     size_t oldSize = m_registerFile.size();
997     size_t newSize = registerOffset + codeBlock->numVars + codeBlock->numConstants + codeBlock->numTemporaries + RegisterFile::CallFrameHeaderSize;
998     if (!m_registerFile.grow(newSize)) {
999         *exception = createStackOverflowError(exec);
1000         return 0;
1001     }
1002
1003     Register* callFrame = m_registerFile.base() + registerOffset;
1004
1005     // a 0 codeBlock indicates a built-in caller
1006     initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0);
1007
1008     Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
1009     r[codeBlock->thisRegister] = thisObj;
1010
1011     for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
1012         r[i] = codeBlock->constantRegisters[i];
1013
1014     if (codeBlock->needsFullScopeChain)
1015         scopeChain = scopeChain->copy();
1016
1017     ExecState newExec(exec, &m_registerFile, scopeChain, 0);
1018
1019     Profiler** profiler = Profiler::enabledProfilerReference();
1020     if (*profiler)
1021         (*profiler)->willExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
1022
1023     m_reentryDepth++;
1024 #if ENABLE(CTI)
1025     if (!codeBlock->ctiCode)
1026         CTI::compile(this, exec, codeBlock);
1027     JSValue* result = CTI::execute(codeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
1028 #else
1029     JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
1030 #endif
1031     m_reentryDepth--;
1032
1033     MACHINE_SAMPLING_privateExecuteReturned();
1034
1035     if (*profiler)
1036         (*profiler)->didExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
1037
1038     m_registerFile.shrink(oldSize);
1039     return result;
1040 }
1041
1042 ALWAYS_INLINE void Machine::setScopeChain(ExecState* exec, ScopeChainNode*& scopeChain, ScopeChainNode* newScopeChain)
1043 {
1044     scopeChain = newScopeChain;
1045     exec->m_scopeChain = newScopeChain;
1046 }
1047
1048 NEVER_INLINE void Machine::debug(ExecState* exec, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register* r, DebugHookID debugHookID, int firstLine, int lastLine)
1049 {
1050     Debugger* debugger = exec->dynamicGlobalObject()->debugger();
1051     if (!debugger)
1052         return;
1053
1054     DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, 0);
1055
1056     switch (debugHookID) {
1057         case DidEnterCallFrame:
1058             debugger->callEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
1059             return;
1060         case WillLeaveCallFrame:
1061             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
1062             return;
1063         case WillExecuteStatement:
1064             debugger->atStatement(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
1065             return;
1066         case WillExecuteProgram:
1067             debugger->willExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
1068             return;
1069         case DidExecuteProgram:
1070             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
1071             return;
1072         case DidReachBreakpoint:
1073             debugger->didReachBreakpoint(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
1074             return;
1075     }
1076 }
1077
1078 void Machine::resetTimeoutCheck()
1079 {
1080     m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
1081     m_timeAtLastCheckTimeout = 0;
1082     m_timeExecuting = 0;
1083 }
1084
1085 // Returns the time the current thread has spent executing, in milliseconds.
1086 static inline unsigned getCPUTime()
1087 {
1088 #if PLATFORM(DARWIN)
1089     mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
1090     thread_basic_info_data_t info;
1091
1092     // Get thread information
1093     thread_info(mach_thread_self(), THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &infoCount);
1094     
1095     unsigned time = info.user_time.seconds * 1000 + info.user_time.microseconds / 1000;
1096     time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000;
1097     
1098     return time;
1099 #elif HAVE(SYS_TIME_H)
1100     // FIXME: This should probably use getrusage with the RUSAGE_THREAD flag.
1101     struct timeval tv;
1102     gettimeofday(&tv, 0);
1103     return tv.tv_sec * 1000 + tv.tv_usec / 1000;
1104 #elif PLATFORM(QT)
1105     QDateTime t = QDateTime::currentDateTime();
1106     return t.toTime_t() * 1000 + t.time().msec();
1107 #elif PLATFORM(WIN_OS)
1108     union {
1109         FILETIME fileTime;
1110         unsigned long long fileTimeAsLong;
1111     } userTime, kernelTime;
1112     
1113     // GetThreadTimes won't accept NULL arguments so we pass these even though
1114     // they're not used.
1115     FILETIME creationTime, exitTime;
1116     
1117     GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime);
1118     
1119     return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000;
1120 #else
1121 #error Platform does not have getCurrentTime function
1122 #endif
1123 }
1124
1125 // We have to return a JSValue here, gcc seems to produce worse code if 
1126 // we attempt to return a bool
1127 ALWAYS_INLINE JSValue* Machine::checkTimeout(JSGlobalObject* globalObject)
1128 {
1129     unsigned currentTime = getCPUTime();
1130     
1131     if (!m_timeAtLastCheckTimeout) {
1132         // Suspicious amount of looping in a script -- start timing it
1133         m_timeAtLastCheckTimeout = currentTime;
1134         return 0;
1135     }
1136     
1137     unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout;
1138     
1139     if (timeDiff == 0)
1140         timeDiff = 1;
1141     
1142     m_timeExecuting += timeDiff;
1143     m_timeAtLastCheckTimeout = currentTime;
1144     
1145     // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in 
1146     // preferredScriptCheckTimeInterval
1147     m_ticksUntilNextTimeoutCheck = static_cast<unsigned>((static_cast<float>(preferredScriptCheckTimeInterval) / timeDiff) * m_ticksUntilNextTimeoutCheck);
1148     // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
1149     // preferred script check time interval.
1150     if (m_ticksUntilNextTimeoutCheck == 0)
1151         m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
1152     
1153     if (m_timeoutTime && m_timeExecuting > m_timeoutTime) {
1154         if (globalObject->shouldInterruptScript())
1155             return jsNull(); // Appeasing GCC, all we need is a non-null js value.
1156         
1157         resetTimeoutCheck();
1158     }
1159     
1160     return 0;
1161 }
1162
1163 static NEVER_INLINE ScopeChainNode* createExceptionScope(ExecState* exec, CodeBlock* codeBlock, const Instruction* vPC, Register* r, ScopeChainNode* scopeChain)
1164 {
1165     int dst = (++vPC)->u.operand;
1166     Identifier& property = codeBlock->identifiers[(++vPC)->u.operand];
1167     JSValue* value = r[(++vPC)->u.operand].jsValue(exec);
1168     JSObject* scope = new (exec) JSStaticScopeObject(exec, property, value, DontDelete);
1169     r[dst] = scope;
1170     return scopeChain->push(scope);
1171 }
1172
1173 static StructureIDChain* cachePrototypeChain(ExecState* exec, StructureID* structureID)
1174 {
1175     JSValue* prototype = structureID->prototypeForLookup(exec);
1176     if (JSImmediate::isImmediate(prototype))
1177         return 0;
1178     RefPtr<StructureIDChain> chain = StructureIDChain::create(static_cast<JSObject*>(prototype)->structureID());
1179     structureID->setCachedPrototypeChain(chain.release());
1180     return structureID->cachedPrototypeChain();
1181 }
1182
1183 NEVER_INLINE void Machine::tryCachePutByID(ExecState* exec, CodeBlock* codeBlock, Instruction* vPC, JSValue* baseValue, const PutPropertySlot& slot)
1184 {
1185     // Recursive invocation may already have specialized this instruction.
1186     if (vPC[0].u.opcode != getOpcode(op_put_by_id))
1187         return;
1188
1189     if (JSImmediate::isImmediate(baseValue))
1190         return;
1191
1192     // Uncacheable: give up.
1193     if (!slot.isCacheable()) {
1194         vPC[0] = getOpcode(op_put_by_id_generic);
1195         return;
1196     }
1197     
1198     JSCell* baseCell = static_cast<JSCell*>(baseValue);
1199     StructureID* structureID = baseCell->structureID();
1200
1201     if (structureID->isDictionary()) {
1202         vPC[0] = getOpcode(op_put_by_id_generic);
1203         return;
1204     }
1205
1206     // Cache miss: record StructureID to compare against next time.
1207     StructureID* lastStructureID = vPC[4].u.structureID;
1208     if (structureID != lastStructureID) {
1209         // First miss: record StructureID to compare against next time.
1210         if (!lastStructureID) {
1211             vPC[4] = structureID;
1212             return;
1213         }
1214
1215         // Second miss: give up.
1216         vPC[0] = getOpcode(op_put_by_id_generic);
1217         return;
1218     }
1219
1220     // Cache hit: Specialize instruction and ref StructureIDs.
1221
1222     // If baseCell != slot.base(), then baseCell must be a proxy for another object.
1223     if (baseCell != slot.base()) {
1224         vPC[0] = getOpcode(op_put_by_id_generic);
1225         return;
1226     }
1227
1228     // StructureID transition, cache transition info
1229     if (slot.type() == PutPropertySlot::NewProperty) {
1230         vPC[0] = getOpcode(op_put_by_id_transition);
1231         vPC[4] = structureID->previousID();
1232         vPC[5] = structureID;
1233         StructureIDChain* chain = structureID->cachedPrototypeChain();
1234         if (!chain) {
1235             chain = cachePrototypeChain(exec, structureID);
1236             if (!chain) {
1237                 // This happens if someone has manually inserted null into the prototype chain
1238                 vPC[0] = getOpcode(op_put_by_id_generic);
1239                 return;
1240             }
1241         }
1242         vPC[6] = chain;
1243         vPC[7] = slot.cachedOffset();
1244         codeBlock->refStructureIDs(vPC);
1245         return;
1246     }
1247
1248     vPC[0] = getOpcode(op_put_by_id_replace);
1249     vPC[5] = slot.cachedOffset();
1250     codeBlock->refStructureIDs(vPC);
1251 }
1252
1253 NEVER_INLINE void Machine::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC)
1254 {
1255     codeBlock->derefStructureIDs(vPC);
1256     vPC[0] = getOpcode(op_put_by_id);
1257     vPC[4] = 0;
1258 }
1259
1260 NEVER_INLINE void Machine::tryCacheGetByID(ExecState* exec, CodeBlock* codeBlock, Instruction* vPC, JSValue* baseValue, const Identifier& propertyName, const PropertySlot& slot)
1261 {
1262     // Recursive invocation may already have specialized this instruction.
1263     if (vPC[0].u.opcode != getOpcode(op_get_by_id))
1264         return;
1265
1266     // FIXME: Cache property access for immediates.
1267     if (JSImmediate::isImmediate(baseValue)) {
1268         vPC[0] = getOpcode(op_get_by_id_generic);
1269         return;
1270     }
1271
1272     if (isJSArray(baseValue) && propertyName == exec->propertyNames().length) {
1273         vPC[0] = getOpcode(op_get_array_length);
1274         return;
1275     }
1276
1277     if (isJSString(baseValue) && propertyName == exec->propertyNames().length) {
1278         vPC[0] = getOpcode(op_get_string_length);
1279         return;
1280     }
1281
1282     // Uncacheable: give up.
1283     if (!slot.isCacheable()) {
1284         vPC[0] = getOpcode(op_get_by_id_generic);
1285         return;
1286     }
1287
1288     StructureID* structureID = static_cast<JSCell*>(baseValue)->structureID();
1289
1290     if (structureID->isDictionary()) {
1291         vPC[0] = getOpcode(op_get_by_id_generic);
1292         return;
1293     }
1294
1295     // Cache miss
1296     StructureID* lastStructureID = vPC[4].u.structureID;
1297     if (structureID != lastStructureID) {
1298         // First miss: record StructureID to compare against next time.
1299         if (!lastStructureID) {
1300             vPC[4] = structureID;
1301             return;
1302         }
1303
1304         // Second miss: give up.
1305         vPC[0] = getOpcode(op_get_by_id_generic);
1306         return;
1307     }
1308
1309     // Cache hit: Specialize instruction and ref StructureIDs.
1310
1311     if (slot.slotBase() == baseValue) {
1312         vPC[0] = getOpcode(op_get_by_id_self);
1313         vPC[5] = slot.cachedOffset();
1314
1315         codeBlock->refStructureIDs(vPC);
1316         return;
1317     }
1318
1319     if (slot.slotBase() == structureID->prototypeForLookup(exec)) {
1320         ASSERT(slot.slotBase()->isObject());
1321
1322         JSObject* baseObject = static_cast<JSObject*>(slot.slotBase());
1323
1324         // Heavy access to a prototype is a good indication that it's not being
1325         // used as a dictionary.
1326         if (baseObject->structureID()->isDictionary()) {
1327             RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(baseObject->structureID());
1328             baseObject->setStructureID(transition.release());
1329             static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
1330         }
1331
1332         vPC[0] = getOpcode(op_get_by_id_proto);
1333         vPC[5] = baseObject->structureID();
1334         vPC[6] = slot.cachedOffset();
1335
1336         codeBlock->refStructureIDs(vPC);
1337         return;
1338     }
1339
1340     size_t count = 0;
1341     JSObject* o = static_cast<JSObject*>(baseValue);
1342     while (slot.slotBase() != o) {
1343         JSValue* v = o->structureID()->prototypeForLookup(exec);
1344
1345         // If we didn't find base in baseValue's prototype chain, then baseValue
1346         // must be a proxy for another object.
1347         if (v->isNull()) {
1348             vPC[0] = getOpcode(op_get_by_id_generic);
1349             return;
1350         }
1351
1352         o = static_cast<JSObject*>(v);
1353
1354         // Heavy access to a prototype is a good indication that it's not being
1355         // used as a dictionary.
1356         if (o->structureID()->isDictionary()) {
1357             RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(o->structureID());
1358             o->setStructureID(transition.release());
1359             static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
1360         }
1361
1362         ++count;
1363     }
1364
1365     StructureIDChain* chain = structureID->cachedPrototypeChain();
1366     if (!chain)
1367         chain = cachePrototypeChain(exec, structureID);
1368     ASSERT(chain);
1369
1370     vPC[0] = getOpcode(op_get_by_id_chain);
1371     vPC[4] = structureID;
1372     vPC[5] = chain;
1373     vPC[6] = count;
1374     vPC[7] = slot.cachedOffset();
1375     codeBlock->refStructureIDs(vPC);
1376 }
1377
1378 NEVER_INLINE void Machine::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC)
1379 {
1380     codeBlock->derefStructureIDs(vPC);
1381     vPC[0] = getOpcode(op_get_by_id);
1382     vPC[4] = 0;
1383 }
1384
1385 JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception)
1386 {
1387     // One-time initialization of our address tables. We have to put this code
1388     // here because our labels are only in scope inside this function.
1389     if (flag == InitializeAndReturn) {
1390         #if HAVE(COMPUTED_GOTO)
1391             #define ADD_OPCODE(id) m_opcodeTable[id] = &&id;
1392                 FOR_EACH_OPCODE_ID(ADD_OPCODE);
1393             #undef ADD_OPCODE
1394
1395             #define ADD_OPCODE_ID(id) m_opcodeIDTable.add(&&id, id);
1396                 FOR_EACH_OPCODE_ID(ADD_OPCODE_ID);
1397             #undef ADD_OPCODE_ID
1398             ASSERT(m_opcodeIDTable.size() == numOpcodeIDs);
1399             op_throw_end_indirect = &&op_throw_end;
1400             op_call_indirect = &&op_call;
1401         #endif // HAVE(COMPUTED_GOTO)
1402         return 0;
1403     }
1404
1405 #if ENABLE(CTI)
1406     // Currently with CTI enabled we never interpret functions
1407     ASSERT_NOT_REACHED();
1408 #endif
1409
1410     JSValue* exceptionValue = 0;
1411     Instruction* handlerVPC = 0;
1412
1413     Register* registerBase = registerFile->base();
1414     Instruction* vPC = codeBlock->instructions.begin();
1415     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
1416     unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1;
1417
1418 #define VM_CHECK_EXCEPTION() \
1419     do { \
1420         if (UNLIKELY(exec->hadException())) { \
1421             exceptionValue = exec->exception(); \
1422             goto vm_throw; \
1423         } \
1424     } while (0)
1425
1426 #if DUMP_OPCODE_STATS
1427     OpcodeStats::resetLastInstruction();
1428 #endif
1429
1430 #define CHECK_FOR_TIMEOUT() \
1431     if (!--tickCount) { \
1432         if ((exceptionValue = checkTimeout(exec->dynamicGlobalObject()))) \
1433             goto vm_throw; \
1434         tickCount = m_ticksUntilNextTimeoutCheck; \
1435     }
1436
1437 #if HAVE(COMPUTED_GOTO)
1438     #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); goto *vPC->u.opcode
1439 #if DUMP_OPCODE_STATS
1440     #define BEGIN_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
1441 #else
1442     #define BEGIN_OPCODE(opcode) opcode:
1443 #endif
1444     NEXT_OPCODE;
1445 #else
1446     #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); continue
1447 #if DUMP_OPCODE_STATS
1448     #define BEGIN_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
1449 #else
1450     #define BEGIN_OPCODE(opcode) case opcode:
1451 #endif
1452     while (1) // iterator loop begins
1453     switch (vPC->u.opcode)
1454 #endif
1455     {
1456     BEGIN_OPCODE(op_new_object) {
1457         /* new_object dst(r)
1458
1459            Constructs a new empty Object instance using the original
1460            constructor, and puts the result in register dst.
1461         */
1462         int dst = (++vPC)->u.operand;
1463         r[dst] = constructEmptyObject(exec);
1464
1465         ++vPC;
1466         NEXT_OPCODE;
1467     }
1468     BEGIN_OPCODE(op_new_array) {
1469         /* new_array dst(r) firstArg(r) argCount(n)
1470
1471            Constructs a new Array instance using the original
1472            constructor, and puts the result in register dst.
1473            The array will contain argCount elements with values
1474            taken from registers starting at register firstArg.
1475         */
1476         int dst = (++vPC)->u.operand;
1477         int firstArg = (++vPC)->u.operand;
1478         int argCount = (++vPC)->u.operand;
1479         ArgList args(r + firstArg, argCount);
1480         r[dst] = constructArray(exec, args);
1481
1482         ++vPC;
1483         NEXT_OPCODE;
1484     }
1485     BEGIN_OPCODE(op_new_regexp) {
1486         /* new_regexp dst(r) regExp(re)
1487
1488            Constructs a new RegExp instance using the original
1489            constructor from regexp regExp, and puts the result in
1490            register dst.
1491         */
1492         int dst = (++vPC)->u.operand;
1493         int regExp = (++vPC)->u.operand;
1494         r[dst] = new (exec) RegExpObject(scopeChain->globalObject()->regExpPrototype(), codeBlock->regexps[regExp]);
1495
1496         ++vPC;
1497         NEXT_OPCODE;
1498     }
1499     BEGIN_OPCODE(op_mov) {
1500         /* mov dst(r) src(r)
1501
1502            Copies register src to register dst.
1503         */
1504         int dst = (++vPC)->u.operand;
1505         int src = (++vPC)->u.operand;
1506         r[dst] = r[src];
1507
1508         ++vPC;
1509         NEXT_OPCODE;
1510     }
1511     BEGIN_OPCODE(op_eq) {
1512         /* eq dst(r) src1(r) src2(r)
1513
1514            Checks whether register src1 and register src2 are equal,
1515            as with the ECMAScript '==' operator, and puts the result
1516            as a boolean in register dst.
1517         */
1518         int dst = (++vPC)->u.operand;
1519         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1520         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1521         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1522             r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1523         else {
1524             JSValue* result = jsBoolean(equal(exec, src1, src2));
1525             VM_CHECK_EXCEPTION();
1526             r[dst] = result;
1527         }
1528
1529         ++vPC;
1530         NEXT_OPCODE;
1531     }
1532     BEGIN_OPCODE(op_eq_null) {
1533         /* neq dst(r) src(r)
1534
1535            Checks whether register src is null, as with the ECMAScript '!='
1536            operator, and puts the result as a boolean in register dst.
1537         */
1538         int dst = (++vPC)->u.operand;
1539         JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1540
1541         if (src->isUndefinedOrNull()) {
1542             r[dst] = jsBoolean(true);
1543             ++vPC;
1544             NEXT_OPCODE;
1545         }
1546         
1547         r[dst] = jsBoolean(!JSImmediate::isImmediate(src) && static_cast<JSCell*>(src)->masqueradeAsUndefined());
1548         ++vPC;
1549         NEXT_OPCODE;
1550     }
1551     BEGIN_OPCODE(op_neq) {
1552         /* neq dst(r) src1(r) src2(r)
1553
1554            Checks whether register src1 and register src2 are not
1555            equal, as with the ECMAScript '!=' operator, and puts the
1556            result as a boolean in register dst.
1557         */
1558         int dst = (++vPC)->u.operand;
1559         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1560         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1561         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1562             r[dst] = jsBoolean(src1 != src2);
1563         else {
1564             JSValue* result = jsBoolean(!equal(exec, src1, src2));
1565             VM_CHECK_EXCEPTION();
1566             r[dst] = result;
1567         }
1568
1569         ++vPC;
1570         NEXT_OPCODE;
1571     }
1572     BEGIN_OPCODE(op_neq_null) {
1573         /* neq dst(r) src(r)
1574
1575            Checks whether register src is not null, as with the ECMAScript '!='
1576            operator, and puts the result as a boolean in register dst.
1577         */
1578         int dst = (++vPC)->u.operand;
1579         JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1580
1581         if (src->isUndefinedOrNull()) {
1582             r[dst] = jsBoolean(false);
1583             ++vPC;
1584             NEXT_OPCODE;
1585         }
1586         
1587         r[dst] = jsBoolean(JSImmediate::isImmediate(src) || !static_cast<JSCell*>(src)->masqueradeAsUndefined());
1588         ++vPC;
1589         NEXT_OPCODE;
1590     }
1591     BEGIN_OPCODE(op_stricteq) {
1592         /* stricteq dst(r) src1(r) src2(r)
1593
1594            Checks whether register src1 and register src2 are strictly
1595            equal, as with the ECMAScript '===' operator, and puts the
1596            result as a boolean in register dst.
1597         */
1598         int dst = (++vPC)->u.operand;
1599         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1600         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1601         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1602             r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1603         else
1604             r[dst] = jsBoolean(strictEqual(src1, src2));
1605
1606         ++vPC;
1607         NEXT_OPCODE;
1608     }
1609     BEGIN_OPCODE(op_nstricteq) {
1610         /* nstricteq dst(r) src1(r) src2(r)
1611
1612            Checks whether register src1 and register src2 are not
1613            strictly equal, as with the ECMAScript '!==' operator, and
1614            puts the result as a boolean in register dst.
1615         */
1616         int dst = (++vPC)->u.operand;
1617         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1618         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1619         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1620             r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
1621         else
1622             r[dst] = jsBoolean(!strictEqual(src1, src2));
1623
1624         ++vPC;
1625         NEXT_OPCODE;
1626     }
1627     BEGIN_OPCODE(op_less) {
1628         /* less dst(r) src1(r) src2(r)
1629
1630            Checks whether register src1 is less than register src2, as
1631            with the ECMAScript '<' operator, and puts the result as
1632            a boolean in register dst.
1633         */
1634         int dst = (++vPC)->u.operand;
1635         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1636         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1637         JSValue* result = jsBoolean(jsLess(exec, src1, src2));
1638         VM_CHECK_EXCEPTION();
1639         r[dst] = result;
1640
1641         ++vPC;
1642         NEXT_OPCODE;
1643     }
1644     BEGIN_OPCODE(op_lesseq) {
1645         /* lesseq dst(r) src1(r) src2(r)
1646
1647            Checks whether register src1 is less than or equal to
1648            register src2, as with the ECMAScript '<=' operator, and
1649            puts the result as a boolean in register dst.
1650         */
1651         int dst = (++vPC)->u.operand;
1652         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1653         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1654         JSValue* result = jsBoolean(jsLessEq(exec, src1, src2));
1655         VM_CHECK_EXCEPTION();
1656         r[dst] = result;
1657
1658         ++vPC;
1659         NEXT_OPCODE;
1660     }
1661     BEGIN_OPCODE(op_pre_inc) {
1662         /* pre_inc srcDst(r)
1663
1664            Converts register srcDst to number, adds one, and puts the result
1665            back in register srcDst.
1666         */
1667         int srcDst = (++vPC)->u.operand;
1668         JSValue* v = r[srcDst].jsValue(exec);
1669         if (JSImmediate::canDoFastAdditiveOperations(v))
1670             r[srcDst] = JSImmediate::incImmediateNumber(v);
1671         else {
1672             JSValue* result = jsNumber(exec, v->toNumber(exec) + 1);
1673             VM_CHECK_EXCEPTION();
1674             r[srcDst] = result;
1675         }
1676
1677         ++vPC;
1678         NEXT_OPCODE;
1679     }
1680     BEGIN_OPCODE(op_pre_dec) {
1681         /* pre_dec srcDst(r)
1682
1683            Converts register srcDst to number, subtracts one, and puts the result
1684            back in register srcDst.
1685         */
1686         int srcDst = (++vPC)->u.operand;
1687         JSValue* v = r[srcDst].jsValue(exec);
1688         if (JSImmediate::canDoFastAdditiveOperations(v))
1689             r[srcDst] = JSImmediate::decImmediateNumber(v);
1690         else {
1691             JSValue* result = jsNumber(exec, v->toNumber(exec) - 1);
1692             VM_CHECK_EXCEPTION();
1693             r[srcDst] = result;
1694         }
1695
1696         ++vPC;
1697         NEXT_OPCODE;
1698     }
1699     BEGIN_OPCODE(op_post_inc) {
1700         /* post_inc dst(r) srcDst(r)
1701
1702            Converts register srcDst to number. The number itself is
1703            written to register dst, and the number plus one is written
1704            back to register srcDst.
1705         */
1706         int dst = (++vPC)->u.operand;
1707         int srcDst = (++vPC)->u.operand;
1708         JSValue* v = r[srcDst].jsValue(exec);
1709         if (JSImmediate::canDoFastAdditiveOperations(v)) {
1710             r[dst] = v;
1711             r[srcDst] = JSImmediate::incImmediateNumber(v);
1712         } else {
1713             JSValue* number = r[srcDst].jsValue(exec)->toJSNumber(exec);
1714             VM_CHECK_EXCEPTION();
1715             r[dst] = number;
1716             r[srcDst] = jsNumber(exec, number->uncheckedGetNumber() + 1);
1717         }
1718
1719         ++vPC;
1720         NEXT_OPCODE;
1721     }
1722     BEGIN_OPCODE(op_post_dec) {
1723         /* post_dec dst(r) srcDst(r)
1724
1725            Converts register srcDst to number. The number itself is
1726            written to register dst, and the number minus one is written
1727            back to register srcDst.
1728         */
1729         int dst = (++vPC)->u.operand;
1730         int srcDst = (++vPC)->u.operand;
1731         JSValue* v = r[srcDst].jsValue(exec);
1732         if (JSImmediate::canDoFastAdditiveOperations(v)) {
1733             r[dst] = v;
1734             r[srcDst] = JSImmediate::decImmediateNumber(v);
1735         } else {
1736             JSValue* number = r[srcDst].jsValue(exec)->toJSNumber(exec);
1737             VM_CHECK_EXCEPTION();
1738             r[dst] = number;
1739             r[srcDst] = jsNumber(exec, number->uncheckedGetNumber() - 1);
1740         }
1741
1742         ++vPC;
1743         NEXT_OPCODE;
1744     }
1745     BEGIN_OPCODE(op_to_jsnumber) {
1746         /* to_jsnumber dst(r) src(r)
1747
1748            Converts register src to number, and puts the result
1749            in register dst.
1750         */
1751         int dst = (++vPC)->u.operand;
1752         int src = (++vPC)->u.operand;
1753         JSValue* result = r[src].jsValue(exec)->toJSNumber(exec);
1754         VM_CHECK_EXCEPTION();
1755
1756         r[dst] = result;
1757
1758         ++vPC;
1759         NEXT_OPCODE;
1760     }
1761     BEGIN_OPCODE(op_negate) {
1762         /* negate dst(r) src(r)
1763
1764            Converts register src to number, negates it, and puts the
1765            result in register dst.
1766         */
1767         int dst = (++vPC)->u.operand;
1768         JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1769         double v;
1770         if (fastIsNumber(src, v))
1771             r[dst] = jsNumber(exec, -v);
1772         else {
1773             JSValue* result = jsNumber(exec, -src->toNumber(exec));
1774             VM_CHECK_EXCEPTION();
1775             r[dst] = result;
1776         }
1777
1778         ++vPC;
1779         NEXT_OPCODE;
1780     }
1781     BEGIN_OPCODE(op_add) {
1782         /* add dst(r) src1(r) src2(r)
1783
1784            Adds register src1 and register src2, and puts the result
1785            in register dst. (JS add may be string concatenation or
1786            numeric add, depending on the types of the operands.)
1787         */
1788         int dst = (++vPC)->u.operand;
1789         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1790         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1791         if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1792             r[dst] = JSImmediate::addImmediateNumbers(src1, src2);
1793         else {
1794             JSValue* result = jsAdd(exec, src1, src2);
1795             VM_CHECK_EXCEPTION();
1796             r[dst] = result;
1797         }
1798         ++vPC;
1799         NEXT_OPCODE;
1800     }
1801     BEGIN_OPCODE(op_mul) {
1802         /* mul dst(r) src1(r) src2(r)
1803
1804            Multiplies register src1 and register src2 (converted to
1805            numbers), and puts the product in register dst.
1806         */
1807         int dst = (++vPC)->u.operand;
1808         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1809         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1810         double left;
1811         double right;
1812         if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
1813             r[dst] = jsNumber(exec, left * right);
1814         else {
1815             JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
1816             VM_CHECK_EXCEPTION();
1817             r[dst] = result;
1818         }
1819
1820         ++vPC;
1821         NEXT_OPCODE;
1822     }
1823     BEGIN_OPCODE(op_div) {
1824         /* div dst(r) dividend(r) divisor(r)
1825
1826            Divides register dividend (converted to number) by the
1827            register divisor (converted to number), and puts the
1828            quotient in register dst.
1829         */
1830         int dst = (++vPC)->u.operand;
1831         JSValue* dividend = r[(++vPC)->u.operand].jsValue(exec);
1832         JSValue* divisor = r[(++vPC)->u.operand].jsValue(exec);
1833         double left;
1834         double right;
1835         if (fastIsNumber(dividend, left) && fastIsNumber(divisor, right))
1836             r[dst] = jsNumber(exec, left / right);
1837         else {
1838             JSValue* result = jsNumber(exec, dividend->toNumber(exec) / divisor->toNumber(exec));
1839             VM_CHECK_EXCEPTION();
1840             r[dst] = result;
1841         }
1842         ++vPC;
1843         NEXT_OPCODE;
1844     }
1845     BEGIN_OPCODE(op_mod) {
1846         /* mod dst(r) dividend(r) divisor(r)
1847
1848            Divides register dividend (converted to number) by
1849            register divisor (converted to number), and puts the
1850            remainder in register dst.
1851         */
1852         int dst = (++vPC)->u.operand;
1853         int dividend = (++vPC)->u.operand;
1854         int divisor = (++vPC)->u.operand;
1855
1856         JSValue* dividendValue = r[dividend].jsValue(exec);
1857         JSValue* divisorValue = r[divisor].jsValue(exec);
1858
1859         if (JSImmediate::areBothImmediateNumbers(dividendValue, divisorValue) && divisorValue != JSImmediate::from(0)) {
1860             r[dst] = JSImmediate::from(JSImmediate::getTruncatedInt32(dividendValue) % JSImmediate::getTruncatedInt32(divisorValue));
1861             ++vPC;
1862             NEXT_OPCODE;
1863         }
1864
1865         double d = dividendValue->toNumber(exec);
1866         JSValue* result = jsNumber(exec, fmod(d, divisorValue->toNumber(exec)));
1867         VM_CHECK_EXCEPTION();
1868         r[dst] = result;
1869         ++vPC;
1870         NEXT_OPCODE;
1871     }
1872     BEGIN_OPCODE(op_sub) {
1873         /* sub dst(r) src1(r) src2(r)
1874
1875            Subtracts register src2 (converted to number) from register
1876            src1 (converted to number), and puts the difference in
1877            register dst.
1878         */
1879         int dst = (++vPC)->u.operand;
1880         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1881         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1882         double left;
1883         double right;
1884         if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1885             r[dst] = JSImmediate::subImmediateNumbers(src1, src2);
1886         else if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
1887             r[dst] = jsNumber(exec, left - right);
1888         else {
1889             JSValue* result = jsNumber(exec, src1->toNumber(exec) - src2->toNumber(exec));
1890             VM_CHECK_EXCEPTION();
1891             r[dst] = result;
1892         }
1893         ++vPC;
1894         NEXT_OPCODE;
1895     }
1896     BEGIN_OPCODE(op_lshift) {
1897         /* lshift dst(r) val(r) shift(r)
1898
1899            Performs left shift of register val (converted to int32) by
1900            register shift (converted to uint32), and puts the result
1901            in register dst.
1902         */
1903         int dst = (++vPC)->u.operand;
1904         JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1905         JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1906         int32_t left;
1907         uint32_t right;
1908         if (JSImmediate::areBothImmediateNumbers(val, shift))
1909             r[dst] = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::getTruncatedUInt32(shift) & 0x1f));
1910         else if (fastToInt32(val, left) && fastToUInt32(shift, right))
1911             r[dst] = jsNumber(exec, left << (right & 0x1f));
1912         else {
1913             JSValue* result = jsNumber(exec, (val->toInt32(exec)) << (shift->toUInt32(exec) & 0x1f));
1914             VM_CHECK_EXCEPTION();
1915             r[dst] = result;
1916         }
1917
1918         ++vPC;
1919         NEXT_OPCODE;
1920     }
1921     BEGIN_OPCODE(op_rshift) {
1922         /* rshift dst(r) val(r) shift(r)
1923
1924            Performs arithmetic right shift of register val (converted
1925            to int32) by register shift (converted to
1926            uint32), and puts the result in register dst.
1927         */
1928         int dst = (++vPC)->u.operand;
1929         JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1930         JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1931         int32_t left;
1932         uint32_t right;
1933         if (JSImmediate::areBothImmediateNumbers(val, shift))
1934             r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
1935         else if (fastToInt32(val, left) && fastToUInt32(shift, right))
1936             r[dst] = jsNumber(exec, left >> (right & 0x1f));
1937         else {
1938             JSValue* result = jsNumber(exec, (val->toInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1939             VM_CHECK_EXCEPTION();
1940             r[dst] = result;
1941         }
1942
1943         ++vPC;
1944         NEXT_OPCODE;
1945     }
1946     BEGIN_OPCODE(op_urshift) {
1947         /* rshift dst(r) val(r) shift(r)
1948
1949            Performs logical right shift of register val (converted
1950            to uint32) by register shift (converted to
1951            uint32), and puts the result in register dst.
1952         */
1953         int dst = (++vPC)->u.operand;
1954         JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1955         JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1956         if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val))
1957             r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
1958         else {
1959             JSValue* result = jsNumber(exec, (val->toUInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1960             VM_CHECK_EXCEPTION();
1961             r[dst] = result;
1962         }
1963
1964         ++vPC;
1965         NEXT_OPCODE;
1966     }
1967     BEGIN_OPCODE(op_bitand) {
1968         /* bitand dst(r) src1(r) src2(r)
1969
1970            Computes bitwise AND of register src1 (converted to int32)
1971            and register src2 (converted to int32), and puts the result
1972            in register dst.
1973         */
1974         int dst = (++vPC)->u.operand;
1975         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1976         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1977         int32_t left;
1978         int32_t right;
1979         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1980             r[dst] = JSImmediate::andImmediateNumbers(src1, src2);
1981         else if (fastToInt32(src1, left) && fastToInt32(src2, right))
1982             r[dst] = jsNumber(exec, left & right);
1983         else {
1984             JSValue* result = jsNumber(exec, src1->toInt32(exec) & src2->toInt32(exec));
1985             VM_CHECK_EXCEPTION();
1986             r[dst] = result;
1987         }
1988
1989         ++vPC;
1990         NEXT_OPCODE;
1991     }
1992     BEGIN_OPCODE(op_bitxor) {
1993         /* bitxor dst(r) src1(r) src2(r)
1994
1995            Computes bitwise XOR of register src1 (converted to int32)
1996            and register src2 (converted to int32), and puts the result
1997            in register dst.
1998         */
1999         int dst = (++vPC)->u.operand;
2000         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2001         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2002         int32_t left;
2003         int32_t right;
2004         if (JSImmediate::areBothImmediateNumbers(src1, src2))
2005             r[dst] = JSImmediate::xorImmediateNumbers(src1, src2);
2006         else if (fastToInt32(src1, left) && fastToInt32(src2, right))
2007             r[dst] = jsNumber(exec, left ^ right);
2008         else {
2009             JSValue* result = jsNumber(exec, src1->toInt32(exec) ^ src2->toInt32(exec));
2010             VM_CHECK_EXCEPTION();
2011             r[dst] = result;
2012         }
2013
2014         ++vPC;
2015         NEXT_OPCODE;
2016     }
2017     BEGIN_OPCODE(op_bitor) {
2018         /* bitor dst(r) src1(r) src2(r)
2019
2020            Computes bitwise OR of register src1 (converted to int32)
2021            and register src2 (converted to int32), and puts the
2022            result in register dst.
2023         */
2024         int dst = (++vPC)->u.operand;
2025         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2026         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2027         int32_t left;
2028         int32_t right;
2029         if (JSImmediate::areBothImmediateNumbers(src1, src2))
2030             r[dst] = JSImmediate::orImmediateNumbers(src1, src2);
2031         else if (fastToInt32(src1, left) && fastToInt32(src2, right))
2032             r[dst] = jsNumber(exec, left | right);
2033         else {
2034             JSValue* result = jsNumber(exec, src1->toInt32(exec) | src2->toInt32(exec));
2035             VM_CHECK_EXCEPTION();
2036             r[dst] = result;
2037         }
2038
2039         ++vPC;
2040         NEXT_OPCODE;
2041     }
2042     BEGIN_OPCODE(op_bitnot) {
2043         /* bitnot dst(r) src(r)
2044
2045            Computes bitwise NOT of register src1 (converted to int32),
2046            and puts the result in register dst.
2047         */
2048         int dst = (++vPC)->u.operand;
2049         JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
2050         int32_t value;
2051         if (fastToInt32(src, value))
2052             r[dst] = jsNumber(exec, ~value);
2053         else {
2054             JSValue* result = jsNumber(exec, ~src->toInt32(exec));
2055             VM_CHECK_EXCEPTION();
2056             r[dst] = result;
2057         }
2058         ++vPC;
2059         NEXT_OPCODE;
2060     }
2061     BEGIN_OPCODE(op_not) {
2062         /* not dst(r) src(r)
2063
2064            Computes logical NOT of register src (converted to
2065            boolean), and puts the result in register dst.
2066         */
2067         int dst = (++vPC)->u.operand;
2068         int src = (++vPC)->u.operand;
2069         JSValue* result = jsBoolean(!r[src].jsValue(exec)->toBoolean(exec));
2070         VM_CHECK_EXCEPTION();
2071         r[dst] = result;
2072
2073         ++vPC;
2074         NEXT_OPCODE;
2075     }
2076     BEGIN_OPCODE(op_instanceof) {
2077         /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
2078
2079            Tests whether register value is an instance of register
2080            constructor, and puts the boolean result in register
2081            dst. Register constructorProto must contain the "prototype"
2082            property (not the actual prototype) of the object in
2083            register constructor. This lookup is separated so that
2084            polymorphic inline caching can apply.
2085
2086            Raises an exception if register constructor is not an
2087            object.
2088         */
2089         int dst = (++vPC)->u.operand;
2090         int value = (++vPC)->u.operand;
2091         int base = (++vPC)->u.operand;
2092         int baseProto = (++vPC)->u.operand;
2093
2094         JSValue* baseVal = r[base].jsValue(exec);
2095
2096         if (isNotObject(exec, true, codeBlock, vPC, baseVal, exceptionValue))
2097             goto vm_throw;
2098
2099         JSObject* baseObj = static_cast<JSObject*>(baseVal);
2100         r[dst] = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, r[value].jsValue(exec), r[baseProto].jsValue(exec)) : false);
2101
2102         ++vPC;
2103         NEXT_OPCODE;
2104     }
2105     BEGIN_OPCODE(op_typeof) {
2106         /* typeof dst(r) src(r)
2107
2108            Determines the type string for src according to ECMAScript
2109            rules, and puts the result in register dst.
2110         */
2111         int dst = (++vPC)->u.operand;
2112         int src = (++vPC)->u.operand;
2113         r[dst] = jsTypeStringForValue(exec, r[src].jsValue(exec));
2114
2115         ++vPC;
2116         NEXT_OPCODE;
2117     }
2118     BEGIN_OPCODE(op_is_undefined) {
2119         /* is_undefined dst(r) src(r)
2120
2121            Determines whether the type string for src according to
2122            the ECMAScript rules is "undefined", and puts the result
2123            in register dst.
2124         */
2125         int dst = (++vPC)->u.operand;
2126         int src = (++vPC)->u.operand;
2127         JSValue* v = r[src].jsValue(exec);
2128         r[dst] = jsBoolean(v->isUndefined() || (v->isObject() && static_cast<JSObject*>(v)->masqueradeAsUndefined()));
2129
2130         ++vPC;
2131         NEXT_OPCODE;
2132     }
2133     BEGIN_OPCODE(op_is_boolean) {
2134         /* is_boolean dst(r) src(r)
2135
2136            Determines whether the type string for src according to
2137            the ECMAScript rules is "boolean", and puts the result
2138            in register dst.
2139         */
2140         int dst = (++vPC)->u.operand;
2141         int src = (++vPC)->u.operand;
2142         r[dst] = jsBoolean(r[src].jsValue(exec)->isBoolean());
2143
2144         ++vPC;
2145         NEXT_OPCODE;
2146     }
2147     BEGIN_OPCODE(op_is_number) {
2148         /* is_number dst(r) src(r)
2149
2150            Determines whether the type string for src according to
2151            the ECMAScript rules is "number", and puts the result
2152            in register dst.
2153         */
2154         int dst = (++vPC)->u.operand;
2155         int src = (++vPC)->u.operand;
2156         r[dst] = jsBoolean(r[src].jsValue(exec)->isNumber());
2157
2158         ++vPC;
2159         NEXT_OPCODE;
2160     }
2161     BEGIN_OPCODE(op_is_string) {
2162         /* is_string dst(r) src(r)
2163
2164            Determines whether the type string for src according to
2165            the ECMAScript rules is "string", and puts the result
2166            in register dst.
2167         */
2168         int dst = (++vPC)->u.operand;
2169         int src = (++vPC)->u.operand;
2170         r[dst] = jsBoolean(r[src].jsValue(exec)->isString());
2171
2172         ++vPC;
2173         NEXT_OPCODE;
2174     }
2175     BEGIN_OPCODE(op_is_object) {
2176         /* is_object dst(r) src(r)
2177
2178            Determines whether the type string for src according to
2179            the ECMAScript rules is "object", and puts the result
2180            in register dst.
2181         */
2182         int dst = (++vPC)->u.operand;
2183         int src = (++vPC)->u.operand;
2184         r[dst] = jsBoolean(jsIsObjectType(r[src].jsValue(exec)));
2185
2186         ++vPC;
2187         NEXT_OPCODE;
2188     }
2189     BEGIN_OPCODE(op_is_function) {
2190         /* is_function dst(r) src(r)
2191
2192            Determines whether the type string for src according to
2193            the ECMAScript rules is "function", and puts the result
2194            in register dst.
2195         */
2196         int dst = (++vPC)->u.operand;
2197         int src = (++vPC)->u.operand;
2198         r[dst] = jsBoolean(jsIsFunctionType(r[src].jsValue(exec)));
2199
2200         ++vPC;
2201         NEXT_OPCODE;
2202     }
2203     BEGIN_OPCODE(op_in) {
2204         /* in dst(r) property(r) base(r)
2205
2206            Tests whether register base has a property named register
2207            property, and puts the boolean result in register dst.
2208
2209            Raises an exception if register constructor is not an
2210            object.
2211         */
2212         int dst = (++vPC)->u.operand;
2213         int property = (++vPC)->u.operand;
2214         int base = (++vPC)->u.operand;
2215
2216         JSValue* baseVal = r[base].jsValue(exec);
2217         if (isNotObject(exec, false, codeBlock, vPC, baseVal, exceptionValue))
2218             goto vm_throw;
2219
2220         JSObject* baseObj = static_cast<JSObject*>(baseVal);
2221
2222         JSValue* propName = r[property].jsValue(exec);
2223
2224         uint32_t i;
2225         if (propName->getUInt32(i))
2226             r[dst] = jsBoolean(baseObj->hasProperty(exec, i));
2227         else {
2228             Identifier property(exec, propName->toString(exec));
2229             VM_CHECK_EXCEPTION();
2230             r[dst] = jsBoolean(baseObj->hasProperty(exec, property));
2231         }
2232
2233         ++vPC;
2234         NEXT_OPCODE;
2235     }
2236     BEGIN_OPCODE(op_resolve) {
2237         /* resolve dst(r) property(id)
2238
2239            Looks up the property named by identifier property in the
2240            scope chain, and writes the resulting value to register
2241            dst. If the property is not found, raises an exception.
2242         */
2243         if (UNLIKELY(!resolve(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
2244             goto vm_throw;
2245
2246         vPC += 3;
2247         NEXT_OPCODE;
2248     }
2249     BEGIN_OPCODE(op_resolve_skip) {
2250         /* resolve_skip dst(r) property(id) skip(n)
2251
2252          Looks up the property named by identifier property in the
2253          scope chain skipping the top 'skip' levels, and writes the resulting
2254          value to register dst. If the property is not found, raises an exception.
2255          */
2256         if (UNLIKELY(!resolve_skip(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
2257             goto vm_throw;
2258
2259         vPC += 4;
2260
2261         NEXT_OPCODE;
2262     }
2263     BEGIN_OPCODE(op_resolve_global) {
2264         /* resolve_skip dst(r) globalObject(c) property(id) structureID(sID) offset(n)
2265          
2266            Performs a dynamic property lookup for the given property, on the provided
2267            global object.  If structureID matches the StructureID of the global then perform
2268            a fast lookup using the case offset, otherwise fall back to a full resolve and
2269            cache the new structureID and offset
2270          */
2271         if (UNLIKELY(!resolveGlobal(exec, vPC, r,  codeBlock, exceptionValue)))
2272             goto vm_throw;
2273         
2274         vPC += 6;
2275         
2276         NEXT_OPCODE;
2277     }
2278     BEGIN_OPCODE(op_get_global_var) {
2279         /* get_global_var dst(r) globalObject(c) index(n)
2280
2281            Gets the global var at global slot index and places it in register dst.
2282          */
2283         int dst = (++vPC)->u.operand;
2284         JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
2285         ASSERT(scope->isGlobalObject());
2286         int index = (++vPC)->u.operand;
2287
2288         r[dst] = scope->registerAt(index);
2289         ++vPC;
2290         NEXT_OPCODE;
2291     }
2292     BEGIN_OPCODE(op_put_global_var) {
2293         /* put_global_var globalObject(c) index(n) value(r)
2294          
2295            Puts value into global slot index.
2296          */
2297         JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
2298         ASSERT(scope->isGlobalObject());
2299         int index = (++vPC)->u.operand;
2300         int value = (++vPC)->u.operand;
2301         
2302         scope->registerAt(index) = r[value].jsValue(exec);
2303         ++vPC;
2304         NEXT_OPCODE;
2305     }            
2306     BEGIN_OPCODE(op_get_scoped_var) {
2307         /* get_scoped_var dst(r) index(n) skip(n)
2308
2309          Loads the contents of the index-th local from the scope skip nodes from
2310          the top of the scope chain, and places it in register dst
2311          */
2312         int dst = (++vPC)->u.operand;
2313         int index = (++vPC)->u.operand;
2314         int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
2315
2316         ScopeChainIterator iter = scopeChain->begin();
2317         ScopeChainIterator end = scopeChain->end();
2318         ASSERT(iter != end);
2319         while (skip--) {
2320             ++iter;
2321             ASSERT(iter != end);
2322         }
2323
2324         ASSERT((*iter)->isVariableObject());
2325         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
2326         r[dst] = scope->registerAt(index);
2327         ++vPC;
2328         NEXT_OPCODE;
2329     }
2330     BEGIN_OPCODE(op_put_scoped_var) {
2331         /* put_scoped_var index(n) skip(n) value(r)
2332
2333          */
2334         int index = (++vPC)->u.operand;
2335         int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
2336         int value = (++vPC)->u.operand;
2337
2338         ScopeChainIterator iter = scopeChain->begin();
2339         ScopeChainIterator end = scopeChain->end();
2340         ASSERT(iter != end);
2341         while (skip--) {
2342             ++iter;
2343             ASSERT(iter != end);
2344         }
2345
2346         ASSERT((*iter)->isVariableObject());
2347         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
2348         scope->registerAt(index) = r[value].jsValue(exec);
2349         ++vPC;
2350         NEXT_OPCODE;
2351     }
2352     BEGIN_OPCODE(op_resolve_base) {
2353         /* resolve_base dst(r) property(id)
2354
2355            Searches the scope chain for an object containing
2356            identifier property, and if one is found, writes it to
2357            register dst. If none is found, the outermost scope (which
2358            will be the global object) is stored in register dst.
2359         */
2360         resolveBase(exec, vPC, r, scopeChain, codeBlock);
2361
2362         vPC += 3;
2363         NEXT_OPCODE;
2364     }
2365     BEGIN_OPCODE(op_resolve_with_base) {
2366         /* resolve_with_base baseDst(r) propDst(r) property(id)
2367
2368            Searches the scope chain for an object containing
2369            identifier property, and if one is found, writes it to
2370            register srcDst, and the retrieved property value to register
2371            propDst. If the property is not found, raises an exception.
2372
2373            This is more efficient than doing resolve_base followed by
2374            resolve, or resolve_base followed by get_by_id, as it
2375            avoids duplicate hash lookups.
2376         */
2377         if (UNLIKELY(!resolveBaseAndProperty(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
2378             goto vm_throw;
2379
2380         vPC += 4;
2381         NEXT_OPCODE;
2382     }
2383     BEGIN_OPCODE(op_resolve_func) {
2384         /* resolve_func baseDst(r) funcDst(r) property(id)
2385
2386            Searches the scope chain for an object containing
2387            identifier property, and if one is found, writes the
2388            appropriate object to use as "this" when calling its
2389            properties to register baseDst; and the retrieved property
2390            value to register propDst. If the property is not found,
2391            raises an exception.
2392
2393            This differs from resolve_with_base, because the
2394            global this value will be substituted for activations or
2395            the global object, which is the right behavior for function
2396            calls but not for other property lookup.
2397         */
2398         if (UNLIKELY(!resolveBaseAndFunc(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
2399             goto vm_throw;
2400
2401         vPC += 4;
2402         NEXT_OPCODE;
2403     }
2404     BEGIN_OPCODE(op_get_by_id) {
2405         /* get_by_id dst(r) base(r) property(id) structureID(sID) nop(n) nop(n) nop(n)
2406
2407            Generic property access: Gets the property named by identifier
2408            property from the value base, and puts the result in register dst.
2409         */
2410         int dst = vPC[1].u.operand;
2411         int base = vPC[2].u.operand;
2412         int property = vPC[3].u.operand;
2413
2414         Identifier& ident = codeBlock->identifiers[property];
2415         JSValue* baseValue = r[base].jsValue(exec);
2416         PropertySlot slot(baseValue);
2417         JSValue* result = baseValue->get(exec, ident, slot);
2418         VM_CHECK_EXCEPTION();
2419
2420         tryCacheGetByID(exec, codeBlock, vPC, baseValue, ident, slot);
2421
2422         r[dst] = result;
2423         vPC += 8;
2424         NEXT_OPCODE;
2425     }
2426     BEGIN_OPCODE(op_get_by_id_self) {
2427         /* op_get_by_id_self dst(r) base(r) property(id) structureID(sID) offset(n) nop(n) nop(n)
2428
2429            Cached property access: Attempts to get a cached property from the
2430            value base. If the cache misses, op_get_by_id_self reverts to
2431            op_get_by_id.
2432         */
2433         int base = vPC[2].u.operand;
2434         JSValue* baseValue = r[base].jsValue(exec);
2435
2436         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2437             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2438             StructureID* structureID = vPC[4].u.structureID;
2439
2440             if (LIKELY(baseCell->structureID() == structureID)) {
2441                 ASSERT(baseCell->isObject());
2442                 JSObject* baseObject = static_cast<JSObject*>(baseCell);
2443                 int dst = vPC[1].u.operand;
2444                 int offset = vPC[5].u.operand;
2445
2446                 ASSERT(baseObject->get(exec, codeBlock->identifiers[vPC[3].u.operand]) == baseObject->getDirectOffset(offset));
2447                 r[dst] = baseObject->getDirectOffset(offset);
2448
2449                 vPC += 8;
2450                 NEXT_OPCODE;
2451             }
2452         }
2453
2454         uncacheGetByID(codeBlock, vPC);
2455         NEXT_OPCODE;
2456     }
2457     BEGIN_OPCODE(op_get_by_id_proto) {
2458         /* op_get_by_id_proto dst(r) base(r) property(id) structureID(sID) protoStructureID(sID) offset(n) nop(n)
2459
2460            Cached property access: Attempts to get a cached property from the
2461            value base's prototype. If the cache misses, op_get_by_id_proto
2462            reverts to op_get_by_id.
2463         */
2464         int base = vPC[2].u.operand;
2465         JSValue* baseValue = r[base].jsValue(exec);
2466
2467         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2468             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2469             StructureID* structureID = vPC[4].u.structureID;
2470
2471             if (LIKELY(baseCell->structureID() == structureID)) {
2472                 ASSERT(structureID->prototypeForLookup(exec)->isObject());
2473                 JSObject* protoObject = static_cast<JSObject*>(structureID->prototypeForLookup(exec));
2474                 StructureID* protoStructureID = vPC[5].u.structureID;
2475
2476                 if (LIKELY(protoObject->structureID() == protoStructureID)) {
2477                     int dst = vPC[1].u.operand;
2478                     int offset = vPC[6].u.operand;
2479
2480                     ASSERT(protoObject->get(exec, codeBlock->identifiers[vPC[3].u.operand]) == protoObject->getDirectOffset(offset));
2481                     r[dst] = protoObject->getDirectOffset(offset);
2482
2483                     vPC += 8;
2484                     NEXT_OPCODE;
2485                 }
2486             }
2487         }
2488
2489         uncacheGetByID(codeBlock, vPC);
2490         NEXT_OPCODE;
2491     }
2492     BEGIN_OPCODE(op_get_by_id_chain) {
2493         /* op_get_by_id_chain dst(r) base(r) property(id) structureID(sID) structureIDChain(sIDc) count(n) offset(n)
2494
2495            Cached property access: Attempts to get a cached property from the
2496            value base's prototype chain. If the cache misses, op_get_by_id_chain
2497            reverts to op_get_by_id.
2498         */
2499         int base = vPC[2].u.operand;
2500         JSValue* baseValue = r[base].jsValue(exec);
2501
2502         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2503             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2504             StructureID* structureID = vPC[4].u.structureID;
2505
2506             if (LIKELY(baseCell->structureID() == structureID)) {
2507                 RefPtr<StructureID>* it = vPC[5].u.structureIDChain->head();
2508                 size_t count = vPC[6].u.operand;
2509                 RefPtr<StructureID>* end = it + count;
2510
2511                 JSObject* baseObject = static_cast<JSObject*>(baseCell);
2512                 while (1) {
2513                     baseObject = static_cast<JSObject*>(baseObject->structureID()->prototypeForLookup(exec));
2514                     if (UNLIKELY(baseObject->structureID() != (*it).get()))
2515                         break;
2516
2517                     if (++it == end) {
2518                         int dst = vPC[1].u.operand;
2519                         int offset = vPC[7].u.operand;
2520
2521                         ASSERT(baseObject->get(exec, codeBlock->identifiers[vPC[3].u.operand]) == baseObject->getDirectOffset(offset));
2522                         r[dst] = baseObject->getDirectOffset(offset);
2523
2524                         vPC += 8;
2525                         NEXT_OPCODE;
2526                     }
2527                 }
2528             }
2529         }
2530
2531         uncacheGetByID(codeBlock, vPC);
2532         NEXT_OPCODE;
2533     }
2534     BEGIN_OPCODE(op_get_by_id_generic) {
2535         /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2536
2537            Generic property access: Gets the property named by identifier
2538            property from the value base, and puts the result in register dst.
2539         */
2540         int dst = vPC[1].u.operand;
2541         int base = vPC[2].u.operand;
2542         int property = vPC[3].u.operand;
2543
2544         Identifier& ident = codeBlock->identifiers[property];
2545
2546         JSValue* baseValue = r[base].jsValue(exec);
2547         PropertySlot slot(baseValue);
2548         JSValue* result = baseValue->get(exec, ident, slot);
2549         VM_CHECK_EXCEPTION();
2550
2551         r[dst] = result;
2552         vPC += 8;
2553         NEXT_OPCODE;
2554     }
2555     BEGIN_OPCODE(op_get_array_length) {
2556         /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2557
2558            Cached property access: Gets the length of the array in register base,
2559            and puts the result in register dst. If register base does not hold
2560            an array, op_get_array_length reverts to op_get_by_id.
2561         */
2562
2563         int base = vPC[2].u.operand;
2564         JSValue* baseValue = r[base].jsValue(exec);
2565         if (LIKELY(isJSArray(baseValue))) {
2566             int dst = vPC[1].u.operand;
2567             r[dst] = jsNumber(exec, static_cast<JSArray*>(baseValue)->length());
2568             vPC += 8;
2569             NEXT_OPCODE;
2570         }
2571
2572         uncacheGetByID(codeBlock, vPC);
2573         NEXT_OPCODE;
2574     }
2575     BEGIN_OPCODE(op_get_string_length) {
2576         /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2577
2578            Cached property access: Gets the length of the string in register base,
2579            and puts the result in register dst. If register base does not hold
2580            a string, op_get_string_length reverts to op_get_by_id.
2581         */
2582
2583         int base = vPC[2].u.operand;
2584         JSValue* baseValue = r[base].jsValue(exec);
2585         if (LIKELY(isJSString(baseValue))) {
2586             int dst = vPC[1].u.operand;
2587             r[dst] = jsNumber(exec, static_cast<JSString*>(baseValue)->value().size());
2588             vPC += 8;
2589             NEXT_OPCODE;
2590         }
2591
2592         uncacheGetByID(codeBlock, vPC);
2593         NEXT_OPCODE;
2594     }
2595     BEGIN_OPCODE(op_put_by_id) {
2596         /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
2597
2598            Generic property access: Sets the property named by identifier
2599            property, belonging to register base, to register value.
2600
2601            Unlike many opcodes, this one does not write any output to
2602            the register file.
2603         */
2604
2605         int base = vPC[1].u.operand;
2606         int property = vPC[2].u.operand;
2607         int value = vPC[3].u.operand;
2608
2609         JSValue* baseValue = r[base].jsValue(exec);
2610
2611         PutPropertySlot slot;
2612         Identifier& ident = codeBlock->identifiers[property];
2613         baseValue->put(exec, ident, r[value].jsValue(exec), slot);
2614         VM_CHECK_EXCEPTION();
2615
2616         tryCachePutByID(exec, codeBlock, vPC, baseValue, slot);
2617
2618         vPC += 8;
2619         NEXT_OPCODE;
2620     }
2621     BEGIN_OPCODE(op_put_by_id_transition) {
2622         /* op_put_by_id_transition base(r) property(id) value(r) oldStructureID(sID) newStructureID(sID) structureIDChain(sIDc) offset(n)
2623          
2624            Cached property access: Attempts to set a new property with a cached transition
2625            property named by identifier property, belonging to register base,
2626            to register value. If the cache misses, op_put_by_id_transition
2627            reverts to op_put_by_id_generic.
2628          
2629            Unlike many opcodes, this one does not write any output to
2630            the register file.
2631          */
2632         int base = vPC[1].u.operand;
2633         JSValue* baseValue = r[base].jsValue(exec);
2634         
2635         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2636             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2637             StructureID* oldStructureID = vPC[4].u.structureID;
2638             StructureID* newStructureID = vPC[5].u.structureID;
2639             
2640             if (LIKELY(baseCell->structureID() == oldStructureID)) {
2641                 ASSERT(baseCell->isObject());
2642                 JSObject* baseObject = static_cast<JSObject*>(baseCell);
2643
2644                 RefPtr<StructureID>* it = vPC[6].u.structureIDChain->head();
2645
2646                 JSObject* proto = static_cast<JSObject*>(baseObject->structureID()->prototypeForLookup(exec));
2647                 while (!proto->isNull()) {
2648                     if (UNLIKELY(proto->structureID() != (*it).get())) {
2649                         uncachePutByID(codeBlock, vPC);
2650                         NEXT_OPCODE;
2651                     }
2652                     ++it;
2653                     proto = static_cast<JSObject*>(proto->structureID()->prototypeForLookup(exec));
2654                 }
2655
2656                 baseObject->transitionTo(newStructureID);
2657                 if (oldStructureID->propertyMap().storageSize() == JSObject::inlineStorageCapacity)
2658                     baseObject->allocatePropertyStorage(oldStructureID->propertyMap().storageSize(), oldStructureID->propertyMap().size());
2659
2660                 int value = vPC[3].u.operand;
2661                 unsigned offset = vPC[7].u.operand;
2662                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(codeBlock->identifiers[vPC[2].u.operand])) == offset);
2663                 baseObject->putDirectOffset(offset, r[value].jsValue(exec));
2664
2665                 vPC += 8;
2666                 NEXT_OPCODE;
2667             }
2668         }
2669         
2670         uncachePutByID(codeBlock, vPC);
2671         NEXT_OPCODE;
2672     }
2673     BEGIN_OPCODE(op_put_by_id_replace) {
2674         /* op_put_by_id_replace base(r) property(id) value(r) structureID(sID) offset(n) nop(n) nop(n)
2675
2676            Cached property access: Attempts to set a pre-existing, cached
2677            property named by identifier property, belonging to register base,
2678            to register value. If the cache misses, op_put_by_id_replace
2679            reverts to op_put_by_id.
2680
2681            Unlike many opcodes, this one does not write any output to
2682            the register file.
2683         */
2684         int base = vPC[1].u.operand;
2685         JSValue* baseValue = r[base].jsValue(exec);
2686
2687         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2688             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2689             StructureID* structureID = vPC[4].u.structureID;
2690
2691             if (LIKELY(baseCell->structureID() == structureID)) {
2692                 ASSERT(baseCell->isObject());
2693                 JSObject* baseObject = static_cast<JSObject*>(baseCell);
2694                 int value = vPC[3].u.operand;
2695                 unsigned offset = vPC[5].u.operand;
2696                 
2697                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(codeBlock->identifiers[vPC[2].u.operand])) == offset);
2698                 baseObject->putDirectOffset(offset, r[value].jsValue(exec));
2699
2700                 vPC += 8;
2701                 NEXT_OPCODE;
2702             }
2703         }
2704
2705         uncachePutByID(codeBlock, vPC);
2706         NEXT_OPCODE;
2707     }
2708     BEGIN_OPCODE(op_put_by_id_generic) {
2709         /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
2710
2711            Generic property access: Sets the property named by identifier
2712            property, belonging to register base, to register value.
2713
2714            Unlike many opcodes, this one does not write any output to
2715            the register file.
2716         */
2717         int base = vPC[1].u.operand;
2718         int property = vPC[2].u.operand;
2719         int value = vPC[3].u.operand;
2720
2721         JSValue* baseValue = r[base].jsValue(exec);
2722
2723         PutPropertySlot slot;
2724         Identifier& ident = codeBlock->identifiers[property];
2725         baseValue->put(exec, ident, r[value].jsValue(exec), slot);
2726         VM_CHECK_EXCEPTION();
2727
2728         vPC += 8;
2729         NEXT_OPCODE;
2730     }
2731     BEGIN_OPCODE(op_del_by_id) {
2732         /* del_by_id dst(r) base(r) property(id)
2733
2734            Converts register base to Object, deletes the property
2735            named by identifier property from the object, and writes a
2736            boolean indicating success (if true) or failure (if false)
2737            to register dst.
2738         */
2739         int dst = (++vPC)->u.operand;
2740         int base = (++vPC)->u.operand;
2741         int property = (++vPC)->u.operand;
2742
2743         JSObject* baseObj = r[base].jsValue(exec)->toObject(exec);
2744
2745         Identifier& ident = codeBlock->identifiers[property];
2746         JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
2747         VM_CHECK_EXCEPTION();
2748         r[dst] = result;
2749         ++vPC;
2750         NEXT_OPCODE;
2751     }
2752     BEGIN_OPCODE(op_get_by_val) {
2753         /* get_by_val dst(r) base(r) property(r)
2754
2755            Converts register base to Object, gets the property named
2756            by register property from the object, and puts the result
2757            in register dst. property is nominally converted to string
2758            but numbers are treated more efficiently.
2759         */
2760         int dst = (++vPC)->u.operand;
2761         int base = (++vPC)->u.operand;
2762         int property = (++vPC)->u.operand;
2763         
2764         JSValue* baseValue = r[base].jsValue(exec);
2765         JSValue* subscript = r[property].jsValue(exec);
2766
2767         JSValue* result;
2768         unsigned i;
2769
2770         bool isUInt32 = JSImmediate::getUInt32(subscript, i);
2771         if (LIKELY(isUInt32)) {
2772             if (isJSArray(baseValue)) {
2773                 JSArray* jsArray = static_cast<JSArray*>(baseValue);
2774                 if (jsArray->canGetIndex(i))
2775                     result = jsArray->getIndex(i);
2776                 else
2777                     result = jsArray->JSArray::get(exec, i);
2778             } else if (isJSString(baseValue) && static_cast<JSString*>(baseValue)->canGetIndex(i))
2779                 result = static_cast<JSString*>(baseValue)->getIndex(exec, i);
2780             else
2781                 result = baseValue->get(exec, i);
2782         } else {
2783             Identifier property(exec, subscript->toString(exec));
2784             result = baseValue->get(exec, property);
2785         }
2786
2787         VM_CHECK_EXCEPTION();
2788         r[dst] = result;
2789         ++vPC;
2790         NEXT_OPCODE;
2791     }
2792     BEGIN_OPCODE(op_put_by_val) {
2793         /* put_by_val base(r) property(r) value(r)
2794
2795            Sets register value on register base as the property named
2796            by register property. Base is converted to object
2797            first. register property is nominally converted to string
2798            but numbers are treated more efficiently.
2799
2800            Unlike many opcodes, this one does not write any output to
2801            the register file.
2802         */
2803         int base = (++vPC)->u.operand;
2804         int property = (++vPC)->u.operand;
2805         int value = (++vPC)->u.operand;
2806
2807         JSValue* baseValue = r[base].jsValue(exec);
2808         JSValue* subscript = r[property].jsValue(exec);
2809
2810         unsigned i;
2811
2812         bool isUInt32 = JSImmediate::getUInt32(subscript, i);
2813         if (LIKELY(isUInt32)) {
2814             if (isJSArray(baseValue)) {
2815                 JSArray* jsArray = static_cast<JSArray*>(baseValue);
2816                 if (jsArray->canSetIndex(i))
2817                     jsArray->setIndex(i, r[value].jsValue(exec));
2818                 else
2819                     jsArray->JSArray::put(exec, i, r[value].jsValue(exec));
2820             } else
2821                 baseValue->put(exec, i, r[value].jsValue(exec));
2822         } else {
2823             Identifier property(exec, subscript->toString(exec));
2824             if (!exec->hadException()) { // Don't put to an object if toString threw an exception.
2825                 PutPropertySlot slot;
2826                 baseValue->put(exec, property, r[value].jsValue(exec), slot);
2827             }
2828         }
2829
2830         VM_CHECK_EXCEPTION();
2831         ++vPC;
2832         NEXT_OPCODE;
2833     }
2834     BEGIN_OPCODE(op_del_by_val) {
2835         /* del_by_val dst(r) base(r) property(r)
2836
2837            Converts register base to Object, deletes the property
2838            named by register property from the object, and writes a
2839            boolean indicating success (if true) or failure (if false)
2840            to register dst.
2841         */
2842         int dst = (++vPC)->u.operand;
2843         int base = (++vPC)->u.operand;
2844         int property = (++vPC)->u.operand;
2845
2846         JSObject* baseObj = r[base].jsValue(exec)->toObject(exec); // may throw
2847
2848         JSValue* subscript = r[property].jsValue(exec);
2849         JSValue* result;
2850         uint32_t i;
2851         if (subscript->getUInt32(i))
2852             result = jsBoolean(baseObj->deleteProperty(exec, i));
2853         else {
2854             VM_CHECK_EXCEPTION();
2855             Identifier property(exec, subscript->toString(exec));
2856             VM_CHECK_EXCEPTION();
2857             result = jsBoolean(baseObj->deleteProperty(exec, property));
2858         }
2859
2860         VM_CHECK_EXCEPTION();
2861         r[dst] = result;
2862         ++vPC;
2863         NEXT_OPCODE;
2864     }
2865     BEGIN_OPCODE(op_put_by_index) {
2866         /* put_by_index base(r) property(n) value(r)
2867
2868            Sets register value on register base as the property named
2869            by the immediate number property. Base is converted to
2870            object first.
2871
2872            Unlike many opcodes, this one does not write any output to
2873            the register file.
2874
2875            This opcode is mainly used to initialize array literals.
2876         */
2877         int base = (++vPC)->u.operand;
2878         unsigned property = (++vPC)->u.operand;
2879         int value = (++vPC)->u.operand;
2880
2881         r[base].jsValue(exec)->put(exec, property, r[value].jsValue(exec));
2882
2883         ++vPC;
2884         NEXT_OPCODE;
2885     }
2886     BEGIN_OPCODE(op_loop) {
2887         /* loop target(offset)
2888          
2889            Jumps unconditionally to offset target from the current
2890            instruction.
2891
2892            Additionally this loop instruction may terminate JS execution is
2893            the JS timeout is reached.
2894          */
2895 #if DUMP_OPCODE_STATS
2896         OpcodeStats::resetLastInstruction();
2897 #endif
2898         int target = (++vPC)->u.operand;
2899         CHECK_FOR_TIMEOUT();
2900         vPC += target;
2901         NEXT_OPCODE;
2902     }
2903     BEGIN_OPCODE(op_jmp) {
2904         /* jmp target(offset)
2905
2906            Jumps unconditionally to offset target from the current
2907            instruction.
2908         */
2909 #if DUMP_OPCODE_STATS
2910         OpcodeStats::resetLastInstruction();
2911 #endif
2912         int target = (++vPC)->u.operand;
2913
2914         vPC += target;
2915         NEXT_OPCODE;
2916     }
2917     BEGIN_OPCODE(op_loop_if_true) {
2918         /* loop_if_true cond(r) target(offset)
2919          
2920            Jumps to offset target from the current instruction, if and
2921            only if register cond converts to boolean as true.
2922
2923            Additionally this loop instruction may terminate JS execution is
2924            the JS timeout is reached.
2925          */
2926         int cond = (++vPC)->u.operand;
2927         int target = (++vPC)->u.operand;
2928         if (r[cond].jsValue(exec)->toBoolean(exec)) {
2929             vPC += target;
2930             CHECK_FOR_TIMEOUT();
2931             NEXT_OPCODE;
2932         }
2933         
2934         ++vPC;
2935         NEXT_OPCODE;
2936     }
2937     BEGIN_OPCODE(op_jtrue) {
2938         /* jtrue cond(r) target(offset)
2939
2940            Jumps to offset target from the current instruction, if and
2941            only if register cond converts to boolean as true.
2942         */
2943         int cond = (++vPC)->u.operand;
2944         int target = (++vPC)->u.operand;
2945         if (r[cond].jsValue(exec)->toBoolean(exec)) {
2946             vPC += target;
2947             NEXT_OPCODE;
2948         }
2949
2950         ++vPC;
2951         NEXT_OPCODE;
2952     }
2953     BEGIN_OPCODE(op_jfalse) {
2954         /* jfalse cond(r) target(offset)
2955
2956            Jumps to offset target from the current instruction, if and
2957            only if register cond converts to boolean as false.
2958         */
2959         int cond = (++vPC)->u.operand;
2960         int target = (++vPC)->u.operand;
2961         if (!r[cond].jsValue(exec)->toBoolean(exec)) {
2962             vPC += target;
2963             NEXT_OPCODE;
2964         }
2965
2966         ++vPC;
2967         NEXT_OPCODE;
2968     }
2969     BEGIN_OPCODE(op_loop_if_less) {
2970         /* loop_if_less src1(r) src2(r) target(offset)
2971
2972            Checks whether register src1 is less than register src2, as
2973            with the ECMAScript '<' operator, and then jumps to offset
2974            target from the current instruction, if and only if the 
2975            result of the comparison is true.
2976
2977            Additionally this loop instruction may terminate JS execution is
2978            the JS timeout is reached.
2979          */
2980         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2981         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2982         int target = (++vPC)->u.operand;
2983         
2984         bool result = jsLess(exec, src1, src2);
2985         VM_CHECK_EXCEPTION();
2986         
2987         if (result) {
2988             vPC += target;
2989             CHECK_FOR_TIMEOUT();
2990             NEXT_OPCODE;
2991         }
2992         
2993         ++vPC;
2994         NEXT_OPCODE;
2995     }
2996     BEGIN_OPCODE(op_loop_if_lesseq) {
2997         /* loop_if_lesseq src1(r) src2(r) target(offset)
2998
2999            Checks whether register src1 is less than or equal to register
3000            src2, as with the ECMAScript '<=' operator, and then jumps to
3001            offset target from the current instruction, if and only if the 
3002            result of the comparison is true.
3003
3004            Additionally this loop instruction may terminate JS execution is
3005            the JS timeout is reached.
3006         */
3007         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
3008         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
3009         int target = (++vPC)->u.operand;
3010         
3011         bool result = jsLessEq(exec, src1, src2);
3012         VM_CHECK_EXCEPTION();
3013         
3014         if (result) {
3015             vPC += target;
3016             CHECK_FOR_TIMEOUT();
3017             NEXT_OPCODE;
3018         }
3019         
3020         ++vPC;
3021         NEXT_OPCODE;
3022     }
3023     BEGIN_OPCODE(op_jnless) {
3024         /* jnless src1(r) src2(r) target(offset)
3025
3026            Checks whether register src1 is less than register src2, as
3027            with the ECMAScript '<' operator, and then jumps to offset
3028            target from the current instruction, if and only if the 
3029            result of the comparison is false.
3030         */
3031         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
3032         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
3033         int target = (++vPC)->u.operand;
3034
3035         bool result = jsLess(exec, src1, src2);
3036         VM_CHECK_EXCEPTION();
3037         
3038         if (!result) {
3039             vPC += target;
3040             NEXT_OPCODE;
3041         }
3042
3043         ++vPC;
3044         NEXT_OPCODE;
3045     }
3046     BEGIN_OPCODE(op_switch_imm) {
3047         /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
3048
3049            Performs a range checked switch on the scrutinee value, using
3050            the tableIndex-th immediate switch jump table.  If the scrutinee value
3051            is an immediate number in the range covered by the referenced jump
3052            table, and the value at jumpTable[scrutinee value] is non-zero, then
3053            that value is used as the jump offset, otherwise defaultOffset is used.
3054          */
3055         int tableIndex = (++vPC)->u.operand;
3056         int defaultOffset = (++vPC)->u.operand;
3057         JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
3058         if (!JSImmediate::isNumber(scrutinee))
3059             vPC += defaultOffset;
3060         else {
3061             int32_t value = JSImmediate::getTruncatedInt32(scrutinee);
3062             vPC += codeBlock->immediateSwitchJumpTables[tableIndex].offsetForValue(value, defaultOffset);
3063         }
3064         NEXT_OPCODE;
3065     }
3066     BEGIN_OPCODE(op_switch_char) {
3067         /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
3068
3069            Performs a range checked switch on the scrutinee value, using
3070            the tableIndex-th character switch jump table.  If the scrutinee value
3071            is a single character string in the range covered by the referenced jump
3072            table, and the value at jumpTable[scrutinee value] is non-zero, then
3073            that value is used as the jump offset, otherwise defaultOffset is used.
3074          */
3075         int tableIndex = (++vPC)->u.operand;
3076         int defaultOffset = (++vPC)->u.operand;
3077         JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
3078         if (!scrutinee->isString())
3079             vPC += defaultOffset;
3080         else {
3081             UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
3082             if (value->size() != 1)
3083                 vPC += defaultOffset;
3084             else
3085                 vPC += codeBlock->characterSwitchJumpTables[tableIndex].offsetForValue(value->data()[0], defaultOffset);
3086         }
3087         NEXT_OPCODE;
3088     }
3089     BEGIN_OPCODE(op_switch_string) {
3090         /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
3091
3092            Performs a sparse hashmap based switch on the value in the scrutinee
3093            register, using the tableIndex-th string switch jump table.  If the 
3094            scrutinee value is a string that exists as a key in the referenced 
3095            jump table, then the value associated with the string is used as the 
3096            jump offset, otherwise defaultOffset is used.
3097          */
3098         int tableIndex = (++vPC)->u.operand;
3099         int defaultOffset = (++vPC)->u.operand;
3100         JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
3101         if (!scrutinee->isString())
3102             vPC += defaultOffset;
3103         else 
3104             vPC += codeBlock->stringSwitchJumpTables[tableIndex].offsetForValue(static_cast<JSString*>(scrutinee)->value().rep(), defaultOffset);
3105         NEXT_OPCODE;
3106     }
3107     BEGIN_OPCODE(op_new_func) {
3108         /* new_func dst(r) func(f)
3109
3110            Constructs a new Function instance from function func and
3111            the current scope chain using the original Function
3112            constructor, using the rules for function declarations, and
3113            puts the result in register dst.
3114         */
3115         int dst = (++vPC)->u.operand;
3116         int func = (++vPC)->u.operand;
3117
3118         r[dst] = codeBlock->functions[func]->makeFunction(exec, scopeChain);
3119
3120         ++vPC;
3121         NEXT_OPCODE;
3122     }
3123     BEGIN_OPCODE(op_new_func_exp) {
3124         /* new_func_exp dst(r) func(f)
3125
3126            Constructs a new Function instance from function func and
3127            the current scope chain using the original Function
3128            constructor, using the rules for function expressions, and
3129            puts the result in register dst.
3130         */
3131         int dst = (++vPC)->u.operand;
3132         int func = (++vPC)->u.operand;
3133
3134         r[dst] = codeBlock->functionExpressions[func]->makeFunction(exec, scopeChain);
3135
3136         ++vPC;
3137         NEXT_OPCODE;
3138     }
3139     BEGIN_OPCODE(op_call_eval) {
3140         /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
3141
3142            Call a function named "eval" with no explicit "this" value
3143            (which may therefore be the eval operator). If register
3144            thisVal is the global object, and register func contains
3145            that global object's original global eval function, then
3146            perform the eval operator in local scope (interpreting
3147            the argument registers as for the "call"
3148            opcode). Otherwise, act exactly as the "call" opcode would.
3149          */
3150
3151         int dst = (++vPC)->u.operand;
3152         int func = (++vPC)->u.operand;
3153         int thisVal = (++vPC)->u.operand;
3154         int firstArg = (++vPC)->u.operand;
3155         int argCount = (++vPC)->u.operand;
3156
3157         JSValue* funcVal = r[func].jsValue(exec);
3158         JSValue* baseVal = r[thisVal].jsValue(exec);
3159
3160         if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
3161             JSObject* thisObject = static_cast<JSObject*>(r[codeBlock->thisRegister].jsValue(exec));
3162             JSValue* result = callEval(exec, codeBlock, thisObject, scopeChain, registerFile, r, firstArg, argCount, exceptionValue);
3163             if (exceptionValue)
3164                 goto vm_throw;
3165
3166             r[dst] = result;
3167
3168             ++vPC;
3169             NEXT_OPCODE;
3170         }
3171
3172         // We didn't find the blessed version of eval, so reset vPC and process
3173         // this instruction as a normal function call, supplying the proper 'this'
3174         // value.
3175         vPC -= 5;
3176         r[thisVal] = baseVal->toThisObject(exec);
3177
3178 #if HAVE(COMPUTED_GOTO)
3179         // Hack around gcc performance quirk by performing an indirect goto
3180         // in order to set the vPC -- attempting to do so directly results in a
3181         // significant regression.
3182         goto *op_call_indirect; // indirect goto -> op_call
3183 #endif
3184         // fall through to op_call
3185     }
3186     BEGIN_OPCODE(op_call) {
3187         /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
3188
3189            Perform a function call. Specifically, call register func
3190            with a "this" value of register thisVal, and put the result
3191            in register dst.
3192
3193            The arguments start at register firstArg and go up to
3194            argCount, but the "this" value is considered an implicit
3195            first argument, so the argCount should be one greater than
3196            the number of explicit arguments passed, and the register
3197            after firstArg should contain the actual first
3198            argument. This opcode will copy from the thisVal register
3199            to the firstArg register, unless the register index of
3200            thisVal is the special missing this object marker, which is
3201            2^31-1; in that case, the global object will be used as the
3202            "this" value.
3203
3204            If func is a native code function, then this opcode calls
3205            it and returns the value immediately. 
3206
3207            But if it is a JS function, then the current scope chain
3208            and code block is set to the function's, and we slide the
3209            register window so that the arguments would form the first
3210            few local registers of the called function's register
3211            window. In addition, a call frame header is written
3212            immediately before the arguments; see the call frame
3213            documentation for an explanation of how many registers a
3214            call frame takes and what they contain. That many registers
3215            before the firstArg register will be overwritten by the
3216            call. In addition, any registers higher than firstArg +
3217            argCount may be overwritten. Once this setup is complete,
3218            execution continues from the called function's first
3219            argument, and does not return until a "ret" opcode is
3220            encountered.
3221          */
3222
3223         int dst = (++vPC)->u.operand;
3224         int func = (++vPC)->u.operand;
3225         int thisVal = (++vPC)->u.operand;
3226         int firstArg = (++vPC)->u.operand;
3227         int argCount = (++vPC)->u.operand;
3228
3229         JSValue* v = r[func].jsValue(exec);
3230
3231         CallData callData;
3232         CallType callType = v->getCallData(callData);
3233
3234         if (*enabledProfilerReference)
3235             (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
3236
3237         Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
3238         initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, v);
3239         exec->m_callFrame = callFrame;
3240
3241         if (callType == CallTypeJS) {
3242
3243             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
3244             FunctionBodyNode* functionBodyNode = callData.js.functionBody;
3245             CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
3246
3247             r[firstArg] = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
3248
3249             r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
3250             if (UNLIKELY(exceptionValue != 0))
3251                 goto vm_throw;
3252
3253             codeBlock = newCodeBlock;
3254             setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
3255             vPC = codeBlock->instructions.begin();
3256
3257 #if DUMP_OPCODE_STATS
3258             OpcodeStats::resetLastInstruction();
3259 #endif
3260             
3261             NEXT_OPCODE;
3262         }
3263
3264         if (callType == CallTypeHost) {
3265             JSValue* thisValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
3266             ArgList args(r + firstArg + 1, argCount - 1);
3267
3268             MACHINE_SAMPLING_callingHostFunction();
3269
3270             JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(v), thisValue, args);
3271             exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3272             VM_CHECK_EXCEPTION();
3273
3274             r[dst] = returnValue;
3275
3276             if (*enabledProfilerReference)
3277                 (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(v));
3278
3279             ++vPC;
3280             NEXT_OPCODE;
3281         }
3282
3283         ASSERT(callType == CallTypeNone);
3284
3285         exceptionValue = createNotAFunctionError(exec, v, vPC, codeBlock);
3286         exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3287         goto vm_throw;
3288     }
3289     BEGIN_OPCODE(op_ret) {
3290         /* ret result(r)
3291            
3292            Return register result as the return value of the current
3293            function call, writing it into the caller's expected return
3294            value register. In addition, unwind one call frame and
3295            restore the scope chain, code block instruction pointer and
3296            register base to those of the calling function.
3297         */
3298            
3299         int result = (++vPC)->u.operand;
3300
3301         Register* callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3302         if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
3303             ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
3304             ASSERT(activation->isActivationObject());
3305             activation->copyRegisters();
3306         }
3307
3308         if (*enabledProfilerReference)
3309             (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
3310
3311         if (codeBlock->needsFullScopeChain)
3312             scopeChain->deref();
3313
3314         JSValue* returnValue = r[result].jsValue(exec);
3315
3316         codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
3317         if (!codeBlock)
3318             return returnValue;
3319
3320         vPC = callFrame[RegisterFile::ReturnVPC].vPC();
3321         setScopeChain(exec, scopeChain, callFrame[RegisterFile::CallerScopeChain].scopeChain());
3322         r = callFrame[RegisterFile::CallerRegisters].r();
3323         exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3324         int dst = callFrame[RegisterFile::ReturnValueRegister].i();
3325         r[dst] = returnValue;
3326
3327         NEXT_OPCODE;
3328     }
3329     BEGIN_OPCODE(op_construct) {
3330         /* construct dst(r) constr(r) constrProto(r) firstArg(r) argCount(n)
3331
3332            Invoke register "constr" as a constructor. For JS
3333            functions, the calling convention is exactly as for the
3334            "call" opcode, except that the "this" value is a newly
3335            created Object. For native constructors, a null "this"
3336            value is passed. In either case, the firstArg and argCount
3337            registers are interpreted as for the "call" opcode.
3338
3339            Register constrProto must contain the prototype property of
3340            register constsr. This is to enable polymorphic inline
3341            caching of this lookup.
3342         */
3343
3344         int dst = (++vPC)->u.operand;
3345         int constr = (++vPC)->u.operand;
3346         int constrProto = (++vPC)->u.operand;
3347         int firstArg = (++vPC)->u.operand;
3348         int argCount = (++vPC)->u.operand;
3349
3350         JSValue* constrVal = r[constr].jsValue(exec);
3351
3352         ConstructData constructData;
3353         ConstructType constructType = constrVal->getConstructData(constructData);
3354
3355         // Removing this line of code causes a measurable regression on squirrelfish.
3356         JSObject* constructor = static_cast<JSObject*>(constrVal);
3357
3358         if (constructType == ConstructTypeJS) {
3359             if (*enabledProfilerReference)
3360                 (*enabledProfilerReference)->willExecute(exec, constructor);
3361
3362             JSObject* prototype;
3363             JSValue* p = r[constrProto].jsValue(exec);
3364             if (p->isObject())
3365                 prototype = static_cast<JSObject*>(p);
3366             else
3367                 prototype = scopeChain->globalObject()->objectPrototype();
3368             JSObject* newObject = new (exec) JSObject(prototype);
3369
3370             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
3371             FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
3372             CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
3373
3374             r[firstArg] = newObject; // "this" value
3375
3376             Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
3377             initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, constructor);
3378             exec->m_callFrame = callFrame;
3379
3380             r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
3381             if (exceptionValue)
3382                 goto vm_throw;
3383
3384             codeBlock = newCodeBlock;
3385             setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
3386             vPC = codeBlock->instructions.begin();
3387
3388             NEXT_OPCODE;
3389         }
3390
3391         if (constructType == ConstructTypeHost) {
3392             if (*enabledProfilerReference)
3393                 (*enabledProfilerReference)->willExecute(exec, constructor);
3394
3395             ArgList args(r + firstArg + 1, argCount - 1);
3396
3397             MACHINE_SAMPLING_callingHostFunction();
3398
3399             JSValue* returnValue = constructData.native.function(exec, constructor, args);
3400
3401             VM_CHECK_EXCEPTION();
3402             r[dst] = returnValue;
3403
3404             if (*enabledProfilerReference)
3405                 (*enabledProfilerReference)->didExecute(exec, constructor);
3406
3407             ++vPC;
3408             NEXT_OPCODE;
3409         }
3410
3411         ASSERT(constructType == ConstructTypeNone);
3412
3413         exceptionValue = createNotAConstructorError(exec, constrVal, vPC, codeBlock);
3414         goto vm_throw;
3415     }
3416     BEGIN_OPCODE(op_construct_verify) {
3417         /* construct_verify dst(r) override(r)
3418
3419            Verifies that register dst holds an object. If not, moves
3420            the object in register override to register dst.
3421         */
3422
3423         int dst = vPC[1].u.operand;;
3424         if (LIKELY(r[dst].jsValue(exec)->isObject())) {
3425             vPC += 3;
3426             NEXT_OPCODE;
3427         }
3428
3429         int override = vPC[2].u.operand;
3430         r[dst] = r[override];
3431
3432         vPC += 3;
3433         NEXT_OPCODE;
3434     }
3435     BEGIN_OPCODE(op_push_scope) {
3436         /* push_scope scope(r)
3437
3438            Converts register scope to object, and pushes it onto the top
3439            of the current scope chain.
3440         */
3441         int scope = (++vPC)->u.ope