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