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