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