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