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