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