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