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