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