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