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