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