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
1819         JSValue* srcVal = r[src].jsValue(exec);
1820
1821         if (LIKELY(JSImmediate::isNumber(srcVal) || static_cast<JSCell*>(srcVal)->structureID()->typeInfo().type() == NumberType)) {
1822             r[dst] = r[src];
1823         } else {
1824             JSValue* result = srcVal->toJSNumber(exec);
1825             VM_CHECK_EXCEPTION();
1826             r[dst] = result;
1827         }
1828
1829         ++vPC;
1830         NEXT_OPCODE;
1831     }
1832     BEGIN_OPCODE(op_negate) {
1833         /* negate dst(r) src(r)
1834
1835            Converts register src to number, negates it, and puts the
1836            result in register dst.
1837         */
1838         int dst = (++vPC)->u.operand;
1839         JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1840         double v;
1841         if (fastIsNumber(src, v))
1842             r[dst] = jsNumber(exec, -v);
1843         else {
1844             JSValue* result = jsNumber(exec, -src->toNumber(exec));
1845             VM_CHECK_EXCEPTION();
1846             r[dst] = result;
1847         }
1848
1849         ++vPC;
1850         NEXT_OPCODE;
1851     }
1852     BEGIN_OPCODE(op_add) {
1853         /* add dst(r) src1(r) src2(r)
1854
1855            Adds register src1 and register src2, and puts the result
1856            in register dst. (JS add may be string concatenation or
1857            numeric add, depending on the types of the operands.)
1858         */
1859         int dst = (++vPC)->u.operand;
1860         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1861         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1862         if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1863             r[dst] = JSImmediate::addImmediateNumbers(src1, src2);
1864         else {
1865             JSValue* result = jsAdd(exec, src1, src2);
1866             VM_CHECK_EXCEPTION();
1867             r[dst] = result;
1868         }
1869         vPC += 2;
1870         NEXT_OPCODE;
1871     }
1872     BEGIN_OPCODE(op_mul) {
1873         /* mul dst(r) src1(r) src2(r)
1874
1875            Multiplies register src1 and register src2 (converted to
1876            numbers), and puts the product in register dst.
1877         */
1878         int dst = (++vPC)->u.operand;
1879         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1880         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1881         double left;
1882         double right;
1883         if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
1884             r[dst] = jsNumber(exec, left * right);
1885         else {
1886             JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
1887             VM_CHECK_EXCEPTION();
1888             r[dst] = result;
1889         }
1890
1891         vPC += 2;
1892         NEXT_OPCODE;
1893     }
1894     BEGIN_OPCODE(op_div) {
1895         /* div dst(r) dividend(r) divisor(r)
1896
1897            Divides register dividend (converted to number) by the
1898            register divisor (converted to number), and puts the
1899            quotient in register dst.
1900         */
1901         int dst = (++vPC)->u.operand;
1902         JSValue* dividend = r[(++vPC)->u.operand].jsValue(exec);
1903         JSValue* divisor = r[(++vPC)->u.operand].jsValue(exec);
1904         double left;
1905         double right;
1906         if (fastIsNumber(dividend, left) && fastIsNumber(divisor, right))
1907             r[dst] = jsNumber(exec, left / right);
1908         else {
1909             JSValue* result = jsNumber(exec, dividend->toNumber(exec) / divisor->toNumber(exec));
1910             VM_CHECK_EXCEPTION();
1911             r[dst] = result;
1912         }
1913         ++vPC;
1914         NEXT_OPCODE;
1915     }
1916     BEGIN_OPCODE(op_mod) {
1917         /* mod dst(r) dividend(r) divisor(r)
1918
1919            Divides register dividend (converted to number) by
1920            register divisor (converted to number), and puts the
1921            remainder in register dst.
1922         */
1923         int dst = (++vPC)->u.operand;
1924         int dividend = (++vPC)->u.operand;
1925         int divisor = (++vPC)->u.operand;
1926
1927         JSValue* dividendValue = r[dividend].jsValue(exec);
1928         JSValue* divisorValue = r[divisor].jsValue(exec);
1929
1930         if (JSImmediate::areBothImmediateNumbers(dividendValue, divisorValue) && divisorValue != JSImmediate::from(0)) {
1931             r[dst] = JSImmediate::from(JSImmediate::getTruncatedInt32(dividendValue) % JSImmediate::getTruncatedInt32(divisorValue));
1932             ++vPC;
1933             NEXT_OPCODE;
1934         }
1935
1936         double d = dividendValue->toNumber(exec);
1937         JSValue* result = jsNumber(exec, fmod(d, divisorValue->toNumber(exec)));
1938         VM_CHECK_EXCEPTION();
1939         r[dst] = result;
1940         ++vPC;
1941         NEXT_OPCODE;
1942     }
1943     BEGIN_OPCODE(op_sub) {
1944         /* sub dst(r) src1(r) src2(r)
1945
1946            Subtracts register src2 (converted to number) from register
1947            src1 (converted to number), and puts the difference in
1948            register dst.
1949         */
1950         int dst = (++vPC)->u.operand;
1951         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1952         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1953         double left;
1954         double right;
1955         if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1956             r[dst] = JSImmediate::subImmediateNumbers(src1, src2);
1957         else if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
1958             r[dst] = jsNumber(exec, left - right);
1959         else {
1960             JSValue* result = jsNumber(exec, src1->toNumber(exec) - src2->toNumber(exec));
1961             VM_CHECK_EXCEPTION();
1962             r[dst] = result;
1963         }
1964         vPC += 2;
1965         NEXT_OPCODE;
1966     }
1967     BEGIN_OPCODE(op_lshift) {
1968         /* lshift dst(r) val(r) shift(r)
1969
1970            Performs left shift of register val (converted to int32) by
1971            register shift (converted to uint32), and puts the result
1972            in register dst.
1973         */
1974         int dst = (++vPC)->u.operand;
1975         JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1976         JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1977         int32_t left;
1978         uint32_t right;
1979         if (JSImmediate::areBothImmediateNumbers(val, shift))
1980             r[dst] = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::getTruncatedUInt32(shift) & 0x1f));
1981         else if (fastToInt32(val, left) && fastToUInt32(shift, right))
1982             r[dst] = jsNumber(exec, left << (right & 0x1f));
1983         else {
1984             JSValue* result = jsNumber(exec, (val->toInt32(exec)) << (shift->toUInt32(exec) & 0x1f));
1985             VM_CHECK_EXCEPTION();
1986             r[dst] = result;
1987         }
1988
1989         ++vPC;
1990         NEXT_OPCODE;
1991     }
1992     BEGIN_OPCODE(op_rshift) {
1993         /* rshift dst(r) val(r) shift(r)
1994
1995            Performs arithmetic right shift of register val (converted
1996            to int32) by register shift (converted to
1997            uint32), and puts the result in register dst.
1998         */
1999         int dst = (++vPC)->u.operand;
2000         JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
2001         JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
2002         int32_t left;
2003         uint32_t right;
2004         if (JSImmediate::areBothImmediateNumbers(val, shift))
2005             r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
2006         else if (fastToInt32(val, left) && fastToUInt32(shift, right))
2007             r[dst] = jsNumber(exec, left >> (right & 0x1f));
2008         else {
2009             JSValue* result = jsNumber(exec, (val->toInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
2010             VM_CHECK_EXCEPTION();
2011             r[dst] = result;
2012         }
2013
2014         ++vPC;
2015         NEXT_OPCODE;
2016     }
2017     BEGIN_OPCODE(op_urshift) {
2018         /* rshift dst(r) val(r) shift(r)
2019
2020            Performs logical right shift of register val (converted
2021            to uint32) by register shift (converted to
2022            uint32), and puts the result in register dst.
2023         */
2024         int dst = (++vPC)->u.operand;
2025         JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
2026         JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
2027         if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val))
2028             r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
2029         else {
2030             JSValue* result = jsNumber(exec, (val->toUInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
2031             VM_CHECK_EXCEPTION();
2032             r[dst] = result;
2033         }
2034
2035         ++vPC;
2036         NEXT_OPCODE;
2037     }
2038     BEGIN_OPCODE(op_bitand) {
2039         /* bitand dst(r) src1(r) src2(r)
2040
2041            Computes bitwise AND of register src1 (converted to int32)
2042            and register src2 (converted to int32), and puts the result
2043            in register dst.
2044         */
2045         int dst = (++vPC)->u.operand;
2046         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2047         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2048         int32_t left;
2049         int32_t right;
2050         if (JSImmediate::areBothImmediateNumbers(src1, src2))
2051             r[dst] = JSImmediate::andImmediateNumbers(src1, src2);
2052         else if (fastToInt32(src1, left) && fastToInt32(src2, right))
2053             r[dst] = jsNumber(exec, left & right);
2054         else {
2055             JSValue* result = jsNumber(exec, src1->toInt32(exec) & src2->toInt32(exec));
2056             VM_CHECK_EXCEPTION();
2057             r[dst] = result;
2058         }
2059
2060         vPC += 2;
2061         NEXT_OPCODE;
2062     }
2063     BEGIN_OPCODE(op_bitxor) {
2064         /* bitxor dst(r) src1(r) src2(r)
2065
2066            Computes bitwise XOR of register src1 (converted to int32)
2067            and register src2 (converted to int32), and puts the result
2068            in register dst.
2069         */
2070         int dst = (++vPC)->u.operand;
2071         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2072         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2073         int32_t left;
2074         int32_t right;
2075         if (JSImmediate::areBothImmediateNumbers(src1, src2))
2076             r[dst] = JSImmediate::xorImmediateNumbers(src1, src2);
2077         else if (fastToInt32(src1, left) && fastToInt32(src2, right))
2078             r[dst] = jsNumber(exec, left ^ right);
2079         else {
2080             JSValue* result = jsNumber(exec, src1->toInt32(exec) ^ src2->toInt32(exec));
2081             VM_CHECK_EXCEPTION();
2082             r[dst] = result;
2083         }
2084
2085         vPC += 2;
2086         NEXT_OPCODE;
2087     }
2088     BEGIN_OPCODE(op_bitor) {
2089         /* bitor dst(r) src1(r) src2(r)
2090
2091            Computes bitwise OR of register src1 (converted to int32)
2092            and register src2 (converted to int32), and puts the
2093            result in register dst.
2094         */
2095         int dst = (++vPC)->u.operand;
2096         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2097         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2098         int32_t left;
2099         int32_t right;
2100         if (JSImmediate::areBothImmediateNumbers(src1, src2))
2101             r[dst] = JSImmediate::orImmediateNumbers(src1, src2);
2102         else if (fastToInt32(src1, left) && fastToInt32(src2, right))
2103             r[dst] = jsNumber(exec, left | right);
2104         else {
2105             JSValue* result = jsNumber(exec, src1->toInt32(exec) | src2->toInt32(exec));
2106             VM_CHECK_EXCEPTION();
2107             r[dst] = result;
2108         }
2109
2110         vPC += 2;
2111         NEXT_OPCODE;
2112     }
2113     BEGIN_OPCODE(op_bitnot) {
2114         /* bitnot dst(r) src(r)
2115
2116            Computes bitwise NOT of register src1 (converted to int32),
2117            and puts the result in register dst.
2118         */
2119         int dst = (++vPC)->u.operand;
2120         JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
2121         int32_t value;
2122         if (fastToInt32(src, value))
2123             r[dst] = jsNumber(exec, ~value);
2124         else {
2125             JSValue* result = jsNumber(exec, ~src->toInt32(exec));
2126             VM_CHECK_EXCEPTION();
2127             r[dst] = result;
2128         }
2129         ++vPC;
2130         NEXT_OPCODE;
2131     }
2132     BEGIN_OPCODE(op_not) {
2133         /* not dst(r) src(r)
2134
2135            Computes logical NOT of register src (converted to
2136            boolean), and puts the result in register dst.
2137         */
2138         int dst = (++vPC)->u.operand;
2139         int src = (++vPC)->u.operand;
2140         JSValue* result = jsBoolean(!r[src].jsValue(exec)->toBoolean(exec));
2141         VM_CHECK_EXCEPTION();
2142         r[dst] = result;
2143
2144         ++vPC;
2145         NEXT_OPCODE;
2146     }
2147     BEGIN_OPCODE(op_instanceof) {
2148         /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
2149
2150            Tests whether register value is an instance of register
2151            constructor, and puts the boolean result in register
2152            dst. Register constructorProto must contain the "prototype"
2153            property (not the actual prototype) of the object in
2154            register constructor. This lookup is separated so that
2155            polymorphic inline caching can apply.
2156
2157            Raises an exception if register constructor is not an
2158            object.
2159         */
2160         int dst = (++vPC)->u.operand;
2161         int value = (++vPC)->u.operand;
2162         int base = (++vPC)->u.operand;
2163         int baseProto = (++vPC)->u.operand;
2164
2165         JSValue* baseVal = r[base].jsValue(exec);
2166
2167         if (isNotObject(exec, true, codeBlock(r), vPC, baseVal, exceptionValue))
2168             goto vm_throw;
2169
2170         JSObject* baseObj = static_cast<JSObject*>(baseVal);
2171         r[dst] = jsBoolean(baseObj->structureID()->typeInfo().implementsHasInstance() ? baseObj->hasInstance(exec, r[value].jsValue(exec), r[baseProto].jsValue(exec)) : false);
2172
2173         ++vPC;
2174         NEXT_OPCODE;
2175     }
2176     BEGIN_OPCODE(op_typeof) {
2177         /* typeof dst(r) src(r)
2178
2179            Determines the type string for src according to ECMAScript
2180            rules, and puts the result in register dst.
2181         */
2182         int dst = (++vPC)->u.operand;
2183         int src = (++vPC)->u.operand;
2184         r[dst] = jsTypeStringForValue(exec, r[src].jsValue(exec));
2185
2186         ++vPC;
2187         NEXT_OPCODE;
2188     }
2189     BEGIN_OPCODE(op_is_undefined) {
2190         /* is_undefined dst(r) src(r)
2191
2192            Determines whether the type string for src according to
2193            the ECMAScript rules is "undefined", and puts the result
2194            in register dst.
2195         */
2196         int dst = (++vPC)->u.operand;
2197         int src = (++vPC)->u.operand;
2198         JSValue* v = r[src].jsValue(exec);
2199         r[dst] = jsBoolean(JSImmediate::isImmediate(v) ? v->isUndefined() : v->asCell()->structureID()->typeInfo().masqueradesAsUndefined());
2200
2201         ++vPC;
2202         NEXT_OPCODE;
2203     }
2204     BEGIN_OPCODE(op_is_boolean) {
2205         /* is_boolean dst(r) src(r)
2206
2207            Determines whether the type string for src according to
2208            the ECMAScript rules is "boolean", and puts the result
2209            in register dst.
2210         */
2211         int dst = (++vPC)->u.operand;
2212         int src = (++vPC)->u.operand;
2213         r[dst] = jsBoolean(r[src].jsValue(exec)->isBoolean());
2214
2215         ++vPC;
2216         NEXT_OPCODE;
2217     }
2218     BEGIN_OPCODE(op_is_number) {
2219         /* is_number dst(r) src(r)
2220
2221            Determines whether the type string for src according to
2222            the ECMAScript rules is "number", and puts the result
2223            in register dst.
2224         */
2225         int dst = (++vPC)->u.operand;
2226         int src = (++vPC)->u.operand;
2227         r[dst] = jsBoolean(r[src].jsValue(exec)->isNumber());
2228
2229         ++vPC;
2230         NEXT_OPCODE;
2231     }
2232     BEGIN_OPCODE(op_is_string) {
2233         /* is_string dst(r) src(r)
2234
2235            Determines whether the type string for src according to
2236            the ECMAScript rules is "string", and puts the result
2237            in register dst.
2238         */
2239         int dst = (++vPC)->u.operand;
2240         int src = (++vPC)->u.operand;
2241         r[dst] = jsBoolean(r[src].jsValue(exec)->isString());
2242
2243         ++vPC;
2244         NEXT_OPCODE;
2245     }
2246     BEGIN_OPCODE(op_is_object) {
2247         /* is_object dst(r) src(r)
2248
2249            Determines whether the type string for src according to
2250            the ECMAScript rules is "object", and puts the result
2251            in register dst.
2252         */
2253         int dst = (++vPC)->u.operand;
2254         int src = (++vPC)->u.operand;
2255         r[dst] = jsBoolean(jsIsObjectType(r[src].jsValue(exec)));
2256
2257         ++vPC;
2258         NEXT_OPCODE;
2259     }
2260     BEGIN_OPCODE(op_is_function) {
2261         /* is_function dst(r) src(r)
2262
2263            Determines whether the type string for src according to
2264            the ECMAScript rules is "function", and puts the result
2265            in register dst.
2266         */
2267         int dst = (++vPC)->u.operand;
2268         int src = (++vPC)->u.operand;
2269         r[dst] = jsBoolean(jsIsFunctionType(r[src].jsValue(exec)));
2270
2271         ++vPC;
2272         NEXT_OPCODE;
2273     }
2274     BEGIN_OPCODE(op_in) {
2275         /* in dst(r) property(r) base(r)
2276
2277            Tests whether register base has a property named register
2278            property, and puts the boolean result in register dst.
2279
2280            Raises an exception if register constructor is not an
2281            object.
2282         */
2283         int dst = (++vPC)->u.operand;
2284         int property = (++vPC)->u.operand;
2285         int base = (++vPC)->u.operand;
2286
2287         JSValue* baseVal = r[base].jsValue(exec);
2288         if (isNotObject(exec, false, codeBlock(r), vPC, baseVal, exceptionValue))
2289             goto vm_throw;
2290
2291         JSObject* baseObj = static_cast<JSObject*>(baseVal);
2292
2293         JSValue* propName = r[property].jsValue(exec);
2294
2295         uint32_t i;
2296         if (propName->getUInt32(i))
2297             r[dst] = jsBoolean(baseObj->hasProperty(exec, i));
2298         else {
2299             Identifier property(exec, propName->toString(exec));
2300             VM_CHECK_EXCEPTION();
2301             r[dst] = jsBoolean(baseObj->hasProperty(exec, property));
2302         }
2303
2304         ++vPC;
2305         NEXT_OPCODE;
2306     }
2307     BEGIN_OPCODE(op_resolve) {
2308         /* resolve dst(r) property(id)
2309
2310            Looks up the property named by identifier property in the
2311            scope chain, and writes the resulting value to register
2312            dst. If the property is not found, raises an exception.
2313         */
2314         if (UNLIKELY(!resolve(exec, vPC, r, exceptionValue)))
2315             goto vm_throw;
2316
2317         vPC += 3;
2318         NEXT_OPCODE;
2319     }
2320     BEGIN_OPCODE(op_resolve_skip) {
2321         /* resolve_skip dst(r) property(id) skip(n)
2322
2323          Looks up the property named by identifier property in the
2324          scope chain skipping the top 'skip' levels, and writes the resulting
2325          value to register dst. If the property is not found, raises an exception.
2326          */
2327         if (UNLIKELY(!resolveSkip(exec, vPC, r, exceptionValue)))
2328             goto vm_throw;
2329
2330         vPC += 4;
2331
2332         NEXT_OPCODE;
2333     }
2334     BEGIN_OPCODE(op_resolve_global) {
2335         /* resolve_skip dst(r) globalObject(c) property(id) structureID(sID) offset(n)
2336          
2337            Performs a dynamic property lookup for the given property, on the provided
2338            global object.  If structureID matches the StructureID of the global then perform
2339            a fast lookup using the case offset, otherwise fall back to a full resolve and
2340            cache the new structureID and offset
2341          */
2342         if (UNLIKELY(!resolveGlobal(exec, vPC, r,  exceptionValue)))
2343             goto vm_throw;
2344         
2345         vPC += 6;
2346         
2347         NEXT_OPCODE;
2348     }
2349     BEGIN_OPCODE(op_get_global_var) {
2350         /* get_global_var dst(r) globalObject(c) index(n)
2351
2352            Gets the global var at global slot index and places it in register dst.
2353          */
2354         int dst = (++vPC)->u.operand;
2355         JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
2356         ASSERT(scope->isGlobalObject());
2357         int index = (++vPC)->u.operand;
2358
2359         r[dst] = scope->registerAt(index);
2360         ++vPC;
2361         NEXT_OPCODE;
2362     }
2363     BEGIN_OPCODE(op_put_global_var) {
2364         /* put_global_var globalObject(c) index(n) value(r)
2365          
2366            Puts value into global slot index.
2367          */
2368         JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
2369         ASSERT(scope->isGlobalObject());
2370         int index = (++vPC)->u.operand;
2371         int value = (++vPC)->u.operand;
2372         
2373         scope->registerAt(index) = r[value].jsValue(exec);
2374         ++vPC;
2375         NEXT_OPCODE;
2376     }            
2377     BEGIN_OPCODE(op_get_scoped_var) {
2378         /* get_scoped_var dst(r) index(n) skip(n)
2379
2380          Loads the contents of the index-th local from the scope skip nodes from
2381          the top of the scope chain, and places it in register dst
2382          */
2383         int dst = (++vPC)->u.operand;
2384         int index = (++vPC)->u.operand;
2385         int skip = (++vPC)->u.operand + codeBlock(r)->needsFullScopeChain;
2386
2387         ScopeChainNode* scopeChain = this->scopeChain(r);
2388         ScopeChainIterator iter = scopeChain->begin();
2389         ScopeChainIterator end = scopeChain->end();
2390         ASSERT(iter != end);
2391         while (skip--) {
2392             ++iter;
2393             ASSERT(iter != end);
2394         }
2395
2396         ASSERT((*iter)->isVariableObject());
2397         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
2398         r[dst] = scope->registerAt(index);
2399         ++vPC;
2400         NEXT_OPCODE;
2401     }
2402     BEGIN_OPCODE(op_put_scoped_var) {
2403         /* put_scoped_var index(n) skip(n) value(r)
2404
2405          */
2406         int index = (++vPC)->u.operand;
2407         int skip = (++vPC)->u.operand + codeBlock(r)->needsFullScopeChain;
2408         int value = (++vPC)->u.operand;
2409
2410         ScopeChainNode* scopeChain = this->scopeChain(r);
2411         ScopeChainIterator iter = scopeChain->begin();
2412         ScopeChainIterator end = scopeChain->end();
2413         ASSERT(iter != end);
2414         while (skip--) {
2415             ++iter;
2416             ASSERT(iter != end);
2417         }
2418
2419         ASSERT((*iter)->isVariableObject());
2420         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
2421         scope->registerAt(index) = r[value].jsValue(exec);
2422         ++vPC;
2423         NEXT_OPCODE;
2424     }
2425     BEGIN_OPCODE(op_resolve_base) {
2426         /* resolve_base dst(r) property(id)
2427
2428            Searches the scope chain for an object containing
2429            identifier property, and if one is found, writes it to
2430            register dst. If none is found, the outermost scope (which
2431            will be the global object) is stored in register dst.
2432         */
2433         resolveBase(exec, vPC, r);
2434
2435         vPC += 3;
2436         NEXT_OPCODE;
2437     }
2438     BEGIN_OPCODE(op_resolve_with_base) {
2439         /* resolve_with_base baseDst(r) propDst(r) property(id)
2440
2441            Searches the scope chain for an object containing
2442            identifier property, and if one is found, writes it to
2443            register srcDst, and the retrieved property value to register
2444            propDst. If the property is not found, raises an exception.
2445
2446            This is more efficient than doing resolve_base followed by
2447            resolve, or resolve_base followed by get_by_id, as it
2448            avoids duplicate hash lookups.
2449         */
2450         if (UNLIKELY(!resolveBaseAndProperty(exec, vPC, r, exceptionValue)))
2451             goto vm_throw;
2452
2453         vPC += 4;
2454         NEXT_OPCODE;
2455     }
2456     BEGIN_OPCODE(op_resolve_func) {
2457         /* resolve_func baseDst(r) funcDst(r) property(id)
2458
2459            Searches the scope chain for an object containing
2460            identifier property, and if one is found, writes the
2461            appropriate object to use as "this" when calling its
2462            properties to register baseDst; and the retrieved property
2463            value to register propDst. If the property is not found,
2464            raises an exception.
2465
2466            This differs from resolve_with_base, because the
2467            global this value will be substituted for activations or
2468            the global object, which is the right behavior for function
2469            calls but not for other property lookup.
2470         */
2471         if (UNLIKELY(!resolveBaseAndFunc(exec, vPC, r, exceptionValue)))
2472             goto vm_throw;
2473
2474         vPC += 4;
2475         NEXT_OPCODE;
2476     }
2477     BEGIN_OPCODE(op_get_by_id) {
2478         /* get_by_id dst(r) base(r) property(id) structureID(sID) nop(n) nop(n) nop(n)
2479
2480            Generic property access: Gets the property named by identifier
2481            property from the value base, and puts the result in register dst.
2482         */
2483         int dst = vPC[1].u.operand;
2484         int base = vPC[2].u.operand;
2485         int property = vPC[3].u.operand;
2486
2487         CodeBlock* codeBlock = this->codeBlock(r);
2488         Identifier& ident = codeBlock->identifiers[property];
2489         JSValue* baseValue = r[base].jsValue(exec);
2490         PropertySlot slot(baseValue);
2491         JSValue* result = baseValue->get(exec, ident, slot);
2492         VM_CHECK_EXCEPTION();
2493
2494         tryCacheGetByID(exec, codeBlock, vPC, baseValue, ident, slot);
2495
2496         r[dst] = result;
2497         vPC += 8;
2498         NEXT_OPCODE;
2499     }
2500     BEGIN_OPCODE(op_get_by_id_self) {
2501         /* op_get_by_id_self dst(r) base(r) property(id) structureID(sID) offset(n) nop(n) nop(n)
2502
2503            Cached property access: Attempts to get a cached property from the
2504            value base. If the cache misses, op_get_by_id_self reverts to
2505            op_get_by_id.
2506         */
2507         int base = vPC[2].u.operand;
2508         JSValue* baseValue = r[base].jsValue(exec);
2509
2510         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2511             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2512             StructureID* structureID = vPC[4].u.structureID;
2513
2514             if (LIKELY(baseCell->structureID() == structureID)) {
2515                 ASSERT(baseCell->isObject());
2516                 JSObject* baseObject = static_cast<JSObject*>(baseCell);
2517                 int dst = vPC[1].u.operand;
2518                 int offset = vPC[5].u.operand;
2519
2520                 ASSERT(baseObject->get(exec, codeBlock(r)->identifiers[vPC[3].u.operand]) == baseObject->getDirectOffset(offset));
2521                 r[dst] = baseObject->getDirectOffset(offset);
2522
2523                 vPC += 8;
2524                 NEXT_OPCODE;
2525             }
2526         }
2527
2528         uncacheGetByID(codeBlock(r), vPC);
2529         NEXT_OPCODE;
2530     }
2531     BEGIN_OPCODE(op_get_by_id_proto) {
2532         /* op_get_by_id_proto dst(r) base(r) property(id) structureID(sID) protoStructureID(sID) offset(n) nop(n)
2533
2534            Cached property access: Attempts to get a cached property from the
2535            value base's prototype. If the cache misses, op_get_by_id_proto
2536            reverts to op_get_by_id.
2537         */
2538         int base = vPC[2].u.operand;
2539         JSValue* baseValue = r[base].jsValue(exec);
2540
2541         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2542             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2543             StructureID* structureID = vPC[4].u.structureID;
2544
2545             if (LIKELY(baseCell->structureID() == structureID)) {
2546                 ASSERT(structureID->prototypeForLookup(exec)->isObject());
2547                 JSObject* protoObject = static_cast<JSObject*>(structureID->prototypeForLookup(exec));
2548                 StructureID* protoStructureID = vPC[5].u.structureID;
2549
2550                 if (LIKELY(protoObject->structureID() == protoStructureID)) {
2551                     int dst = vPC[1].u.operand;
2552                     int offset = vPC[6].u.operand;
2553
2554                     ASSERT(protoObject->get(exec, codeBlock(r)->identifiers[vPC[3].u.operand]) == protoObject->getDirectOffset(offset));
2555                     r[dst] = protoObject->getDirectOffset(offset);
2556
2557                     vPC += 8;
2558                     NEXT_OPCODE;
2559                 }
2560             }
2561         }
2562
2563         uncacheGetByID(codeBlock(r), vPC);
2564         NEXT_OPCODE;
2565     }
2566     BEGIN_OPCODE(op_get_by_id_chain) {
2567         /* op_get_by_id_chain dst(r) base(r) property(id) structureID(sID) structureIDChain(sIDc) count(n) offset(n)
2568
2569            Cached property access: Attempts to get a cached property from the
2570            value base's prototype chain. If the cache misses, op_get_by_id_chain
2571            reverts to op_get_by_id.
2572         */
2573         int base = vPC[2].u.operand;
2574         JSValue* baseValue = r[base].jsValue(exec);
2575
2576         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2577             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2578             StructureID* structureID = vPC[4].u.structureID;
2579
2580             if (LIKELY(baseCell->structureID() == structureID)) {
2581                 RefPtr<StructureID>* it = vPC[5].u.structureIDChain->head();
2582                 size_t count = vPC[6].u.operand;
2583                 RefPtr<StructureID>* end = it + count;
2584
2585                 JSObject* baseObject = static_cast<JSObject*>(baseCell);
2586                 while (1) {
2587                     baseObject = static_cast<JSObject*>(baseObject->structureID()->prototypeForLookup(exec));
2588                     if (UNLIKELY(baseObject->structureID() != (*it).get()))
2589                         break;
2590
2591                     if (++it == end) {
2592                         int dst = vPC[1].u.operand;
2593                         int offset = vPC[7].u.operand;
2594
2595                         ASSERT(baseObject->get(exec, codeBlock(r)->identifiers[vPC[3].u.operand]) == baseObject->getDirectOffset(offset));
2596                         r[dst] = baseObject->getDirectOffset(offset);
2597
2598                         vPC += 8;
2599                         NEXT_OPCODE;
2600                     }
2601                 }
2602             }
2603         }
2604
2605         uncacheGetByID(codeBlock(r), vPC);
2606         NEXT_OPCODE;
2607     }
2608     BEGIN_OPCODE(op_get_by_id_generic) {
2609         /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2610
2611            Generic property access: Gets the property named by identifier
2612            property from the value base, and puts the result in register dst.
2613         */
2614         int dst = vPC[1].u.operand;
2615         int base = vPC[2].u.operand;
2616         int property = vPC[3].u.operand;
2617
2618         Identifier& ident = codeBlock(r)->identifiers[property];
2619         JSValue* baseValue = r[base].jsValue(exec);
2620         PropertySlot slot(baseValue);
2621         JSValue* result = baseValue->get(exec, ident, slot);
2622         VM_CHECK_EXCEPTION();
2623
2624         r[dst] = result;
2625         vPC += 8;
2626         NEXT_OPCODE;
2627     }
2628     BEGIN_OPCODE(op_get_array_length) {
2629         /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2630
2631            Cached property access: Gets the length of the array in register base,
2632            and puts the result in register dst. If register base does not hold
2633            an array, op_get_array_length reverts to op_get_by_id.
2634         */
2635
2636         int base = vPC[2].u.operand;
2637         JSValue* baseValue = r[base].jsValue(exec);
2638         if (LIKELY(isJSArray(baseValue))) {
2639             int dst = vPC[1].u.operand;
2640             r[dst] = jsNumber(exec, static_cast<JSArray*>(baseValue)->length());
2641             vPC += 8;
2642             NEXT_OPCODE;
2643         }
2644
2645         uncacheGetByID(codeBlock(r), vPC);
2646         NEXT_OPCODE;
2647     }
2648     BEGIN_OPCODE(op_get_string_length) {
2649         /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2650
2651            Cached property access: Gets the length of the string in register base,
2652            and puts the result in register dst. If register base does not hold
2653            a string, op_get_string_length reverts to op_get_by_id.
2654         */
2655
2656         int base = vPC[2].u.operand;
2657         JSValue* baseValue = r[base].jsValue(exec);
2658         if (LIKELY(isJSString(baseValue))) {
2659             int dst = vPC[1].u.operand;
2660             r[dst] = jsNumber(exec, static_cast<JSString*>(baseValue)->value().size());
2661             vPC += 8;
2662             NEXT_OPCODE;
2663         }
2664
2665         uncacheGetByID(codeBlock(r), vPC);
2666         NEXT_OPCODE;
2667     }
2668     BEGIN_OPCODE(op_put_by_id) {
2669         /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
2670
2671            Generic property access: Sets the property named by identifier
2672            property, belonging to register base, to register value.
2673
2674            Unlike many opcodes, this one does not write any output to
2675            the register file.
2676         */
2677
2678         int base = vPC[1].u.operand;
2679         int property = vPC[2].u.operand;
2680         int value = vPC[3].u.operand;
2681
2682         CodeBlock* codeBlock = this->codeBlock(r);
2683         JSValue* baseValue = r[base].jsValue(exec);
2684         Identifier& ident = codeBlock->identifiers[property];
2685         PutPropertySlot slot;
2686         baseValue->put(exec, ident, r[value].jsValue(exec), slot);
2687         VM_CHECK_EXCEPTION();
2688
2689         tryCachePutByID(exec, codeBlock, vPC, baseValue, slot);
2690
2691         vPC += 8;
2692         NEXT_OPCODE;
2693     }
2694     BEGIN_OPCODE(op_put_by_id_transition) {
2695         /* op_put_by_id_transition base(r) property(id) value(r) oldStructureID(sID) newStructureID(sID) structureIDChain(sIDc) offset(n)
2696          
2697            Cached property access: Attempts to set a new property with a cached transition
2698            property named by identifier property, belonging to register base,
2699            to register value. If the cache misses, op_put_by_id_transition
2700            reverts to op_put_by_id_generic.
2701          
2702            Unlike many opcodes, this one does not write any output to
2703            the register file.
2704          */
2705         int base = vPC[1].u.operand;
2706         JSValue* baseValue = r[base].jsValue(exec);
2707         
2708         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2709             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2710             StructureID* oldStructureID = vPC[4].u.structureID;
2711             StructureID* newStructureID = vPC[5].u.structureID;
2712             
2713             if (LIKELY(baseCell->structureID() == oldStructureID)) {
2714                 ASSERT(baseCell->isObject());
2715                 JSObject* baseObject = static_cast<JSObject*>(baseCell);
2716
2717                 RefPtr<StructureID>* it = vPC[6].u.structureIDChain->head();
2718
2719                 JSObject* proto = static_cast<JSObject*>(baseObject->structureID()->prototypeForLookup(exec));
2720                 while (!proto->isNull()) {
2721                     if (UNLIKELY(proto->structureID() != (*it).get())) {
2722                         uncachePutByID(codeBlock(r), vPC);
2723                         NEXT_OPCODE;
2724                     }
2725                     ++it;
2726                     proto = static_cast<JSObject*>(proto->structureID()->prototypeForLookup(exec));
2727                 }
2728
2729                 baseObject->transitionTo(newStructureID);
2730
2731                 int value = vPC[3].u.operand;
2732                 unsigned offset = vPC[7].u.operand;
2733                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(codeBlock(r)->identifiers[vPC[2].u.operand])) == offset);
2734                 baseObject->putDirectOffset(offset, r[value].jsValue(exec));
2735
2736                 vPC += 8;
2737                 NEXT_OPCODE;
2738             }
2739         }
2740         
2741         uncachePutByID(codeBlock(r), vPC);
2742         NEXT_OPCODE;
2743     }
2744     BEGIN_OPCODE(op_put_by_id_replace) {
2745         /* op_put_by_id_replace base(r) property(id) value(r) structureID(sID) offset(n) nop(n) nop(n)
2746
2747            Cached property access: Attempts to set a pre-existing, cached
2748            property named by identifier property, belonging to register base,
2749            to register value. If the cache misses, op_put_by_id_replace
2750            reverts to op_put_by_id.
2751
2752            Unlike many opcodes, this one does not write any output to
2753            the register file.
2754         */
2755         int base = vPC[1].u.operand;
2756         JSValue* baseValue = r[base].jsValue(exec);
2757
2758         if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2759             JSCell* baseCell = static_cast<JSCell*>(baseValue);
2760             StructureID* structureID = vPC[4].u.structureID;
2761
2762             if (LIKELY(baseCell->structureID() == structureID)) {
2763                 ASSERT(baseCell->isObject());
2764                 JSObject* baseObject = static_cast<JSObject*>(baseCell);
2765                 int value = vPC[3].u.operand;
2766                 unsigned offset = vPC[5].u.operand;
2767                 
2768                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(codeBlock(r)->identifiers[vPC[2].u.operand])) == offset);
2769                 baseObject->putDirectOffset(offset, r[value].jsValue(exec));
2770
2771                 vPC += 8;
2772                 NEXT_OPCODE;
2773             }
2774         }
2775
2776         uncachePutByID(codeBlock(r), vPC);
2777         NEXT_OPCODE;
2778     }
2779     BEGIN_OPCODE(op_put_by_id_generic) {
2780         /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
2781
2782            Generic property access: Sets the property named by identifier
2783            property, belonging to register base, to register value.
2784
2785            Unlike many opcodes, this one does not write any output to
2786            the register file.
2787         */
2788         int base = vPC[1].u.operand;
2789         int property = vPC[2].u.operand;
2790         int value = vPC[3].u.operand;
2791
2792         JSValue* baseValue = r[base].jsValue(exec);
2793         Identifier& ident = codeBlock(r)->identifiers[property];
2794         PutPropertySlot slot;
2795         baseValue->put(exec, ident, r[value].jsValue(exec), slot);
2796         VM_CHECK_EXCEPTION();
2797
2798         vPC += 8;
2799         NEXT_OPCODE;
2800     }
2801     BEGIN_OPCODE(op_del_by_id) {
2802         /* del_by_id dst(r) base(r) property(id)
2803
2804            Converts register base to Object, deletes the property
2805            named by identifier property from the object, and writes a
2806            boolean indicating success (if true) or failure (if false)
2807            to register dst.
2808         */
2809         int dst = (++vPC)->u.operand;
2810         int base = (++vPC)->u.operand;
2811         int property = (++vPC)->u.operand;
2812
2813         JSObject* baseObj = r[base].jsValue(exec)->toObject(exec);
2814         Identifier& ident = codeBlock(r)->identifiers[property];
2815         JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
2816         VM_CHECK_EXCEPTION();
2817         r[dst] = result;
2818         ++vPC;
2819         NEXT_OPCODE;
2820     }
2821     BEGIN_OPCODE(op_get_by_val) {
2822         /* get_by_val dst(r) base(r) property(r)
2823
2824            Converts register base to Object, gets the property named
2825            by register property from the object, and puts the result
2826            in register dst. property is nominally converted to string
2827            but numbers are treated more efficiently.
2828         */
2829         int dst = (++vPC)->u.operand;
2830         int base = (++vPC)->u.operand;
2831         int property = (++vPC)->u.operand;
2832         
2833         JSValue* baseValue = r[base].jsValue(exec);
2834         JSValue* subscript = r[property].jsValue(exec);
2835
2836         JSValue* result;
2837         unsigned i;
2838
2839         bool isUInt32 = JSImmediate::getUInt32(subscript, i);
2840         if (LIKELY(isUInt32)) {
2841             if (isJSArray(baseValue)) {
2842                 JSArray* jsArray = static_cast<JSArray*>(baseValue);
2843                 if (jsArray->canGetIndex(i))
2844                     result = jsArray->getIndex(i);
2845                 else
2846                     result = jsArray->JSArray::get(exec, i);
2847             } else if (isJSString(baseValue) && static_cast<JSString*>(baseValue)->canGetIndex(i))
2848                 result = static_cast<JSString*>(baseValue)->getIndex(&exec->globalData(), i);
2849             else
2850                 result = baseValue->get(exec, i);
2851         } else {
2852             Identifier property(exec, subscript->toString(exec));
2853             result = baseValue->get(exec, property);
2854         }
2855
2856         VM_CHECK_EXCEPTION();
2857         r[dst] = result;
2858         ++vPC;
2859         NEXT_OPCODE;
2860     }
2861     BEGIN_OPCODE(op_put_by_val) {
2862         /* put_by_val base(r) property(r) value(r)
2863
2864            Sets register value on register base as the property named
2865            by register property. Base is converted to object
2866            first. register property is nominally converted to string
2867            but numbers are treated more efficiently.
2868
2869            Unlike many opcodes, this one does not write any output to
2870            the register file.
2871         */
2872         int base = (++vPC)->u.operand;
2873         int property = (++vPC)->u.operand;
2874         int value = (++vPC)->u.operand;
2875
2876         JSValue* baseValue = r[base].jsValue(exec);
2877         JSValue* subscript = r[property].jsValue(exec);
2878
2879         unsigned i;
2880
2881         bool isUInt32 = JSImmediate::getUInt32(subscript, i);
2882         if (LIKELY(isUInt32)) {
2883             if (isJSArray(baseValue)) {
2884                 JSArray* jsArray = static_cast<JSArray*>(baseValue);
2885                 if (jsArray->canSetIndex(i))
2886                     jsArray->setIndex(i, r[value].jsValue(exec));
2887                 else
2888                     jsArray->JSArray::put(exec, i, r[value].jsValue(exec));
2889             } else
2890                 baseValue->put(exec, i, r[value].jsValue(exec));
2891         } else {
2892             Identifier property(exec, subscript->toString(exec));
2893             if (!exec->hadException()) { // Don't put to an object if toString threw an exception.
2894                 PutPropertySlot slot;
2895                 baseValue->put(exec, property, r[value].jsValue(exec), slot);
2896             }
2897         }
2898
2899         VM_CHECK_EXCEPTION();
2900         ++vPC;
2901         NEXT_OPCODE;
2902     }
2903     BEGIN_OPCODE(op_del_by_val) {
2904         /* del_by_val dst(r) base(r) property(r)
2905
2906            Converts register base to Object, deletes the property
2907            named by register property from the object, and writes a
2908            boolean indicating success (if true) or failure (if false)
2909            to register dst.
2910         */
2911         int dst = (++vPC)->u.operand;
2912         int base = (++vPC)->u.operand;
2913         int property = (++vPC)->u.operand;
2914
2915         JSObject* baseObj = r[base].jsValue(exec)->toObject(exec); // may throw
2916
2917         JSValue* subscript = r[property].jsValue(exec);
2918         JSValue* result;
2919         uint32_t i;
2920         if (subscript->getUInt32(i))
2921             result = jsBoolean(baseObj->deleteProperty(exec, i));
2922         else {
2923             VM_CHECK_EXCEPTION();
2924             Identifier property(exec, subscript->toString(exec));
2925             VM_CHECK_EXCEPTION();
2926             result = jsBoolean(baseObj->deleteProperty(exec, property));
2927         }
2928
2929         VM_CHECK_EXCEPTION();
2930         r[dst] = result;
2931         ++vPC;
2932         NEXT_OPCODE;
2933     }
2934     BEGIN_OPCODE(op_put_by_index) {
2935         /* put_by_index base(r) property(n) value(r)
2936
2937            Sets register value on register base as the property named
2938            by the immediate number property. Base is converted to
2939            object first.
2940
2941            Unlike many opcodes, this one does not write any output to
2942            the register file.
2943
2944            This opcode is mainly used to initialize array literals.
2945         */
2946         int base = (++vPC)->u.operand;
2947         unsigned property = (++vPC)->u.operand;
2948         int value = (++vPC)->u.operand;
2949
2950         r[base].jsValue(exec)->put(exec, property, r[value].jsValue(exec));
2951
2952         ++vPC;
2953         NEXT_OPCODE;
2954     }
2955     BEGIN_OPCODE(op_loop) {
2956         /* loop target(offset)
2957          
2958            Jumps unconditionally to offset target from the current
2959            instruction.
2960
2961            Additionally this loop instruction may terminate JS execution is
2962            the JS timeout is reached.
2963          */
2964 #if DUMP_OPCODE_STATS
2965         OpcodeStats::resetLastInstruction();
2966 #endif
2967         int target = (++vPC)->u.operand;
2968         CHECK_FOR_TIMEOUT();
2969         vPC += target;
2970         NEXT_OPCODE;
2971     }
2972     BEGIN_OPCODE(op_jmp) {
2973         /* jmp target(offset)
2974
2975            Jumps unconditionally to offset target from the current
2976            instruction.
2977         */
2978 #if DUMP_OPCODE_STATS
2979         OpcodeStats::resetLastInstruction();
2980 #endif
2981         int target = (++vPC)->u.operand;
2982
2983         vPC += target;
2984         NEXT_OPCODE;
2985     }
2986     BEGIN_OPCODE(op_loop_if_true) {
2987         /* loop_if_true cond(r) target(offset)
2988          
2989            Jumps to offset target from the current instruction, if and
2990            only if register cond converts to boolean as true.
2991
2992            Additionally this loop instruction may terminate JS execution is
2993            the JS timeout is reached.
2994          */
2995         int cond = (++vPC)->u.operand;
2996         int target = (++vPC)->u.operand;
2997         if (r[cond].jsValue(exec)->toBoolean(exec)) {
2998             vPC += target;
2999             CHECK_FOR_TIMEOUT();
3000             NEXT_OPCODE;
3001         }
3002         
3003         ++vPC;
3004         NEXT_OPCODE;
3005     }
3006     BEGIN_OPCODE(op_jtrue) {
3007         /* jtrue cond(r) target(offset)
3008
3009            Jumps to offset target from the current instruction, if and
3010            only if register cond converts to boolean as true.
3011         */
3012         int cond = (++vPC)->u.operand;
3013         int target = (++vPC)->u.operand;
3014         if (r[cond].jsValue(exec)->toBoolean(exec)) {
3015             vPC += target;
3016             NEXT_OPCODE;
3017         }
3018
3019         ++vPC;
3020         NEXT_OPCODE;
3021     }
3022     BEGIN_OPCODE(op_jfalse) {
3023         /* jfalse cond(r) target(offset)
3024
3025            Jumps to offset target from the current instruction, if and
3026            only if register cond converts to boolean as false.
3027         */
3028         int cond = (++vPC)->u.operand;
3029         int target = (++vPC)->u.operand;
3030         if (!r[cond].jsValue(exec)->toBoolean(exec)) {
3031             vPC += target;
3032             NEXT_OPCODE;
3033         }
3034
3035         ++vPC;
3036         NEXT_OPCODE;
3037     }
3038     BEGIN_OPCODE(op_loop_if_less) {
3039         /* loop_if_less src1(r) src2(r) target(offset)
3040
3041            Checks whether register src1 is less than register src2, as
3042            with the ECMAScript '<' operator, and then jumps to offset
3043            target from the current instruction, if and only if the 
3044            result of the comparison is true.
3045
3046            Additionally this loop instruction may terminate JS execution is
3047            the JS timeout is reached.
3048          */
3049         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
3050         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
3051         int target = (++vPC)->u.operand;
3052         
3053         bool result = jsLess(exec, src1, src2);
3054         VM_CHECK_EXCEPTION();
3055         
3056         if (result) {
3057             vPC += target;
3058             CHECK_FOR_TIMEOUT();
3059             NEXT_OPCODE;
3060         }
3061         
3062         ++vPC;
3063         NEXT_OPCODE;
3064     }
3065     BEGIN_OPCODE(op_loop_if_lesseq) {
3066         /* loop_if_lesseq src1(r) src2(r) target(offset)
3067
3068            Checks whether register src1 is less than or equal to register
3069            src2, as with the ECMAScript '<=' operator, and then jumps to
3070            offset target from the current instruction, if and only if the 
3071            result of the comparison is true.
3072
3073            Additionally this loop instruction may terminate JS execution is
3074            the JS timeout is reached.
3075         */
3076         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
3077         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
3078         int target = (++vPC)->u.operand;
3079         
3080         bool result = jsLessEq(exec, src1, src2);
3081         VM_CHECK_EXCEPTION();
3082         
3083         if (result) {
3084             vPC += target;
3085             CHECK_FOR_TIMEOUT();
3086             NEXT_OPCODE;
3087         }
3088         
3089         ++vPC;
3090         NEXT_OPCODE;
3091     }
3092     BEGIN_OPCODE(op_jnless) {
3093         /* jnless src1(r) src2(r) target(offset)
3094
3095            Checks whether register src1 is less than register src2, as
3096            with the ECMAScript '<' operator, and then jumps to offset
3097            target from the current instruction, if and only if the 
3098            result of the comparison is false.
3099         */
3100         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
3101         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
3102         int target = (++vPC)->u.operand;
3103
3104         bool result = jsLess(exec, src1, src2);
3105         VM_CHECK_EXCEPTION();
3106         
3107         if (!result) {
3108             vPC += target;
3109             NEXT_OPCODE;
3110         }
3111
3112         ++vPC;
3113         NEXT_OPCODE;
3114     }
3115     BEGIN_OPCODE(op_switch_imm) {
3116         /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
3117
3118            Performs a range checked switch on the scrutinee value, using
3119            the tableIndex-th immediate switch jump table.  If the scrutinee value
3120            is an immediate number in the range covered by the referenced jump
3121            table, and the value at jumpTable[scrutinee value] is non-zero, then
3122            that value is used as the jump offset, otherwise defaultOffset is used.
3123          */
3124         int tableIndex = (++vPC)->u.operand;
3125         int defaultOffset = (++vPC)->u.operand;
3126         JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
3127         if (!JSImmediate::isNumber(scrutinee))
3128             vPC += defaultOffset;
3129         else {
3130             int32_t value = JSImmediate::getTruncatedInt32(scrutinee);
3131             vPC += codeBlock(r)->immediateSwitchJumpTables[tableIndex].offsetForValue(value, defaultOffset);
3132         }
3133         NEXT_OPCODE;
3134     }
3135     BEGIN_OPCODE(op_switch_char) {
3136         /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
3137
3138            Performs a range checked switch on the scrutinee value, using
3139            the tableIndex-th character switch jump table.  If the scrutinee value
3140            is a single character string in the range covered by the referenced jump
3141            table, and the value at jumpTable[scrutinee value] is non-zero, then
3142            that value is used as the jump offset, otherwise defaultOffset is used.
3143          */
3144         int tableIndex = (++vPC)->u.operand;
3145         int defaultOffset = (++vPC)->u.operand;
3146         JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
3147         if (!scrutinee->isString())
3148             vPC += defaultOffset;
3149         else {
3150             UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
3151             if (value->size() != 1)
3152                 vPC += defaultOffset;
3153             else
3154                 vPC += codeBlock(r)->characterSwitchJumpTables[tableIndex].offsetForValue(value->data()[0], defaultOffset);
3155         }
3156         NEXT_OPCODE;
3157     }
3158     BEGIN_OPCODE(op_switch_string) {
3159         /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
3160
3161            Performs a sparse hashmap based switch on the value in the scrutinee
3162            register, using the tableIndex-th string switch jump table.  If the 
3163            scrutinee value is a string that exists as a key in the referenced 
3164            jump table, then the value associated with the string is used as the 
3165            jump offset, otherwise defaultOffset is used.
3166          */
3167         int tableIndex = (++vPC)->u.operand;
3168         int defaultOffset = (++vPC)->u.operand;
3169         JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
3170         if (!scrutinee->isString())
3171             vPC += defaultOffset;
3172         else 
3173             vPC += codeBlock(r)->stringSwitchJumpTables[tableIndex].offsetForValue(static_cast<JSString*>(scrutinee)->value().rep(), defaultOffset);
3174         NEXT_OPCODE;
3175     }
3176     BEGIN_OPCODE(op_new_func) {
3177         /* new_func dst(r) func(f)
3178
3179            Constructs a new Function instance from function func and
3180            the current scope chain using the original Function
3181            constructor, using the rules for function declarations, and
3182            puts the result in register dst.
3183         */
3184         int dst = (++vPC)->u.operand;
3185         int func = (++vPC)->u.operand;
3186
3187         r[dst] = codeBlock(r)->functions[func]->makeFunction(exec, scopeChain(r));
3188
3189         ++vPC;
3190         NEXT_OPCODE;
3191     }
3192     BEGIN_OPCODE(op_new_func_exp) {
3193         /* new_func_exp dst(r) func(f)
3194
3195            Constructs a new Function instance from function func and
3196            the current scope chain using the original Function
3197            constructor, using the rules for function expressions, and
3198            puts the result in register dst.
3199         */
3200         int dst = (++vPC)->u.operand;
3201         int func = (++vPC)->u.operand;
3202
3203         r[dst] = codeBlock(r)->functionExpressions[func]->makeFunction(exec, scopeChain(r));
3204
3205         ++vPC;
3206         NEXT_OPCODE;
3207     }
3208     BEGIN_OPCODE(op_call_eval) {
3209         /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
3210
3211            Call a function named "eval" with no explicit "this" value
3212            (which may therefore be the eval operator). If register
3213            thisVal is the global object, and register func contains
3214            that global object's original global eval function, then
3215            perform the eval operator in local scope (interpreting
3216            the argument registers as for the "call"
3217            opcode). Otherwise, act exactly as the "call" opcode would.
3218          */
3219
3220         int dst = (++vPC)->u.operand;
3221         int func = (++vPC)->u.operand;
3222         int thisVal = (++vPC)->u.operand;
3223         int firstArg = (++vPC)->u.operand;
3224         int argCount = (++vPC)->u.operand;
3225         ++vPC; // registerOffset
3226
3227         JSValue* funcVal = r[func].jsValue(exec);
3228         JSValue* baseVal = r[thisVal].jsValue(exec);
3229
3230         ScopeChainNode* scopeChain = this->scopeChain(r);
3231         if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
3232             JSObject* thisObject = static_cast<JSObject*>(r[codeBlock(r)->thisRegister].jsValue(exec));
3233             JSValue* result = callEval(exec, thisObject, scopeChain, registerFile, r, firstArg, argCount, exceptionValue);
3234             if (exceptionValue)
3235                 goto vm_throw;
3236
3237             r[dst] = result;
3238
3239             ++vPC;
3240             NEXT_OPCODE;
3241         }
3242
3243         // We didn't find the blessed version of eval, so reset vPC and process
3244         // this instruction as a normal function call, supplying the proper 'this'
3245         // value.
3246         vPC -= 6;
3247         r[thisVal] = baseVal->toThisObject(exec);
3248
3249 #if HAVE(COMPUTED_GOTO)
3250         // Hack around gcc performance quirk by performing an indirect goto
3251         // in order to set the vPC -- attempting to do so directly results in a
3252         // significant regression.
3253         goto *op_call_indirect; // indirect goto -> op_call
3254 #endif
3255         // fall through to op_call
3256     }
3257     BEGIN_OPCODE(op_call) {
3258         /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n) registerOffset(n)
3259
3260            Perform a function call. Specifically, call register func
3261            with a "this" value of register thisVal, and put the result
3262            in register dst.
3263
3264            The arguments start at register firstArg and go up to
3265            argCount, but the "this" value is considered an implicit
3266            first argument, so the argCount should be one greater than
3267            the number of explicit arguments passed, and the register
3268            after firstArg should contain the actual first
3269            argument. This opcode will copy from the thisVal register
3270            to the firstArg register, unless the register index of
3271            thisVal is the special missing this object marker, which is
3272            2^31-1; in that case, the global object will be used as the
3273            "this" value.
3274
3275            If func is a native code function, then this opcode calls
3276            it and returns the value immediately. 
3277
3278            But if it is a JS function, then the current scope chain
3279            and code block is set to the function's, and we slide the
3280            register window so that the arguments would form the first
3281            few local registers of the called function's register
3282            window. In addition, a call frame header is written
3283            immediately before the arguments; see the call frame
3284            documentation for an explanation of how many registers a
3285            call frame takes and what they contain. That many registers
3286            before the firstArg register will be overwritten by the
3287            call. In addition, any registers higher than firstArg +
3288            argCount may be overwritten. Once this setup is complete,
3289            execution continues from the called function's first
3290            argument, and does not return until a "ret" opcode is
3291            encountered.
3292          */
3293
3294         int dst = (++vPC)->u.operand;
3295         int func = (++vPC)->u.operand;
3296         int thisVal = (++vPC)->u.operand;
3297         int firstArg = (++vPC)->u.operand;
3298         int argCount = (++vPC)->u.operand;
3299         int registerOffset = (++vPC)->u.operand;
3300
3301         JSValue* v = r[func].jsValue(exec);
3302
3303         CallData callData;
3304         CallType callType = v->getCallData(callData);
3305
3306         if (callType == CallTypeJS) {
3307             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
3308             FunctionBodyNode* functionBodyNode = callData.js.functionBody;
3309             CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
3310
3311             r[firstArg] = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
3312             
3313             Register* savedR = r;
3314
3315             r = slideRegisterWindowForCall(newCodeBlock, registerFile, r, registerOffset, argCount);
3316             if (UNLIKELY(!r)) {
3317                 r = savedR;
3318                 exceptionValue = createStackOverflowError(CallFrame::create(r));
3319                 goto vm_throw;
3320             }
3321
3322             initializeCallFrame(r, newCodeBlock, vPC + 1, callDataScopeChain, savedR, dst, argCount, v);
3323     
3324             if (*enabledProfilerReference)
3325                 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
3326
3327             vPC = newCodeBlock->instructions.begin();
3328
3329 #if DUMP_OPCODE_STATS
3330             OpcodeStats::resetLastInstruction();
3331 #endif
3332
3333             NEXT_OPCODE;
3334         }
3335
3336         if (callType == CallTypeHost) {
3337             JSValue* thisValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
3338             ArgList args(r + firstArg + 1, argCount - 1);
3339
3340             ScopeChainNode* scopeChain = this->scopeChain(r);
3341             initializeCallFrame(r + registerOffset, 0, vPC + 1, scopeChain, r, dst, argCount, v);
3342             ExecState* callFrame = CallFrame::create(r + registerOffset);
3343
3344             if (*enabledProfilerReference)
3345                 (*enabledProfilerReference)->willExecute(callFrame, static_cast<JSObject*>(v));
3346
3347             MACHINE_SAMPLING_callingHostFunction();
3348
3349             JSValue* returnValue = callData.native.function(callFrame, static_cast<JSObject*>(v), thisValue, args);
3350             VM_CHECK_EXCEPTION();
3351
3352             r[dst] = returnValue;
3353
3354             if (*enabledProfilerReference)
3355                 (*enabledProfilerReference)->didExecute(CallFrame::create(r), static_cast<JSObject*>(v));
3356
3357             ++vPC;
3358             NEXT_OPCODE;
3359         }
3360
3361         ASSERT(callType == CallTypeNone);
3362
3363         exceptionValue = createNotAFunctionError(exec, v, vPC, codeBlock(r));
3364         goto vm_throw;
3365     }
3366     BEGIN_OPCODE(op_tear_off_activation) {
3367         int src = (++vPC)->u.operand;
3368         JSActivation* activation = static_cast<JSActivation*>(r[src].getJSValue());
3369         ASSERT(codeBlock(r)->needsFullScopeChain);
3370         ASSERT(activation->isObject(&JSActivation::info));
3371
3372         Arguments* arguments = static_cast<Arguments*>(r[RegisterFile::OptionalCalleeArguments].getJSValue());
3373         ASSERT(!arguments || arguments->isObject(&Arguments::info));
3374         activation->copyRegisters(arguments);
3375
3376         ++vPC;
3377         NEXT_OPCODE;
3378     }
3379     BEGIN_OPCODE(op_tear_off_arguments) {
3380         Arguments* arguments = static_cast<Arguments*>(r[RegisterFile::OptionalCalleeArguments].getJSValue());
3381         ASSERT(codeBlock(r)->usesArguments && !codeBlock(r)->needsFullScopeChain);
3382         ASSERT(arguments->isObject(&Arguments::info));
3383
3384         arguments->copyRegisters();
3385
3386         ++vPC;
3387         NEXT_OPCODE;
3388     }
3389     BEGIN_OPCODE(op_ret) {
3390         /* ret result(r)
3391            
3392            Return register result as the return value of the current
3393            function call, writing it into the caller's expected return
3394            value register. In addition, unwind one call frame and
3395            restore the scope chain, code block instruction pointer and
3396            register base to those of the calling function.
3397         */
3398
3399         int result = (++vPC)->u.operand;
3400
3401         if (*enabledProfilerReference)
3402             (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(r[RegisterFile::Callee].jsValue(exec)));
3403
3404         if (codeBlock(r)->needsFullScopeChain)
3405             scopeChain(r)->deref();
3406
3407         JSValue* returnValue = r[result].jsValue(exec);
3408
3409         vPC = r[RegisterFile::ReturnPC].vPC();
3410         int dst = r[RegisterFile::ReturnValueRegister].i();
3411         r = r[RegisterFile::CallerRegisters].r();
3412         
3413         if (isHostCallFrame(r))
3414             return returnValue;
3415
3416         r[dst] = returnValue;
3417
3418         NEXT_OPCODE;
3419     }
3420     BEGIN_OPCODE(op_enter) {
3421         /* enter
3422
3423            Initializes local variables to undefined and fills constant
3424            registers with their values. If the code block requires an
3425            activation, enter_with_activation should be used instead.
3426
3427            This opcode should only be used at the beginning of a code
3428            block.
3429         */
3430
3431         size_t i = 0;
3432         CodeBlock* codeBlock = this->codeBlock(r);
3433         
3434         for (size_t count = codeBlock->numVars; i < count; ++i)
3435             r[i] = jsUndefined();
3436
3437         for (size_t count = codeBlock->constantRegisters.size(), j = 0; j < count; ++i, ++j)
3438             r[i] = codeBlock->constantRegisters[j];
3439
3440         ++vPC;
3441         NEXT_OPCODE;
3442     }
3443     BEGIN_OPCODE(op_enter_with_activation) {
3444         /* enter_with_activation dst(r)
3445
3446            Initializes local variables to undefined, fills constant
3447            registers with their values, creates an activation object,
3448            and places the new activation both in dst and at the top
3449            of the scope chain. If the code block does not require an
3450            activation, enter should be used instead.
3451
3452            This opcode should only be used at the beginning of a code
3453            block.
3454         */
3455
3456         size_t i = 0;
3457         CodeBlock* codeBlock = this->codeBlock(r);
3458
3459         for (size_t count = codeBlock->numVars; i < count; ++i)
3460             r[i] = jsUndefined();
3461
3462         for (size_t count = codeBlock->constantRegisters.size(), j = 0; j < count; ++i, ++j)
3463             r[i] = codeBlock->constantRegisters[j];
3464
3465         int dst = (++vPC)->u.operand;
3466         JSActivation* activation = new (globalData) JSActivation(exec, static_cast<FunctionBodyNode*>(codeBlock->ownerNode), r);
3467         r[dst] = activation;
3468         r[RegisterFile::ScopeChain] = scopeChain(r)->copy()->push(activation);
3469
3470         ++vPC;
3471         NEXT_OPCODE;
3472     }
3473     BEGIN_OPCODE(op_convert_this) {
3474         int thisRegister = (++vPC)->u.operand;
3475         JSValue* thisVal = r[thisRegister].getJSValue();
3476         if (thisVal->needsThisConversion())
3477             r[thisRegister] = thisVal->toThisObject(exec);
3478
3479         ++vPC;
3480         NEXT_OPCODE;
3481     }
3482     BEGIN_OPCODE(op_create_arguments) {
3483         /* create_arguments
3484
3485            Creates the 'arguments' object and places it in both the
3486            'arguments' call frame slot and the local 'arguments'
3487            register.
3488
3489            This opcode should only be used at the beginning of a code
3490            block.
3491         */
3492
3493         Arguments* arguments = new (globalData) Arguments(exec, r);
3494         r[RegisterFile::OptionalCalleeArguments] = arguments;
3495         r[RegisterFile::ArgumentsRegister] = arguments;
3496         
3497         ++vPC;
3498         NEXT_OPCODE;
3499     }
3500     BEGIN_OPCODE(op_construct) {
3501         /* construct dst(r) constr(r) constrProto(r) firstArg(r) argCount(n) registerOffset(n)
3502
3503            Invoke register "constr" as a constructor. For JS
3504            functions, the calling convention is exactly as for the
3505            "call" opcode, except that the "this" value is a newly
3506            created Object. For native constructors, a null "this"
3507            value is passed. In either case, the firstArg and argCount
3508            registers are interpreted as for the "call" opcode.
3509
3510            Register constrProto must contain the prototype property of
3511            register constsr. This is to enable polymorphic inline
3512            caching of this lookup.
3513         */
3514
3515         int dst = (++vPC)->u.operand;
3516         int constr = (++vPC)->u.operand;
3517         int constrProto = (++vPC)->u.operand;
3518         int firstArg = (++vPC)->u.operand;
3519         int argCount = (++vPC)->u.operand;
3520         int registerOffset = (++vPC)->u.operand;
3521