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