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