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