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