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