d31ae42672c073acc788ca1e0fc8a054b726d500
[WebKit-https.git] / Source / JavaScriptCore / interpreter / Interpreter.cpp
1 /*
2  * Copyright (C) 2008, 2009, 2010 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 "CallFrame.h"
36 #include "CallFrameClosure.h"
37 #include "CodeBlock.h"
38 #include "Heap.h"
39 #include "Debugger.h"
40 #include "DebuggerCallFrame.h"
41 #include "ErrorInstance.h"
42 #include "EvalCodeCache.h"
43 #include "ExceptionHelpers.h"
44 #include "GetterSetter.h"
45 #include "JSActivation.h"
46 #include "JSArray.h"
47 #include "JSBoundFunction.h"
48 #include "JSNotAnObject.h"
49 #include "JSPropertyNameIterator.h"
50 #include "LiteralParser.h"
51 #include "JSStaticScopeObject.h"
52 #include "JSString.h"
53 #include "ObjectPrototype.h"
54 #include "Operations.h"
55 #include "Parser.h"
56 #include "Profiler.h"
57 #include "RegExpObject.h"
58 #include "RegExpPrototype.h"
59 #include "Register.h"
60 #include "SamplingTool.h"
61 #include "StrictEvalActivation.h"
62 #include "StrongInlines.h"
63 #include "UStringConcatenate.h"
64 #include <limits.h>
65 #include <stdio.h>
66 #include <wtf/Threading.h>
67 #include <wtf/text/StringBuilder.h>
68
69 #if ENABLE(JIT)
70 #include "JIT.h"
71 #endif
72
73 #define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND ((ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)) && !defined(__llvm__))
74
75 using namespace std;
76
77 namespace JSC {
78
79 // Returns the depth of the scope chain within a given call frame.
80 static int depth(CodeBlock* codeBlock, ScopeChainNode* sc)
81 {
82     if (!codeBlock->needsFullScopeChain())
83         return 0;
84     return sc->localDepth();
85 }
86
87 #if ENABLE(CLASSIC_INTERPRETER) 
88 static NEVER_INLINE JSValue concatenateStrings(ExecState* exec, Register* strings, unsigned count)
89 {
90     return jsString(exec, strings, count);
91 }
92
93 NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
94 {
95     int dst = vPC[1].u.operand;
96     int property = vPC[2].u.operand;
97
98     ScopeChainNode* scopeChain = callFrame->scopeChain();
99     ScopeChainIterator iter = scopeChain->begin();
100     ScopeChainIterator end = scopeChain->end();
101     ASSERT(iter != end);
102
103     CodeBlock* codeBlock = callFrame->codeBlock();
104     Identifier& ident = codeBlock->identifier(property);
105     do {
106         JSObject* o = iter->get();
107         PropertySlot slot(o);
108         if (o->getPropertySlot(callFrame, ident, slot)) {
109             JSValue result = slot.getValue(callFrame, ident);
110             exceptionValue = callFrame->globalData().exception;
111             if (exceptionValue)
112                 return false;
113             callFrame->uncheckedR(dst) = JSValue(result);
114             return true;
115         }
116     } while (++iter != end);
117     exceptionValue = createUndefinedVariableError(callFrame, ident);
118     return false;
119 }
120
121 NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
122 {
123     CodeBlock* codeBlock = callFrame->codeBlock();
124
125     int dst = vPC[1].u.operand;
126     int property = vPC[2].u.operand;
127     int skip = vPC[3].u.operand;
128
129     ScopeChainNode* scopeChain = callFrame->scopeChain();
130     ScopeChainIterator iter = scopeChain->begin();
131     ScopeChainIterator end = scopeChain->end();
132     ASSERT(iter != end);
133     bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
134     ASSERT(skip || !checkTopLevel);
135     if (checkTopLevel && skip--) {
136         if (callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
137             ++iter;
138     }
139     while (skip--) {
140         ++iter;
141         ASSERT(iter != end);
142     }
143     Identifier& ident = codeBlock->identifier(property);
144     do {
145         JSObject* o = iter->get();
146         PropertySlot slot(o);
147         if (o->getPropertySlot(callFrame, ident, slot)) {
148             JSValue result = slot.getValue(callFrame, ident);
149             exceptionValue = callFrame->globalData().exception;
150             if (exceptionValue)
151                 return false;
152             ASSERT(result);
153             callFrame->uncheckedR(dst) = JSValue(result);
154             return true;
155         }
156     } while (++iter != end);
157     exceptionValue = createUndefinedVariableError(callFrame, ident);
158     return false;
159 }
160
161 NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
162 {
163     int dst = vPC[1].u.operand;
164     CodeBlock* codeBlock = callFrame->codeBlock();
165     JSGlobalObject* globalObject = codeBlock->globalObject();
166     ASSERT(globalObject->isGlobalObject());
167     int property = vPC[2].u.operand;
168     Structure* structure = vPC[3].u.structure.get();
169     int offset = vPC[4].u.operand;
170
171     if (structure == globalObject->structure()) {
172         callFrame->uncheckedR(dst) = JSValue(globalObject->getDirectOffset(offset));
173         return true;
174     }
175
176     Identifier& ident = codeBlock->identifier(property);
177     PropertySlot slot(globalObject);
178     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
179         JSValue result = slot.getValue(callFrame, ident);
180         if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
181             vPC[3].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
182             vPC[4] = slot.cachedOffset();
183             callFrame->uncheckedR(dst) = JSValue(result);
184             return true;
185         }
186
187         exceptionValue = callFrame->globalData().exception;
188         if (exceptionValue)
189             return false;
190         callFrame->uncheckedR(dst) = JSValue(result);
191         return true;
192     }
193
194     exceptionValue = createUndefinedVariableError(callFrame, ident);
195     return false;
196 }
197
198 NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
199 {
200     int dst = vPC[1].u.operand;
201     CodeBlock* codeBlock = callFrame->codeBlock();
202     JSGlobalObject* globalObject = codeBlock->globalObject();
203     ASSERT(globalObject->isGlobalObject());
204     int property = vPC[2].u.operand;
205     Structure* structure = vPC[3].u.structure.get();
206     int offset = vPC[4].u.operand;
207     int skip = vPC[5].u.operand;
208     
209     ScopeChainNode* scopeChain = callFrame->scopeChain();
210     ScopeChainIterator iter = scopeChain->begin();
211     ScopeChainIterator end = scopeChain->end();
212     ASSERT(iter != end);
213     bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
214     ASSERT(skip || !checkTopLevel);
215     if (checkTopLevel && skip--) {
216         if (callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
217             ++iter;
218     }
219     while (skip--) {
220         JSObject* o = iter->get();
221         if (o->hasCustomProperties()) {
222             Identifier& ident = codeBlock->identifier(property);
223             do {
224                 PropertySlot slot(o);
225                 if (o->getPropertySlot(callFrame, ident, slot)) {
226                     JSValue result = slot.getValue(callFrame, ident);
227                     exceptionValue = callFrame->globalData().exception;
228                     if (exceptionValue)
229                         return false;
230                     ASSERT(result);
231                     callFrame->uncheckedR(dst) = JSValue(result);
232                     return true;
233                 }
234                 if (iter == end)
235                     break;
236                 o = iter->get();
237                 ++iter;
238             } while (true);
239             exceptionValue = createUndefinedVariableError(callFrame, ident);
240             return false;
241         }
242         ++iter;
243     }
244     
245     if (structure == globalObject->structure()) {
246         callFrame->uncheckedR(dst) = JSValue(globalObject->getDirectOffset(offset));
247         ASSERT(callFrame->uncheckedR(dst).jsValue());
248         return true;
249     }
250
251     Identifier& ident = codeBlock->identifier(property);
252     PropertySlot slot(globalObject);
253     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
254         JSValue result = slot.getValue(callFrame, ident);
255         if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
256             vPC[3].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
257             vPC[4] = slot.cachedOffset();
258             ASSERT(result);
259             callFrame->uncheckedR(dst) = JSValue(result);
260             return true;
261         }
262         
263         exceptionValue = callFrame->globalData().exception;
264         if (exceptionValue)
265             return false;
266         ASSERT(result);
267         callFrame->uncheckedR(dst) = JSValue(result);
268         return true;
269     }
270     
271     exceptionValue = createUndefinedVariableError(callFrame, ident);
272     return false;
273 }
274
275 NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC)
276 {
277     int dst = vPC[1].u.operand;
278     int property = vPC[2].u.operand;
279     bool isStrictPut = vPC[3].u.operand;
280     Identifier ident = callFrame->codeBlock()->identifier(property);
281     JSValue result = JSC::resolveBase(callFrame, ident, callFrame->scopeChain(), isStrictPut);
282     if (result) {
283         callFrame->uncheckedR(dst) = result;
284         ASSERT(callFrame->uncheckedR(dst).jsValue());
285     } else
286         callFrame->globalData().exception = createErrorForInvalidGlobalAssignment(callFrame, ident.ustring());
287 }
288
289 NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
290 {
291     int baseDst = vPC[1].u.operand;
292     int propDst = vPC[2].u.operand;
293     int property = vPC[3].u.operand;
294
295     ScopeChainNode* scopeChain = callFrame->scopeChain();
296     ScopeChainIterator iter = scopeChain->begin();
297     ScopeChainIterator end = scopeChain->end();
298
299     // FIXME: add scopeDepthIsZero optimization
300
301     ASSERT(iter != end);
302
303     CodeBlock* codeBlock = callFrame->codeBlock();
304     Identifier& ident = codeBlock->identifier(property);
305     JSObject* base;
306     do {
307         base = iter->get();
308         PropertySlot slot(base);
309         if (base->getPropertySlot(callFrame, ident, slot)) {
310             JSValue result = slot.getValue(callFrame, ident);
311             exceptionValue = callFrame->globalData().exception;
312             if (exceptionValue)
313                 return false;
314             callFrame->uncheckedR(propDst) = JSValue(result);
315             callFrame->uncheckedR(baseDst) = JSValue(base);
316             return true;
317         }
318         ++iter;
319     } while (iter != end);
320
321     exceptionValue = createUndefinedVariableError(callFrame, ident);
322     return false;
323 }
324
325 NEVER_INLINE bool Interpreter::resolveThisAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
326 {
327     int thisDst = vPC[1].u.operand;
328     int propDst = vPC[2].u.operand;
329     int property = vPC[3].u.operand;
330
331     ScopeChainNode* scopeChain = callFrame->scopeChain();
332     ScopeChainIterator iter = scopeChain->begin();
333     ScopeChainIterator end = scopeChain->end();
334
335     // FIXME: add scopeDepthIsZero optimization
336
337     ASSERT(iter != end);
338
339     CodeBlock* codeBlock = callFrame->codeBlock();
340     Identifier& ident = codeBlock->identifier(property);
341     JSObject* base;
342     do {
343         base = iter->get();
344         ++iter;
345         PropertySlot slot(base);
346         if (base->getPropertySlot(callFrame, ident, slot)) {
347             JSValue result = slot.getValue(callFrame, ident);
348             exceptionValue = callFrame->globalData().exception;
349             if (exceptionValue)
350                 return false;
351             callFrame->uncheckedR(propDst) = JSValue(result);
352             // All entries on the scope chain should be EnvironmentRecords (activations etc),
353             // other then 'with' object, which are directly referenced from the scope chain,
354             // and the global object. If we hit either an EnvironmentRecord or a global
355             // object at the end of the scope chain, this is undefined. If we hit a non-
356             // EnvironmentRecord within the scope chain, pass the base as the this value.
357             if (iter == end || base->structure()->typeInfo().isEnvironmentRecord())
358                 callFrame->uncheckedR(thisDst) = jsUndefined();
359             else
360                 callFrame->uncheckedR(thisDst) = JSValue(base);
361             return true;
362         }
363     } while (iter != end);
364
365     exceptionValue = createUndefinedVariableError(callFrame, ident);
366     return false;
367 }
368
369 #endif // ENABLE(CLASSIC_INTERPRETER)
370
371 ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argumentCountIncludingThis)
372 {
373     // This ensures enough space for the worst case scenario of zero arguments passed by the caller.
374     if (!registerFile->grow(callFrame->registers() + registerOffset + newCodeBlock->numParameters() + newCodeBlock->m_numCalleeRegisters))
375         return 0;
376
377     if (argumentCountIncludingThis >= newCodeBlock->numParameters()) {
378         Register* newCallFrame = callFrame->registers() + registerOffset;
379         return CallFrame::create(newCallFrame);
380     }
381
382     // Too few arguments -- copy arguments, then fill in missing arguments with undefined.
383     size_t delta = newCodeBlock->numParameters() - argumentCountIncludingThis;
384     CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset + delta);
385
386     Register* dst = &newCallFrame->uncheckedR(CallFrame::thisArgumentOffset());
387     Register* end = dst - argumentCountIncludingThis;
388     for ( ; dst != end; --dst)
389         *dst = *(dst - delta);
390
391     end -= delta;
392     for ( ; dst != end; --dst)
393         *dst = jsUndefined();
394
395     return newCallFrame;
396 }
397
398 #if ENABLE(CLASSIC_INTERPRETER)
399 static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, JSValue value, JSValue& exceptionData)
400 {
401     if (value.isObject())
402         return false;
403     exceptionData = createInvalidParamError(callFrame, "in" , value);
404     return true;
405 }
406
407 static NEVER_INLINE bool isInvalidParamForInstanceOf(CallFrame* callFrame, JSValue value, JSValue& exceptionData)
408 {
409     if (value.isObject() && asObject(value)->structure()->typeInfo().implementsHasInstance())
410         return false;
411     exceptionData = createInvalidParamError(callFrame, "instanceof" , value);
412     return true;
413 }
414 #endif
415
416 JSValue eval(CallFrame* callFrame)
417 {
418     if (!callFrame->argumentCount())
419         return jsUndefined();
420
421     JSValue program = callFrame->argument(0);
422     if (!program.isString())
423         return program;
424     
425     TopCallFrameSetter topCallFrame(callFrame->globalData(), callFrame);
426     UString programSource = asString(program)->value(callFrame);
427     if (callFrame->hadException())
428         return JSValue();
429     
430     CallFrame* callerFrame = callFrame->callerFrame();
431     CodeBlock* callerCodeBlock = callerFrame->codeBlock();
432     ScopeChainNode* callerScopeChain = callerFrame->scopeChain();
433     EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(callerCodeBlock->isStrictMode(), programSource, callerScopeChain);
434
435     if (!eval) {
436         if (!callerCodeBlock->isStrictMode()) {
437             // FIXME: We can use the preparser in strict mode, we just need additional logic
438             // to prevent duplicates.
439             if (programSource.is8Bit()) {
440                 LiteralParser<LChar> preparser(callFrame, programSource.characters8(), programSource.length(), NonStrictJSON);
441                 if (JSValue parsedObject = preparser.tryLiteralParse())
442                     return parsedObject;
443             } else {
444                 LiteralParser<UChar> preparser(callFrame, programSource.characters16(), programSource.length(), NonStrictJSON);
445                 if (JSValue parsedObject = preparser.tryLiteralParse())
446                     return parsedObject;                
447             }
448         }
449
450         JSValue exceptionValue;
451         eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->ownerExecutable(), callerCodeBlock->isStrictMode(), programSource, callerScopeChain, exceptionValue);
452         
453         ASSERT(!eval == exceptionValue);
454         if (UNLIKELY(!eval))
455             return throwError(callFrame, exceptionValue);
456     }
457
458     JSValue thisValue = callerFrame->thisValue();
459     ASSERT(isValidThisObject(thisValue, callFrame));
460     Interpreter* interpreter = callFrame->globalData().interpreter;
461     return interpreter->execute(eval, callFrame, thisValue, callerScopeChain, callFrame->registers() - interpreter->registerFile().begin() + 1 + RegisterFile::CallFrameHeaderSize);
462 }
463
464 CallFrame* loadVarargs(CallFrame* callFrame, RegisterFile* registerFile, JSValue thisValue, JSValue arguments, int firstFreeRegister)
465 {
466     if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
467         unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
468         CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize);
469         if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !registerFile->grow(newCallFrame->registers())) {
470             callFrame->globalData().exception = createStackOverflowError(callFrame);
471             return 0;
472         }
473
474         newCallFrame->setArgumentCountIncludingThis(argumentCountIncludingThis);
475         newCallFrame->setThisValue(thisValue);
476         for (size_t i = 0; i < callFrame->argumentCount(); ++i)
477             newCallFrame->setArgument(i, callFrame->argument(i));
478         return newCallFrame;
479     }
480
481     if (arguments.isUndefinedOrNull()) {
482         CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + 1 + RegisterFile::CallFrameHeaderSize);
483         if (!registerFile->grow(newCallFrame->registers())) {
484             callFrame->globalData().exception = createStackOverflowError(callFrame);
485             return 0;
486         }
487         newCallFrame->setArgumentCountIncludingThis(1);
488         newCallFrame->setThisValue(thisValue);
489         return newCallFrame;
490     }
491
492     if (!arguments.isObject()) {
493         callFrame->globalData().exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
494         return 0;
495     }
496
497     if (asObject(arguments)->classInfo() == &Arguments::s_info) {
498         Arguments* argsObject = asArguments(arguments);
499         unsigned argCount = argsObject->length(callFrame);
500         CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
501         if (argCount > Arguments::MaxArguments || !registerFile->grow(newCallFrame->registers())) {
502             callFrame->globalData().exception = createStackOverflowError(callFrame);
503             return 0;
504         }
505         newCallFrame->setArgumentCountIncludingThis(argCount + 1);
506         newCallFrame->setThisValue(thisValue);
507         argsObject->copyToArguments(callFrame, newCallFrame, argCount);
508         return newCallFrame;
509     }
510
511     if (isJSArray(arguments)) {
512         JSArray* array = asArray(arguments);
513         unsigned argCount = array->length();
514         CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
515         if (argCount > Arguments::MaxArguments || !registerFile->grow(newCallFrame->registers())) {
516             callFrame->globalData().exception = createStackOverflowError(callFrame);
517             return 0;
518         }
519         newCallFrame->setArgumentCountIncludingThis(argCount + 1);
520         newCallFrame->setThisValue(thisValue);
521         array->copyToArguments(callFrame, newCallFrame, argCount);
522         return newCallFrame;
523     }
524
525     JSObject* argObject = asObject(arguments);
526     unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
527     CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
528     if (argCount > Arguments::MaxArguments || !registerFile->grow(newCallFrame->registers())) {
529         callFrame->globalData().exception = createStackOverflowError(callFrame);
530         return 0;
531     }
532     newCallFrame->setArgumentCountIncludingThis(argCount + 1);
533     newCallFrame->setThisValue(thisValue);
534     for (size_t i = 0; i < argCount; ++i) {
535         newCallFrame->setArgument(i, asObject(arguments)->get(callFrame, i));
536         if (UNLIKELY(callFrame->globalData().exception))
537             return 0;
538     }
539     return newCallFrame;
540 }
541
542 Interpreter::Interpreter()
543     : m_sampleEntryDepth(0)
544     , m_reentryDepth(0)
545 #if !ASSERT_DISABLED
546     , m_initialized(false)
547 #endif
548     , m_classicEnabled(false)
549 {
550 }
551
552 Interpreter::~Interpreter()
553 {
554 #if ENABLE(LLINT)
555     if (m_classicEnabled)
556         delete[] m_opcodeTable;
557 #endif
558 }
559
560 void Interpreter::initialize(LLInt::Data* llintData, bool canUseJIT)
561 {
562     UNUSED_PARAM(llintData);
563     UNUSED_PARAM(canUseJIT);
564
565     // If we have LLInt, then we shouldn't be building any kind of classic interpreter.
566 #if ENABLE(LLINT) && ENABLE(CLASSIC_INTERPRETER)
567 #error "Building both LLInt and the Classic Interpreter is not supported because it doesn't make sense."
568 #endif
569
570 #if ENABLE(LLINT)
571     m_opcodeTable = llintData->opcodeMap();
572     for (int i = 0; i < numOpcodeIDs; ++i)
573         m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
574     m_classicEnabled = false;
575 #elif ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
576     if (canUseJIT) {
577         // If the JIT is present, don't use jump destinations for opcodes.
578         
579         for (int i = 0; i < numOpcodeIDs; ++i) {
580             Opcode opcode = bitwise_cast<void*>(static_cast<uintptr_t>(i));
581             m_opcodeTable[i] = opcode;
582         }
583         m_classicEnabled = false;
584     } else {
585         privateExecute(InitializeAndReturn, 0, 0);
586         
587         for (int i = 0; i < numOpcodeIDs; ++i)
588             m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
589         
590         m_classicEnabled = true;
591     }
592 #else
593 #if ENABLE(CLASSIC_INTERPRETER)
594     m_classicEnabled = true;
595 #else
596     m_classicEnabled = false;
597 #endif
598 #endif // ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
599 #if !ASSERT_DISABLED
600     m_initialized = true;
601 #endif
602
603 #if ENABLE(OPCODE_SAMPLING)
604     enableSampler();
605 #endif
606 }
607
608 #ifndef NDEBUG
609
610 void Interpreter::dumpCallFrame(CallFrame* callFrame)
611 {
612     callFrame->codeBlock()->dump(callFrame);
613     dumpRegisters(callFrame);
614 }
615
616 void Interpreter::dumpRegisters(CallFrame* callFrame)
617 {
618     dataLog("Register frame: \n\n");
619     dataLog("-----------------------------------------------------------------------------\n");
620     dataLog("            use            |   address  |                value               \n");
621     dataLog("-----------------------------------------------------------------------------\n");
622
623     CodeBlock* codeBlock = callFrame->codeBlock();
624     const Register* it;
625     const Register* end;
626     JSValue v;
627
628     it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->numParameters();
629     v = (*it).jsValue();
630 #if USE(JSVALUE32_64)
631     dataLog("[this]                     | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); ++it;
632 #else
633     dataLog("[this]                     | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); ++it;
634 #endif
635     end = it + max(codeBlock->numParameters() - 1, 0); // - 1 to skip "this"
636     if (it != end) {
637         do {
638             v = (*it).jsValue();
639 #if USE(JSVALUE32_64)
640             dataLog("[param]                    | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
641 #else
642             dataLog("[param]                    | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
643 #endif
644             ++it;
645         } while (it != end);
646     }
647     dataLog("-----------------------------------------------------------------------------\n");
648     dataLog("[CodeBlock]                | %10p | %p \n", it, (*it).codeBlock()); ++it;
649     dataLog("[ScopeChain]               | %10p | %p \n", it, (*it).scopeChain()); ++it;
650     dataLog("[CallerRegisters]          | %10p | %d \n", it, (*it).i()); ++it;
651     dataLog("[ReturnPC]                 | %10p | %p \n", it, (*it).vPC()); ++it;
652     dataLog("[ArgumentCount]            | %10p | %d \n", it, (*it).i()); ++it;
653     dataLog("[Callee]                   | %10p | %p \n", it, (*it).function()); ++it;
654     dataLog("-----------------------------------------------------------------------------\n");
655
656     int registerCount = 0;
657
658     end = it + codeBlock->m_numVars;
659     if (it != end) {
660         do {
661             v = (*it).jsValue();
662 #if USE(JSVALUE32_64)
663             dataLog("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
664 #else
665             dataLog("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
666 #endif
667             ++it;
668             ++registerCount;
669         } while (it != end);
670     }
671     dataLog("-----------------------------------------------------------------------------\n");
672
673     end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars;
674     if (it != end) {
675         do {
676             v = (*it).jsValue();
677 #if USE(JSVALUE32_64)
678             dataLog("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
679 #else
680             dataLog("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
681 #endif
682             ++it;
683             ++registerCount;
684         } while (it != end);
685     }
686     dataLog("-----------------------------------------------------------------------------\n");
687 }
688
689 #endif
690
691 bool Interpreter::isOpcode(Opcode opcode)
692 {
693 #if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
694 #if !ENABLE(LLINT)
695     if (!m_classicEnabled)
696         return opcode >= 0 && static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)) <= op_end;
697 #endif
698     return opcode != HashTraits<Opcode>::emptyValue()
699         && !HashTraits<Opcode>::isDeletedValue(opcode)
700         && m_opcodeIDTable.contains(opcode);
701 #else
702     return opcode >= 0 && opcode <= op_end;
703 #endif
704 }
705
706 NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
707 {
708     CodeBlock* oldCodeBlock = codeBlock;
709     ScopeChainNode* scopeChain = callFrame->scopeChain();
710
711     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
712         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
713         if (callFrame->callee())
714             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
715         else
716             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
717     }
718
719     // If this call frame created an activation or an 'arguments' object, tear it off.
720     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
721         if (!callFrame->uncheckedR(oldCodeBlock->activationRegister()).jsValue()) {
722             oldCodeBlock->createActivation(callFrame);
723             scopeChain = callFrame->scopeChain();
724         }
725         while (!scopeChain->object->inherits(&JSActivation::s_info))
726             scopeChain = scopeChain->pop();
727
728         callFrame->setScopeChain(scopeChain);
729         JSActivation* activation = asActivation(scopeChain->object.get());
730         activation->tearOff(*scopeChain->globalData);
731         if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue())
732             asArguments(arguments)->didTearOffActivation(callFrame->globalData(), activation);
733     } else if (oldCodeBlock->usesArguments() && !oldCodeBlock->isStrictMode()) {
734         if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue())
735             asArguments(arguments)->tearOff(callFrame);
736     }
737
738     CallFrame* callerFrame = callFrame->callerFrame();
739     callFrame->globalData().topCallFrame = callerFrame;
740     if (callerFrame->hasHostCallFrameFlag())
741         return false;
742
743     codeBlock = callerFrame->codeBlock();
744     
745     // Because of how the JIT records call site->bytecode offset
746     // information the JIT reports the bytecodeOffset for the returnPC
747     // to be at the beginning of the opcode that has caused the call.
748     // In the interpreter we have an actual return address, which is
749     // the beginning of next instruction to execute. To get an offset
750     // inside the call instruction that triggered the exception we
751     // have to subtract 1.
752 #if ENABLE(JIT) && ENABLE(CLASSIC_INTERPRETER)
753     if (callerFrame->globalData().canUseJIT())
754         bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
755     else
756         bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
757 #elif ENABLE(JIT)
758     bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
759 #else
760     bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
761 #endif
762
763     callFrame = callerFrame;
764     return true;
765 }
766
767 static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception, unsigned bytecodeOffset)
768 {
769     exception->clearAppendSourceToMessage();
770
771     if (!callFrame->codeBlock()->hasExpressionInfo())
772         return;
773
774     int startOffset = 0;
775     int endOffset = 0;
776     int divotPoint = 0;
777
778     CodeBlock* codeBlock = callFrame->codeBlock();
779     codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divotPoint, startOffset, endOffset);
780
781     int expressionStart = divotPoint - startOffset;
782     int expressionStop = divotPoint + endOffset;
783
784     if (!expressionStop || expressionStart > codeBlock->source()->length())
785         return;
786
787     JSGlobalData* globalData = &callFrame->globalData();
788     JSValue jsMessage = exception->getDirect(*globalData, globalData->propertyNames->message);
789     if (!jsMessage || !jsMessage.isString())
790         return;
791
792     UString message = asString(jsMessage)->value(callFrame);
793
794     if (expressionStart < expressionStop)
795         message =  makeUString(message, " (evaluating '", codeBlock->source()->getRange(expressionStart, expressionStop), "')");
796     else {
797         // No range information, so give a few characters of context
798         const StringImpl* data = codeBlock->source()->data();
799         int dataLength = codeBlock->source()->length();
800         int start = expressionStart;
801         int stop = expressionStart;
802         // Get up to 20 characters of context to the left and right of the divot, clamping to the line.
803         // then strip whitespace.
804         while (start > 0 && (expressionStart - start < 20) && (*data)[start - 1] != '\n')
805             start--;
806         while (start < (expressionStart - 1) && isStrWhiteSpace((*data)[start]))
807             start++;
808         while (stop < dataLength && (stop - expressionStart < 20) && (*data)[stop] != '\n')
809             stop++;
810         while (stop > expressionStart && isStrWhiteSpace((*data)[stop - 1]))
811             stop--;
812         message = makeUString(message, " (near '...", codeBlock->source()->getRange(start, stop), "...')");
813     }
814
815     exception->putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message));
816 }
817
818 static int getLineNumberForCallFrame(JSGlobalData* globalData, CallFrame* callFrame)
819 {
820     UNUSED_PARAM(globalData);
821     callFrame = callFrame->removeHostCallFrameFlag();
822     CodeBlock* codeBlock = callFrame->codeBlock();
823     if (!codeBlock)
824         return -1;
825 #if ENABLE(CLASSIC_INTERPRETER)
826     if (!globalData->canUseJIT())
827         return codeBlock->lineNumberForBytecodeOffset(callFrame->bytecodeOffsetForNonDFGCode() - 1);
828 #endif
829 #if ENABLE(JIT)
830 #if ENABLE(DFG_JIT)
831     if (codeBlock->getJITType() == JITCode::DFGJIT)
832         return codeBlock->lineNumberForBytecodeOffset(codeBlock->codeOrigin(callFrame->codeOriginIndexForDFG()).bytecodeIndex);
833 #endif
834     return codeBlock->lineNumberForBytecodeOffset(callFrame->bytecodeOffsetForNonDFGCode());
835 #else
836     return -1;
837 #endif
838 }
839
840 static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, int& lineNumber)
841 {
842     UNUSED_PARAM(globalData);
843     unsigned bytecodeOffset = 0;
844     lineNumber = -1;
845     ASSERT(!callFrame->hasHostCallFrameFlag());
846     CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : callFrame->callerFrame()->removeHostCallFrameFlag();
847     bool callframeIsHost = callerFrame->addHostCallFrameFlag() == callFrame->callerFrame();
848     ASSERT(!callerFrame->hasHostCallFrameFlag());
849
850     if (callerFrame == CallFrame::noCaller() || !callerFrame || !callerFrame->codeBlock())
851         return callerFrame;
852     
853     CodeBlock* callerCodeBlock = callerFrame->codeBlock();
854     
855 #if ENABLE(JIT)
856     if (!callFrame->hasReturnPC())
857         callframeIsHost = true;
858 #endif
859 #if ENABLE(DFG_JIT)
860     if (callFrame->isInlineCallFrame())
861         callframeIsHost = false;
862 #endif
863
864     if (callframeIsHost) {
865         // Don't need to deal with inline callframes here as by definition we haven't
866         // inlined a call with an intervening native call frame.
867 #if ENABLE(CLASSIC_INTERPRETER)
868         if (!globalData->canUseJIT()) {
869             bytecodeOffset = callerFrame->bytecodeOffsetForNonDFGCode();
870             lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
871             return callerFrame;
872         }
873 #endif
874 #if ENABLE(JIT)
875 #if ENABLE(DFG_JIT)
876         if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) {
877             unsigned codeOriginIndex = callerFrame->codeOriginIndexForDFG();
878             bytecodeOffset = callerCodeBlock->codeOrigin(codeOriginIndex).bytecodeIndex;
879         } else
880 #endif
881             bytecodeOffset = callerFrame->bytecodeOffsetForNonDFGCode();
882 #endif
883     } else {
884 #if ENABLE(CLASSIC_INTERPRETER)
885         if (!globalData->canUseJIT()) {
886             bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC());
887             lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
888             return callerFrame;
889         }
890 #endif
891 #if ENABLE(JIT)
892     #if ENABLE(DFG_JIT)
893         if (callFrame->isInlineCallFrame()) {
894             InlineCallFrame* icf = callFrame->inlineCallFrame();
895             bytecodeOffset = icf->caller.bytecodeIndex;
896             if (InlineCallFrame* parentCallFrame = icf->caller.inlineCallFrame) {
897                 FunctionExecutable* executable = static_cast<FunctionExecutable*>(parentCallFrame->executable.get());
898                 CodeBlock* newCodeBlock = executable->baselineCodeBlockFor(parentCallFrame->isCall ? CodeForCall : CodeForConstruct);
899                 ASSERT(newCodeBlock);
900                 ASSERT(newCodeBlock->instructionCount() > bytecodeOffset);
901                 callerCodeBlock = newCodeBlock;
902             }
903         } else if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) {
904             CodeOrigin origin;
905             if (!callerCodeBlock->codeOriginForReturn(callFrame->returnPC(), origin))
906                 ASSERT_NOT_REACHED();
907             bytecodeOffset = origin.bytecodeIndex;
908             if (InlineCallFrame* icf = origin.inlineCallFrame) {
909                 FunctionExecutable* executable = static_cast<FunctionExecutable*>(icf->executable.get());
910                 CodeBlock* newCodeBlock = executable->baselineCodeBlockFor(icf->isCall ? CodeForCall : CodeForConstruct);
911                 ASSERT(newCodeBlock);
912                 ASSERT(newCodeBlock->instructionCount() > bytecodeOffset);
913                 callerCodeBlock = newCodeBlock;
914             }
915         } else
916     #endif
917             bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
918 #endif
919     }
920
921     lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset);
922     return callerFrame;
923 }
924
925 static ALWAYS_INLINE const UString getSourceURLFromCallFrame(CallFrame* callFrame) 
926 {
927     ASSERT(!callFrame->hasHostCallFrameFlag());
928 #if ENABLE(CLASSIC_INTERPRETER)
929 #if ENABLE(JIT)
930     if (callFrame->globalData().canUseJIT())
931         return callFrame->codeBlock()->ownerExecutable()->sourceURL();
932 #endif
933     return callFrame->codeBlock()->source()->url();
934
935 #else
936     return callFrame->codeBlock()->ownerExecutable()->sourceURL();
937 #endif
938 }
939
940 static StackFrameCodeType getStackFrameCodeType(CallFrame* callFrame)
941 {
942     ASSERT(!callFrame->hasHostCallFrameFlag());
943
944     switch (callFrame->codeBlock()->codeType()) {
945     case EvalCode:
946         return StackFrameEvalCode;
947     case FunctionCode:
948         return StackFrameFunctionCode;
949     case GlobalCode:
950         return StackFrameGlobalCode;
951     }
952     ASSERT_NOT_REACHED();
953     return StackFrameGlobalCode;
954 }
955
956 void Interpreter::getStackTrace(JSGlobalData* globalData, Vector<StackFrame>& results)
957 {
958     CallFrame* callFrame = globalData->topCallFrame->removeHostCallFrameFlag();
959     if (!callFrame || callFrame == CallFrame::noCaller()) 
960         return;
961     int line = getLineNumberForCallFrame(globalData, callFrame);
962
963     callFrame = callFrame->trueCallFrameFromVMCode();
964
965     while (callFrame && callFrame != CallFrame::noCaller()) {
966         UString sourceURL;
967         if (callFrame->codeBlock()) {
968             sourceURL = getSourceURLFromCallFrame(callFrame);
969             StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), getStackFrameCodeType(callFrame), Strong<ExecutableBase>(*globalData, callFrame->codeBlock()->ownerExecutable()), line, sourceURL};
970             results.append(s);
971         } else {
972             StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), -1, UString()};
973             results.append(s);
974         }
975         callFrame = getCallerInfo(globalData, callFrame, line);
976     }
977 }
978
979 void Interpreter::addStackTraceIfNecessary(CallFrame* callFrame, JSObject* error)
980 {
981     JSGlobalData* globalData = &callFrame->globalData();
982     ASSERT(callFrame == globalData->topCallFrame || callFrame == callFrame->lexicalGlobalObject()->globalExec() || callFrame == callFrame->dynamicGlobalObject()->globalExec());
983     if (error->hasProperty(callFrame, globalData->propertyNames->stack))
984         return;
985
986     Vector<StackFrame> stackTrace;
987     getStackTrace(&callFrame->globalData(), stackTrace);
988     
989     if (stackTrace.isEmpty())
990         return;
991     
992     JSGlobalObject* globalObject = 0;
993     if (isTerminatedExecutionException(error) || isInterruptedExecutionException(error))
994         globalObject = globalData->dynamicGlobalObject;
995     else
996         globalObject = error->globalObject();
997     StringBuilder builder;
998     for (unsigned i = 0; i < stackTrace.size(); i++) {
999         builder.append(String(stackTrace[i].toString(globalObject->globalExec()).impl()));
1000         if (i != stackTrace.size() - 1)
1001             builder.append('\n');
1002     }
1003     
1004     error->putDirect(*globalData, globalData->propertyNames->stack, jsString(globalData, UString(builder.toString().impl())), ReadOnly | DontDelete);
1005 }
1006
1007 NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
1008 {
1009     CodeBlock* codeBlock = callFrame->codeBlock();
1010     bool isInterrupt = false;
1011
1012     ASSERT(!exceptionValue.isEmpty());
1013     ASSERT(!exceptionValue.isCell() || exceptionValue.asCell());
1014     // This shouldn't be possible (hence the assertions), but we're already in the slowest of
1015     // slow cases, so let's harden against it anyway to be safe.
1016     if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
1017         exceptionValue = jsNull();
1018
1019     // Set up the exception object
1020     if (exceptionValue.isObject()) {
1021         JSObject* exception = asObject(exceptionValue);
1022
1023         if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage())
1024             appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), bytecodeOffset);
1025
1026         if (codeBlock->hasLineInfo() && !hasErrorInfo(callFrame, exception)) {
1027             // FIXME: should only really be adding these properties to VM generated exceptions,
1028             // but the inspector currently requires these for all thrown objects.
1029             addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source());
1030         }
1031
1032         isInterrupt = isInterruptedExecutionException(exception) || isTerminatedExecutionException(exception);
1033     }
1034
1035     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
1036         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
1037         bool hasHandler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
1038         debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), hasHandler);
1039     }
1040
1041     // Calculate an exception handler vPC, unwinding call frames as necessary.
1042     HandlerInfo* handler = 0;
1043     while (isInterrupt || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
1044         if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
1045             if (Profiler* profiler = *Profiler::enabledProfilerReference())
1046                 profiler->exceptionUnwind(callFrame);
1047             callFrame->globalData().topCallFrame = callFrame;
1048             return 0;
1049         }
1050     }
1051     callFrame->globalData().topCallFrame = callFrame;
1052
1053     if (Profiler* profiler = *Profiler::enabledProfilerReference())
1054         profiler->exceptionUnwind(callFrame);
1055
1056     // Shrink the JS stack, in case stack overflow made it huge.
1057     Register* highWaterMark = 0;
1058     for (CallFrame* callerFrame = callFrame; callerFrame; callerFrame = callerFrame->callerFrame()->removeHostCallFrameFlag()) {
1059         CodeBlock* codeBlock = callerFrame->codeBlock();
1060         if (!codeBlock)
1061             continue;
1062         Register* callerHighWaterMark = callerFrame->registers() + codeBlock->m_numCalleeRegisters;
1063         highWaterMark = max(highWaterMark, callerHighWaterMark);
1064     }
1065     m_registerFile.shrink(highWaterMark);
1066
1067     // Unwind the scope chain within the exception handler's call frame.
1068     ScopeChainNode* scopeChain = callFrame->scopeChain();
1069     int scopeDelta = 0;
1070     if (!codeBlock->needsFullScopeChain() || codeBlock->codeType() != FunctionCode 
1071         || callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
1072         scopeDelta = depth(codeBlock, scopeChain) - handler->scopeDepth;
1073     ASSERT(scopeDelta >= 0);
1074     while (scopeDelta--)
1075         scopeChain = scopeChain->pop();
1076     callFrame->setScopeChain(scopeChain);
1077
1078     return handler;
1079 }
1080
1081 static inline JSValue checkedReturn(JSValue returnValue)
1082 {
1083     ASSERT(returnValue);
1084     return returnValue;
1085 }
1086
1087 static inline JSObject* checkedReturn(JSObject* returnValue)
1088 {
1089     ASSERT(returnValue);
1090     return returnValue;
1091 }
1092
1093 JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj)
1094 {
1095     ASSERT(isValidThisObject(thisObj, callFrame));
1096     ASSERT(!scopeChain->globalData->exception);
1097     ASSERT(!callFrame->globalData().isCollectorBusy());
1098     if (callFrame->globalData().isCollectorBusy())
1099         return jsNull();
1100
1101     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
1102         return checkedReturn(throwStackOverflowError(callFrame));
1103
1104     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
1105     Vector<JSONPData> JSONPData;
1106     bool parseResult;
1107     const UString programSource = program->source().toString();
1108     if (programSource.isNull())
1109         return jsUndefined();
1110     if (programSource.is8Bit()) {
1111         LiteralParser<LChar> literalParser(callFrame, programSource.characters8(), programSource.length(), JSONP);
1112         parseResult = literalParser.tryJSONPParse(JSONPData, scopeChain->globalObject->globalObjectMethodTable()->supportsRichSourceInfo(scopeChain->globalObject.get()));
1113     } else {
1114         LiteralParser<UChar> literalParser(callFrame, programSource.characters16(), programSource.length(), JSONP);
1115         parseResult = literalParser.tryJSONPParse(JSONPData, scopeChain->globalObject->globalObjectMethodTable()->supportsRichSourceInfo(scopeChain->globalObject.get()));
1116     }
1117
1118     if (parseResult) {
1119         JSGlobalObject* globalObject = scopeChain->globalObject.get();
1120         JSValue result;
1121         for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
1122             Vector<JSONPPathEntry> JSONPPath;
1123             JSONPPath.swap(JSONPData[entry].m_path);
1124             JSValue JSONPValue = JSONPData[entry].m_value.get();
1125             if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclare) {
1126                 if (globalObject->hasProperty(callFrame, JSONPPath[0].m_pathEntryName)) {
1127                     PutPropertySlot slot;
1128                     globalObject->methodTable()->put(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
1129                 } else
1130                     globalObject->methodTable()->putDirectVirtual(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, DontEnum | DontDelete);
1131                 // var declarations return undefined
1132                 result = jsUndefined();
1133                 continue;
1134             }
1135             JSValue baseObject(globalObject);
1136             for (unsigned i = 0; i < JSONPPath.size() - 1; i++) {
1137                 ASSERT(JSONPPath[i].m_type != JSONPPathEntryTypeDeclare);
1138                 switch (JSONPPath[i].m_type) {
1139                 case JSONPPathEntryTypeDot: {
1140                     if (i == 0) {
1141                         PropertySlot slot(globalObject);
1142                         if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
1143                             if (entry)
1144                                 return throwError(callFrame, createUndefinedVariableError(globalObject->globalExec(), JSONPPath[i].m_pathEntryName));
1145                             goto failedJSONP;
1146                         }
1147                         baseObject = slot.getValue(callFrame, JSONPPath[i].m_pathEntryName);
1148                     } else
1149                         baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathEntryName);
1150                     if (callFrame->hadException())
1151                         return jsUndefined();
1152                     continue;
1153                 }
1154                 case JSONPPathEntryTypeLookup: {
1155                     baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
1156                     if (callFrame->hadException())
1157                         return jsUndefined();
1158                     continue;
1159                 }
1160                 default:
1161                     ASSERT_NOT_REACHED();
1162                     return jsUndefined();
1163                 }
1164             }
1165             PutPropertySlot slot;
1166             switch (JSONPPath.last().m_type) {
1167             case JSONPPathEntryTypeCall: {
1168                 JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
1169                 if (callFrame->hadException())
1170                     return jsUndefined();
1171                 CallData callData;
1172                 CallType callType = getCallData(function, callData);
1173                 if (callType == CallTypeNone)
1174                     return throwError(callFrame, createNotAFunctionError(callFrame, function));
1175                 MarkedArgumentBuffer jsonArg;
1176                 jsonArg.append(JSONPValue);
1177                 JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined(): baseObject;
1178                 JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg);
1179                 if (callFrame->hadException())
1180                     return jsUndefined();
1181                 break;
1182             }
1183             case JSONPPathEntryTypeDot: {
1184                 baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
1185                 if (callFrame->hadException())
1186                     return jsUndefined();
1187                 break;
1188             }
1189             case JSONPPathEntryTypeLookup: {
1190                 baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
1191                 if (callFrame->hadException())
1192                     return jsUndefined();
1193                 break;
1194             }
1195             default:
1196                 ASSERT_NOT_REACHED();
1197                     return jsUndefined();
1198             }
1199             result = JSONPValue;
1200         }
1201         return result;
1202     }
1203 failedJSONP:
1204     JSObject* error = program->compile(callFrame, scopeChain);
1205     if (error)
1206         return checkedReturn(throwError(callFrame, error));
1207     CodeBlock* codeBlock = &program->generatedBytecode();
1208
1209     Register* oldEnd = m_registerFile.end();
1210     Register* newEnd = oldEnd + codeBlock->numParameters() + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
1211     if (!m_registerFile.grow(newEnd))
1212         return checkedReturn(throwStackOverflowError(callFrame));
1213
1214     CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->numParameters() + RegisterFile::CallFrameHeaderSize);
1215     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1216     newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), codeBlock->numParameters(), 0);
1217     newCallFrame->setThisValue(thisObj);
1218     TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
1219
1220     Profiler** profiler = Profiler::enabledProfilerReference();
1221     if (*profiler)
1222         (*profiler)->willExecute(callFrame, program->sourceURL(), program->lineNo());
1223
1224     JSValue result;
1225     {
1226         SamplingTool::CallRecord callRecord(m_sampler.get());
1227
1228         m_reentryDepth++;  
1229 #if ENABLE(JIT)
1230         if (!classicEnabled())
1231             result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
1232         else
1233 #endif
1234             result = privateExecute(Normal, &m_registerFile, newCallFrame);
1235
1236         m_reentryDepth--;
1237     }
1238
1239     if (*profiler)
1240         (*profiler)->didExecute(callFrame, program->sourceURL(), program->lineNo());
1241
1242     m_registerFile.shrink(oldEnd);
1243
1244     return checkedReturn(result);
1245 }
1246
1247 JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
1248 {
1249     ASSERT(isValidThisObject(thisValue, callFrame));
1250     ASSERT(!callFrame->hadException());
1251     ASSERT(!callFrame->globalData().isCollectorBusy());
1252     if (callFrame->globalData().isCollectorBusy())
1253         return jsNull();
1254
1255     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
1256         return checkedReturn(throwStackOverflowError(callFrame));
1257
1258     Register* oldEnd = m_registerFile.end();
1259     ASSERT(callFrame->frameExtent() <= oldEnd || callFrame == callFrame->scopeChain()->globalObject->globalExec());
1260     int argCount = 1 + args.size(); // implicit "this" parameter
1261     size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
1262
1263     CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset);
1264     if (!m_registerFile.grow(newCallFrame->registers()))
1265         return checkedReturn(throwStackOverflowError(callFrame));
1266
1267     newCallFrame->setThisValue(thisValue);
1268     for (size_t i = 0; i < args.size(); ++i)
1269         newCallFrame->setArgument(i, args.at(i));
1270
1271     if (callType == CallTypeJS) {
1272         ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
1273
1274         DynamicGlobalObjectScope globalObjectScope(*callDataScopeChain->globalData, callDataScopeChain->globalObject.get());
1275
1276         JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
1277         if (UNLIKELY(!!compileError)) {
1278             m_registerFile.shrink(oldEnd);
1279             return checkedReturn(throwError(callFrame, compileError));
1280         }
1281
1282         CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
1283         newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, 0, argCount);
1284         if (UNLIKELY(!newCallFrame)) {
1285             m_registerFile.shrink(oldEnd);
1286             return checkedReturn(throwStackOverflowError(callFrame));
1287         }
1288
1289         newCallFrame->init(newCodeBlock, 0, callDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
1290
1291         TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
1292
1293         Profiler** profiler = Profiler::enabledProfilerReference();
1294         if (*profiler)
1295             (*profiler)->willExecute(callFrame, function);
1296
1297         JSValue result;
1298         {
1299             SamplingTool::CallRecord callRecord(m_sampler.get());
1300
1301             m_reentryDepth++;  
1302 #if ENABLE(JIT)
1303             if (!classicEnabled())
1304                 result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData);
1305             else
1306 #endif
1307                 result = privateExecute(Normal, &m_registerFile, newCallFrame);
1308             m_reentryDepth--;
1309         }
1310
1311         if (*profiler)
1312             (*profiler)->didExecute(callFrame, function);
1313
1314         m_registerFile.shrink(oldEnd);
1315         return checkedReturn(result);
1316     }
1317
1318     ASSERT(callType == CallTypeHost);
1319     ScopeChainNode* scopeChain = callFrame->scopeChain();
1320     newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
1321
1322     TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
1323
1324     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
1325
1326     Profiler** profiler = Profiler::enabledProfilerReference();
1327     if (*profiler)
1328         (*profiler)->willExecute(callFrame, function);
1329
1330     JSValue result;
1331     {
1332         SamplingTool::HostCallRecord callRecord(m_sampler.get());
1333         result = JSValue::decode(callData.native.function(newCallFrame));
1334     }
1335
1336     if (*profiler)
1337         (*profiler)->didExecute(callFrame, function);
1338
1339     m_registerFile.shrink(oldEnd);
1340     return checkedReturn(result);
1341 }
1342
1343 JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
1344 {
1345     ASSERT(!callFrame->hadException());
1346     ASSERT(!callFrame->globalData().isCollectorBusy());
1347     // We throw in this case because we have to return something "valid" but we're
1348     // already in an invalid state.
1349     if (callFrame->globalData().isCollectorBusy())
1350         return checkedReturn(throwStackOverflowError(callFrame));
1351
1352     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
1353         return checkedReturn(throwStackOverflowError(callFrame));
1354
1355     Register* oldEnd = m_registerFile.end();
1356     int argCount = 1 + args.size(); // implicit "this" parameter
1357     size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
1358
1359     if (!m_registerFile.grow(oldEnd + registerOffset))
1360         return checkedReturn(throwStackOverflowError(callFrame));
1361
1362     CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset);
1363     newCallFrame->setThisValue(jsUndefined());
1364     for (size_t i = 0; i < args.size(); ++i)
1365         newCallFrame->setArgument(i, args.at(i));
1366
1367     if (constructType == ConstructTypeJS) {
1368         ScopeChainNode* constructDataScopeChain = constructData.js.scopeChain;
1369
1370         DynamicGlobalObjectScope globalObjectScope(*constructDataScopeChain->globalData, constructDataScopeChain->globalObject.get());
1371
1372         JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, constructDataScopeChain);
1373         if (UNLIKELY(!!compileError)) {
1374             m_registerFile.shrink(oldEnd);
1375             return checkedReturn(throwError(callFrame, compileError));
1376         }
1377
1378         CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
1379         newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, 0, argCount);
1380         if (UNLIKELY(!newCallFrame)) {
1381             m_registerFile.shrink(oldEnd);
1382             return checkedReturn(throwStackOverflowError(callFrame));
1383         }
1384
1385         newCallFrame->init(newCodeBlock, 0, constructDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
1386
1387         TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
1388
1389         Profiler** profiler = Profiler::enabledProfilerReference();
1390         if (*profiler)
1391             (*profiler)->willExecute(callFrame, constructor);
1392
1393         JSValue result;
1394         {
1395             SamplingTool::CallRecord callRecord(m_sampler.get());
1396
1397             m_reentryDepth++;  
1398 #if ENABLE(JIT)
1399             if (!classicEnabled())
1400                 result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData);
1401             else
1402 #endif
1403                 result = privateExecute(Normal, &m_registerFile, newCallFrame);
1404             m_reentryDepth--;
1405         }
1406
1407         if (*profiler)
1408             (*profiler)->didExecute(callFrame, constructor);
1409
1410         m_registerFile.shrink(oldEnd);
1411         if (callFrame->hadException())
1412             return 0;
1413         ASSERT(result.isObject());
1414         return checkedReturn(asObject(result));
1415     }
1416
1417     ASSERT(constructType == ConstructTypeHost);
1418     ScopeChainNode* scopeChain = callFrame->scopeChain();
1419     newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
1420
1421     TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
1422
1423     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
1424
1425     Profiler** profiler = Profiler::enabledProfilerReference();
1426     if (*profiler)
1427         (*profiler)->willExecute(callFrame, constructor);
1428
1429     JSValue result;
1430     {
1431         SamplingTool::HostCallRecord callRecord(m_sampler.get());
1432         result = JSValue::decode(constructData.native.function(newCallFrame));
1433     }
1434
1435     if (*profiler)
1436         (*profiler)->didExecute(callFrame, constructor);
1437
1438     m_registerFile.shrink(oldEnd);
1439     if (callFrame->hadException())
1440         return 0;
1441     ASSERT(result.isObject());
1442     return checkedReturn(asObject(result));
1443 }
1444
1445 CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, int argumentCountIncludingThis, ScopeChainNode* scopeChain)
1446 {
1447     ASSERT(!scopeChain->globalData->exception);
1448     
1449     if (callFrame->globalData().isCollectorBusy())
1450         return CallFrameClosure();
1451
1452     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
1453         throwStackOverflowError(callFrame);
1454         return CallFrameClosure();
1455     }
1456
1457     Register* oldEnd = m_registerFile.end();
1458     size_t registerOffset = argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize;
1459
1460     CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset);
1461     if (!m_registerFile.grow(newCallFrame->registers())) {
1462         throwStackOverflowError(callFrame);
1463         return CallFrameClosure();
1464     }
1465
1466     JSObject* error = functionExecutable->compileForCall(callFrame, scopeChain);
1467     if (error) {
1468         throwError(callFrame, error);
1469         m_registerFile.shrink(oldEnd);
1470         return CallFrameClosure();
1471     }
1472     CodeBlock* codeBlock = &functionExecutable->generatedBytecodeForCall();
1473
1474     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, 0, argumentCountIncludingThis);
1475     if (UNLIKELY(!newCallFrame)) {
1476         throwStackOverflowError(callFrame);
1477         m_registerFile.shrink(oldEnd);
1478         return CallFrameClosure();
1479     }
1480     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), argumentCountIncludingThis, function);  
1481     scopeChain->globalData->topCallFrame = newCallFrame;
1482     CallFrameClosure result = { callFrame, newCallFrame, function, functionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->numParameters(), argumentCountIncludingThis };
1483     return result;
1484 }
1485
1486 JSValue Interpreter::execute(CallFrameClosure& closure) 
1487 {
1488     ASSERT(!closure.oldCallFrame->globalData().isCollectorBusy());
1489     if (closure.oldCallFrame->globalData().isCollectorBusy())
1490         return jsNull();
1491     closure.resetCallFrame();
1492     Profiler** profiler = Profiler::enabledProfilerReference();
1493     if (*profiler)
1494         (*profiler)->willExecute(closure.oldCallFrame, closure.function);
1495
1496     TopCallFrameSetter topCallFrame(*closure.globalData, closure.newCallFrame);
1497
1498     JSValue result;
1499     {
1500         SamplingTool::CallRecord callRecord(m_sampler.get());
1501         
1502         m_reentryDepth++;  
1503 #if ENABLE(JIT)
1504 #if ENABLE(CLASSIC_INTERPRETER)
1505         if (closure.newCallFrame->globalData().canUseJIT())
1506 #endif
1507             result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData);
1508 #if ENABLE(CLASSIC_INTERPRETER)
1509         else
1510 #endif
1511 #endif
1512 #if ENABLE(CLASSIC_INTERPRETER)
1513             result = privateExecute(Normal, &m_registerFile, closure.newCallFrame);
1514 #endif
1515         m_reentryDepth--;
1516     }
1517
1518     if (*profiler)
1519         (*profiler)->didExecute(closure.oldCallFrame, closure.function);
1520     return checkedReturn(result);
1521 }
1522
1523 void Interpreter::endRepeatCall(CallFrameClosure& closure)
1524 {
1525     closure.globalData->topCallFrame = closure.oldCallFrame;
1526     m_registerFile.shrink(closure.oldEnd);
1527 }
1528
1529 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, ScopeChainNode* scopeChain, int globalRegisterOffset)
1530 {
1531     ASSERT(isValidThisObject(thisValue, callFrame));
1532     ASSERT(!scopeChain->globalData->exception);
1533     ASSERT(!callFrame->globalData().isCollectorBusy());
1534     if (callFrame->globalData().isCollectorBusy())
1535         return jsNull();
1536
1537     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
1538
1539     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
1540         return checkedReturn(throwStackOverflowError(callFrame));
1541
1542     JSObject* compileError = eval->compile(callFrame, scopeChain);
1543     if (UNLIKELY(!!compileError))
1544         return checkedReturn(throwError(callFrame, compileError));
1545     EvalCodeBlock* codeBlock = &eval->generatedBytecode();
1546
1547     JSObject* variableObject;
1548     for (ScopeChainNode* node = scopeChain; ; node = node->next.get()) {
1549         ASSERT(node);
1550         if (node->object->isVariableObject() && !node->object->isStaticScopeObject()) {
1551             variableObject = jsCast<JSVariableObject*>(node->object.get());
1552             break;
1553         }
1554     }
1555
1556     unsigned numVariables = codeBlock->numVariables();
1557     int numFunctions = codeBlock->numberOfFunctionDecls();
1558     bool pushedScope = false;
1559     if (numVariables || numFunctions) {
1560         if (codeBlock->isStrictMode()) {
1561             variableObject = StrictEvalActivation::create(callFrame);
1562             scopeChain = scopeChain->push(variableObject);
1563             pushedScope = true;
1564         }
1565         // Scope for BatchedTransitionOptimizer
1566         BatchedTransitionOptimizer optimizer(callFrame->globalData(), variableObject);
1567
1568         for (unsigned i = 0; i < numVariables; ++i) {
1569             const Identifier& ident = codeBlock->variable(i);
1570             if (!variableObject->hasProperty(callFrame, ident)) {
1571                 PutPropertySlot slot;
1572                 variableObject->methodTable()->put(variableObject, callFrame, ident, jsUndefined(), slot);
1573             }
1574         }
1575
1576         for (int i = 0; i < numFunctions; ++i) {
1577             FunctionExecutable* function = codeBlock->functionDecl(i);
1578             PutPropertySlot slot;
1579             variableObject->methodTable()->put(variableObject, callFrame, function->name(), function->make(callFrame, scopeChain), slot);
1580         }
1581     }
1582
1583     Register* oldEnd = m_registerFile.end();
1584     Register* newEnd = m_registerFile.begin() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
1585     if (!m_registerFile.grow(newEnd)) {
1586         if (pushedScope)
1587             scopeChain->pop();
1588         return checkedReturn(throwStackOverflowError(callFrame));
1589     }
1590
1591     CallFrame* newCallFrame = CallFrame::create(m_registerFile.begin() + globalRegisterOffset);
1592
1593     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1594     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), codeBlock->numParameters(), 0);
1595     newCallFrame->setThisValue(thisValue);
1596
1597     TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
1598
1599     Profiler** profiler = Profiler::enabledProfilerReference();
1600     if (*profiler)
1601         (*profiler)->willExecute(callFrame, eval->sourceURL(), eval->lineNo());
1602
1603     JSValue result;
1604     {
1605         SamplingTool::CallRecord callRecord(m_sampler.get());
1606
1607         m_reentryDepth++;
1608         
1609 #if ENABLE(JIT)
1610 #if ENABLE(CLASSIC_INTERPRETER)
1611         if (callFrame->globalData().canUseJIT())
1612 #endif
1613             result = eval->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
1614 #if ENABLE(CLASSIC_INTERPRETER)
1615         else
1616 #endif
1617 #endif
1618 #if ENABLE(CLASSIC_INTERPRETER)
1619             result = privateExecute(Normal, &m_registerFile, newCallFrame);
1620 #endif
1621         m_reentryDepth--;
1622     }
1623
1624     if (*profiler)
1625         (*profiler)->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
1626
1627     m_registerFile.shrink(oldEnd);
1628     if (pushedScope)
1629         scopeChain->pop();
1630     return checkedReturn(result);
1631 }
1632
1633 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine)
1634 {
1635     Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
1636     if (!debugger)
1637         return;
1638
1639     switch (debugHookID) {
1640         case DidEnterCallFrame:
1641             debugger->callEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
1642             return;
1643         case WillLeaveCallFrame:
1644             debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
1645             return;
1646         case WillExecuteStatement:
1647             debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
1648             return;
1649         case WillExecuteProgram:
1650             debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
1651             return;
1652         case DidExecuteProgram:
1653             debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
1654             return;
1655         case DidReachBreakpoint:
1656             debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
1657             return;
1658     }
1659 }
1660     
1661 #if ENABLE(CLASSIC_INTERPRETER)
1662 NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
1663 {
1664     int dst = vPC[1].u.operand;
1665     CodeBlock* codeBlock = callFrame->codeBlock();
1666     Identifier& property = codeBlock->identifier(vPC[2].u.operand);
1667     JSValue value = callFrame->r(vPC[3].u.operand).jsValue();
1668     JSObject* scope = JSStaticScopeObject::create(callFrame, property, value, DontDelete);
1669     callFrame->uncheckedR(dst) = JSValue(scope);
1670
1671     return callFrame->scopeChain()->push(scope);
1672 }
1673
1674 NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const PutPropertySlot& slot)
1675 {
1676     // Recursive invocation may already have specialized this instruction.
1677     if (vPC[0].u.opcode != getOpcode(op_put_by_id))
1678         return;
1679
1680     if (!baseValue.isCell())
1681         return;
1682
1683     // Uncacheable: give up.
1684     if (!slot.isCacheable()) {
1685         vPC[0] = getOpcode(op_put_by_id_generic);
1686         return;
1687     }
1688     
1689     JSCell* baseCell = baseValue.asCell();
1690     Structure* structure = baseCell->structure();
1691
1692     if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
1693         vPC[0] = getOpcode(op_put_by_id_generic);
1694         return;
1695     }
1696
1697     // Cache miss: record Structure to compare against next time.
1698     Structure* lastStructure = vPC[4].u.structure.get();
1699     if (structure != lastStructure) {
1700         // First miss: record Structure to compare against next time.
1701         if (!lastStructure) {
1702             vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
1703             return;
1704         }
1705
1706         // Second miss: give up.
1707         vPC[0] = getOpcode(op_put_by_id_generic);
1708         return;
1709     }
1710
1711     // Cache hit: Specialize instruction and ref Structures.
1712
1713     // If baseCell != slot.base(), then baseCell must be a proxy for another object.
1714     if (baseCell != slot.base()) {
1715         vPC[0] = getOpcode(op_put_by_id_generic);
1716         return;
1717     }
1718
1719     // Structure transition, cache transition info
1720     if (slot.type() == PutPropertySlot::NewProperty) {
1721         if (structure->isDictionary()) {
1722             vPC[0] = getOpcode(op_put_by_id_generic);
1723             return;
1724         }
1725
1726         // put_by_id_transition checks the prototype chain for setters.
1727         normalizePrototypeChain(callFrame, baseCell);
1728         JSCell* owner = codeBlock->ownerExecutable();
1729         JSGlobalData& globalData = callFrame->globalData();
1730         // Get the prototype here because the call to prototypeChain could cause a 
1731         // GC allocation, which we don't want to happen while we're in the middle of 
1732         // initializing the union.
1733         StructureChain* prototypeChain = structure->prototypeChain(callFrame);
1734         vPC[0] = getOpcode(op_put_by_id_transition);
1735         vPC[4].u.structure.set(globalData, owner, structure->previousID());
1736         vPC[5].u.structure.set(globalData, owner, structure);
1737         vPC[6].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), prototypeChain);
1738         ASSERT(vPC[6].u.structureChain);
1739         vPC[7] = slot.cachedOffset();
1740         return;
1741     }
1742
1743     vPC[0] = getOpcode(op_put_by_id_replace);
1744     vPC[5] = slot.cachedOffset();
1745 }
1746
1747 NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock*, Instruction* vPC)
1748 {
1749     vPC[0] = getOpcode(op_put_by_id);
1750     vPC[4] = 0;
1751 }
1752
1753 NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot)
1754 {
1755     // Recursive invocation may already have specialized this instruction.
1756     if (vPC[0].u.opcode != getOpcode(op_get_by_id))
1757         return;
1758
1759     // FIXME: Cache property access for immediates.
1760     if (!baseValue.isCell()) {
1761         vPC[0] = getOpcode(op_get_by_id_generic);
1762         return;
1763     }
1764
1765     if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
1766         vPC[0] = getOpcode(op_get_array_length);
1767         return;
1768     }
1769
1770     if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
1771         vPC[0] = getOpcode(op_get_string_length);
1772         return;
1773     }
1774
1775     // Uncacheable: give up.
1776     if (!slot.isCacheable()) {
1777         vPC[0] = getOpcode(op_get_by_id_generic);
1778         return;
1779     }
1780
1781     Structure* structure = baseValue.asCell()->structure();
1782
1783     if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
1784         vPC[0] = getOpcode(op_get_by_id_generic);
1785         return;
1786     }
1787
1788     // Cache miss
1789     Structure* lastStructure = vPC[4].u.structure.get();
1790     if (structure != lastStructure) {
1791         // First miss: record Structure to compare against next time.
1792         if (!lastStructure) {
1793             vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
1794             return;
1795         }
1796
1797         // Second miss: give up.
1798         vPC[0] = getOpcode(op_get_by_id_generic);
1799         return;
1800     }
1801
1802     // Cache hit: Specialize instruction and ref Structures.
1803
1804     if (slot.slotBase() == baseValue) {
1805         switch (slot.cachedPropertyType()) {
1806         case PropertySlot::Getter:
1807             vPC[0] = getOpcode(op_get_by_id_getter_self);
1808             vPC[5] = slot.cachedOffset();
1809             break;
1810         case PropertySlot::Custom:
1811             vPC[0] = getOpcode(op_get_by_id_custom_self);
1812             vPC[5] = slot.customGetter();
1813             break;
1814         default:
1815             vPC[0] = getOpcode(op_get_by_id_self);
1816             vPC[5] = slot.cachedOffset();
1817             break;
1818         }
1819         return;
1820     }
1821
1822     if (structure->isDictionary()) {
1823         vPC[0] = getOpcode(op_get_by_id_generic);
1824         return;
1825     }
1826
1827     if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
1828         ASSERT(slot.slotBase().isObject());
1829
1830         JSObject* baseObject = asObject(slot.slotBase());
1831         size_t offset = slot.cachedOffset();
1832
1833         // Since we're accessing a prototype in a loop, it's a good bet that it
1834         // should not be treated as a dictionary.
1835         if (baseObject->structure()->isDictionary()) {
1836             baseObject->flattenDictionaryObject(callFrame->globalData());
1837             offset = baseObject->structure()->get(callFrame->globalData(), propertyName);
1838         }
1839
1840         ASSERT(!baseObject->structure()->isUncacheableDictionary());
1841         
1842         switch (slot.cachedPropertyType()) {
1843         case PropertySlot::Getter:
1844             vPC[0] = getOpcode(op_get_by_id_getter_proto);
1845             vPC[6] = offset;
1846             break;
1847         case PropertySlot::Custom:
1848             vPC[0] = getOpcode(op_get_by_id_custom_proto);
1849             vPC[6] = slot.customGetter();
1850             break;
1851         default:
1852             vPC[0] = getOpcode(op_get_by_id_proto);
1853             vPC[6] = offset;
1854             break;
1855         }
1856         vPC[5].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), baseObject->structure());
1857         return;
1858     }
1859
1860     size_t offset = slot.cachedOffset();
1861     size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
1862     if (!count) {
1863         vPC[0] = getOpcode(op_get_by_id_generic);
1864         return;
1865     }
1866
1867     
1868     StructureChain* prototypeChain = structure->prototypeChain(callFrame);
1869     switch (slot.cachedPropertyType()) {
1870     case PropertySlot::Getter:
1871         vPC[0] = getOpcode(op_get_by_id_getter_chain);
1872         vPC[7] = offset;
1873         break;
1874     case PropertySlot::Custom:
1875         vPC[0] = getOpcode(op_get_by_id_custom_chain);
1876         vPC[7] = slot.customGetter();
1877         break;
1878     default:
1879         vPC[0] = getOpcode(op_get_by_id_chain);
1880         vPC[7] = offset;
1881         break;
1882     }
1883     vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
1884     vPC[5].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), prototypeChain);
1885     vPC[6] = count;
1886 }
1887
1888 NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock*, Instruction* vPC)
1889 {
1890     vPC[0] = getOpcode(op_get_by_id);
1891     vPC[4] = 0;
1892 }
1893
1894 #endif // ENABLE(CLASSIC_INTERPRETER)
1895
1896 JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame)
1897 {
1898     // One-time initialization of our address tables. We have to put this code
1899     // here because our labels are only in scope inside this function.
1900     if (UNLIKELY(flag == InitializeAndReturn)) {
1901         #if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
1902             #define LIST_OPCODE_LABEL(id, length) &&id,
1903                 static Opcode labels[] = { FOR_EACH_OPCODE_ID(LIST_OPCODE_LABEL) };
1904                 for (size_t i = 0; i < WTF_ARRAY_LENGTH(labels); ++i)
1905                     m_opcodeTable[i] = labels[i];
1906             #undef LIST_OPCODE_LABEL
1907         #endif // ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
1908         return JSValue();
1909     }
1910     
1911     ASSERT(m_initialized);
1912     ASSERT(m_classicEnabled);
1913     
1914 #if ENABLE(JIT)
1915 #if ENABLE(CLASSIC_INTERPRETER)
1916     // Mixing Interpreter + JIT is not supported.
1917     if (callFrame->globalData().canUseJIT())
1918 #endif
1919         ASSERT_NOT_REACHED();
1920 #endif
1921
1922 #if !ENABLE(CLASSIC_INTERPRETER)
1923     UNUSED_PARAM(registerFile);
1924     UNUSED_PARAM(callFrame);
1925     return JSValue();
1926 #else
1927
1928     ASSERT(callFrame->globalData().topCallFrame == callFrame);
1929
1930     JSGlobalData* globalData = &callFrame->globalData();
1931     JSValue exceptionValue;
1932     HandlerInfo* handler = 0;
1933     CallFrame** topCallFrameSlot = &globalData->topCallFrame;
1934
1935     CodeBlock* codeBlock = callFrame->codeBlock();
1936     Instruction* vPC = codeBlock->instructions().begin();
1937     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
1938     unsigned tickCount = globalData->timeoutChecker.ticksUntilNextCheck();
1939     JSValue functionReturnValue;
1940
1941 #define CHECK_FOR_EXCEPTION() \
1942     do { \
1943         if (UNLIKELY(globalData->exception != JSValue())) { \
1944             exceptionValue = globalData->exception; \
1945             goto vm_throw; \
1946         } \
1947     } while (0)
1948
1949 #if ENABLE(OPCODE_STATS)
1950     OpcodeStats::resetLastInstruction();
1951 #endif
1952
1953 #define CHECK_FOR_TIMEOUT() \
1954     if (!--tickCount) { \
1955         if (globalData->terminator.shouldTerminate() || globalData->timeoutChecker.didTimeOut(callFrame)) { \
1956             exceptionValue = jsNull(); \
1957             goto vm_throw; \
1958         } \
1959         tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); \
1960     }
1961     
1962 #if ENABLE(OPCODE_SAMPLING)
1963     #define SAMPLE(codeBlock, vPC) m_sampler->sample(codeBlock, vPC)
1964 #else
1965     #define SAMPLE(codeBlock, vPC)
1966 #endif
1967
1968 #define UPDATE_BYTECODE_OFFSET() \
1969     do {\
1970         callFrame->setBytecodeOffsetForNonDFGCode(vPC - codeBlock->instructions().data() + 1);\
1971     } while (0)
1972
1973 #if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
1974     #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto *vPC->u.opcode
1975 #if ENABLE(OPCODE_STATS)
1976     #define DEFINE_OPCODE(opcode) \
1977         opcode:\
1978             OpcodeStats::recordInstruction(opcode);\
1979             UPDATE_BYTECODE_OFFSET();
1980 #else
1981     #define DEFINE_OPCODE(opcode) opcode: UPDATE_BYTECODE_OFFSET();
1982 #endif
1983     NEXT_INSTRUCTION();
1984 #else
1985     #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto interpreterLoopStart
1986 #if ENABLE(OPCODE_STATS)
1987     #define DEFINE_OPCODE(opcode) \
1988         case opcode:\
1989             OpcodeStats::recordInstruction(opcode);\
1990             UPDATE_BYTECODE_OFFSET();
1991 #else
1992     #define DEFINE_OPCODE(opcode) case opcode: UPDATE_BYTECODE_OFFSET();
1993 #endif
1994     while (1) { // iterator loop begins
1995     interpreterLoopStart:;
1996     switch (vPC->u.opcode)
1997 #endif
1998     {
1999     DEFINE_OPCODE(op_new_object) {
2000         /* new_object dst(r)
2001
2002            Constructs a new empty Object instance using the original
2003            constructor, and puts the result in register dst.
2004         */
2005         int dst = vPC[1].u.operand;
2006         callFrame->uncheckedR(dst) = JSValue(constructEmptyObject(callFrame));
2007
2008         vPC += OPCODE_LENGTH(op_new_object);
2009         NEXT_INSTRUCTION();
2010     }
2011     DEFINE_OPCODE(op_new_array) {
2012         /* new_array dst(r) firstArg(r) argCount(n)
2013
2014            Constructs a new Array instance using the original
2015            constructor, and puts the result in register dst.
2016            The array will contain argCount elements with values
2017            taken from registers starting at register firstArg.
2018         */
2019         int dst = vPC[1].u.operand;
2020         int firstArg = vPC[2].u.operand;
2021         int argCount = vPC[3].u.operand;
2022         callFrame->uncheckedR(dst) = JSValue(constructArray(callFrame, reinterpret_cast<JSValue*>(&callFrame->registers()[firstArg]), argCount));
2023
2024         vPC += OPCODE_LENGTH(op_new_array);
2025         NEXT_INSTRUCTION();
2026     }
2027     DEFINE_OPCODE(op_new_array_buffer) {
2028         /* new_array_buffer dst(r) index(n) argCount(n)
2029          
2030          Constructs a new Array instance using the original
2031          constructor, and puts the result in register dst.
2032          The array be initialized with the values from constantBuffer[index]
2033          */
2034         int dst = vPC[1].u.operand;
2035         int firstArg = vPC[2].u.operand;
2036         int argCount = vPC[3].u.operand;
2037         callFrame->uncheckedR(dst) = JSValue(constructArray(callFrame, codeBlock->constantBuffer(firstArg), argCount));
2038         
2039         vPC += OPCODE_LENGTH(op_new_array);
2040         NEXT_INSTRUCTION();
2041     }
2042     DEFINE_OPCODE(op_new_regexp) {
2043         /* new_regexp dst(r) regExp(re)
2044
2045            Constructs a new RegExp instance using the original
2046            constructor from regexp regExp, and puts the result in
2047            register dst.
2048         */
2049         int dst = vPC[1].u.operand;
2050         RegExp* regExp = codeBlock->regexp(vPC[2].u.operand);
2051         if (!regExp->isValid()) {
2052             exceptionValue = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor.");
2053             goto vm_throw;
2054         }
2055         callFrame->uncheckedR(dst) = JSValue(RegExpObject::create(*globalData, callFrame->lexicalGlobalObject(), callFrame->scopeChain()->globalObject->regExpStructure(), regExp));
2056
2057         vPC += OPCODE_LENGTH(op_new_regexp);
2058         NEXT_INSTRUCTION();
2059     }
2060     DEFINE_OPCODE(op_mov) {
2061         /* mov dst(r) src(r)
2062
2063            Copies register src to register dst.
2064         */
2065         int dst = vPC[1].u.operand;
2066         int src = vPC[2].u.operand;
2067         
2068         callFrame->uncheckedR(dst) = callFrame->r(src);
2069
2070         vPC += OPCODE_LENGTH(op_mov);
2071         NEXT_INSTRUCTION();
2072     }
2073     DEFINE_OPCODE(op_eq) {
2074         /* eq dst(r) src1(r) src2(r)
2075
2076            Checks whether register src1 and register src2 are equal,
2077            as with the ECMAScript '==' operator, and puts the result
2078            as a boolean in register dst.
2079         */
2080         int dst = vPC[1].u.operand;
2081         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2082         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2083         if (src1.isInt32() && src2.isInt32())
2084             callFrame->uncheckedR(dst) = jsBoolean(src1.asInt32() == src2.asInt32());
2085         else {
2086             JSValue result = jsBoolean(JSValue::equalSlowCase(callFrame, src1, src2));
2087             CHECK_FOR_EXCEPTION();
2088             callFrame->uncheckedR(dst) = result;
2089         }
2090
2091         vPC += OPCODE_LENGTH(op_eq);
2092         NEXT_INSTRUCTION();
2093     }
2094     DEFINE_OPCODE(op_eq_null) {
2095         /* eq_null dst(r) src(r)
2096
2097            Checks whether register src is null, as with the ECMAScript '!='
2098            operator, and puts the result as a boolean in register dst.
2099         */
2100         int dst = vPC[1].u.operand;
2101         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
2102
2103         if (src.isUndefinedOrNull()) {
2104             callFrame->uncheckedR(dst) = jsBoolean(true);
2105             vPC += OPCODE_LENGTH(op_eq_null);
2106             NEXT_INSTRUCTION();
2107         }
2108         
2109         callFrame->uncheckedR(dst) = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
2110         vPC += OPCODE_LENGTH(op_eq_null);
2111         NEXT_INSTRUCTION();
2112     }
2113     DEFINE_OPCODE(op_neq) {
2114         /* neq dst(r) src1(r) src2(r)
2115
2116            Checks whether register src1 and register src2 are not
2117            equal, as with the ECMAScript '!=' operator, and puts the
2118            result as a boolean in register dst.
2119         */
2120         int dst = vPC[1].u.operand;
2121         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2122         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2123         if (src1.isInt32() && src2.isInt32())
2124             callFrame->uncheckedR(dst) = jsBoolean(src1.asInt32() != src2.asInt32());
2125         else {
2126             JSValue result = jsBoolean(!JSValue::equalSlowCase(callFrame, src1, src2));
2127             CHECK_FOR_EXCEPTION();
2128             callFrame->uncheckedR(dst) = result;
2129         }
2130
2131         vPC += OPCODE_LENGTH(op_neq);
2132         NEXT_INSTRUCTION();
2133     }
2134     DEFINE_OPCODE(op_neq_null) {
2135         /* neq_null dst(r) src(r)
2136
2137            Checks whether register src is not null, as with the ECMAScript '!='
2138            operator, and puts the result as a boolean in register dst.
2139         */
2140         int dst = vPC[1].u.operand;
2141         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
2142
2143         if (src.isUndefinedOrNull()) {
2144             callFrame->uncheckedR(dst) = jsBoolean(false);
2145             vPC += OPCODE_LENGTH(op_neq_null);
2146             NEXT_INSTRUCTION();
2147         }
2148         
2149         callFrame->uncheckedR(dst) = jsBoolean(!src.isCell() || !src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
2150         vPC += OPCODE_LENGTH(op_neq_null);
2151         NEXT_INSTRUCTION();
2152     }
2153     DEFINE_OPCODE(op_stricteq) {
2154         /* stricteq dst(r) src1(r) src2(r)
2155
2156            Checks whether register src1 and register src2 are strictly
2157            equal, as with the ECMAScript '===' operator, and puts the
2158            result as a boolean in register dst.
2159         */
2160         int dst = vPC[1].u.operand;
2161         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2162         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2163         bool result = JSValue::strictEqual(callFrame, src1, src2);
2164         CHECK_FOR_EXCEPTION();
2165         callFrame->uncheckedR(dst) = jsBoolean(result);
2166
2167         vPC += OPCODE_LENGTH(op_stricteq);
2168         NEXT_INSTRUCTION();
2169     }
2170     DEFINE_OPCODE(op_nstricteq) {
2171         /* nstricteq dst(r) src1(r) src2(r)
2172
2173            Checks whether register src1 and register src2 are not
2174            strictly equal, as with the ECMAScript '!==' operator, and
2175            puts the result as a boolean in register dst.
2176         */
2177         int dst = vPC[1].u.operand;
2178         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2179         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2180         bool result = !JSValue::strictEqual(callFrame, src1, src2);
2181         CHECK_FOR_EXCEPTION();
2182         callFrame->uncheckedR(dst) = jsBoolean(result);
2183
2184         vPC += OPCODE_LENGTH(op_nstricteq);
2185         NEXT_INSTRUCTION();
2186     }
2187     DEFINE_OPCODE(op_less) {
2188         /* less dst(r) src1(r) src2(r)
2189
2190            Checks whether register src1 is less than register src2, as
2191            with the ECMAScript '<' operator, and puts the result as
2192            a boolean in register dst.
2193         */
2194         int dst = vPC[1].u.operand;
2195         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2196         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2197         JSValue result = jsBoolean(jsLess<true>(callFrame, src1, src2));
2198         CHECK_FOR_EXCEPTION();
2199         callFrame->uncheckedR(dst) = result;
2200
2201         vPC += OPCODE_LENGTH(op_less);
2202         NEXT_INSTRUCTION();
2203     }
2204     DEFINE_OPCODE(op_lesseq) {
2205         /* lesseq dst(r) src1(r) src2(r)
2206
2207            Checks whether register src1 is less than or equal to
2208            register src2, as with the ECMAScript '<=' operator, and
2209            puts the result as a boolean in register dst.
2210         */
2211         int dst = vPC[1].u.operand;
2212         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2213         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2214         JSValue result = jsBoolean(jsLessEq<true>(callFrame, src1, src2));
2215         CHECK_FOR_EXCEPTION();
2216         callFrame->uncheckedR(dst) = result;
2217
2218         vPC += OPCODE_LENGTH(op_lesseq);
2219         NEXT_INSTRUCTION();
2220     }
2221     DEFINE_OPCODE(op_greater) {
2222         /* greater dst(r) src1(r) src2(r)
2223
2224            Checks whether register src1 is greater than register src2, as
2225            with the ECMAScript '>' operator, and puts the result as
2226            a boolean in register dst.
2227         */
2228         int dst = vPC[1].u.operand;
2229         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2230         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2231         JSValue result = jsBoolean(jsLess<false>(callFrame, src2, src1));
2232         CHECK_FOR_EXCEPTION();
2233         callFrame->uncheckedR(dst) = result;
2234
2235         vPC += OPCODE_LENGTH(op_greater);
2236         NEXT_INSTRUCTION();
2237     }
2238     DEFINE_OPCODE(op_greatereq) {
2239         /* greatereq dst(r) src1(r) src2(r)
2240
2241            Checks whether register src1 is greater than or equal to
2242            register src2, as with the ECMAScript '>=' operator, and
2243            puts the result as a boolean in register dst.
2244         */
2245         int dst = vPC[1].u.operand;
2246         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2247         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2248         JSValue result = jsBoolean(jsLessEq<false>(callFrame, src2, src1));
2249         CHECK_FOR_EXCEPTION();
2250         callFrame->uncheckedR(dst) = result;
2251
2252         vPC += OPCODE_LENGTH(op_greatereq);
2253         NEXT_INSTRUCTION();
2254     }
2255     DEFINE_OPCODE(op_pre_inc) {
2256         /* pre_inc srcDst(r)
2257
2258            Converts register srcDst to number, adds one, and puts the result
2259            back in register srcDst.
2260         */
2261         int srcDst = vPC[1].u.operand;
2262         JSValue v = callFrame->r(srcDst).jsValue();
2263         if (v.isInt32() && v.asInt32() < INT_MAX)
2264             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() + 1);
2265         else {
2266             JSValue result = jsNumber(v.toNumber(callFrame) + 1);
2267             CHECK_FOR_EXCEPTION();
2268             callFrame->uncheckedR(srcDst) = result;
2269         }
2270
2271         vPC += OPCODE_LENGTH(op_pre_inc);
2272         NEXT_INSTRUCTION();
2273     }
2274     DEFINE_OPCODE(op_pre_dec) {
2275         /* pre_dec srcDst(r)
2276
2277            Converts register srcDst to number, subtracts one, and puts the result
2278            back in register srcDst.
2279         */
2280         int srcDst = vPC[1].u.operand;
2281         JSValue v = callFrame->r(srcDst).jsValue();
2282         if (v.isInt32() && v.asInt32() > INT_MIN)
2283             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() - 1);
2284         else {
2285             JSValue result = jsNumber(v.toNumber(callFrame) - 1);
2286             CHECK_FOR_EXCEPTION();
2287             callFrame->uncheckedR(srcDst) = result;
2288         }
2289
2290         vPC += OPCODE_LENGTH(op_pre_dec);
2291         NEXT_INSTRUCTION();
2292     }
2293     DEFINE_OPCODE(op_post_inc) {
2294         /* post_inc dst(r) srcDst(r)
2295
2296            Converts register srcDst to number. The number itself is
2297            written to register dst, and the number plus one is written
2298            back to register srcDst.
2299         */
2300         int dst = vPC[1].u.operand;
2301         int srcDst = vPC[2].u.operand;
2302         JSValue v = callFrame->r(srcDst).jsValue();
2303         if (v.isInt32() && v.asInt32() < INT_MAX) {
2304             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() + 1);
2305             callFrame->uncheckedR(dst) = v;
2306         } else {
2307             double number = callFrame->r(srcDst).jsValue().toNumber(callFrame);
2308             CHECK_FOR_EXCEPTION();
2309             callFrame->uncheckedR(srcDst) = jsNumber(number + 1);
2310             callFrame->uncheckedR(dst) = jsNumber(number);
2311         }
2312
2313         vPC += OPCODE_LENGTH(op_post_inc);
2314         NEXT_INSTRUCTION();
2315     }
2316     DEFINE_OPCODE(op_post_dec) {
2317         /* post_dec dst(r) srcDst(r)
2318
2319            Converts register srcDst to number. The number itself is
2320            written to register dst, and the number minus one is written
2321            back to register srcDst.
2322         */
2323         int dst = vPC[1].u.operand;
2324         int srcDst = vPC[2].u.operand;
2325         JSValue v = callFrame->r(srcDst).jsValue();
2326         if (v.isInt32() && v.asInt32() > INT_MIN) {
2327             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() - 1);
2328             callFrame->uncheckedR(dst) = v;
2329         } else {
2330             double number = callFrame->r(srcDst).jsValue().toNumber(callFrame);
2331             CHECK_FOR_EXCEPTION();
2332             callFrame->uncheckedR(srcDst) = jsNumber(number - 1);
2333             callFrame->uncheckedR(dst) = jsNumber(number);
2334         }
2335
2336         vPC += OPCODE_LENGTH(op_post_dec);
2337         NEXT_INSTRUCTION();
2338     }
2339     DEFINE_OPCODE(op_to_jsnumber) {
2340         /* to_jsnumber dst(r) src(r)
2341
2342            Converts register src to number, and puts the result
2343            in register dst.
2344         */
2345         int dst = vPC[1].u.operand;
2346         int src = vPC[2].u.operand;
2347
2348         JSValue srcVal = callFrame->r(src).jsValue();
2349
2350         if (LIKELY(srcVal.isNumber()))
2351             callFrame->uncheckedR(dst) = callFrame->r(src);
2352         else {
2353             double number = srcVal.toNumber(callFrame);
2354             CHECK_FOR_EXCEPTION();
2355             callFrame->uncheckedR(dst) = jsNumber(number);
2356         }
2357
2358         vPC += OPCODE_LENGTH(op_to_jsnumber);
2359         NEXT_INSTRUCTION();
2360     }
2361     DEFINE_OPCODE(op_negate) {
2362         /* negate dst(r) src(r)
2363
2364            Converts register src to number, negates it, and puts the
2365            result in register dst.
2366         */
2367         int dst = vPC[1].u.operand;
2368         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
2369         if (src.isInt32() && (src.asInt32() & 0x7fffffff)) // non-zero and no overflow
2370             callFrame->uncheckedR(dst) = jsNumber(-src.asInt32());
2371         else {
2372             JSValue result = jsNumber(-src.toNumber(callFrame));
2373             CHECK_FOR_EXCEPTION();
2374             callFrame->uncheckedR(dst) = result;
2375         }
2376
2377         vPC += OPCODE_LENGTH(op_negate);
2378         NEXT_INSTRUCTION();
2379     }
2380     DEFINE_OPCODE(op_add) {
2381         /* add dst(r) src1(r) src2(r)
2382
2383            Adds register src1 and register src2, and puts the result
2384            in register dst. (JS add may be string concatenation or
2385            numeric add, depending on the types of the operands.)
2386         */
2387         int dst = vPC[1].u.operand;
2388         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2389         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2390         if (src1.isInt32() && src2.isInt32() && !((src1.asInt32() | src2.asInt32()) & 0xc0000000)) // no overflow
2391             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() + src2.asInt32());
2392         else {
2393             JSValue result = jsAdd(callFrame, src1, src2);
2394             CHECK_FOR_EXCEPTION();
2395             callFrame->uncheckedR(dst) = result;
2396         }
2397         vPC += OPCODE_LENGTH(op_add);
2398         NEXT_INSTRUCTION();
2399     }
2400     DEFINE_OPCODE(op_mul) {
2401         /* mul dst(r) src1(r) src2(r)
2402
2403            Multiplies register src1 and register src2 (converted to
2404            numbers), and puts the product in register dst.
2405         */
2406         int dst = vPC[1].u.operand;
2407         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2408         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2409         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32()) >> 15) // no overflow
2410                 callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() * src2.asInt32());
2411         else {
2412             JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
2413             CHECK_FOR_EXCEPTION();
2414             callFrame->uncheckedR(dst) = result;
2415         }
2416
2417         vPC += OPCODE_LENGTH(op_mul);
2418         NEXT_INSTRUCTION();
2419     }
2420     DEFINE_OPCODE(op_div) {
2421         /* div dst(r) dividend(r) divisor(r)
2422
2423            Divides register dividend (converted to number) by the
2424            register divisor (converted to number), and puts the
2425            quotient in register dst.
2426         */
2427         int dst = vPC[1].u.operand;
2428         JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
2429         JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
2430
2431         JSValue result = jsNumber(dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
2432         CHECK_FOR_EXCEPTION();
2433         callFrame->uncheckedR(dst) = result;
2434
2435         vPC += OPCODE_LENGTH(op_div);
2436         NEXT_INSTRUCTION();
2437     }
2438     DEFINE_OPCODE(op_mod) {
2439         /* mod dst(r) dividend(r) divisor(r)
2440
2441            Divides register dividend (converted to number) by
2442            register divisor (converted to number), and puts the
2443            remainder in register dst.
2444         */
2445         int dst = vPC[1].u.operand;
2446         JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
2447         JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
2448
2449         if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0 && divisor.asInt32() != -1) {
2450             JSValue result = jsNumber(dividend.asInt32() % divisor.asInt32());
2451             ASSERT(result);
2452             callFrame->uncheckedR(dst) = result;
2453             vPC += OPCODE_LENGTH(op_mod);
2454             NEXT_INSTRUCTION();
2455         }
2456
2457         // Conversion to double must happen outside the call to fmod since the
2458         // order of argument evaluation is not guaranteed.
2459         double d1 = dividend.toNumber(callFrame);
2460         double d2 = divisor.toNumber(callFrame);
2461         JSValue result = jsNumber(fmod(d1, d2));
2462         CHECK_FOR_EXCEPTION();
2463         callFrame->uncheckedR(dst) = result;
2464         vPC += OPCODE_LENGTH(op_mod);
2465         NEXT_INSTRUCTION();
2466     }
2467     DEFINE_OPCODE(op_sub) {
2468         /* sub dst(r) src1(r) src2(r)
2469
2470            Subtracts register src2 (converted to number) from register
2471            src1 (converted to number), and puts the difference in
2472            register dst.
2473         */
2474         int dst = vPC[1].u.operand;
2475         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2476         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2477         if (src1.isInt32() && src2.isInt32() && !((src1.asInt32() | src2.asInt32()) & 0xc0000000)) // no overflow
2478             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() - src2.asInt32());
2479         else {
2480             JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
2481             CHECK_FOR_EXCEPTION();
2482             callFrame->uncheckedR(dst) = result;
2483         }
2484         vPC += OPCODE_LENGTH(op_sub);
2485         NEXT_INSTRUCTION();
2486     }
2487     DEFINE_OPCODE(op_lshift) {
2488         /* lshift dst(r) val(r) shift(r)
2489
2490            Performs left shift of register val (converted to int32) by
2491            register shift (converted to uint32), and puts the result
2492            in register dst.
2493         */
2494         int dst = vPC[1].u.operand;
2495         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
2496         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
2497
2498         if (val.isInt32() && shift.isInt32())
2499             callFrame->uncheckedR(dst) = jsNumber(val.asInt32() << (shift.asInt32() & 0x1f));
2500         else {
2501             JSValue result = jsNumber((val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
2502             CHECK_FOR_EXCEPTION();
2503             callFrame->uncheckedR(dst) = result;
2504         }
2505
2506         vPC += OPCODE_LENGTH(op_lshift);
2507         NEXT_INSTRUCTION();
2508     }
2509     DEFINE_OPCODE(op_rshift) {
2510         /* rshift dst(r) val(r) shift(r)
2511
2512            Performs arithmetic right shift of register val (converted
2513            to int32) by register shift (converted to
2514            uint32), and puts the result in register dst.
2515         */
2516         int dst = vPC[1].u.operand;
2517         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
2518         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
2519
2520         if (val.isInt32() && shift.isInt32())
2521             callFrame->uncheckedR(dst) = jsNumber(val.asInt32() >> (shift.asInt32() & 0x1f));
2522         else {
2523             JSValue result = jsNumber((val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
2524             CHECK_FOR_EXCEPTION();
2525             callFrame->uncheckedR(dst) = result;
2526         }
2527
2528         vPC += OPCODE_LENGTH(op_rshift);
2529         NEXT_INSTRUCTION();
2530     }
2531     DEFINE_OPCODE(op_urshift) {
2532         /* rshift dst(r) val(r) shift(r)
2533
2534            Performs logical right shift of register val (converted
2535            to uint32) by register shift (converted to
2536            uint32), and puts the result in register dst.
2537         */
2538         int dst = vPC[1].u.operand;
2539         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
2540         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
2541         if (val.isUInt32() && shift.isInt32())
2542             callFrame->uncheckedR(dst) = jsNumber(val.asInt32() >> (shift.asInt32() & 0x1f));
2543         else {
2544             JSValue result = jsNumber((val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
2545             CHECK_FOR_EXCEPTION();
2546             callFrame->uncheckedR(dst) = result;
2547         }
2548
2549         vPC += OPCODE_LENGTH(op_urshift);
2550         NEXT_INSTRUCTION();
2551     }
2552     DEFINE_OPCODE(op_bitand) {
2553         /* bitand dst(r) src1(r) src2(r)
2554
2555            Computes bitwise AND of register src1 (converted to int32)
2556            and register src2 (converted to int32), and puts the result
2557            in register dst.
2558         */
2559         int dst = vPC[1].u.operand;
2560         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2561         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2562         if (src1.isInt32() && src2.isInt32())
2563             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() & src2.asInt32());
2564         else {
2565             JSValue result = jsNumber(src1.toInt32(callFrame) & src2.toInt32(callFrame));
2566             CHECK_FOR_EXCEPTION();
2567             callFrame->uncheckedR(dst) = result;
2568         }
2569
2570         vPC += OPCODE_LENGTH(op_bitand);
2571         NEXT_INSTRUCTION();
2572     }
2573     DEFINE_OPCODE(op_bitxor) {
2574         /* bitxor dst(r) src1(r) src2(r)
2575
2576            Computes bitwise XOR of register src1 (converted to int32)
2577            and register src2 (converted to int32), and puts the result
2578            in register dst.
2579         */
2580         int dst = vPC[1].u.operand;
2581         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2582         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2583         if (src1.isInt32() && src2.isInt32())
2584             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() ^ src2.asInt32());
2585         else {
2586             JSValue result = jsNumber(src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
2587             CHECK_FOR_EXCEPTION();
2588             callFrame->uncheckedR(dst) = result;
2589         }
2590
2591         vPC += OPCODE_LENGTH(op_bitxor);
2592         NEXT_INSTRUCTION();
2593     }
2594     DEFINE_OPCODE(op_bitor) {
2595         /* bitor dst(r) src1(r) src2(r)
2596
2597            Computes bitwise OR of register src1 (converted to int32)
2598            and register src2 (converted to int32), and puts the
2599            result in register dst.
2600         */
2601         int dst = vPC[1].u.operand;
2602         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
2603         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
2604         if (src1.isInt32() && src2.isInt32())
2605             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() | src2.asInt32());
2606         else {
2607             JSValue result = jsNumber(src1.toInt32(callFrame) | src2.toInt32(callFrame));
2608             CHECK_FOR_EXCEPTION();
2609             callFrame->uncheckedR(dst) = result;
2610         }
2611
2612         vPC += OPCODE_LENGTH(op_bitor);
2613         NEXT_INSTRUCTION();
2614     }
2615     DEFINE_OPCODE(op_not) {
2616         /* not dst(r) src(r)
2617
2618            Computes logical NOT of register src (converted to
2619            boolean), and puts the result in register dst.
2620         */
2621         int dst = vPC[1].u.operand;
2622         int src = vPC[2].u.operand;
2623         JSValue result = jsBoolean(!callFrame->r(src).jsValue().toBoolean());
2624         CHECK_FOR_EXCEPTION();
2625         callFrame->uncheckedR(dst) = result;
2626
2627         vPC += OPCODE_LENGTH(op_not);
2628         NEXT_INSTRUCTION();
2629     }
2630     DEFINE_OPCODE(op_check_has_instance) {
2631         /* check_has_instance constructor(r)
2632
2633            Check 'constructor' is an object with the internal property
2634            [HasInstance] (i.e. is a function ... *shakes head sadly at
2635            JSC API*). Raises an exception if register constructor is not
2636            an valid parameter for instanceof.
2637         */
2638         int base = vPC[1].u.operand;
2639         JSValue baseVal = callFrame->r(base).jsValue();
2640
2641         if (isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue))
2642             goto vm_throw;
2643
2644         vPC += OPCODE_LENGTH(op_check_has_instance);
2645         NEXT_INSTRUCTION();
2646     }
2647     DEFINE_OPCODE(op_instanceof) {
2648         /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
2649
2650            Tests whether register value is an instance of register
2651            constructor, and puts the boolean result in register
2652            dst. Register constructorProto must contain the "prototype"
2653            property (not the actual prototype) of the object in
2654            register constructor. This lookup is separated so that
2655            polymorphic inline caching can apply.
2656
2657            Raises an exception if register constructor is not an
2658            object.
2659         */
2660         int dst = vPC[1].u.operand;
2661         int value = vPC[2].u.operand;
2662         int base = vPC[3].u.operand;
2663         int baseProto = vPC[4].u.operand;
2664
2665         JSValue baseVal = callFrame->r(base).jsValue();
2666
2667         ASSERT(!isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue));
2668
2669         bool result = asObject(baseVal)->methodTable()->hasInstance(asObject(baseVal), callFrame, callFrame->r(value).jsValue(), callFrame->r(baseProto).jsValue());
2670         CHECK_FOR_EXCEPTION();
2671         callFrame->uncheckedR(dst) = jsBoolean(result);
2672
2673         vPC += OPCODE_LENGTH(op_instanceof);
2674         NEXT_INSTRUCTION();
2675     }
2676     DEFINE_OPCODE(op_typeof) {
2677         /* typeof dst(r) src(r)
2678
2679            Determines the type string for src according to ECMAScript
2680            rules, and puts the result in register dst.
2681         */
2682         int dst = vPC[1].u.operand;
2683         int src = vPC[2].u.operand;
2684         callFrame->uncheckedR(dst) = JSValue(jsTypeStringForValue(callFrame, callFrame->r(src).jsValue()));
2685
2686         vPC += OPCODE_LENGTH(op_typeof);
2687         NEXT_INSTRUCTION();
2688     }
2689     DEFINE_OPCODE(op_is_undefined) {
2690         /* is_undefined dst(r) src(r)
2691
2692            Determines whether the type string for src according to
2693            the ECMAScript rules is "undefined", and puts the result
2694            in register dst.
2695         */
2696         int dst = vPC[1].u.operand;
2697         int src = vPC[2].u.operand;
2698         JSValue v = callFrame->r(src).jsValue();
2699         callFrame->uncheckedR(dst) = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined());
2700
2701         vPC += OPCODE_LENGTH(op_is_undefined);
2702         NEXT_INSTRUCTION();
2703     }
2704     DEFINE_OPCODE(op_is_boolean) {
2705         /* is_boolean dst(r) src(r)
2706
2707            Determines whether the type string for src according to
2708            the ECMAScript rules is "boolean", and puts the result
2709            in register dst.
2710         */
2711         int dst = vPC[1].u.operand;
2712         int src = vPC[2].u.operand;
2713         callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isBoolean());
2714
2715         vPC += OPCODE_LENGTH(op_is_boolean);
2716         NEXT_INSTRUCTION();
2717     }
2718     DEFINE_OPCODE(op_is_number) {
2719         /* is_number dst(r) src(r)
2720
2721            Determines whether the type string for src according to
2722            the ECMAScript rules is "number", and puts the result
2723            in register dst.
2724         */
2725         int dst = vPC[1].u.operand;
2726         int src = vPC[2].u.operand;
2727         callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isNumber());
2728
2729         vPC += OPCODE_LENGTH(op_is_number);
2730         NEXT_INSTRUCTION();
2731     }
2732     DEFINE_OPCODE(op_is_string) {
2733         /* is_string dst(r) src(r)
2734
2735            Determines whether the type string for src according to
2736            the ECMAScript rules is "string", and puts the result
2737            in register dst.
2738         */
2739         int dst = vPC[1].u.operand;
2740         int src = vPC[2].u.operand;
2741         callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isString());
2742
2743         vPC += OPCODE_LENGTH(op_is_string);
2744         NEXT_INSTRUCTION();
2745     }
2746     DEFINE_OPCODE(op_is_object) {
2747         /* is_object dst(r) src(r)
2748
2749            Determines whether the type string for src according to
2750            the ECMAScript rules is "object", and puts the result
2751            in register dst.
2752         */
2753         int dst = vPC[1].u.operand;
2754         int src = vPC[2].u.operand;
2755         callFrame->uncheckedR(dst) = jsBoolean(jsIsObjectType(callFrame->r(src).jsValue()));
2756
2757         vPC += OPCODE_LENGTH(op_is_object);
2758         NEXT_INSTRUCTION();
2759     }
2760     DEFINE_OPCODE(op_is_function) {
2761         /* is_function dst(r) src(r)
2762
2763            Determines whether the type string for src according to
2764            the ECMAScript rules is "function", and puts the result
2765            in register dst.
2766         */
2767         int dst = vPC[1].u.operand;
2768         int src = vPC[2].u.operand;
2769         callFrame->uncheckedR(dst) = jsBoolean(jsIsFunctionType(callFrame->r(src).jsValue()));
2770
2771         vPC += OPCODE_LENGTH(op_is_function);
2772         NEXT_INSTRUCTION();
2773     }
2774     DEFINE_OPCODE(op_in) {
2775         /* in dst(r) property(r) base(r)
2776
2777            Tests whether register base has a property named register
2778            property, and puts the boolean result in register dst.
2779
2780            Raises an exception if register constructor is not an
2781            object.
2782         */
2783         int dst = vPC[1].u.operand;
2784         int property = vPC[2].u.operand;
2785         int base = vPC[3].u.operand;
2786
2787         JSValue baseVal = callFrame->r(base).jsValue();
2788         if (isInvalidParamForIn(callFrame, baseVal, exceptionValue))
2789             goto vm_throw;
2790
2791         JSObject* baseObj = asObject(baseVal);
2792
2793         JSValue propName = callFrame->r(property).jsValue();
2794
2795         uint32_t i;
2796         if (propName.getUInt32(i))
2797             callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, i));
2798         else {
2799             Identifier property(callFrame, propName.toString(callFrame)->value(callFrame));
2800             CHECK_FOR_EXCEPTION();
2801             callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, property));
2802         }
2803
2804         vPC += OPCODE_LENGTH(op_in);
2805         NEXT_INSTRUCTION();
2806     }
2807     DEFINE_OPCODE(op_resolve) {
2808         /* resolve dst(r) property(id)
2809
2810            Looks up the property named by identifier property in the
2811            scope chain, and writes the resulting value to register
2812            dst. If the property is not found, raises an exception.
2813         */
2814         if (UNLIKELY(!resolve(callFrame, vPC, exceptionValue)))
2815             goto vm_throw;
2816
2817         vPC += OPCODE_LENGTH(op_resolve);
2818         NEXT_INSTRUCTION();
2819     }
2820     DEFINE_OPCODE(op_resolve_skip) {
2821         /* resolve_skip dst(r) property(id) skip(n)
2822
2823          Looks up the property named by identifier property in the
2824          scope chain skipping the top 'skip' levels, and writes the resulting
2825          value to register dst. If the property is not found, raises an exception.
2826          */
2827         if (UNLIKELY(!resolveSkip(callFrame, vPC, exceptionValue)))
2828             goto vm_throw;
2829
2830         vPC += OPCODE_LENGTH(op_resolve_skip);
2831
2832         NEXT_INSTRUCTION();
2833     }
2834     DEFINE_OPCODE(op_resolve_global) {
2835         /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n)
2836          
2837            Performs a dynamic property lookup for the given property, on the provided
2838            global object.  If structure matches the Structure of the global then perform
2839            a fast lookup using the case offset, otherwise fall back to a full resolve and
2840            cache the new structure and offset
2841          */
2842         if (UNLIKELY(!resolveGlobal(callFrame, vPC, exceptionValue)))
2843             goto vm_throw;
2844         
2845         vPC += OPCODE_LENGTH(op_resolve_global);
2846         
2847         NEXT_INSTRUCTION();
2848     }
2849     DEFINE_OPCODE(op_resolve_global_dynamic) {
2850         /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n), depth(n)
2851          
2852          Performs a dynamic property lookup for the given property, on the provided
2853          global object.  If structure matches the Structure of the global then perform
2854          a fast lookup using the case offset, otherwise fall back to a full resolve and
2855          cache the new structure and offset.
2856          
2857          This walks through n levels of the scope chain to verify that none of those levels
2858          in the scope chain include dynamically added properties.
2859          */
2860         if (UNLIKELY(!resolveGlobalDynamic(callFrame, vPC, exceptionValue)))
2861             goto vm_throw;
2862         
2863         vPC += OPCODE_LENGTH(op_resolve_global_dynamic);
2864         
2865         NEXT_INSTRUCTION();
2866     }
2867     DEFINE_OPCODE(op_get_global_var) {
2868         /* get_global_var dst(r) globalObject(c) index(n)
2869
2870            Gets the global var at global slot index and places it in register dst.
2871          */
2872         int dst = vPC[1].u.operand;
2873         JSGlobalObject* scope = codeBlock->globalObject();
2874         ASSERT(scope->isGlobalObject());
2875         int index = vPC[2].u.operand;
2876
2877         callFrame->uncheckedR(dst) = scope->registerAt(index).get();
2878         vPC += OPCODE_LENGTH(op_get_global_var);
2879         NEXT_INSTRUCTION();
2880     }
2881     DEFINE_OPCODE(op_put_global_var) {
2882         /* put_global_var globalObject(c) index(n) value(r)
2883          
2884            Puts value into global slot index.
2885          */
2886         JSGlobalObject* scope = codeBlock->globalObject();
2887         ASSERT(scope->isGlobalObject());
2888         int index = vPC[1].u.operand;
2889         int value = vPC[2].u.operand;
2890         
2891         scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue());
2892         vPC += OPCODE_LENGTH(op_put_global_var);
2893         NEXT_INSTRUCTION();
2894     }
2895     DEFINE_OPCODE(op_get_scoped_var) {
2896         /* get_scoped_var dst(r) index(n) skip(n)
2897
2898          Loads the contents of the index-th local from the scope skip nodes from
2899          the top of the scope chain, and places it in register dst.
2900          */
2901         int dst = vPC[1].u.operand;
2902         int index = vPC[2].u.operand;
2903         int skip = vPC[3].u.operand;
2904
2905         ScopeChainNode* scopeChain = callFrame->scopeChain();
2906         ScopeChainIterator iter = scopeChain->begin();
2907         ScopeChainIterator end = scopeChain->end();
2908         ASSERT_UNUSED(end, iter != end);
2909         ASSERT(codeBlock == callFrame->codeBlock());
2910         bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
2911         ASSERT(skip || !checkTopLevel);
2912         if (checkTopLevel && skip--) {
2913             if (callFrame->r(codeBlock->activationRegister()).jsValue())
2914                 ++iter;
2915         }
2916         while (skip--) {
2917             ++iter;
2918             ASSERT_UNUSED(end, iter != end);
2919         }
2920         ASSERT((*iter)->isVariableObject());
2921         JSVariableObject* scope = jsCast<JSVariableObject*>(iter->get());
2922         callFrame->uncheckedR(dst) = scope->registerAt(index).get();
2923         ASSERT(callFrame->r(dst).jsValue());
2924         vPC += OPCODE_LENGTH(op_get_scoped_var);
2925         NEXT_INSTRUCTION();
2926     }
2927     DEFINE_OPCODE(op_put_scoped_var) {
2928         /* put_scoped_var index(n) skip(n) value(r)
2929
2930          */
2931         int index = vPC[1].u.operand;
2932         int skip = vPC[2].u.operand;
2933         int value = vPC[3].u.operand;
2934
2935         ScopeChainNode* scopeChain = callFrame->scopeChain();
2936         ScopeChainIterator iter = scopeChain->begin();
2937         ScopeChainIterator end = scopeChain->end();
2938         ASSERT(codeBlock == callFrame->codeBlock());
2939         ASSERT_UNUSED(end, iter != end);
2940         bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
2941         ASSERT(skip || !checkTopLevel);
2942         if (checkTopLevel && skip--) {
2943             if (callFrame->r(codeBlock->activationRegister()).jsValue())
2944                 ++iter;
2945         }
2946         while (skip--) {
2947             ++iter;
2948             ASSERT_UNUSED(end, iter != end);
2949         }
2950
2951         ASSERT((*iter)->isVariableObject());
2952         JSVariableObject* scope = jsCast<JSVariableObject*>(iter->get());
2953         ASSERT(callFrame->r(value).jsValue());
2954         scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue());
2955         vPC += OPCODE_LENGTH(op_put_scoped_var);
2956         NEXT_INSTRUCTION();
2957     }
2958     DEFINE_OPCODE(op_resolve_base) {
2959         /* resolve_base dst(r) property(id) isStrict(bool)
2960
2961            Searches the scope chain for an object containing
2962            identifier property, and if one is found, writes it to
2963            register dst. If none is found and isStrict is false, the
2964            outermost scope (which will be the global object) is
2965            stored in register dst.
2966         */
2967         resolveBase(callFrame, vPC);
2968         CHECK_FOR_EXCEPTION();
2969
2970         vPC += OPCODE_LENGTH(op_resolve_base);
2971         NEXT_INSTRUCTION();
2972     }
2973     DEFINE_OPCODE(op_ensure_property_exists) {
2974         /* ensure_property_exists base(r) property(id)
2975
2976            Throws an exception if property does not exist on base
2977          */
2978         int base = vPC[1].u.operand;
2979         int property = vPC[2].u.operand;
2980         Identifier& ident = codeBlock->identifier(property);
2981         
2982         JSValue baseVal = callFrame->r(base).jsValue();
2983         JSObject* baseObject = asObject(baseVal);
2984         PropertySlot slot(baseVal);
2985         if (!baseObject->getPropertySlot(callFrame, ident, slot)) {
2986             exceptionValue = createErrorForInvalidGlobalAssignment(callFrame, ident.ustring());
2987             goto vm_throw;
2988         }
2989
2990         vPC += OPCODE_LENGTH(op_ensure_property_exists);
2991         NEXT_INSTRUCTION();
2992     }
2993     DEFINE_OPCODE(op_resolve_with_base) {
2994         /* resolve_with_base baseDst(r) propDst(r) property(id)
2995
2996            Searches the scope chain for an object containing
2997            identifier property, and if one is found, writes it to
2998            register srcDst, and the retrieved property value to register
2999            propDst. If the property is not found, raises an exception.
3000
3001            This is more efficient than doing resolve_base followed by
3002            resolve, or resolve_base followed by get_by_id, as it
3003            avoids duplicate hash lookups.
3004         */
3005         if (UNLIKELY(!resolveBaseAndProperty(callFrame, vPC, exceptionValue)))
3006             goto vm_throw;
3007
3008         vPC += OPCODE_LENGTH(op_resolve_with_base);
3009         NEXT_INSTRUCTION();
3010     }
3011     DEFINE_OPCODE(op_resolve_with_this) {
3012         /* resolve_with_this thisDst(r) propDst(r) property(id)
3013
3014            Searches the scope chain for an object containing
3015            identifier property, and if one is found, writes the
3016            retrieved property value to register propDst, and the
3017            this object to pass in a call to thisDst.
3018
3019            If the property is not found, raises an exception.
3020         */
3021         if (UNLIKELY(!resolveThisAndProperty(callFrame, vPC, exceptionValue)))
3022             goto vm_throw;
3023
3024         vPC += OPCODE_LENGTH(op_resolve_with_this);
3025         NEXT_INSTRUCTION();
3026     }
3027     DEFINE_OPCODE(op_get_by_id) {
3028         /* get_by_id dst(r) base(r) property(id) structure(sID) nop(n) nop(n) nop(n)
3029
3030            Generic property access: Gets the property named by identifier
3031            property from the value base, and puts the result in register dst.
3032         */
3033         int dst = vPC[1].u.operand;
3034         int base = vPC[2].u.operand;
3035         int property = vPC[3].u.operand;
3036
3037         Identifier& ident = codeBlock->identifier(property);
3038         JSValue baseValue = callFrame->r(base).jsValue();
3039         PropertySlot slot(baseValue);
3040         JSValue result = baseValue.get(callFrame, ident, slot);
3041         CHECK_FOR_EXCEPTION();
3042
3043         tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
3044
3045         callFrame->uncheckedR(dst) = result;
3046         vPC += OPCODE_LENGTH(op_get_by_id);
3047         NEXT_INSTRUCTION();
3048     }
3049     DEFINE_OPCODE(op_get_by_id_self) {
3050         /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
3051
3052            Cached property access: Attempts to get a cached property from the
3053            value base. If the cache misses, op_get_by_id_self reverts to
3054            op_get_by_id.
3055         */
3056         int base = vPC[2].u.operand;
3057         JSValue baseValue = callFrame->r(base).jsValue();
3058
3059         if (LIKELY(baseValue.isCell())) {
3060             JSCell* baseCell = baseValue.asCell();
3061             Structure* structure = vPC[4].u.structure.get();
3062
3063             if (LIKELY(baseCell->structure() == structure)) {
3064                 ASSERT(baseCell->isObject());
3065                 JSObject* baseObject = asObject(baseCell);
3066                 int dst = vPC[1].u.operand;
3067                 int offset = vPC[5].u.operand;
3068
3069                 ASSERT(baseObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
3070                 callFrame->uncheckedR(dst) = JSValue(baseObject->getDirectOffset(offset));
3071
3072                 vPC += OPCODE_LENGTH(op_get_by_id_self);
3073                 NEXT_INSTRUCTION();
3074             }
3075         }
3076
3077         uncacheGetByID(codeBlock, vPC);
3078         NEXT_INSTRUCTION();
3079     }
3080     DEFINE_OPCODE(op_get_by_id_proto) {
3081         /* op_get_by_id_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
3082
3083            Cached property access: Attempts to get a cached property from the
3084            value base's prototype. If the cache misses, op_get_by_id_proto
3085            reverts to op_get_by_id.
3086         */
3087         int base = vPC[2].u.operand;
3088         JSValue baseValue = callFrame->r(base).jsValue();
3089
3090         if (LIKELY(baseValue.isCell())) {
3091             JSCell* baseCell = baseValue.asCell();
3092             Structure* structure = vPC[4].u.structure.get();
3093
3094             if (LIKELY(baseCell->structure() == structure)) {
3095                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
3096                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
3097                 Structure* prototypeStructure = vPC[5].u.structure.get();
3098
3099                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
3100                     int dst = vPC[1].u.operand;
3101                     int offset = vPC[6].u.operand;
3102
3103                     ASSERT(protoObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
3104                     ASSERT(baseValue.get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
3105                     callFrame->uncheckedR(dst) = JSValue(protoObject->getDirectOffset(offset));
3106
3107                     vPC += OPCODE_LENGTH(op_get_by_id_proto);
3108                     NEXT_INSTRUCTION();
3109                 }
3110             }
3111         }
3112
3113         uncacheGetByID(codeBlock, vPC);
3114         NEXT_INSTRUCTION();
3115     }
3116 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3117     goto *(&&skip_id_getter_proto);
3118 #endif
3119     DEFINE_OPCODE(op_get_by_id_getter_proto) {
3120         /* op_get_by_id_getter_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
3121          
3122          Cached property access: Attempts to get a cached getter property from the
3123          value base's prototype. If the cache misses, op_get_by_id_getter_proto
3124          reverts to op_get_by_id.
3125          */
3126         int base = vPC[2].u.operand;
3127         JSValue baseValue = callFrame->r(base).jsValue();
3128         
3129         if (LIKELY(baseValue.isCell())) {
3130             JSCell* baseCell = baseValue.asCell();
3131             Structure* structure = vPC[4].u.structure.get();
3132             
3133             if (LIKELY(baseCell->structure() == structure)) {
3134                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
3135                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
3136                 Structure* prototypeStructure = vPC[5].u.structure.get();
3137                 
3138                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
3139                     int dst = vPC[1].u.operand;
3140                     int offset = vPC[6].u.operand;
3141                     if (GetterSetter* getterSetter = asGetterSetter(protoObject->getDirectOffset(offset).asCell())) {
3142                         JSObject* getter = getterSetter->getter();
3143                         CallData callData;
3144                         CallType callType = getter->methodTable()->getCallData(getter, callData);
3145                         JSValue result = call(callFrame, getter, callType, callData, asObject(baseCell), ArgList());
3146                         CHECK_FOR_EXCEPTION();
3147                         callFrame->uncheckedR(dst) = result;
3148                     } else
3149                         callFrame->uncheckedR(dst) = jsUndefined();
3150                     vPC += OPCODE_LENGTH(op_get_by_id_getter_proto);
3151                     NEXT_INSTRUCTION();
3152                 }
3153             }
3154         }
3155         uncacheGetByID(codeBlock, vPC);
3156         NEXT_INSTRUCTION();
3157     }
3158 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3159     skip_id_getter_proto:
3160 #endif
3161 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3162     goto *(&&skip_id_custom_proto);
3163 #endif
3164     DEFINE_OPCODE(op_get_by_id_custom_proto) {
3165         /* op_get_by_id_custom_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
3166          
3167          Cached property access: Attempts to use a cached named property getter
3168          from the value base's prototype. If the cache misses, op_get_by_id_custom_proto
3169          reverts to op_get_by_id.
3170          */
3171         int base = vPC[2].u.operand;
3172         JSValue baseValue = callFrame->r(base).jsValue();
3173         
3174         if (LIKELY(baseValue.isCell())) {
3175             JSCell* baseCell = baseValue.asCell();
3176             Structure* structure = vPC[4].u.structure.get();
3177             
3178             if (LIKELY(baseCell->structure() == structure)) {
3179                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
3180                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
3181                 Structure* prototypeStructure = vPC[5].u.structure.get();
3182                 
3183                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
3184                     int dst = vPC[1].u.operand;
3185                     int property = vPC[3].u.operand;
3186                     Identifier& ident = codeBlock->identifier(property);
3187                     
3188                     PropertySlot::GetValueFunc getter = vPC[6].u.getterFunc;
3189                     JSValue result = getter(callFrame, protoObject, ident);
3190                     CHECK_FOR_EXCEPTION();
3191                     callFrame->uncheckedR(dst) = result;
3192                     vPC += OPCODE_LENGTH(op_get_by_id_custom_proto);
3193                     NEXT_INSTRUCTION();
3194                 }
3195             }
3196         }
3197         uncacheGetByID(codeBlock, vPC);
3198         NEXT_INSTRUCTION();
3199     }
3200 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3201     skip_id_custom_proto:
3202 #endif
3203 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3204     goto *(&&skip_get_by_id_chain);
3205 #endif
3206     DEFINE_OPCODE(op_get_by_id_chain) {
3207         /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
3208
3209            Cached property access: Attempts to get a cached property from the
3210            value base's prototype chain. If the cache misses, op_get_by_id_chain
3211            reverts to op_get_by_id.
3212         */
3213         int base = vPC[2].u.operand;
3214         JSValue baseValue = callFrame->r(base).jsValue();
3215
3216         if (LIKELY(baseValue.isCell())) {
3217             JSCell* baseCell = baseValue.asCell();
3218             Structure* structure = vPC[4].u.structure.get();
3219
3220             if (LIKELY(baseCell->structure() == structure)) {
3221                 WriteBarrier<Structure>* it = vPC[5].u.structureChain->head();
3222                 size_t count = vPC[6].u.operand;
3223                 WriteBarrier<Structure>* end = it + count;
3224
3225                 while (true) {
3226                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
3227
3228                     if (UNLIKELY(baseObject->structure() != (*it).get()))
3229                         break;
3230
3231                     if (++it == end) {
3232                         int dst = vPC[1].u.operand;
3233                         int offset = vPC[7].u.operand;
3234
3235                         ASSERT(baseObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
3236                         ASSERT(baseValue.get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
3237                         callFrame->uncheckedR(dst) = JSValue(baseObject->getDirectOffset(offset));
3238
3239                         vPC += OPCODE_LENGTH(op_get_by_id_chain);
3240                         NEXT_INSTRUCTION();
3241                     }
3242
3243                     // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
3244                     baseCell = baseObject;
3245                 }
3246             }
3247         }
3248
3249         uncacheGetByID(codeBlock, vPC);
3250         NEXT_INSTRUCTION();
3251     }
3252 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3253     skip_get_by_id_chain:
3254     goto *(&&skip_id_getter_self);
3255 #endif
3256     DEFINE_OPCODE(op_get_by_id_getter_self) {
3257         /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
3258          
3259          Cached property access: Attempts to get a cached property from the
3260          value base. If the cache misses, op_get_by_id_getter_self reverts to
3261          op_get_by_id.
3262          */
3263         int base = vPC[2].u.operand;
3264         JSValue baseValue = callFrame->r(base).jsValue();
3265         
3266         if (LIKELY(baseValue.isCell())) {
3267             JSCell* baseCell = baseValue.asCell();
3268             Structure* structure = vPC[4].u.structure.get();
3269             
3270             if (LIKELY(baseCell->structure() == structure)) {
3271                 ASSERT(baseCell->isObject());
3272                 JSObject* baseObject = asObject(baseCell);
3273                 int dst = vPC[1].u.operand;
3274                 int offset = vPC[5].u.operand;
3275
3276                 if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) {
3277                     JSObject* getter = getterSetter->getter();
3278                     CallData callData;
3279                     CallType callType = getter->methodTable()->getCallData(getter, callData);
3280                     JSValue result = call(callFrame, getter, callType, callData, baseObject, ArgList());
3281                     CHECK_FOR_EXCEPTION();
3282                     callFrame->uncheckedR(dst) = result;
3283                 } else
3284                     callFrame->uncheckedR(dst) = jsUndefined();
3285
3286                 vPC += OPCODE_LENGTH(op_get_by_id_getter_self);
3287                 NEXT_INSTRUCTION();
3288             }
3289         }
3290         uncacheGetByID(codeBlock, vPC);
3291         NEXT_INSTRUCTION();
3292     }
3293 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3294     skip_id_getter_self:
3295 #endif
3296 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3297     goto *(&&skip_id_custom_self);
3298 #endif
3299     DEFINE_OPCODE(op_get_by_id_custom_self) {
3300         /* op_get_by_id_custom_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
3301          
3302          Cached property access: Attempts to use a cached named property getter
3303          from the value base. If the cache misses, op_get_by_id_custom_self reverts to
3304          op_get_by_id.
3305          */
3306         int base = vPC[2].u.operand;
3307         JSValue baseValue = callFrame->r(base).jsValue();
3308         
3309         if (LIKELY(baseValue.isCell())) {
3310             JSCell* baseCell = baseValue.asCell();
3311             Structure* structure = vPC[4].u.structure.get();
3312             
3313             if (LIKELY(baseCell->structure() == structure)) {
3314                 ASSERT(baseCell->isObject());
3315                 int dst = vPC[1].u.operand;
3316                 int property = vPC[3].u.operand;
3317                 Identifier& ident = codeBlock->identifier(property);
3318
3319                 PropertySlot::GetValueFunc getter = vPC[5].u.getterFunc;
3320                 JSValue result = getter(callFrame, baseValue, ident);
3321                 CHECK_FOR_EXCEPTION();
3322                 callFrame->uncheckedR(dst) = result;
3323                 vPC += OPCODE_LENGTH(op_get_by_id_custom_self);
3324                 NEXT_INSTRUCTION();
3325             }
3326         }
3327         uncacheGetByID(codeBlock, vPC);
3328         NEXT_INSTRUCTION();
3329     }
3330 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3331 skip_id_custom_self:
3332 #endif
3333     DEFINE_OPCODE(op_get_by_id_generic) {
3334         /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
3335
3336            Generic property access: Gets the property named by identifier
3337            property from the value base, and puts the result in register dst.
3338         */
3339         int dst = vPC[1].u.operand;
3340         int base = vPC[2].u.operand;
3341         int property = vPC[3].u.operand;
3342
3343         Identifier& ident = codeBlock->identifier(property);
3344         JSValue baseValue = callFrame->r(base).jsValue();
3345         PropertySlot slot(baseValue);
3346         JSValue result = baseValue.get(callFrame, ident, slot);
3347         CHECK_FOR_EXCEPTION();
3348
3349         callFrame->uncheckedR(dst) = result;
3350         vPC += OPCODE_LENGTH(op_get_by_id_generic);
3351         NEXT_INSTRUCTION();
3352     }
3353 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3354     goto *(&&skip_id_getter_chain);
3355 #endif
3356     DEFINE_OPCODE(op_get_by_id_getter_chain) {
3357         /* op_get_by_id_getter_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
3358          
3359          Cached property access: Attempts to get a cached property from the
3360          value base's prototype chain. If the cache misses, op_get_by_id_getter_chain
3361          reverts to op_get_by_id.
3362          */
3363         int base = vPC[2].u.operand;
3364         JSValue baseValue = callFrame->r(base).jsValue();
3365         
3366         if (LIKELY(baseValue.isCell())) {
3367             JSCell* baseCell = baseValue.asCell();
3368             Structure* structure = vPC[4].u.structure.get();
3369             
3370             if (LIKELY(baseCell->structure() == structure)) {
3371                 WriteBarrier<Structure>* it = vPC[5].u.structureChain->head();
3372                 size_t count = vPC[6].u.operand;
3373                 WriteBarrier<Structure>* end = it + count;
3374                 
3375                 while (true) {
3376                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
3377                     
3378                     if (UNLIKELY(baseObject->structure() != (*it).get()))
3379                         break;
3380                     
3381                     if (++it == end) {
3382                         int dst = vPC[1].u.operand;
3383                         int offset = vPC[7].u.operand;
3384                         if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) {
3385                             JSObject* getter = getterSetter->getter();
3386                             CallData callData;
3387                             CallType callType = getter->methodTable()->getCallData(getter, callData);
3388                             JSValue result = call(callFrame, getter, callType, callData, baseValue, ArgList());
3389                             CHECK_FOR_EXCEPTION();
3390                             callFrame->uncheckedR(dst) = result;
3391                         } else
3392                             callFrame->uncheckedR(dst) = jsUndefined();
3393                         vPC += OPCODE_LENGTH(op_get_by_id_getter_chain);
3394                         NEXT_INSTRUCTION();
3395                     }
3396                     
3397                     // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
3398                     baseCell = baseObject;
3399                 }
3400             }
3401         }
3402         uncacheGetByID(codeBlock, vPC);
3403         NEXT_INSTRUCTION();
3404     }
3405 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3406     skip_id_getter_chain:
3407 #endif
3408 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3409     goto *(&&skip_id_custom_chain);
3410 #endif
3411     DEFINE_OPCODE(op_get_by_id_custom_chain) {
3412         /* op_get_by_id_custom_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
3413          
3414          Cached property access: Attempts to use a cached named property getter on the
3415          value base's prototype chain. If the cache misses, op_get_by_id_custom_chain
3416          reverts to op_get_by_id.
3417          */
3418         int base = vPC[2].u.operand;
3419         JSValue baseValue = callFrame->r(base).jsValue();
3420         
3421         if (LIKELY(baseValue.isCell())) {
3422             JSCell* baseCell = baseValue.asCell();
3423             Structure* structure = vPC[4].u.structure.get();
3424             
3425             if (LIKELY(baseCell->structure() == structure)) {
3426                 WriteBarrier<Structure>* it = vPC[5].u.structureChain->head();
3427                 size_t count = vPC[6].u.operand;
3428                 WriteBarrier<Structure>* end = it + count;
3429                 
3430                 while (true) {
3431                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
3432                     
3433                     if (UNLIKELY(baseObject->structure() != (*it).get()))
3434                         break;
3435                     
3436                     if (++it == end) {
3437                         int dst = vPC[1].u.operand;
3438                         int property = vPC[3].u.operand;
3439                         Identifier& ident = codeBlock->identifier(property);
3440                         
3441                         PropertySlot::GetValueFunc getter = vPC[7].u.getterFunc;
3442                         JSValue result = getter(callFrame, baseObject, ident);
3443                         CHECK_FOR_EXCEPTION();
3444                         callFrame->uncheckedR(dst) = result;
3445                         vPC += OPCODE_LENGTH(op_get_by_id_custom_chain);
3446                         NEXT_INSTRUCTION();
3447                     }
3448                     
3449                     // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
3450                     baseCell = baseObject;
3451                 }
3452             }
3453         }
3454         uncacheGetByID(codeBlock, vPC);
3455         NEXT_INSTRUCTION();
3456     }
3457 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3458     skip_id_custom_chain:
3459     goto *(&&skip_get_array_length);
3460 #endif
3461     DEFINE_OPCODE(op_get_array_length) {
3462         /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
3463
3464            Cached property access: Gets the length of the array in register base,
3465            and puts the result in register dst. If register base does not hold
3466            an array, op_get_array_length reverts to op_get_by_id.
3467         */
3468
3469         int base = vPC[2].u.operand;
3470         JSValue baseValue = callFrame->r(base).jsValue();
3471         if (LIKELY(isJSArray(baseValue))) {
3472             int dst = vPC[1].u.operand;
3473             callFrame->uncheckedR(dst) = jsNumber(asArray(baseValue)->length());
3474             vPC += OPCODE_LENGTH(op_get_array_length);
3475             NEXT_INSTRUCTION();
3476         }
3477
3478         uncacheGetByID(codeBlock, vPC);
3479         NEXT_INSTRUCTION();
3480     }
3481 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3482     skip_get_array_length:
3483     goto *(&&skip_get_string_length);
3484 #endif
3485     DEFINE_OPCODE(op_get_string_length) {
3486         /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
3487
3488            Cached property access: Gets the length of the string in register base,
3489            and puts the result in register dst. If register base does not hold
3490            a string, op_get_string_length reverts to op_get_by_id.
3491         */
3492
3493         int base = vPC[2].u.operand;
3494         JSValue baseValue = callFrame->r(base).jsValue();
3495         if (LIKELY(isJSString(baseValue))) {
3496             int dst = vPC[1].u.operand;
3497             callFrame->uncheckedR(dst) = jsNumber(asString(baseValue)->length());
3498             vPC += OPCODE_LENGTH(op_get_string_length);
3499             NEXT_INSTRUCTION();
3500         }
3501
3502         uncacheGetByID(codeBlock, vPC);
3503         NEXT_INSTRUCTION();
3504     }
3505 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3506     skip_get_string_length:
3507     goto *(&&skip_put_by_id);
3508 #endif
3509     DEFINE_OPCODE(op_put_by_id) {
3510         /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b)
3511
3512            Generic property access: Sets the property named by identifier
3513            property, belonging to register base, to register value.
3514
3515            Unlike many opcodes, this one does not write any output to
3516            the register file.
3517
3518            The "direct" flag should only be set this put_by_id is to initialize
3519            an object literal.
3520         */
3521
3522         int base = vPC[1].u.operand;
3523         int property = vPC[2].u.operand;
3524         int value = vPC[3].u.operand;
3525         int direct = vPC[8].u.operand;
3526
3527         JSValue baseValue = callFrame->r(base).jsValue();
3528         Identifier& ident = codeBlock->identifier(property);
3529         PutPropertySlot slot(codeBlock->isStrictMode());
3530         if (direct) {
3531             ASSERT(baseValue.isObject());
3532             asObject(baseValue)->putDirect(*globalData, ident, callFrame->r(value).jsValue(), slot);
3533         } else
3534             baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
3535         CHECK_FOR_EXCEPTION();
3536
3537         tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
3538
3539         vPC += OPCODE_LENGTH(op_put_by_id);
3540         NEXT_INSTRUCTION();
3541     }
3542 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
3543       skip_put_by_id:
3544 #endif
3545     DEFINE_OPCODE(op_put_by_id_transition_direct)
3546     DEFINE_OPCODE(op_put_by_id_transition_normal)
3547     DEFINE_OPCODE(op_put_by_id_transition) {
3548         /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n) direct(b)
3549          
3550            Cached property access: Attempts to set a new property with a cached transition
3551            property named by identifier property, belonging to register base,
3552            to register value. If the cache misses, op_put_by_id_transition
3553            reverts to op_put_by_id_generic.
3554          
3555            Unlike many opcodes, this one does not write any output to
3556            the register file.
3557          */
3558         int base = vPC[1].u.operand;
3559         JSValue baseValue = callFrame->r(base).jsValue();
3560         
3561         if (LIKELY(baseValue.isCell())) {
3562             JSCell* baseCell = baseValue.asCell();
3563             Structure* oldStructure = vPC[4].u.structure.get();
3564             Structure* newStructure = vPC[5].u.structure.get();
3565             
3566             if (LIKELY(baseCell->structure() == oldStructure)) {
3567                 ASSERT(baseCell->isObject());
3568                 JSObject* baseObject = asObject(baseCell);
3569                 int direct = vPC[8].u.operand;
3570                 
3571                 if (!direct) {
3572                     WriteBarrier<Structure>* it = vPC[6].u.structureChain->head();
3573
3574                     JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
3575                     while (!proto.isNull()) {
3576                         if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
3577                             uncachePutByID(codeBlock, vPC);
3578                             NEXT_INSTRUCTION();
3579                         }
3580                         ++it;
3581                         proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
3582                     }
3583                 }
3584                 baseObject->transitionTo(*globalData, newStructure);
3585
3586                 int value = vPC[3].u.operand;
3587                 unsigned offset = vPC[7].u.operand;
3588                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(*globalData, codeBlock->identifier(vPC[2].u.operand))) == offset);
3589                 baseObject->putDirectOffset(callFrame->globalData(), offset, callFrame->r(value).jsValue());
3590
3591                 vPC += OPCODE_LENGTH(op_put_by_id_transition);
3592                 NEXT_INSTRUCTION();
3593             }
3594         }
3595         
3596         uncachePutByID(codeBlock, vPC);
3597         NEXT_INSTRUCTION();
3598     }
3599     DEFINE_OPCODE(op_put_by_id_replace) {
3600         /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n) direct(b)
3601
3602            Cached property access: Attempts to set a pre-existing, cached
3603            property named by identifier property, belonging to register base,
3604            to register value. If the cache misses, op_put_by_id_replace
3605            reverts to op_put_by_id.
3606
3607            Unlike many opcodes, this one does not write any output to
3608            the register file.
3609         */
3610         int base = vPC[1].u.operand;
3611         JSValue baseValue = callFrame->r(base).jsValue();
3612
3613         if (LIKELY(baseValue.isCell())) {
3614             JSCell* baseCell = baseValue.asCell();
3615             Structure* structure = vPC[4].u.structure.get();
3616
3617             if (LIKELY(baseCell->structure() == structure)) {
3618                 ASSERT(baseCell->isObject());
3619                 JSObject* baseObject = asObject(baseCell);
3620                 int value = vPC[3].u.operand;
3621                 unsigned offset = vPC[5].u.operand;
3622                 
3623                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(*globalData, codeBlock->identifier(vPC[2].u.operand))) == offset);
3624                 baseObject->putDirectOffset(callFrame->globalData(), offset, callFrame->r(value).jsValue());
3625
3626                 vPC += OPCODE_LENGTH(op_put_by_id_replace);
3627                 NEXT_INSTRUCTION();
3628             }
3629         }
3630
3631         uncachePutByID(codeBlock, vPC);
3632         NEXT_INSTRUCTION();
3633     }
3634     DEFINE_OPCODE(op_put_by_id_generic) {
3635         /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b)
3636
3637            Generic property access: Sets the property named by identifier
3638            property, belonging to register base, to register value.
3639
3640            Unlike many opcodes, this one does not write any output to
3641            the register file.
3642         */
3643         int base = vPC[1].u.operand;
3644         int property = vPC[2].u.operand;
3645         int value = vPC[3].u.operand;
3646         int direct = vPC[8].u.operand;
3647
3648         JSValue baseValue = callFrame->r(base).jsValue();
3649         Identifier& ident = codeBlock->identifier(property);
3650         PutPropertySlot slot(codeBlock->isStrictMode());
3651         if (direct) {
3652             ASSERT(baseValue.isObject());
3653             asObject(baseValue)->putDirect(*globalData, ident, callFrame->r(value).jsValue(), slot);
3654         } else
3655             baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
3656         CHECK_FOR_EXCEPTION();
3657
3658         vPC += OPCODE_LENGTH(op_put_by_id_generic);
3659         NEXT_INSTRUCTION();
3660     }
3661     DEFINE_OPCODE(op_del_by_id) {
3662         /* del_by_id dst(r) base(r) property(id)
3663
3664            Converts register base to Object, deletes the property
3665            named by identifier property from the object, and writes a
3666            boolean indicating success (if true) or failure (if false)
3667            to register dst.
3668         */
3669         int dst = vPC[1].u.operand;
3670         int base = vPC[2].u.operand;
3671         int property = vPC[3].u.operand;
3672
3673         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame);
3674         Identifier& ident = codeBlock->identifier(property);
3675         bool result = baseObj->methodTable()->deleteProperty(baseObj, callFrame, ident);
3676         if (!result && codeBlock->isStrictMode()) {
3677             exceptionValue = createTypeError(callFrame, "Unable to delete property.");
3678             goto vm_throw;
3679         }
3680         CHECK_FOR_EXCEPTION();
3681  &nbs