• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "config.h"
31 #include "Interpreter.h"
32 
33 #include "Arguments.h"
34 #include "BatchedTransitionOptimizer.h"
35 #include "CodeBlock.h"
36 #include "DebuggerCallFrame.h"
37 #include "EvalCodeCache.h"
38 #include "ExceptionHelpers.h"
39 #include "CallFrame.h"
40 #include "GlobalEvalFunction.h"
41 #include "JSActivation.h"
42 #include "JSArray.h"
43 #include "JSByteArray.h"
44 #include "JSFunction.h"
45 #include "JSNotAnObject.h"
46 #include "JSPropertyNameIterator.h"
47 #include "JSStaticScopeObject.h"
48 #include "JSString.h"
49 #include "ObjectPrototype.h"
50 #include "Parser.h"
51 #include "Profiler.h"
52 #include "RegExpObject.h"
53 #include "RegExpPrototype.h"
54 #include "Register.h"
55 #include "Collector.h"
56 #include "Debugger.h"
57 #include "Operations.h"
58 #include "SamplingTool.h"
59 #include <stdio.h>
60 
61 #if ENABLE(JIT)
62 #include "JIT.h"
63 #endif
64 
65 #if ENABLE(ASSEMBLER)
66 #include "AssemblerBuffer.h"
67 #endif
68 
69 #if PLATFORM(DARWIN)
70 #include <mach/mach.h>
71 #endif
72 
73 #if HAVE(SYS_TIME_H)
74 #include <sys/time.h>
75 #endif
76 
77 #if PLATFORM(WIN_OS)
78 #include <windows.h>
79 #endif
80 
81 #if PLATFORM(QT)
82 #include <QDateTime>
83 #endif
84 
85 using namespace std;
86 
87 namespace JSC {
88 
89 // Preferred number of milliseconds between each timeout check
90 static const int preferredScriptCheckTimeInterval = 1000;
91 
bytecodeOffsetForPC(CallFrame * callFrame,CodeBlock * codeBlock,void * pc)92 static ALWAYS_INLINE unsigned bytecodeOffsetForPC(CallFrame* callFrame, CodeBlock* codeBlock, void* pc)
93 {
94 #if ENABLE(JIT)
95     return codeBlock->getBytecodeIndex(callFrame, pc);
96 #else
97     UNUSED_PARAM(callFrame);
98     return static_cast<Instruction*>(pc) - codeBlock->instructions().begin();
99 #endif
100 }
101 
102 // Returns the depth of the scope chain within a given call frame.
depth(CodeBlock * codeBlock,ScopeChain & sc)103 static int depth(CodeBlock* codeBlock, ScopeChain& sc)
104 {
105     if (!codeBlock->needsFullScopeChain())
106         return 0;
107     return sc.localDepth();
108 }
109 
jsLess(CallFrame * callFrame,JSValuePtr v1,JSValuePtr v2)110 static inline bool jsLess(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2)
111 {
112     if (JSValuePtr::areBothInt32Fast(v1, v2))
113         return v1.getInt32Fast() < v2.getInt32Fast();
114 
115     double n1;
116     double n2;
117     if (v1.getNumber(n1) && v2.getNumber(n2))
118         return n1 < n2;
119 
120     Interpreter* interpreter = callFrame->interpreter();
121     if (interpreter->isJSString(v1) && interpreter->isJSString(v2))
122         return asString(v1)->value() < asString(v2)->value();
123 
124     JSValuePtr p1;
125     JSValuePtr p2;
126     bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
127     bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
128 
129     if (wasNotString1 | wasNotString2)
130         return n1 < n2;
131 
132     return asString(p1)->value() < asString(p2)->value();
133 }
134 
jsLessEq(CallFrame * callFrame,JSValuePtr v1,JSValuePtr v2)135 static inline bool jsLessEq(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2)
136 {
137     if (JSValuePtr::areBothInt32Fast(v1, v2))
138         return v1.getInt32Fast() <= v2.getInt32Fast();
139 
140     double n1;
141     double n2;
142     if (v1.getNumber(n1) && v2.getNumber(n2))
143         return n1 <= n2;
144 
145     Interpreter* interpreter = callFrame->interpreter();
146     if (interpreter->isJSString(v1) && interpreter->isJSString(v2))
147         return !(asString(v2)->value() < asString(v1)->value());
148 
149     JSValuePtr p1;
150     JSValuePtr p2;
151     bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
152     bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
153 
154     if (wasNotString1 | wasNotString2)
155         return n1 <= n2;
156 
157     return !(asString(p2)->value() < asString(p1)->value());
158 }
159 
jsAddSlowCase(CallFrame * callFrame,JSValuePtr v1,JSValuePtr v2)160 static NEVER_INLINE JSValuePtr jsAddSlowCase(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2)
161 {
162     // exception for the Date exception in defaultValue()
163     JSValuePtr p1 = v1.toPrimitive(callFrame);
164     JSValuePtr p2 = v2.toPrimitive(callFrame);
165 
166     if (p1.isString() || p2.isString()) {
167         RefPtr<UString::Rep> value = concatenate(p1.toString(callFrame).rep(), p2.toString(callFrame).rep());
168         if (!value)
169             return throwOutOfMemoryError(callFrame);
170         return jsString(callFrame, value.release());
171     }
172 
173     return jsNumber(callFrame, p1.toNumber(callFrame) + p2.toNumber(callFrame));
174 }
175 
176 // Fast-path choices here are based on frequency data from SunSpider:
177 //    <times> Add case: <t1> <t2>
178 //    ---------------------------
179 //    5626160 Add case: 3 3 (of these, 3637690 are for immediate values)
180 //    247412  Add case: 5 5
181 //    20900   Add case: 5 6
182 //    13962   Add case: 5 3
183 //    4000    Add case: 3 5
184 
jsAdd(CallFrame * callFrame,JSValuePtr v1,JSValuePtr v2)185 static ALWAYS_INLINE JSValuePtr jsAdd(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2)
186 {
187     double left;
188     double right = 0.0;
189 
190     bool rightIsNumber = v2.getNumber(right);
191     if (rightIsNumber && v1.getNumber(left))
192         return jsNumber(callFrame, left + right);
193 
194     bool leftIsString = v1.isString();
195     if (leftIsString && v2.isString()) {
196         RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep());
197         if (!value)
198             return throwOutOfMemoryError(callFrame);
199         return jsString(callFrame, value.release());
200     }
201 
202     if (rightIsNumber & leftIsString) {
203         RefPtr<UString::Rep> value = v2.isInt32Fast() ?
204             concatenate(asString(v1)->value().rep(), v2.getInt32Fast()) :
205             concatenate(asString(v1)->value().rep(), right);
206 
207         if (!value)
208             return throwOutOfMemoryError(callFrame);
209         return jsString(callFrame, value.release());
210     }
211 
212     // All other cases are pretty uncommon
213     return jsAddSlowCase(callFrame, v1, v2);
214 }
215 
jsTypeStringForValue(CallFrame * callFrame,JSValuePtr v)216 static JSValuePtr jsTypeStringForValue(CallFrame* callFrame, JSValuePtr v)
217 {
218     if (v.isUndefined())
219         return jsNontrivialString(callFrame, "undefined");
220     if (v.isBoolean())
221         return jsNontrivialString(callFrame, "boolean");
222     if (v.isNumber())
223         return jsNontrivialString(callFrame, "number");
224     if (v.isString())
225         return jsNontrivialString(callFrame, "string");
226     if (v.isObject()) {
227         // Return "undefined" for objects that should be treated
228         // as null when doing comparisons.
229         if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined())
230             return jsNontrivialString(callFrame, "undefined");
231         CallData callData;
232         if (asObject(v)->getCallData(callData) != CallTypeNone)
233             return jsNontrivialString(callFrame, "function");
234     }
235     return jsNontrivialString(callFrame, "object");
236 }
237 
jsIsObjectType(JSValuePtr v)238 static bool jsIsObjectType(JSValuePtr v)
239 {
240     if (!v.isCell())
241         return v.isNull();
242 
243     JSType type = asCell(v)->structure()->typeInfo().type();
244     if (type == NumberType || type == StringType)
245         return false;
246     if (type == ObjectType) {
247         if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined())
248             return false;
249         CallData callData;
250         if (asObject(v)->getCallData(callData) != CallTypeNone)
251             return false;
252     }
253     return true;
254 }
255 
jsIsFunctionType(JSValuePtr v)256 static bool jsIsFunctionType(JSValuePtr v)
257 {
258     if (v.isObject()) {
259         CallData callData;
260         if (asObject(v)->getCallData(callData) != CallTypeNone)
261             return true;
262     }
263     return false;
264 }
265 
resolve(CallFrame * callFrame,Instruction * vPC,JSValuePtr & exceptionValue)266 NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
267 {
268     int dst = (vPC + 1)->u.operand;
269     int property = (vPC + 2)->u.operand;
270 
271     ScopeChainNode* scopeChain = callFrame->scopeChain();
272     ScopeChainIterator iter = scopeChain->begin();
273     ScopeChainIterator end = scopeChain->end();
274     ASSERT(iter != end);
275 
276     CodeBlock* codeBlock = callFrame->codeBlock();
277     Identifier& ident = codeBlock->identifier(property);
278     do {
279         JSObject* o = *iter;
280         PropertySlot slot(o);
281         if (o->getPropertySlot(callFrame, ident, slot)) {
282             JSValuePtr result = slot.getValue(callFrame, ident);
283             exceptionValue = callFrame->globalData().exception;
284             if (exceptionValue)
285                 return false;
286             callFrame[dst] = JSValuePtr(result);
287             return true;
288         }
289     } while (++iter != end);
290     exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
291     return false;
292 }
293 
resolveSkip(CallFrame * callFrame,Instruction * vPC,JSValuePtr & exceptionValue)294 NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
295 {
296     CodeBlock* codeBlock = callFrame->codeBlock();
297 
298     int dst = (vPC + 1)->u.operand;
299     int property = (vPC + 2)->u.operand;
300     int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain();
301 
302     ScopeChainNode* scopeChain = callFrame->scopeChain();
303     ScopeChainIterator iter = scopeChain->begin();
304     ScopeChainIterator end = scopeChain->end();
305     ASSERT(iter != end);
306     while (skip--) {
307         ++iter;
308         ASSERT(iter != end);
309     }
310     Identifier& ident = codeBlock->identifier(property);
311     do {
312         JSObject* o = *iter;
313         PropertySlot slot(o);
314         if (o->getPropertySlot(callFrame, ident, slot)) {
315             JSValuePtr result = slot.getValue(callFrame, ident);
316             exceptionValue = callFrame->globalData().exception;
317             if (exceptionValue)
318                 return false;
319             callFrame[dst] = JSValuePtr(result);
320             return true;
321         }
322     } while (++iter != end);
323     exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
324     return false;
325 }
326 
resolveGlobal(CallFrame * callFrame,Instruction * vPC,JSValuePtr & exceptionValue)327 NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
328 {
329     int dst = (vPC + 1)->u.operand;
330     JSGlobalObject* globalObject = static_cast<JSGlobalObject*>((vPC + 2)->u.jsCell);
331     ASSERT(globalObject->isGlobalObject());
332     int property = (vPC + 3)->u.operand;
333     Structure* structure = (vPC + 4)->u.structure;
334     int offset = (vPC + 5)->u.operand;
335 
336     if (structure == globalObject->structure()) {
337         callFrame[dst] = JSValuePtr(globalObject->getDirectOffset(offset));
338         return true;
339     }
340 
341     CodeBlock* codeBlock = callFrame->codeBlock();
342     Identifier& ident = codeBlock->identifier(property);
343     PropertySlot slot(globalObject);
344     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
345         JSValuePtr result = slot.getValue(callFrame, ident);
346         if (slot.isCacheable() && !globalObject->structure()->isDictionary()) {
347             if (vPC[4].u.structure)
348                 vPC[4].u.structure->deref();
349             globalObject->structure()->ref();
350             vPC[4] = globalObject->structure();
351             vPC[5] = slot.cachedOffset();
352             callFrame[dst] = JSValuePtr(result);
353             return true;
354         }
355 
356         exceptionValue = callFrame->globalData().exception;
357         if (exceptionValue)
358             return false;
359         callFrame[dst] = JSValuePtr(result);
360         return true;
361     }
362 
363     exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
364     return false;
365 }
366 
inlineResolveBase(CallFrame * callFrame,Identifier & property,ScopeChainNode * scopeChain)367 static ALWAYS_INLINE JSValuePtr inlineResolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain)
368 {
369     ScopeChainIterator iter = scopeChain->begin();
370     ScopeChainIterator next = iter;
371     ++next;
372     ScopeChainIterator end = scopeChain->end();
373     ASSERT(iter != end);
374 
375     PropertySlot slot;
376     JSObject* base;
377     while (true) {
378         base = *iter;
379         if (next == end || base->getPropertySlot(callFrame, property, slot))
380             return base;
381 
382         iter = next;
383         ++next;
384     }
385 
386     ASSERT_NOT_REACHED();
387     return noValue();
388 }
389 
resolveBase(CallFrame * callFrame,Instruction * vPC)390 NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC)
391 {
392     int dst = (vPC + 1)->u.operand;
393     int property = (vPC + 2)->u.operand;
394     callFrame[dst] = JSValuePtr(inlineResolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain()));
395 }
396 
resolveBaseAndProperty(CallFrame * callFrame,Instruction * vPC,JSValuePtr & exceptionValue)397 NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
398 {
399     int baseDst = (vPC + 1)->u.operand;
400     int propDst = (vPC + 2)->u.operand;
401     int property = (vPC + 3)->u.operand;
402 
403     ScopeChainNode* scopeChain = callFrame->scopeChain();
404     ScopeChainIterator iter = scopeChain->begin();
405     ScopeChainIterator end = scopeChain->end();
406 
407     // FIXME: add scopeDepthIsZero optimization
408 
409     ASSERT(iter != end);
410 
411     CodeBlock* codeBlock = callFrame->codeBlock();
412     Identifier& ident = codeBlock->identifier(property);
413     JSObject* base;
414     do {
415         base = *iter;
416         PropertySlot slot(base);
417         if (base->getPropertySlot(callFrame, ident, slot)) {
418             JSValuePtr result = slot.getValue(callFrame, ident);
419             exceptionValue = callFrame->globalData().exception;
420             if (exceptionValue)
421                 return false;
422             callFrame[propDst] = JSValuePtr(result);
423             callFrame[baseDst] = JSValuePtr(base);
424             return true;
425         }
426         ++iter;
427     } while (iter != end);
428 
429     exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
430     return false;
431 }
432 
resolveBaseAndFunc(CallFrame * callFrame,Instruction * vPC,JSValuePtr & exceptionValue)433 NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
434 {
435     int baseDst = (vPC + 1)->u.operand;
436     int funcDst = (vPC + 2)->u.operand;
437     int property = (vPC + 3)->u.operand;
438 
439     ScopeChainNode* scopeChain = callFrame->scopeChain();
440     ScopeChainIterator iter = scopeChain->begin();
441     ScopeChainIterator end = scopeChain->end();
442 
443     // FIXME: add scopeDepthIsZero optimization
444 
445     ASSERT(iter != end);
446 
447     CodeBlock* codeBlock = callFrame->codeBlock();
448     Identifier& ident = codeBlock->identifier(property);
449     JSObject* base;
450     do {
451         base = *iter;
452         PropertySlot slot(base);
453         if (base->getPropertySlot(callFrame, ident, slot)) {
454             // ECMA 11.2.3 says that if we hit an activation the this value should be null.
455             // However, section 10.2.3 says that in the case where the value provided
456             // by the caller is null, the global object should be used. It also says
457             // that the section does not apply to internal functions, but for simplicity
458             // of implementation we use the global object anyway here. This guarantees
459             // that in host objects you always get a valid object for this.
460             // We also handle wrapper substitution for the global object at the same time.
461             JSObject* thisObj = base->toThisObject(callFrame);
462             JSValuePtr result = slot.getValue(callFrame, ident);
463             exceptionValue = callFrame->globalData().exception;
464             if (exceptionValue)
465                 return false;
466 
467             callFrame[baseDst] = JSValuePtr(thisObj);
468             callFrame[funcDst] = JSValuePtr(result);
469             return true;
470         }
471         ++iter;
472     } while (iter != end);
473 
474     exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
475     return false;
476 }
477 
slideRegisterWindowForCall(CodeBlock * newCodeBlock,RegisterFile * registerFile,CallFrame * callFrame,size_t registerOffset,int argc)478 ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
479 {
480     Register* r = callFrame->registers();
481     Register* newEnd = r + registerOffset + newCodeBlock->m_numCalleeRegisters;
482 
483     if (LIKELY(argc == newCodeBlock->m_numParameters)) { // correct number of arguments
484         if (UNLIKELY(!registerFile->grow(newEnd)))
485             return 0;
486         r += registerOffset;
487     } else if (argc < newCodeBlock->m_numParameters) { // too few arguments -- fill in the blanks
488         size_t omittedArgCount = newCodeBlock->m_numParameters - argc;
489         registerOffset += omittedArgCount;
490         newEnd += omittedArgCount;
491         if (!registerFile->grow(newEnd))
492             return 0;
493         r += registerOffset;
494 
495         Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
496         for (size_t i = 0; i < omittedArgCount; ++i)
497             argv[i] = jsUndefined();
498     } else { // too many arguments -- copy expected arguments, leaving the extra arguments behind
499         size_t numParameters = newCodeBlock->m_numParameters;
500         registerOffset += numParameters;
501         newEnd += numParameters;
502 
503         if (!registerFile->grow(newEnd))
504             return 0;
505         r += registerOffset;
506 
507         Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argc;
508         for (size_t i = 0; i < numParameters; ++i)
509             argv[i + argc] = argv[i];
510     }
511 
512     return CallFrame::create(r);
513 }
514 
isNotObject(CallFrame * callFrame,bool forInstanceOf,CodeBlock * codeBlock,const Instruction * vPC,JSValuePtr value,JSValuePtr & exceptionData)515 static NEVER_INLINE bool isNotObject(CallFrame* callFrame, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValuePtr value, JSValuePtr& exceptionData)
516 {
517     if (value.isObject())
518         return false;
519     exceptionData = createInvalidParamError(callFrame, forInstanceOf ? "instanceof" : "in" , value, vPC - codeBlock->instructions().begin(), codeBlock);
520     return true;
521 }
522 
callEval(CallFrame * callFrame,RegisterFile * registerFile,Register * argv,int argc,int registerOffset,JSValuePtr & exceptionValue)523 NEVER_INLINE JSValuePtr Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValuePtr& exceptionValue)
524 {
525     if (argc < 2)
526         return jsUndefined();
527 
528     JSValuePtr program = argv[1].jsValue(callFrame);
529 
530     if (!program.isString())
531         return program;
532 
533     UString programSource = asString(program)->value();
534 
535     ScopeChainNode* scopeChain = callFrame->scopeChain();
536     CodeBlock* codeBlock = callFrame->codeBlock();
537     RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
538 
539     JSValuePtr result = jsUndefined();
540     if (evalNode)
541         result = callFrame->globalData().interpreter->execute(evalNode.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
542 
543     return result;
544 }
545 
Interpreter()546 Interpreter::Interpreter()
547     : m_sampler(0)
548 #if ENABLE(JIT)
549     , m_ctiArrayLengthTrampoline(0)
550     , m_ctiStringLengthTrampoline(0)
551     , m_ctiVirtualCallPreLink(0)
552     , m_ctiVirtualCallLink(0)
553     , m_ctiVirtualCall(0)
554 #endif
555     , m_reentryDepth(0)
556     , m_timeoutTime(0)
557     , m_timeAtLastCheckTimeout(0)
558     , m_timeExecuting(0)
559     , m_timeoutCheckCount(0)
560     , m_ticksUntilNextTimeoutCheck(initialTickCountThreshold)
561 {
562     initTimeout();
563     privateExecute(InitializeAndReturn, 0, 0, 0);
564 
565     // Bizarrely, calling fastMalloc here is faster than allocating space on the stack.
566     void* storage = fastMalloc(sizeof(CollectorBlock));
567 
568     JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
569     m_jsArrayVptr = jsArray->vptr();
570     jsArray->~JSCell();
571 
572     JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
573     m_jsByteArrayVptr = jsByteArray->vptr();
574     jsByteArray->~JSCell();
575 
576     JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
577     m_jsStringVptr = jsString->vptr();
578     jsString->~JSCell();
579 
580     JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
581     m_jsFunctionVptr = jsFunction->vptr();
582     jsFunction->~JSCell();
583 
584     fastFree(storage);
585 }
586 
initialize(JSGlobalData * globalData)587 void Interpreter::initialize(JSGlobalData* globalData)
588 {
589 #if ENABLE(JIT)
590     JIT::compileCTIMachineTrampolines(globalData);
591 #else
592     UNUSED_PARAM(globalData);
593 #endif
594 }
595 
~Interpreter()596 Interpreter::~Interpreter()
597 {
598 }
599 
600 #ifndef NDEBUG
601 
dumpCallFrame(CallFrame * callFrame)602 void Interpreter::dumpCallFrame(CallFrame* callFrame)
603 {
604     callFrame->codeBlock()->dump(callFrame);
605     dumpRegisters(callFrame);
606 }
607 
dumpRegisters(CallFrame * callFrame)608 void Interpreter::dumpRegisters(CallFrame* callFrame)
609 {
610     printf("Register frame: \n\n");
611     printf("----------------------------------------------------\n");
612     printf("            use            |   address  |   value   \n");
613     printf("----------------------------------------------------\n");
614 
615     CodeBlock* codeBlock = callFrame->codeBlock();
616     RegisterFile* registerFile = &callFrame->scopeChain()->globalObject()->globalData()->interpreter->registerFile();
617     const Register* it;
618     const Register* end;
619 
620     if (codeBlock->codeType() == GlobalCode) {
621         it = registerFile->lastGlobal();
622         end = it + registerFile->numGlobals();
623         while (it != end) {
624             printf("[global var]               | %10p | %10p \n", it, (*it).v());
625             ++it;
626         }
627         printf("----------------------------------------------------\n");
628     }
629 
630     it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->m_numParameters;
631     printf("[this]                     | %10p | %10p \n", it, (*it).v()); ++it;
632     end = it + max(codeBlock->m_numParameters - 1, 0); // - 1 to skip "this"
633     if (it != end) {
634         do {
635             printf("[param]                    | %10p | %10p \n", it, (*it).v());
636             ++it;
637         } while (it != end);
638     }
639     printf("----------------------------------------------------\n");
640 
641     printf("[CodeBlock]                | %10p | %10p \n", it, (*it).v()); ++it;
642     printf("[ScopeChain]               | %10p | %10p \n", it, (*it).v()); ++it;
643     printf("[CallerRegisters]          | %10p | %10p \n", it, (*it).v()); ++it;
644     printf("[ReturnPC]                 | %10p | %10p \n", it, (*it).v()); ++it;
645     printf("[ReturnValueRegister]      | %10p | %10p \n", it, (*it).v()); ++it;
646     printf("[ArgumentCount]            | %10p | %10p \n", it, (*it).v()); ++it;
647     printf("[Callee]                   | %10p | %10p \n", it, (*it).v()); ++it;
648     printf("[OptionalCalleeArguments]  | %10p | %10p \n", it, (*it).v()); ++it;
649     printf("----------------------------------------------------\n");
650 
651     int registerCount = 0;
652 
653     end = it + codeBlock->m_numVars;
654     if (it != end) {
655         do {
656             printf("[r%2d]                      | %10p | %10p \n", registerCount, it, (*it).v());
657             ++it;
658             ++registerCount;
659         } while (it != end);
660     }
661     printf("----------------------------------------------------\n");
662 
663     end = it + codeBlock->m_numConstants;
664     if (it != end) {
665         do {
666             printf("[r%2d]                      | %10p | %10p \n", registerCount, it, (*it).v());
667             ++it;
668             ++registerCount;
669         } while (it != end);
670     }
671     printf("----------------------------------------------------\n");
672 
673     end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numConstants - codeBlock->m_numVars;
674     if (it != end) {
675         do {
676             printf("[r%2d]                      | %10p | %10p \n", registerCount, it, (*it).v());
677             ++it;
678             ++registerCount;
679         } while (it != end);
680     }
681     printf("----------------------------------------------------\n");
682 }
683 
684 #endif
685 
isOpcode(Opcode opcode)686 bool Interpreter::isOpcode(Opcode opcode)
687 {
688 #if HAVE(COMPUTED_GOTO)
689     return opcode != HashTraits<Opcode>::emptyValue()
690         && !HashTraits<Opcode>::isDeletedValue(opcode)
691         && m_opcodeIDTable.contains(opcode);
692 #else
693     return opcode >= 0 && opcode <= op_end;
694 #endif
695 }
696 
unwindCallFrame(CallFrame * & callFrame,JSValuePtr exceptionValue,unsigned & bytecodeOffset,CodeBlock * & codeBlock)697 NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValuePtr exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
698 {
699     CodeBlock* oldCodeBlock = codeBlock;
700     ScopeChainNode* scopeChain = callFrame->scopeChain();
701 
702     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
703         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
704         if (callFrame->callee())
705             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine());
706         else
707             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine());
708     }
709 
710     if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
711         if (callFrame->callee())
712             profiler->didExecute(callFrame, callFrame->callee());
713         else
714             profiler->didExecute(callFrame, codeBlock->ownerNode()->sourceURL(), codeBlock->ownerNode()->lineNo());
715     }
716 
717     // If this call frame created an activation or an 'arguments' object, tear it off.
718     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
719         while (!scopeChain->object->isObject(&JSActivation::info))
720             scopeChain = scopeChain->pop();
721         static_cast<JSActivation*>(scopeChain->object)->copyRegisters(callFrame->optionalCalleeArguments());
722     } else if (Arguments* arguments = callFrame->optionalCalleeArguments()) {
723         if (!arguments->isTornOff())
724             arguments->copyRegisters();
725     }
726 
727     if (oldCodeBlock->needsFullScopeChain())
728         scopeChain->deref();
729 
730     void* returnPC = callFrame->returnPC();
731     callFrame = callFrame->callerFrame();
732     if (callFrame->hasHostCallFrameFlag())
733         return false;
734 
735     codeBlock = callFrame->codeBlock();
736     bytecodeOffset = bytecodeOffsetForPC(callFrame, codeBlock, returnPC);
737     return true;
738 }
739 
throwException(CallFrame * & callFrame,JSValuePtr & exceptionValue,unsigned bytecodeOffset,bool explicitThrow)740 NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValuePtr& exceptionValue, unsigned bytecodeOffset, bool explicitThrow)
741 {
742     // Set up the exception object
743 
744     CodeBlock* codeBlock = callFrame->codeBlock();
745     if (exceptionValue.isObject()) {
746         JSObject* exception = asObject(exceptionValue);
747         if (exception->isNotAnObjectErrorStub()) {
748             exception = createNotAnObjectError(callFrame, static_cast<JSNotAnObjectErrorStub*>(exception), bytecodeOffset, codeBlock);
749             exceptionValue = exception;
750         } else {
751             if (!exception->hasProperty(callFrame, Identifier(callFrame, "line")) &&
752                 !exception->hasProperty(callFrame, Identifier(callFrame, "sourceId")) &&
753                 !exception->hasProperty(callFrame, Identifier(callFrame, "sourceURL")) &&
754                 !exception->hasProperty(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName)) &&
755                 !exception->hasProperty(callFrame, Identifier(callFrame, expressionCaretOffsetPropertyName)) &&
756                 !exception->hasProperty(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName))) {
757                 if (explicitThrow) {
758                     int startOffset = 0;
759                     int endOffset = 0;
760                     int divotPoint = 0;
761                     int line = codeBlock->expressionRangeForBytecodeOffset(callFrame, bytecodeOffset, divotPoint, startOffset, endOffset);
762                     exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, line), ReadOnly | DontDelete);
763 
764                     // We only hit this path for error messages and throw statements, which don't have a specific failure position
765                     // So we just give the full range of the error/throw statement.
766                     exception->putWithAttributes(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName), jsNumber(callFrame, divotPoint - startOffset), ReadOnly | DontDelete);
767                     exception->putWithAttributes(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName), jsNumber(callFrame, divotPoint + endOffset), ReadOnly | DontDelete);
768                 } else
769                     exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)), ReadOnly | DontDelete);
770                 exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerNode()->sourceID()), ReadOnly | DontDelete);
771                 exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerNode()->sourceURL()), ReadOnly | DontDelete);
772             }
773 
774             if (exception->isWatchdogException()) {
775                 while (unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
776                     // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
777                 }
778                 return 0;
779             }
780         }
781     }
782 
783     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
784         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
785         debugger->exception(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset));
786     }
787 
788     // If we throw in the middle of a call instruction, we need to notify
789     // the profiler manually that the call instruction has returned, since
790     // we'll never reach the relevant op_profile_did_call.
791     if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
792 #if !ENABLE(JIT)
793         if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode))
794             profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 2].u.operand].jsValue(callFrame));
795         else if (codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
796             profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 10].u.operand].jsValue(callFrame));
797 #else
798         int functionRegisterIndex;
799         if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex))
800             profiler->didExecute(callFrame, callFrame[functionRegisterIndex].jsValue(callFrame));
801 #endif
802     }
803 
804     // Calculate an exception handler vPC, unwinding call frames as necessary.
805 
806     HandlerInfo* handler = 0;
807     while (!(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
808         if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock))
809             return 0;
810     }
811 
812     // Now unwind the scope chain within the exception handler's call frame.
813 
814     ScopeChainNode* scopeChain = callFrame->scopeChain();
815     ScopeChain sc(scopeChain);
816     int scopeDelta = depth(codeBlock, sc) - handler->scopeDepth;
817     ASSERT(scopeDelta >= 0);
818     while (scopeDelta--)
819         scopeChain = scopeChain->pop();
820     callFrame->setScopeChain(scopeChain);
821 
822     return handler;
823 }
824 
execute(ProgramNode * programNode,CallFrame * callFrame,ScopeChainNode * scopeChain,JSObject * thisObj,JSValuePtr * exception)825 JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValuePtr* exception)
826 {
827     ASSERT(!scopeChain->globalData->exception);
828 
829     if (m_reentryDepth >= MaxReentryDepth) {
830         *exception = createStackOverflowError(callFrame);
831         return jsNull();
832     }
833 
834     CodeBlock* codeBlock = &programNode->bytecode(scopeChain);
835 
836     Register* oldEnd = m_registerFile.end();
837     Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
838     if (!m_registerFile.grow(newEnd)) {
839         *exception = createStackOverflowError(callFrame);
840         return jsNull();
841     }
842 
843     DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject());
844 
845     JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
846     JSGlobalObject* globalObject = callFrame->dynamicGlobalObject();
847     globalObject->copyGlobalsTo(m_registerFile);
848 
849     CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize);
850     newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj);
851     newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), 0, 0, 0);
852 
853     if (codeBlock->needsFullScopeChain())
854         scopeChain->ref();
855 
856     Profiler** profiler = Profiler::enabledProfilerReference();
857     if (*profiler)
858         (*profiler)->willExecute(newCallFrame, programNode->sourceURL(), programNode->lineNo());
859 
860     JSValuePtr result;
861     {
862         SamplingTool::CallRecord callRecord(m_sampler);
863 
864         m_reentryDepth++;
865 #if ENABLE(JIT)
866         if (!codeBlock->jitCode())
867             JIT::compile(scopeChain->globalData, codeBlock);
868         result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception);
869 #else
870         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
871 #endif
872         m_reentryDepth--;
873     }
874 
875     if (*profiler)
876         (*profiler)->didExecute(callFrame, programNode->sourceURL(), programNode->lineNo());
877 
878     if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
879         lastGlobalObject->copyGlobalsTo(m_registerFile);
880 
881     m_registerFile.shrink(oldEnd);
882 
883     return result;
884 }
885 
execute(FunctionBodyNode * functionBodyNode,CallFrame * callFrame,JSFunction * function,JSObject * thisObj,const ArgList & args,ScopeChainNode * scopeChain,JSValuePtr * exception)886 JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValuePtr* exception)
887 {
888     ASSERT(!scopeChain->globalData->exception);
889 
890     if (m_reentryDepth >= MaxReentryDepth) {
891         *exception = createStackOverflowError(callFrame);
892         return jsNull();
893     }
894 
895     Register* oldEnd = m_registerFile.end();
896     int argc = 1 + args.size(); // implicit "this" parameter
897 
898     if (!m_registerFile.grow(oldEnd + argc)) {
899         *exception = createStackOverflowError(callFrame);
900         return jsNull();
901     }
902 
903     DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());
904 
905     CallFrame* newCallFrame = CallFrame::create(oldEnd);
906     size_t dst = 0;
907     newCallFrame[0] = JSValuePtr(thisObj);
908     ArgList::const_iterator end = args.end();
909     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
910         newCallFrame[++dst] = *it;
911 
912     CodeBlock* codeBlock = &functionBodyNode->bytecode(scopeChain);
913     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
914     if (UNLIKELY(!newCallFrame)) {
915         *exception = createStackOverflowError(callFrame);
916         m_registerFile.shrink(oldEnd);
917         return jsNull();
918     }
919     // a 0 codeBlock indicates a built-in caller
920     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);
921 
922     Profiler** profiler = Profiler::enabledProfilerReference();
923     if (*profiler)
924         (*profiler)->willExecute(callFrame, function);
925 
926     JSValuePtr result;
927     {
928         SamplingTool::CallRecord callRecord(m_sampler);
929 
930         m_reentryDepth++;
931 #if ENABLE(JIT)
932         if (!codeBlock->jitCode())
933             JIT::compile(scopeChain->globalData, codeBlock);
934         result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception);
935 #else
936         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
937 #endif
938         m_reentryDepth--;
939     }
940 
941     if (*profiler)
942         (*profiler)->didExecute(callFrame, function);
943 
944     m_registerFile.shrink(oldEnd);
945     return result;
946 }
947 
execute(EvalNode * evalNode,CallFrame * callFrame,JSObject * thisObj,ScopeChainNode * scopeChain,JSValuePtr * exception)948 JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValuePtr* exception)
949 {
950     return execute(evalNode, callFrame, thisObj, m_registerFile.size() + evalNode->bytecode(scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
951 }
952 
execute(EvalNode * evalNode,CallFrame * callFrame,JSObject * thisObj,int globalRegisterOffset,ScopeChainNode * scopeChain,JSValuePtr * exception)953 JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValuePtr* exception)
954 {
955     ASSERT(!scopeChain->globalData->exception);
956 
957     if (m_reentryDepth >= MaxReentryDepth) {
958         *exception = createStackOverflowError(callFrame);
959         return jsNull();
960     }
961 
962     DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());
963 
964     EvalCodeBlock* codeBlock = &evalNode->bytecode(scopeChain);
965 
966     JSVariableObject* variableObject;
967     for (ScopeChainNode* node = scopeChain; ; node = node->next) {
968         ASSERT(node);
969         if (node->object->isVariableObject()) {
970             variableObject = static_cast<JSVariableObject*>(node->object);
971             break;
972         }
973     }
974 
975     { // Scope for BatchedTransitionOptimizer
976 
977         BatchedTransitionOptimizer optimizer(variableObject);
978 
979         const DeclarationStacks::VarStack& varStack = codeBlock->ownerNode()->varStack();
980         DeclarationStacks::VarStack::const_iterator varStackEnd = varStack.end();
981         for (DeclarationStacks::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) {
982             const Identifier& ident = (*it).first;
983             if (!variableObject->hasProperty(callFrame, ident)) {
984                 PutPropertySlot slot;
985                 variableObject->put(callFrame, ident, jsUndefined(), slot);
986             }
987         }
988 
989         const DeclarationStacks::FunctionStack& functionStack = codeBlock->ownerNode()->functionStack();
990         DeclarationStacks::FunctionStack::const_iterator functionStackEnd = functionStack.end();
991         for (DeclarationStacks::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it) {
992             PutPropertySlot slot;
993             variableObject->put(callFrame, (*it)->m_ident, (*it)->makeFunction(callFrame, scopeChain), slot);
994         }
995 
996     }
997 
998     Register* oldEnd = m_registerFile.end();
999     Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
1000     if (!m_registerFile.grow(newEnd)) {
1001         *exception = createStackOverflowError(callFrame);
1002         return jsNull();
1003     }
1004 
1005     CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);
1006 
1007     // a 0 codeBlock indicates a built-in caller
1008     newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj);
1009     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, 0, 0);
1010 
1011     if (codeBlock->needsFullScopeChain())
1012         scopeChain->ref();
1013 
1014     Profiler** profiler = Profiler::enabledProfilerReference();
1015     if (*profiler)
1016         (*profiler)->willExecute(newCallFrame, evalNode->sourceURL(), evalNode->lineNo());
1017 
1018     JSValuePtr result;
1019     {
1020         SamplingTool::CallRecord callRecord(m_sampler);
1021 
1022         m_reentryDepth++;
1023 #if ENABLE(JIT)
1024         if (!codeBlock->jitCode())
1025             JIT::compile(scopeChain->globalData, codeBlock);
1026         result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception);
1027 #else
1028         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
1029 #endif
1030         m_reentryDepth--;
1031     }
1032 
1033     if (*profiler)
1034         (*profiler)->didExecute(callFrame, evalNode->sourceURL(), evalNode->lineNo());
1035 
1036     m_registerFile.shrink(oldEnd);
1037     return result;
1038 }
1039 
debug(CallFrame * callFrame,DebugHookID debugHookID,int firstLine,int lastLine)1040 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine)
1041 {
1042     Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
1043     if (!debugger)
1044         return;
1045 
1046     switch (debugHookID) {
1047         case DidEnterCallFrame:
1048             debugger->callEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);
1049             return;
1050         case WillLeaveCallFrame:
1051             debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);
1052             return;
1053         case WillExecuteStatement:
1054             debugger->atStatement(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);
1055             return;
1056         case WillExecuteProgram:
1057             debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);
1058             return;
1059         case DidExecuteProgram:
1060             debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);
1061             return;
1062         case DidReachBreakpoint:
1063             debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);
1064             return;
1065     }
1066 }
1067 
resetTimeoutCheck()1068 void Interpreter::resetTimeoutCheck()
1069 {
1070     m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
1071     m_timeAtLastCheckTimeout = 0;
1072     m_timeExecuting = 0;
1073 }
1074 
1075 // Returns the time the current thread has spent executing, in milliseconds.
getCPUTime()1076 static inline unsigned getCPUTime()
1077 {
1078 #if PLATFORM(DARWIN)
1079     mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
1080     thread_basic_info_data_t info;
1081 
1082     // Get thread information
1083     mach_port_t threadPort = mach_thread_self();
1084     thread_info(threadPort, THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &infoCount);
1085     mach_port_deallocate(mach_task_self(), threadPort);
1086 
1087     unsigned time = info.user_time.seconds * 1000 + info.user_time.microseconds / 1000;
1088     time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000;
1089 
1090     return time;
1091 #elif HAVE(SYS_TIME_H)
1092     // FIXME: This should probably use getrusage with the RUSAGE_THREAD flag.
1093     struct timeval tv;
1094     gettimeofday(&tv, 0);
1095     return tv.tv_sec * 1000 + tv.tv_usec / 1000;
1096 #elif PLATFORM(QT)
1097     QDateTime t = QDateTime::currentDateTime();
1098     return t.toTime_t() * 1000 + t.time().msec();
1099 #elif PLATFORM(WIN_OS)
1100     union {
1101         FILETIME fileTime;
1102         unsigned long long fileTimeAsLong;
1103     } userTime, kernelTime;
1104 
1105     // GetThreadTimes won't accept NULL arguments so we pass these even though
1106     // they're not used.
1107     FILETIME creationTime, exitTime;
1108 
1109     GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime);
1110 
1111     return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000;
1112 #else
1113 #error Platform does not have getCurrentTime function
1114 #endif
1115 }
1116 
1117 // We have to return a JSValue here, gcc seems to produce worse code if
1118 // we attempt to return a bool
checkTimeout(JSGlobalObject * globalObject)1119 ALWAYS_INLINE bool Interpreter::checkTimeout(JSGlobalObject* globalObject)
1120 {
1121     unsigned currentTime = getCPUTime();
1122 
1123     if (!m_timeAtLastCheckTimeout) {
1124         // Suspicious amount of looping in a script -- start timing it
1125         m_timeAtLastCheckTimeout = currentTime;
1126         return false;
1127     }
1128 
1129     unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout;
1130 
1131     if (timeDiff == 0)
1132         timeDiff = 1;
1133 
1134     m_timeExecuting += timeDiff;
1135     m_timeAtLastCheckTimeout = currentTime;
1136 
1137     // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in
1138     // preferredScriptCheckTimeInterval
1139     m_ticksUntilNextTimeoutCheck = static_cast<unsigned>((static_cast<float>(preferredScriptCheckTimeInterval) / timeDiff) * m_ticksUntilNextTimeoutCheck);
1140     // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
1141     // preferred script check time interval.
1142     if (m_ticksUntilNextTimeoutCheck == 0)
1143         m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
1144 
1145     if (m_timeoutTime && m_timeExecuting > m_timeoutTime) {
1146         if (globalObject->shouldInterruptScript())
1147             return true;
1148 
1149         resetTimeoutCheck();
1150     }
1151 
1152     return false;
1153 }
1154 
createExceptionScope(CallFrame * callFrame,const Instruction * vPC)1155 NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
1156 {
1157     int dst = (++vPC)->u.operand;
1158     CodeBlock* codeBlock = callFrame->codeBlock();
1159     Identifier& property = codeBlock->identifier((++vPC)->u.operand);
1160     JSValuePtr value = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1161     JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete);
1162     callFrame[dst] = JSValuePtr(scope);
1163 
1164     return callFrame->scopeChain()->push(scope);
1165 }
1166 
cachePrototypeChain(CallFrame * callFrame,Structure * structure)1167 static StructureChain* cachePrototypeChain(CallFrame* callFrame, Structure* structure)
1168 {
1169     JSValuePtr prototype = structure->prototypeForLookup(callFrame);
1170     if (!prototype.isCell())
1171         return 0;
1172     RefPtr<StructureChain> chain = StructureChain::create(asObject(prototype)->structure());
1173     structure->setCachedPrototypeChain(chain.release());
1174     return structure->cachedPrototypeChain();
1175 }
1176 
tryCachePutByID(CallFrame * callFrame,CodeBlock * codeBlock,Instruction * vPC,JSValuePtr baseValue,const PutPropertySlot & slot)1177 NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr baseValue, const PutPropertySlot& slot)
1178 {
1179     // Recursive invocation may already have specialized this instruction.
1180     if (vPC[0].u.opcode != getOpcode(op_put_by_id))
1181         return;
1182 
1183     if (!baseValue.isCell())
1184         return;
1185 
1186     // Uncacheable: give up.
1187     if (!slot.isCacheable()) {
1188         vPC[0] = getOpcode(op_put_by_id_generic);
1189         return;
1190     }
1191 
1192     JSCell* baseCell = asCell(baseValue);
1193     Structure* structure = baseCell->structure();
1194 
1195     if (structure->isDictionary()) {
1196         vPC[0] = getOpcode(op_put_by_id_generic);
1197         return;
1198     }
1199 
1200     // Cache miss: record Structure to compare against next time.
1201     Structure* lastStructure = vPC[4].u.structure;
1202     if (structure != lastStructure) {
1203         // First miss: record Structure to compare against next time.
1204         if (!lastStructure) {
1205             vPC[4] = structure;
1206             return;
1207         }
1208 
1209         // Second miss: give up.
1210         vPC[0] = getOpcode(op_put_by_id_generic);
1211         return;
1212     }
1213 
1214     // Cache hit: Specialize instruction and ref Structures.
1215 
1216     // If baseCell != slot.base(), then baseCell must be a proxy for another object.
1217     if (baseCell != slot.base()) {
1218         vPC[0] = getOpcode(op_put_by_id_generic);
1219         return;
1220     }
1221 
1222     // Structure transition, cache transition info
1223     if (slot.type() == PutPropertySlot::NewProperty) {
1224         vPC[0] = getOpcode(op_put_by_id_transition);
1225         vPC[4] = structure->previousID();
1226         vPC[5] = structure;
1227         StructureChain* chain = structure->cachedPrototypeChain();
1228         if (!chain) {
1229             chain = cachePrototypeChain(callFrame, structure);
1230             if (!chain) {
1231                 // This happens if someone has manually inserted null into the prototype chain
1232                 vPC[0] = getOpcode(op_put_by_id_generic);
1233                 return;
1234             }
1235         }
1236         vPC[6] = chain;
1237         vPC[7] = slot.cachedOffset();
1238         codeBlock->refStructures(vPC);
1239         return;
1240     }
1241 
1242     vPC[0] = getOpcode(op_put_by_id_replace);
1243     vPC[5] = slot.cachedOffset();
1244     codeBlock->refStructures(vPC);
1245 }
1246 
uncachePutByID(CodeBlock * codeBlock,Instruction * vPC)1247 NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC)
1248 {
1249     codeBlock->derefStructures(vPC);
1250     vPC[0] = getOpcode(op_put_by_id);
1251     vPC[4] = 0;
1252 }
1253 
countPrototypeChainEntriesAndCheckForProxies(CallFrame * callFrame,JSValuePtr baseValue,const PropertySlot & slot)1254 static size_t countPrototypeChainEntriesAndCheckForProxies(CallFrame* callFrame, JSValuePtr baseValue, const PropertySlot& slot)
1255 {
1256     JSCell* cell = asCell(baseValue);
1257     size_t count = 0;
1258 
1259     while (slot.slotBase() != cell) {
1260         JSValuePtr v = cell->structure()->prototypeForLookup(callFrame);
1261 
1262         // If we didn't find slotBase in baseValue's prototype chain, then baseValue
1263         // must be a proxy for another object.
1264 
1265         if (v.isNull())
1266             return 0;
1267 
1268         cell = asCell(v);
1269 
1270         // Since we're accessing a prototype in a loop, it's a good bet that it
1271         // should not be treated as a dictionary.
1272         if (cell->structure()->isDictionary()) {
1273             RefPtr<Structure> transition = Structure::fromDictionaryTransition(cell->structure());
1274             asObject(cell)->setStructure(transition.release());
1275             cell->structure()->setCachedPrototypeChain(0);
1276         }
1277 
1278         ++count;
1279     }
1280 
1281     ASSERT(count);
1282     return count;
1283 }
1284 
tryCacheGetByID(CallFrame * callFrame,CodeBlock * codeBlock,Instruction * vPC,JSValuePtr baseValue,const Identifier & propertyName,const PropertySlot & slot)1285 NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot& slot)
1286 {
1287     // Recursive invocation may already have specialized this instruction.
1288     if (vPC[0].u.opcode != getOpcode(op_get_by_id))
1289         return;
1290 
1291     // FIXME: Cache property access for immediates.
1292     if (!baseValue.isCell()) {
1293         vPC[0] = getOpcode(op_get_by_id_generic);
1294         return;
1295     }
1296 
1297     if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
1298         vPC[0] = getOpcode(op_get_array_length);
1299         return;
1300     }
1301 
1302     if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
1303         vPC[0] = getOpcode(op_get_string_length);
1304         return;
1305     }
1306 
1307     // Uncacheable: give up.
1308     if (!slot.isCacheable()) {
1309         vPC[0] = getOpcode(op_get_by_id_generic);
1310         return;
1311     }
1312 
1313     Structure* structure = asCell(baseValue)->structure();
1314 
1315     if (structure->isDictionary()) {
1316         vPC[0] = getOpcode(op_get_by_id_generic);
1317         return;
1318     }
1319 
1320     // Cache miss
1321     Structure* lastStructure = vPC[4].u.structure;
1322     if (structure != lastStructure) {
1323         // First miss: record Structure to compare against next time.
1324         if (!lastStructure) {
1325             vPC[4] = structure;
1326             return;
1327         }
1328 
1329         // Second miss: give up.
1330         vPC[0] = getOpcode(op_get_by_id_generic);
1331         return;
1332     }
1333 
1334     // Cache hit: Specialize instruction and ref Structures.
1335 
1336     if (slot.slotBase() == baseValue) {
1337         vPC[0] = getOpcode(op_get_by_id_self);
1338         vPC[5] = slot.cachedOffset();
1339 
1340         codeBlock->refStructures(vPC);
1341         return;
1342     }
1343 
1344     if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
1345         ASSERT(slot.slotBase().isObject());
1346 
1347         JSObject* baseObject = asObject(slot.slotBase());
1348 
1349         // Since we're accessing a prototype in a loop, it's a good bet that it
1350         // should not be treated as a dictionary.
1351         if (baseObject->structure()->isDictionary()) {
1352             RefPtr<Structure> transition = Structure::fromDictionaryTransition(baseObject->structure());
1353             baseObject->setStructure(transition.release());
1354             asCell(baseValue)->structure()->setCachedPrototypeChain(0);
1355         }
1356 
1357         vPC[0] = getOpcode(op_get_by_id_proto);
1358         vPC[5] = baseObject->structure();
1359         vPC[6] = slot.cachedOffset();
1360 
1361         codeBlock->refStructures(vPC);
1362         return;
1363     }
1364 
1365     size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot);
1366     if (!count) {
1367         vPC[0] = getOpcode(op_get_by_id_generic);
1368         return;
1369     }
1370 
1371     StructureChain* chain = structure->cachedPrototypeChain();
1372     if (!chain)
1373         chain = cachePrototypeChain(callFrame, structure);
1374     ASSERT(chain);
1375 
1376     vPC[0] = getOpcode(op_get_by_id_chain);
1377     vPC[4] = structure;
1378     vPC[5] = chain;
1379     vPC[6] = count;
1380     vPC[7] = slot.cachedOffset();
1381     codeBlock->refStructures(vPC);
1382 }
1383 
uncacheGetByID(CodeBlock * codeBlock,Instruction * vPC)1384 NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC)
1385 {
1386     codeBlock->derefStructures(vPC);
1387     vPC[0] = getOpcode(op_get_by_id);
1388     vPC[4] = 0;
1389 }
1390 
privateExecute(ExecutionFlag flag,RegisterFile * registerFile,CallFrame * callFrame,JSValuePtr * exception)1391 JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValuePtr* exception)
1392 {
1393     // One-time initialization of our address tables. We have to put this code
1394     // here because our labels are only in scope inside this function.
1395     if (flag == InitializeAndReturn) {
1396         #if HAVE(COMPUTED_GOTO)
1397             #define ADD_BYTECODE(id, length) m_opcodeTable[id] = &&id;
1398                 FOR_EACH_OPCODE_ID(ADD_BYTECODE);
1399             #undef ADD_BYTECODE
1400 
1401             #define ADD_OPCODE_ID(id, length) m_opcodeIDTable.add(&&id, id);
1402                 FOR_EACH_OPCODE_ID(ADD_OPCODE_ID);
1403             #undef ADD_OPCODE_ID
1404             ASSERT(m_opcodeIDTable.size() == numOpcodeIDs);
1405         #endif // HAVE(COMPUTED_GOTO)
1406         return noValue();
1407     }
1408 
1409 #if ENABLE(JIT)
1410     // Currently with CTI enabled we never interpret functions
1411     ASSERT_NOT_REACHED();
1412 #endif
1413 
1414     JSGlobalData* globalData = &callFrame->globalData();
1415     JSValuePtr exceptionValue = noValue();
1416     HandlerInfo* handler = 0;
1417 
1418     Instruction* vPC = callFrame->codeBlock()->instructions().begin();
1419     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
1420     unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1;
1421 
1422 #define CHECK_FOR_EXCEPTION() \
1423     do { \
1424         if (UNLIKELY(globalData->exception != noValue())) { \
1425             exceptionValue = globalData->exception; \
1426             goto vm_throw; \
1427         } \
1428     } while (0)
1429 
1430 #if ENABLE(OPCODE_STATS)
1431     OpcodeStats::resetLastInstruction();
1432 #endif
1433 
1434 #define CHECK_FOR_TIMEOUT() \
1435     if (!--tickCount) { \
1436         if (checkTimeout(callFrame->dynamicGlobalObject())) { \
1437             exceptionValue = jsNull(); \
1438             goto vm_throw; \
1439         } \
1440         tickCount = m_ticksUntilNextTimeoutCheck; \
1441     }
1442 
1443 #if ENABLE(OPCODE_SAMPLING)
1444     #define SAMPLE(codeBlock, vPC) m_sampler->sample(codeBlock, vPC)
1445     #define CTI_SAMPLER ARG_globalData->interpreter->sampler()
1446 #else
1447     #define SAMPLE(codeBlock, vPC)
1448     #define CTI_SAMPLER 0
1449 #endif
1450 
1451 #if HAVE(COMPUTED_GOTO)
1452     #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto *vPC->u.opcode
1453 #if ENABLE(OPCODE_STATS)
1454     #define DEFINE_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
1455 #else
1456     #define DEFINE_OPCODE(opcode) opcode:
1457 #endif
1458     NEXT_INSTRUCTION();
1459 #else
1460     #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto interpreterLoopStart
1461 #if ENABLE(OPCODE_STATS)
1462     #define DEFINE_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
1463 #else
1464     #define DEFINE_OPCODE(opcode) case opcode:
1465 #endif
1466     while (1) { // iterator loop begins
1467     interpreterLoopStart:;
1468     switch (vPC->u.opcode)
1469 #endif
1470     {
1471     DEFINE_OPCODE(op_new_object) {
1472         /* new_object dst(r)
1473 
1474            Constructs a new empty Object instance using the original
1475            constructor, and puts the result in register dst.
1476         */
1477         int dst = (++vPC)->u.operand;
1478         callFrame[dst] = JSValuePtr(constructEmptyObject(callFrame));
1479 
1480         ++vPC;
1481         NEXT_INSTRUCTION();
1482     }
1483     DEFINE_OPCODE(op_new_array) {
1484         /* new_array dst(r) firstArg(r) argCount(n)
1485 
1486            Constructs a new Array instance using the original
1487            constructor, and puts the result in register dst.
1488            The array will contain argCount elements with values
1489            taken from registers starting at register firstArg.
1490         */
1491         int dst = (++vPC)->u.operand;
1492         int firstArg = (++vPC)->u.operand;
1493         int argCount = (++vPC)->u.operand;
1494         ArgList args(callFrame->registers() + firstArg, argCount);
1495         callFrame[dst] = JSValuePtr(constructArray(callFrame, args));
1496 
1497         ++vPC;
1498         NEXT_INSTRUCTION();
1499     }
1500     DEFINE_OPCODE(op_new_regexp) {
1501         /* new_regexp dst(r) regExp(re)
1502 
1503            Constructs a new RegExp instance using the original
1504            constructor from regexp regExp, and puts the result in
1505            register dst.
1506         */
1507         int dst = (++vPC)->u.operand;
1508         int regExp = (++vPC)->u.operand;
1509         callFrame[dst] = JSValuePtr(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexp(regExp)));
1510 
1511         ++vPC;
1512         NEXT_INSTRUCTION();
1513     }
1514     DEFINE_OPCODE(op_mov) {
1515         /* mov dst(r) src(r)
1516 
1517            Copies register src to register dst.
1518         */
1519         int dst = (++vPC)->u.operand;
1520         int src = (++vPC)->u.operand;
1521         callFrame[dst] = callFrame[src];
1522 
1523         ++vPC;
1524         NEXT_INSTRUCTION();
1525     }
1526     DEFINE_OPCODE(op_eq) {
1527         /* eq dst(r) src1(r) src2(r)
1528 
1529            Checks whether register src1 and register src2 are equal,
1530            as with the ECMAScript '==' operator, and puts the result
1531            as a boolean in register dst.
1532         */
1533         int dst = (++vPC)->u.operand;
1534         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1535         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1536         if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
1537             callFrame[dst] = JSFastMath::equal(src1, src2);
1538         else {
1539             JSValuePtr result = jsBoolean(JSValuePtr::equalSlowCase(callFrame, src1, src2));
1540             CHECK_FOR_EXCEPTION();
1541             callFrame[dst] = result;
1542         }
1543 
1544         ++vPC;
1545         NEXT_INSTRUCTION();
1546     }
1547     DEFINE_OPCODE(op_eq_null) {
1548         /* eq_null dst(r) src(r)
1549 
1550            Checks whether register src is null, as with the ECMAScript '!='
1551            operator, and puts the result as a boolean in register dst.
1552         */
1553         int dst = (++vPC)->u.operand;
1554         JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1555 
1556         if (src.isUndefinedOrNull()) {
1557             callFrame[dst] = jsBoolean(true);
1558             ++vPC;
1559             NEXT_INSTRUCTION();
1560         }
1561 
1562         callFrame[dst] = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
1563         ++vPC;
1564         NEXT_INSTRUCTION();
1565     }
1566     DEFINE_OPCODE(op_neq) {
1567         /* neq dst(r) src1(r) src2(r)
1568 
1569            Checks whether register src1 and register src2 are not
1570            equal, as with the ECMAScript '!=' operator, and puts the
1571            result as a boolean in register dst.
1572         */
1573         int dst = (++vPC)->u.operand;
1574         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1575         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1576         if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
1577             callFrame[dst] = JSFastMath::notEqual(src1, src2);
1578         else {
1579             JSValuePtr result = jsBoolean(!JSValuePtr::equalSlowCase(callFrame, src1, src2));
1580             CHECK_FOR_EXCEPTION();
1581             callFrame[dst] = result;
1582         }
1583 
1584         ++vPC;
1585         NEXT_INSTRUCTION();
1586     }
1587     DEFINE_OPCODE(op_neq_null) {
1588         /* neq_null dst(r) src(r)
1589 
1590            Checks whether register src is not null, as with the ECMAScript '!='
1591            operator, and puts the result as a boolean in register dst.
1592         */
1593         int dst = (++vPC)->u.operand;
1594         JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1595 
1596         if (src.isUndefinedOrNull()) {
1597             callFrame[dst] = jsBoolean(false);
1598             ++vPC;
1599             NEXT_INSTRUCTION();
1600         }
1601 
1602         callFrame[dst] = jsBoolean(!src.isCell() || !asCell(src)->structure()->typeInfo().masqueradesAsUndefined());
1603         ++vPC;
1604         NEXT_INSTRUCTION();
1605     }
1606     DEFINE_OPCODE(op_stricteq) {
1607         /* stricteq dst(r) src1(r) src2(r)
1608 
1609            Checks whether register src1 and register src2 are strictly
1610            equal, as with the ECMAScript '===' operator, and puts the
1611            result as a boolean in register dst.
1612         */
1613         int dst = (++vPC)->u.operand;
1614         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1615         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1616         callFrame[dst] = jsBoolean(JSValuePtr::strictEqual(src1, src2));
1617 
1618         ++vPC;
1619         NEXT_INSTRUCTION();
1620     }
1621     DEFINE_OPCODE(op_nstricteq) {
1622         /* nstricteq dst(r) src1(r) src2(r)
1623 
1624            Checks whether register src1 and register src2 are not
1625            strictly equal, as with the ECMAScript '!==' operator, and
1626            puts the result as a boolean in register dst.
1627         */
1628         int dst = (++vPC)->u.operand;
1629         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1630         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1631         callFrame[dst] = jsBoolean(!JSValuePtr::strictEqual(src1, src2));
1632 
1633         ++vPC;
1634         NEXT_INSTRUCTION();
1635     }
1636     DEFINE_OPCODE(op_less) {
1637         /* less dst(r) src1(r) src2(r)
1638 
1639            Checks whether register src1 is less than register src2, as
1640            with the ECMAScript '<' operator, and puts the result as
1641            a boolean in register dst.
1642         */
1643         int dst = (++vPC)->u.operand;
1644         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1645         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1646         JSValuePtr result = jsBoolean(jsLess(callFrame, src1, src2));
1647         CHECK_FOR_EXCEPTION();
1648         callFrame[dst] = result;
1649 
1650         ++vPC;
1651         NEXT_INSTRUCTION();
1652     }
1653     DEFINE_OPCODE(op_lesseq) {
1654         /* lesseq dst(r) src1(r) src2(r)
1655 
1656            Checks whether register src1 is less than or equal to
1657            register src2, as with the ECMAScript '<=' operator, and
1658            puts the result as a boolean in register dst.
1659         */
1660         int dst = (++vPC)->u.operand;
1661         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1662         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1663         JSValuePtr result = jsBoolean(jsLessEq(callFrame, src1, src2));
1664         CHECK_FOR_EXCEPTION();
1665         callFrame[dst] = result;
1666 
1667         ++vPC;
1668         NEXT_INSTRUCTION();
1669     }
1670     DEFINE_OPCODE(op_pre_inc) {
1671         /* pre_inc srcDst(r)
1672 
1673            Converts register srcDst to number, adds one, and puts the result
1674            back in register srcDst.
1675         */
1676         int srcDst = (++vPC)->u.operand;
1677         JSValuePtr v = callFrame[srcDst].jsValue(callFrame);
1678         if (JSFastMath::canDoFastAdditiveOperations(v))
1679             callFrame[srcDst] = JSValuePtr(JSFastMath::incImmediateNumber(v));
1680         else {
1681             JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) + 1);
1682             CHECK_FOR_EXCEPTION();
1683             callFrame[srcDst] = result;
1684         }
1685 
1686         ++vPC;
1687         NEXT_INSTRUCTION();
1688     }
1689     DEFINE_OPCODE(op_pre_dec) {
1690         /* pre_dec srcDst(r)
1691 
1692            Converts register srcDst to number, subtracts one, and puts the result
1693            back in register srcDst.
1694         */
1695         int srcDst = (++vPC)->u.operand;
1696         JSValuePtr v = callFrame[srcDst].jsValue(callFrame);
1697         if (JSFastMath::canDoFastAdditiveOperations(v))
1698             callFrame[srcDst] = JSValuePtr(JSFastMath::decImmediateNumber(v));
1699         else {
1700             JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) - 1);
1701             CHECK_FOR_EXCEPTION();
1702             callFrame[srcDst] = result;
1703         }
1704 
1705         ++vPC;
1706         NEXT_INSTRUCTION();
1707     }
1708     DEFINE_OPCODE(op_post_inc) {
1709         /* post_inc dst(r) srcDst(r)
1710 
1711            Converts register srcDst to number. The number itself is
1712            written to register dst, and the number plus one is written
1713            back to register srcDst.
1714         */
1715         int dst = (++vPC)->u.operand;
1716         int srcDst = (++vPC)->u.operand;
1717         JSValuePtr v = callFrame[srcDst].jsValue(callFrame);
1718         if (JSFastMath::canDoFastAdditiveOperations(v)) {
1719             callFrame[dst] = v;
1720             callFrame[srcDst] = JSValuePtr(JSFastMath::incImmediateNumber(v));
1721         } else {
1722             JSValuePtr number = callFrame[srcDst].jsValue(callFrame).toJSNumber(callFrame);
1723             CHECK_FOR_EXCEPTION();
1724             callFrame[dst] = number;
1725             callFrame[srcDst] = JSValuePtr(jsNumber(callFrame, number.uncheckedGetNumber() + 1));
1726         }
1727 
1728         ++vPC;
1729         NEXT_INSTRUCTION();
1730     }
1731     DEFINE_OPCODE(op_post_dec) {
1732         /* post_dec dst(r) srcDst(r)
1733 
1734            Converts register srcDst to number. The number itself is
1735            written to register dst, and the number minus one is written
1736            back to register srcDst.
1737         */
1738         int dst = (++vPC)->u.operand;
1739         int srcDst = (++vPC)->u.operand;
1740         JSValuePtr v = callFrame[srcDst].jsValue(callFrame);
1741         if (JSFastMath::canDoFastAdditiveOperations(v)) {
1742             callFrame[dst] = v;
1743             callFrame[srcDst] = JSValuePtr(JSFastMath::decImmediateNumber(v));
1744         } else {
1745             JSValuePtr number = callFrame[srcDst].jsValue(callFrame).toJSNumber(callFrame);
1746             CHECK_FOR_EXCEPTION();
1747             callFrame[dst] = number;
1748             callFrame[srcDst] = JSValuePtr(jsNumber(callFrame, number.uncheckedGetNumber() - 1));
1749         }
1750 
1751         ++vPC;
1752         NEXT_INSTRUCTION();
1753     }
1754     DEFINE_OPCODE(op_to_jsnumber) {
1755         /* to_jsnumber dst(r) src(r)
1756 
1757            Converts register src to number, and puts the result
1758            in register dst.
1759         */
1760         int dst = (++vPC)->u.operand;
1761         int src = (++vPC)->u.operand;
1762 
1763         JSValuePtr srcVal = callFrame[src].jsValue(callFrame);
1764 
1765         if (LIKELY(srcVal.isNumber()))
1766             callFrame[dst] = callFrame[src];
1767         else {
1768             JSValuePtr result = srcVal.toJSNumber(callFrame);
1769             CHECK_FOR_EXCEPTION();
1770             callFrame[dst] = result;
1771         }
1772 
1773         ++vPC;
1774         NEXT_INSTRUCTION();
1775     }
1776     DEFINE_OPCODE(op_negate) {
1777         /* negate dst(r) src(r)
1778 
1779            Converts register src to number, negates it, and puts the
1780            result in register dst.
1781         */
1782         int dst = (++vPC)->u.operand;
1783         JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1784         ++vPC;
1785         double v;
1786         if (src.getNumber(v))
1787             callFrame[dst] = JSValuePtr(jsNumber(callFrame, -v));
1788         else {
1789             JSValuePtr result = jsNumber(callFrame, -src.toNumber(callFrame));
1790             CHECK_FOR_EXCEPTION();
1791             callFrame[dst] = result;
1792         }
1793 
1794         NEXT_INSTRUCTION();
1795     }
1796     DEFINE_OPCODE(op_add) {
1797         /* add dst(r) src1(r) src2(r)
1798 
1799            Adds register src1 and register src2, and puts the result
1800            in register dst. (JS add may be string concatenation or
1801            numeric add, depending on the types of the operands.)
1802         */
1803         int dst = (++vPC)->u.operand;
1804         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1805         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1806         if (JSFastMath::canDoFastAdditiveOperations(src1, src2))
1807             callFrame[dst] = JSValuePtr(JSFastMath::addImmediateNumbers(src1, src2));
1808         else {
1809             JSValuePtr result = jsAdd(callFrame, src1, src2);
1810             CHECK_FOR_EXCEPTION();
1811             callFrame[dst] = result;
1812         }
1813         vPC += 2;
1814         NEXT_INSTRUCTION();
1815     }
1816     DEFINE_OPCODE(op_mul) {
1817         /* mul dst(r) src1(r) src2(r)
1818 
1819            Multiplies register src1 and register src2 (converted to
1820            numbers), and puts the product in register dst.
1821         */
1822         int dst = (++vPC)->u.operand;
1823         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1824         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1825         double left;
1826         double right;
1827         if (JSValuePtr::areBothInt32Fast(src1, src2)) {
1828             int32_t left = src1.getInt32Fast();
1829             int32_t right = src2.getInt32Fast();
1830             if ((left | right) >> 15 == 0)
1831                 callFrame[dst] = JSValuePtr(jsNumber(callFrame, left * right));
1832             else
1833                 callFrame[dst] = JSValuePtr(jsNumber(callFrame, static_cast<double>(left) * static_cast<double>(right)));
1834         } else if (src1.getNumber(left) && src2.getNumber(right))
1835             callFrame[dst] = JSValuePtr(jsNumber(callFrame, left * right));
1836         else {
1837             JSValuePtr result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame));
1838             CHECK_FOR_EXCEPTION();
1839             callFrame[dst] = result;
1840         }
1841 
1842         vPC += 2;
1843         NEXT_INSTRUCTION();
1844     }
1845     DEFINE_OPCODE(op_div) {
1846         /* div dst(r) dividend(r) divisor(r)
1847 
1848            Divides register dividend (converted to number) by the
1849            register divisor (converted to number), and puts the
1850            quotient in register dst.
1851         */
1852         int dst = (++vPC)->u.operand;
1853         JSValuePtr dividend = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1854         JSValuePtr divisor = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1855         double left;
1856         double right;
1857         if (dividend.getNumber(left) && divisor.getNumber(right))
1858             callFrame[dst] = JSValuePtr(jsNumber(callFrame, left / right));
1859         else {
1860             JSValuePtr result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
1861             CHECK_FOR_EXCEPTION();
1862             callFrame[dst] = result;
1863         }
1864         ++vPC;
1865         NEXT_INSTRUCTION();
1866     }
1867     DEFINE_OPCODE(op_mod) {
1868         /* mod dst(r) dividend(r) divisor(r)
1869 
1870            Divides register dividend (converted to number) by
1871            register divisor (converted to number), and puts the
1872            remainder in register dst.
1873         */
1874         int dst = (++vPC)->u.operand;
1875         int dividend = (++vPC)->u.operand;
1876         int divisor = (++vPC)->u.operand;
1877 
1878         JSValuePtr dividendValue = callFrame[dividend].jsValue(callFrame);
1879         JSValuePtr divisorValue = callFrame[divisor].jsValue(callFrame);
1880 
1881         if (JSValuePtr::areBothInt32Fast(dividendValue, divisorValue) && divisorValue != js0()) {
1882             // We expect the result of the modulus of a number that was representable as an int32 to also be representable
1883             // as an int32.
1884             JSValuePtr result = JSValuePtr::makeInt32Fast(dividendValue.getInt32Fast() % divisorValue.getInt32Fast());
1885             ASSERT(result);
1886             callFrame[dst] = result;
1887             ++vPC;
1888             NEXT_INSTRUCTION();
1889         }
1890 
1891         double d = dividendValue.toNumber(callFrame);
1892         JSValuePtr result = jsNumber(callFrame, fmod(d, divisorValue.toNumber(callFrame)));
1893         CHECK_FOR_EXCEPTION();
1894         callFrame[dst] = result;
1895         ++vPC;
1896         NEXT_INSTRUCTION();
1897     }
1898     DEFINE_OPCODE(op_sub) {
1899         /* sub dst(r) src1(r) src2(r)
1900 
1901            Subtracts register src2 (converted to number) from register
1902            src1 (converted to number), and puts the difference in
1903            register dst.
1904         */
1905         int dst = (++vPC)->u.operand;
1906         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1907         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1908         double left;
1909         double right;
1910         if (JSFastMath::canDoFastAdditiveOperations(src1, src2))
1911             callFrame[dst] = JSValuePtr(JSFastMath::subImmediateNumbers(src1, src2));
1912         else if (src1.getNumber(left) && src2.getNumber(right))
1913             callFrame[dst] = JSValuePtr(jsNumber(callFrame, left - right));
1914         else {
1915             JSValuePtr result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame));
1916             CHECK_FOR_EXCEPTION();
1917             callFrame[dst] = result;
1918         }
1919         vPC += 2;
1920         NEXT_INSTRUCTION();
1921     }
1922     DEFINE_OPCODE(op_lshift) {
1923         /* lshift dst(r) val(r) shift(r)
1924 
1925            Performs left shift of register val (converted to int32) by
1926            register shift (converted to uint32), and puts the result
1927            in register dst.
1928         */
1929         int dst = (++vPC)->u.operand;
1930         JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1931         JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1932         int32_t left;
1933         uint32_t right;
1934         if (JSValuePtr::areBothInt32Fast(val, shift))
1935             callFrame[dst] = JSValuePtr(jsNumber(callFrame, val.getInt32Fast() << (shift.getInt32Fast() & 0x1f)));
1936         else if (val.numberToInt32(left) && shift.numberToUInt32(right))
1937             callFrame[dst] = JSValuePtr(jsNumber(callFrame, left << (right & 0x1f)));
1938         else {
1939             JSValuePtr result = jsNumber(callFrame, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
1940             CHECK_FOR_EXCEPTION();
1941             callFrame[dst] = result;
1942         }
1943 
1944         ++vPC;
1945         NEXT_INSTRUCTION();
1946     }
1947     DEFINE_OPCODE(op_rshift) {
1948         /* rshift dst(r) val(r) shift(r)
1949 
1950            Performs arithmetic right shift of register val (converted
1951            to int32) by register shift (converted to
1952            uint32), and puts the result in register dst.
1953         */
1954         int dst = (++vPC)->u.operand;
1955         JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1956         JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1957         int32_t left;
1958         uint32_t right;
1959         if (JSFastMath::canDoFastRshift(val, shift))
1960             callFrame[dst] = JSValuePtr(JSFastMath::rightShiftImmediateNumbers(val, shift));
1961         else if (val.numberToInt32(left) && shift.numberToUInt32(right))
1962             callFrame[dst] = JSValuePtr(jsNumber(callFrame, left >> (right & 0x1f)));
1963         else {
1964             JSValuePtr result = jsNumber(callFrame, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
1965             CHECK_FOR_EXCEPTION();
1966             callFrame[dst] = result;
1967         }
1968 
1969         ++vPC;
1970         NEXT_INSTRUCTION();
1971     }
1972     DEFINE_OPCODE(op_urshift) {
1973         /* rshift dst(r) val(r) shift(r)
1974 
1975            Performs logical right shift of register val (converted
1976            to uint32) by register shift (converted to
1977            uint32), and puts the result in register dst.
1978         */
1979         int dst = (++vPC)->u.operand;
1980         JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1981         JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1982         if (JSFastMath::canDoFastUrshift(val, shift))
1983             callFrame[dst] = JSValuePtr(JSFastMath::rightShiftImmediateNumbers(val, shift));
1984         else {
1985             JSValuePtr result = jsNumber(callFrame, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
1986             CHECK_FOR_EXCEPTION();
1987             callFrame[dst] = result;
1988         }
1989 
1990         ++vPC;
1991         NEXT_INSTRUCTION();
1992     }
1993     DEFINE_OPCODE(op_bitand) {
1994         /* bitand dst(r) src1(r) src2(r)
1995 
1996            Computes bitwise AND of register src1 (converted to int32)
1997            and register src2 (converted to int32), and puts the result
1998            in register dst.
1999         */
2000         int dst = (++vPC)->u.operand;
2001         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2002         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2003         int32_t left;
2004         int32_t right;
2005         if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
2006             callFrame[dst] = JSValuePtr(JSFastMath::andImmediateNumbers(src1, src2));
2007         else if (src1.numberToInt32(left) && src2.numberToInt32(right))
2008             callFrame[dst] = JSValuePtr(jsNumber(callFrame, left & right));
2009         else {
2010             JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame));
2011             CHECK_FOR_EXCEPTION();
2012             callFrame[dst] = result;
2013         }
2014 
2015         vPC += 2;
2016         NEXT_INSTRUCTION();
2017     }
2018     DEFINE_OPCODE(op_bitxor) {
2019         /* bitxor dst(r) src1(r) src2(r)
2020 
2021            Computes bitwise XOR of register src1 (converted to int32)
2022            and register src2 (converted to int32), and puts the result
2023            in register dst.
2024         */
2025         int dst = (++vPC)->u.operand;
2026         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2027         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2028         int32_t left;
2029         int32_t right;
2030         if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
2031             callFrame[dst] = JSValuePtr(JSFastMath::xorImmediateNumbers(src1, src2));
2032         else if (src1.numberToInt32(left) && src2.numberToInt32(right))
2033             callFrame[dst] = JSValuePtr(jsNumber(callFrame, left ^ right));
2034         else {
2035             JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
2036             CHECK_FOR_EXCEPTION();
2037             callFrame[dst] = result;
2038         }
2039 
2040         vPC += 2;
2041         NEXT_INSTRUCTION();
2042     }
2043     DEFINE_OPCODE(op_bitor) {
2044         /* bitor dst(r) src1(r) src2(r)
2045 
2046            Computes bitwise OR of register src1 (converted to int32)
2047            and register src2 (converted to int32), and puts the
2048            result in register dst.
2049         */
2050         int dst = (++vPC)->u.operand;
2051         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2052         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2053         int32_t left;
2054         int32_t right;
2055         if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
2056             callFrame[dst] = JSValuePtr(JSFastMath::orImmediateNumbers(src1, src2));
2057         else if (src1.numberToInt32(left) && src2.numberToInt32(right))
2058             callFrame[dst] = JSValuePtr(jsNumber(callFrame, left | right));
2059         else {
2060             JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame));
2061             CHECK_FOR_EXCEPTION();
2062             callFrame[dst] = result;
2063         }
2064 
2065         vPC += 2;
2066         NEXT_INSTRUCTION();
2067     }
2068     DEFINE_OPCODE(op_bitnot) {
2069         /* bitnot dst(r) src(r)
2070 
2071            Computes bitwise NOT of register src1 (converted to int32),
2072            and puts the result in register dst.
2073         */
2074         int dst = (++vPC)->u.operand;
2075         JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2076         int32_t value;
2077         if (src.numberToInt32(value))
2078             callFrame[dst] = JSValuePtr(jsNumber(callFrame, ~value));
2079         else {
2080             JSValuePtr result = jsNumber(callFrame, ~src.toInt32(callFrame));
2081             CHECK_FOR_EXCEPTION();
2082             callFrame[dst] = result;
2083         }
2084         ++vPC;
2085         NEXT_INSTRUCTION();
2086     }
2087     DEFINE_OPCODE(op_not) {
2088         /* not dst(r) src(r)
2089 
2090            Computes logical NOT of register src (converted to
2091            boolean), and puts the result in register dst.
2092         */
2093         int dst = (++vPC)->u.operand;
2094         int src = (++vPC)->u.operand;
2095         JSValuePtr result = jsBoolean(!callFrame[src].jsValue(callFrame).toBoolean(callFrame));
2096         CHECK_FOR_EXCEPTION();
2097         callFrame[dst] = result;
2098 
2099         ++vPC;
2100         NEXT_INSTRUCTION();
2101     }
2102     DEFINE_OPCODE(op_instanceof) {
2103         /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
2104 
2105            Tests whether register value is an instance of register
2106            constructor, and puts the boolean result in register
2107            dst. Register constructorProto must contain the "prototype"
2108            property (not the actual prototype) of the object in
2109            register constructor. This lookup is separated so that
2110            polymorphic inline caching can apply.
2111 
2112            Raises an exception if register constructor is not an
2113            object.
2114         */
2115         int dst = vPC[1].u.operand;
2116         int value = vPC[2].u.operand;
2117         int base = vPC[3].u.operand;
2118         int baseProto = vPC[4].u.operand;
2119 
2120         JSValuePtr baseVal = callFrame[base].jsValue(callFrame);
2121 
2122         if (isNotObject(callFrame, true, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
2123             goto vm_throw;
2124 
2125         JSObject* baseObj = asObject(baseVal);
2126         callFrame[dst] = jsBoolean(baseObj->structure()->typeInfo().implementsHasInstance() ? baseObj->hasInstance(callFrame, callFrame[value].jsValue(callFrame), callFrame[baseProto].jsValue(callFrame)) : false);
2127 
2128         vPC += 5;
2129         NEXT_INSTRUCTION();
2130     }
2131     DEFINE_OPCODE(op_typeof) {
2132         /* typeof dst(r) src(r)
2133 
2134            Determines the type string for src according to ECMAScript
2135            rules, and puts the result in register dst.
2136         */
2137         int dst = (++vPC)->u.operand;
2138         int src = (++vPC)->u.operand;
2139         callFrame[dst] = JSValuePtr(jsTypeStringForValue(callFrame, callFrame[src].jsValue(callFrame)));
2140 
2141         ++vPC;
2142         NEXT_INSTRUCTION();
2143     }
2144     DEFINE_OPCODE(op_is_undefined) {
2145         /* is_undefined dst(r) src(r)
2146 
2147            Determines whether the type string for src according to
2148            the ECMAScript rules is "undefined", and puts the result
2149            in register dst.
2150         */
2151         int dst = (++vPC)->u.operand;
2152         int src = (++vPC)->u.operand;
2153         JSValuePtr v = callFrame[src].jsValue(callFrame);
2154         callFrame[dst] = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined());
2155 
2156         ++vPC;
2157         NEXT_INSTRUCTION();
2158     }
2159     DEFINE_OPCODE(op_is_boolean) {
2160         /* is_boolean dst(r) src(r)
2161 
2162            Determines whether the type string for src according to
2163            the ECMAScript rules is "boolean", and puts the result
2164            in register dst.
2165         */
2166         int dst = (++vPC)->u.operand;
2167         int src = (++vPC)->u.operand;
2168         callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isBoolean());
2169 
2170         ++vPC;
2171         NEXT_INSTRUCTION();
2172     }
2173     DEFINE_OPCODE(op_is_number) {
2174         /* is_number dst(r) src(r)
2175 
2176            Determines whether the type string for src according to
2177            the ECMAScript rules is "number", and puts the result
2178            in register dst.
2179         */
2180         int dst = (++vPC)->u.operand;
2181         int src = (++vPC)->u.operand;
2182         callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isNumber());
2183 
2184         ++vPC;
2185         NEXT_INSTRUCTION();
2186     }
2187     DEFINE_OPCODE(op_is_string) {
2188         /* is_string dst(r) src(r)
2189 
2190            Determines whether the type string for src according to
2191            the ECMAScript rules is "string", and puts the result
2192            in register dst.
2193         */
2194         int dst = (++vPC)->u.operand;
2195         int src = (++vPC)->u.operand;
2196         callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isString());
2197 
2198         ++vPC;
2199         NEXT_INSTRUCTION();
2200     }
2201     DEFINE_OPCODE(op_is_object) {
2202         /* is_object dst(r) src(r)
2203 
2204            Determines whether the type string for src according to
2205            the ECMAScript rules is "object", and puts the result
2206            in register dst.
2207         */
2208         int dst = (++vPC)->u.operand;
2209         int src = (++vPC)->u.operand;
2210         callFrame[dst] = jsBoolean(jsIsObjectType(callFrame[src].jsValue(callFrame)));
2211 
2212         ++vPC;
2213         NEXT_INSTRUCTION();
2214     }
2215     DEFINE_OPCODE(op_is_function) {
2216         /* is_function dst(r) src(r)
2217 
2218            Determines whether the type string for src according to
2219            the ECMAScript rules is "function", and puts the result
2220            in register dst.
2221         */
2222         int dst = (++vPC)->u.operand;
2223         int src = (++vPC)->u.operand;
2224         callFrame[dst] = jsBoolean(jsIsFunctionType(callFrame[src].jsValue(callFrame)));
2225 
2226         ++vPC;
2227         NEXT_INSTRUCTION();
2228     }
2229     DEFINE_OPCODE(op_in) {
2230         /* in dst(r) property(r) base(r)
2231 
2232            Tests whether register base has a property named register
2233            property, and puts the boolean result in register dst.
2234 
2235            Raises an exception if register constructor is not an
2236            object.
2237         */
2238         int dst = (++vPC)->u.operand;
2239         int property = (++vPC)->u.operand;
2240         int base = (++vPC)->u.operand;
2241 
2242         JSValuePtr baseVal = callFrame[base].jsValue(callFrame);
2243         if (isNotObject(callFrame, false, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
2244             goto vm_throw;
2245 
2246         JSObject* baseObj = asObject(baseVal);
2247 
2248         JSValuePtr propName = callFrame[property].jsValue(callFrame);
2249 
2250         uint32_t i;
2251         if (propName.getUInt32(i))
2252             callFrame[dst] = jsBoolean(baseObj->hasProperty(callFrame, i));
2253         else {
2254             Identifier property(callFrame, propName.toString(callFrame));
2255             CHECK_FOR_EXCEPTION();
2256             callFrame[dst] = jsBoolean(baseObj->hasProperty(callFrame, property));
2257         }
2258 
2259         ++vPC;
2260         NEXT_INSTRUCTION();
2261     }
2262     DEFINE_OPCODE(op_resolve) {
2263         /* resolve dst(r) property(id)
2264 
2265            Looks up the property named by identifier property in the
2266            scope chain, and writes the resulting value to register
2267            dst. If the property is not found, raises an exception.
2268         */
2269         if (UNLIKELY(!resolve(callFrame, vPC, exceptionValue)))
2270             goto vm_throw;
2271 
2272         vPC += 3;
2273         NEXT_INSTRUCTION();
2274     }
2275     DEFINE_OPCODE(op_resolve_skip) {
2276         /* resolve_skip dst(r) property(id) skip(n)
2277 
2278          Looks up the property named by identifier property in the
2279          scope chain skipping the top 'skip' levels, and writes the resulting
2280          value to register dst. If the property is not found, raises an exception.
2281          */
2282         if (UNLIKELY(!resolveSkip(callFrame, vPC, exceptionValue)))
2283             goto vm_throw;
2284 
2285         vPC += 4;
2286 
2287         NEXT_INSTRUCTION();
2288     }
2289     DEFINE_OPCODE(op_resolve_global) {
2290         /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n)
2291 
2292            Performs a dynamic property lookup for the given property, on the provided
2293            global object.  If structure matches the Structure of the global then perform
2294            a fast lookup using the case offset, otherwise fall back to a full resolve and
2295            cache the new structure and offset
2296          */
2297         if (UNLIKELY(!resolveGlobal(callFrame, vPC, exceptionValue)))
2298             goto vm_throw;
2299 
2300         vPC += 6;
2301 
2302         NEXT_INSTRUCTION();
2303     }
2304     DEFINE_OPCODE(op_get_global_var) {
2305         /* get_global_var dst(r) globalObject(c) index(n)
2306 
2307            Gets the global var at global slot index and places it in register dst.
2308          */
2309         int dst = (++vPC)->u.operand;
2310         JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
2311         ASSERT(scope->isGlobalObject());
2312         int index = (++vPC)->u.operand;
2313 
2314         callFrame[dst] = scope->registerAt(index);
2315         ++vPC;
2316         NEXT_INSTRUCTION();
2317     }
2318     DEFINE_OPCODE(op_put_global_var) {
2319         /* put_global_var globalObject(c) index(n) value(r)
2320 
2321            Puts value into global slot index.
2322          */
2323         JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
2324         ASSERT(scope->isGlobalObject());
2325         int index = (++vPC)->u.operand;
2326         int value = (++vPC)->u.operand;
2327 
2328         scope->registerAt(index) = JSValuePtr(callFrame[value].jsValue(callFrame));
2329         ++vPC;
2330         NEXT_INSTRUCTION();
2331     }
2332     DEFINE_OPCODE(op_get_scoped_var) {
2333         /* get_scoped_var dst(r) index(n) skip(n)
2334 
2335          Loads the contents of the index-th local from the scope skip nodes from
2336          the top of the scope chain, and places it in register dst
2337          */
2338         int dst = (++vPC)->u.operand;
2339         int index = (++vPC)->u.operand;
2340         int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain();
2341 
2342         ScopeChainNode* scopeChain = callFrame->scopeChain();
2343         ScopeChainIterator iter = scopeChain->begin();
2344         ScopeChainIterator end = scopeChain->end();
2345         ASSERT(iter != end);
2346         while (skip--) {
2347             ++iter;
2348             ASSERT(iter != end);
2349         }
2350 
2351         ASSERT((*iter)->isVariableObject());
2352         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
2353         callFrame[dst] = scope->registerAt(index);
2354         ++vPC;
2355         NEXT_INSTRUCTION();
2356     }
2357     DEFINE_OPCODE(op_put_scoped_var) {
2358         /* put_scoped_var index(n) skip(n) value(r)
2359 
2360          */
2361         int index = (++vPC)->u.operand;
2362         int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain();
2363         int value = (++vPC)->u.operand;
2364 
2365         ScopeChainNode* scopeChain = callFrame->scopeChain();
2366         ScopeChainIterator iter = scopeChain->begin();
2367         ScopeChainIterator end = scopeChain->end();
2368         ASSERT(iter != end);
2369         while (skip--) {
2370             ++iter;
2371             ASSERT(iter != end);
2372         }
2373 
2374         ASSERT((*iter)->isVariableObject());
2375         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
2376         scope->registerAt(index) = JSValuePtr(callFrame[value].jsValue(callFrame));
2377         ++vPC;
2378         NEXT_INSTRUCTION();
2379     }
2380     DEFINE_OPCODE(op_resolve_base) {
2381         /* resolve_base dst(r) property(id)
2382 
2383            Searches the scope chain for an object containing
2384            identifier property, and if one is found, writes it to
2385            register dst. If none is found, the outermost scope (which
2386            will be the global object) is stored in register dst.
2387         */
2388         resolveBase(callFrame, vPC);
2389 
2390         vPC += 3;
2391         NEXT_INSTRUCTION();
2392     }
2393     DEFINE_OPCODE(op_resolve_with_base) {
2394         /* resolve_with_base baseDst(r) propDst(r) property(id)
2395 
2396            Searches the scope chain for an object containing
2397            identifier property, and if one is found, writes it to
2398            register srcDst, and the retrieved property value to register
2399            propDst. If the property is not found, raises an exception.
2400 
2401            This is more efficient than doing resolve_base followed by
2402            resolve, or resolve_base followed by get_by_id, as it
2403            avoids duplicate hash lookups.
2404         */
2405         if (UNLIKELY(!resolveBaseAndProperty(callFrame, vPC, exceptionValue)))
2406             goto vm_throw;
2407 
2408         vPC += 4;
2409         NEXT_INSTRUCTION();
2410     }
2411     DEFINE_OPCODE(op_resolve_func) {
2412         /* resolve_func baseDst(r) funcDst(r) property(id)
2413 
2414            Searches the scope chain for an object containing
2415            identifier property, and if one is found, writes the
2416            appropriate object to use as "this" when calling its
2417            properties to register baseDst; and the retrieved property
2418            value to register propDst. If the property is not found,
2419            raises an exception.
2420 
2421            This differs from resolve_with_base, because the
2422            global this value will be substituted for activations or
2423            the global object, which is the right behavior for function
2424            calls but not for other property lookup.
2425         */
2426         if (UNLIKELY(!resolveBaseAndFunc(callFrame, vPC, exceptionValue)))
2427             goto vm_throw;
2428 
2429         vPC += 4;
2430         NEXT_INSTRUCTION();
2431     }
2432     DEFINE_OPCODE(op_get_by_id) {
2433         /* get_by_id dst(r) base(r) property(id) structure(sID) nop(n) nop(n) nop(n)
2434 
2435            Generic property access: Gets the property named by identifier
2436            property from the value base, and puts the result in register dst.
2437         */
2438         int dst = vPC[1].u.operand;
2439         int base = vPC[2].u.operand;
2440         int property = vPC[3].u.operand;
2441 
2442         CodeBlock* codeBlock = callFrame->codeBlock();
2443         Identifier& ident = codeBlock->identifier(property);
2444         JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
2445         PropertySlot slot(baseValue);
2446         JSValuePtr result = baseValue.get(callFrame, ident, slot);
2447         CHECK_FOR_EXCEPTION();
2448 
2449         tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
2450 
2451         callFrame[dst] = result;
2452         vPC += 8;
2453         NEXT_INSTRUCTION();
2454     }
2455     DEFINE_OPCODE(op_get_by_id_self) {
2456         /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
2457 
2458            Cached property access: Attempts to get a cached property from the
2459            value base. If the cache misses, op_get_by_id_self reverts to
2460            op_get_by_id.
2461         */
2462         int base = vPC[2].u.operand;
2463         JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
2464 
2465         if (LIKELY(baseValue.isCell())) {
2466             JSCell* baseCell = asCell(baseValue);
2467             Structure* structure = vPC[4].u.structure;
2468 
2469             if (LIKELY(baseCell->structure() == structure)) {
2470                 ASSERT(baseCell->isObject());
2471                 JSObject* baseObject = asObject(baseCell);
2472                 int dst = vPC[1].u.operand;
2473                 int offset = vPC[5].u.operand;
2474 
2475                 ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
2476                 callFrame[dst] = JSValuePtr(baseObject->getDirectOffset(offset));
2477 
2478                 vPC += 8;
2479                 NEXT_INSTRUCTION();
2480             }
2481         }
2482 
2483         uncacheGetByID(callFrame->codeBlock(), vPC);
2484         NEXT_INSTRUCTION();
2485     }
2486     DEFINE_OPCODE(op_get_by_id_proto) {
2487         /* op_get_by_id_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
2488 
2489            Cached property access: Attempts to get a cached property from the
2490            value base's prototype. If the cache misses, op_get_by_id_proto
2491            reverts to op_get_by_id.
2492         */
2493         int base = vPC[2].u.operand;
2494         JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
2495 
2496         if (LIKELY(baseValue.isCell())) {
2497             JSCell* baseCell = asCell(baseValue);
2498             Structure* structure = vPC[4].u.structure;
2499 
2500             if (LIKELY(baseCell->structure() == structure)) {
2501                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
2502                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
2503                 Structure* prototypeStructure = vPC[5].u.structure;
2504 
2505                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
2506                     int dst = vPC[1].u.operand;
2507                     int offset = vPC[6].u.operand;
2508 
2509                     ASSERT(protoObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
2510                     callFrame[dst] = JSValuePtr(protoObject->getDirectOffset(offset));
2511 
2512                     vPC += 8;
2513                     NEXT_INSTRUCTION();
2514                 }
2515             }
2516         }
2517 
2518         uncacheGetByID(callFrame->codeBlock(), vPC);
2519         NEXT_INSTRUCTION();
2520     }
2521     DEFINE_OPCODE(op_get_by_id_self_list) {
2522         // Polymorphic self access caching currently only supported when JITting.
2523         ASSERT_NOT_REACHED();
2524         // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
2525         vPC += 8;
2526         NEXT_INSTRUCTION();
2527     }
2528     DEFINE_OPCODE(op_get_by_id_proto_list) {
2529         // Polymorphic prototype access caching currently only supported when JITting.
2530         ASSERT_NOT_REACHED();
2531         // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
2532         vPC += 8;
2533         NEXT_INSTRUCTION();
2534     }
2535     DEFINE_OPCODE(op_get_by_id_chain) {
2536         /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
2537 
2538            Cached property access: Attempts to get a cached property from the
2539            value base's prototype chain. If the cache misses, op_get_by_id_chain
2540            reverts to op_get_by_id.
2541         */
2542         int base = vPC[2].u.operand;
2543         JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
2544 
2545         if (LIKELY(baseValue.isCell())) {
2546             JSCell* baseCell = asCell(baseValue);
2547             Structure* structure = vPC[4].u.structure;
2548 
2549             if (LIKELY(baseCell->structure() == structure)) {
2550                 RefPtr<Structure>* it = vPC[5].u.structureChain->head();
2551                 size_t count = vPC[6].u.operand;
2552                 RefPtr<Structure>* end = it + count;
2553 
2554                 while (true) {
2555                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
2556 
2557                     if (UNLIKELY(baseObject->structure() != (*it).get()))
2558                         break;
2559 
2560                     if (++it == end) {
2561                         int dst = vPC[1].u.operand;
2562                         int offset = vPC[7].u.operand;
2563 
2564                         ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
2565                         callFrame[dst] = JSValuePtr(baseObject->getDirectOffset(offset));
2566 
2567                         vPC += 8;
2568                         NEXT_INSTRUCTION();
2569                     }
2570 
2571                     // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
2572                     baseCell = baseObject;
2573                 }
2574             }
2575         }
2576 
2577         uncacheGetByID(callFrame->codeBlock(), vPC);
2578         NEXT_INSTRUCTION();
2579     }
2580     DEFINE_OPCODE(op_get_by_id_generic) {
2581         /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2582 
2583            Generic property access: Gets the property named by identifier
2584            property from the value base, and puts the result in register dst.
2585         */
2586         int dst = vPC[1].u.operand;
2587         int base = vPC[2].u.operand;
2588         int property = vPC[3].u.operand;
2589 
2590         Identifier& ident = callFrame->codeBlock()->identifier(property);
2591         JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
2592         PropertySlot slot(baseValue);
2593         JSValuePtr result = baseValue.get(callFrame, ident, slot);
2594         CHECK_FOR_EXCEPTION();
2595 
2596         callFrame[dst] = result;
2597         vPC += 8;
2598         NEXT_INSTRUCTION();
2599     }
2600     DEFINE_OPCODE(op_get_array_length) {
2601         /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2602 
2603            Cached property access: Gets the length of the array in register base,
2604            and puts the result in register dst. If register base does not hold
2605            an array, op_get_array_length reverts to op_get_by_id.
2606         */
2607 
2608         int base = vPC[2].u.operand;
2609         JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
2610         if (LIKELY(isJSArray(baseValue))) {
2611             int dst = vPC[1].u.operand;
2612             callFrame[dst] = JSValuePtr(jsNumber(callFrame, asArray(baseValue)->length()));
2613             vPC += 8;
2614             NEXT_INSTRUCTION();
2615         }
2616 
2617         uncacheGetByID(callFrame->codeBlock(), vPC);
2618         NEXT_INSTRUCTION();
2619     }
2620     DEFINE_OPCODE(op_get_string_length) {
2621         /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2622 
2623            Cached property access: Gets the length of the string in register base,
2624            and puts the result in register dst. If register base does not hold
2625            a string, op_get_string_length reverts to op_get_by_id.
2626         */
2627 
2628         int base = vPC[2].u.operand;
2629         JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
2630         if (LIKELY(isJSString(baseValue))) {
2631             int dst = vPC[1].u.operand;
2632             callFrame[dst] = JSValuePtr(jsNumber(callFrame, asString(baseValue)->value().size()));
2633             vPC += 8;
2634             NEXT_INSTRUCTION();
2635         }
2636 
2637         uncacheGetByID(callFrame->codeBlock(), vPC);
2638         NEXT_INSTRUCTION();
2639     }
2640     DEFINE_OPCODE(op_put_by_id) {
2641         /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
2642 
2643            Generic property access: Sets the property named by identifier
2644            property, belonging to register base, to register value.
2645 
2646            Unlike many opcodes, this one does not write any output to
2647            the register file.
2648         */
2649 
2650         int base = vPC[1].u.operand;
2651         int property = vPC[2].u.operand;
2652         int value = vPC[3].u.operand;
2653 
2654         CodeBlock* codeBlock = callFrame->codeBlock();
2655         JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
2656         Identifier& ident = codeBlock->identifier(property);
2657         PutPropertySlot slot;
2658         baseValue.put(callFrame, ident, callFrame[value].jsValue(callFrame), slot);
2659         CHECK_FOR_EXCEPTION();
2660 
2661         tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
2662 
2663         vPC += 8;
2664         NEXT_INSTRUCTION();
2665     }
2666     DEFINE_OPCODE(op_put_by_id_transition) {
2667         /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n)
2668 
2669            Cached property access: Attempts to set a new property with a cached transition
2670            property named by identifier property, belonging to register base,
2671            to register value. If the cache misses, op_put_by_id_transition
2672            reverts to op_put_by_id_generic.
2673 
2674            Unlike many opcodes, this one does not write any output to
2675            the register file.
2676          */
2677         int base = vPC[1].u.operand;
2678         JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
2679 
2680         if (LIKELY(baseValue.isCell())) {
2681             JSCell* baseCell = asCell(baseValue);
2682             Structure* oldStructure = vPC[4].u.structure;
2683             Structure* newStructure = vPC[5].u.structure;
2684 
2685             if (LIKELY(baseCell->structure() == oldStructure)) {
2686                 ASSERT(baseCell->isObject());
2687                 JSObject* baseObject = asObject(baseCell);
2688 
2689                 RefPtr<Structure>* it = vPC[6].u.structureChain->head();
2690 
2691                 JSValuePtr proto = baseObject->structure()->prototypeForLookup(callFrame);
2692                 while (!proto.isNull()) {
2693                     if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
2694                         uncachePutByID(callFrame->codeBlock(), vPC);
2695                         NEXT_INSTRUCTION();
2696                     }
2697                     ++it;
2698                     proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
2699                 }
2700 
2701                 baseObject->transitionTo(newStructure);
2702 
2703                 int value = vPC[3].u.operand;
2704                 unsigned offset = vPC[7].u.operand;
2705                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
2706                 baseObject->putDirectOffset(offset, callFrame[value].jsValue(callFrame));
2707 
2708                 vPC += 8;
2709                 NEXT_INSTRUCTION();
2710             }
2711         }
2712 
2713         uncachePutByID(callFrame->codeBlock(), vPC);
2714         NEXT_INSTRUCTION();
2715     }
2716     DEFINE_OPCODE(op_put_by_id_replace) {
2717         /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n)
2718 
2719            Cached property access: Attempts to set a pre-existing, cached
2720            property named by identifier property, belonging to register base,
2721            to register value. If the cache misses, op_put_by_id_replace
2722            reverts to op_put_by_id.
2723 
2724            Unlike many opcodes, this one does not write any output to
2725            the register file.
2726         */
2727         int base = vPC[1].u.operand;
2728         JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
2729 
2730         if (LIKELY(baseValue.isCell())) {
2731             JSCell* baseCell = asCell(baseValue);
2732             Structure* structure = vPC[4].u.structure;
2733 
2734             if (LIKELY(baseCell->structure() == structure)) {
2735                 ASSERT(baseCell->isObject());
2736                 JSObject* baseObject = asObject(baseCell);
2737                 int value = vPC[3].u.operand;
2738                 unsigned offset = vPC[5].u.operand;
2739 
2740                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
2741                 baseObject->putDirectOffset(offset, callFrame[value].jsValue(callFrame));
2742 
2743                 vPC += 8;
2744                 NEXT_INSTRUCTION();
2745             }
2746         }
2747 
2748         uncachePutByID(callFrame->codeBlock(), vPC);
2749         NEXT_INSTRUCTION();
2750     }
2751     DEFINE_OPCODE(op_put_by_id_generic) {
2752         /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
2753 
2754            Generic property access: Sets the property named by identifier
2755            property, belonging to register base, to register value.
2756 
2757            Unlike many opcodes, this one does not write any output to
2758            the register file.
2759         */
2760         int base = vPC[1].u.operand;
2761         int property = vPC[2].u.operand;
2762         int value = vPC[3].u.operand;
2763 
2764         JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
2765         Identifier& ident = callFrame->codeBlock()->identifier(property);
2766         PutPropertySlot slot;
2767         baseValue.put(callFrame, ident, callFrame[value].jsValue(callFrame), slot);
2768         CHECK_FOR_EXCEPTION();
2769 
2770         vPC += 8;
2771         NEXT_INSTRUCTION();
2772     }
2773     DEFINE_OPCODE(op_del_by_id) {
2774         /* del_by_id dst(r) base(r) property(id)
2775 
2776            Converts register base to Object, deletes the property
2777            named by identifier property from the object, and writes a
2778            boolean indicating success (if true) or failure (if false)
2779            to register dst.
2780         */
2781         int dst = (++vPC)->u.operand;
2782         int base = (++vPC)->u.operand;
2783         int property = (++vPC)->u.operand;
2784 
2785         JSObject* baseObj = callFrame[base].jsValue(callFrame).toObject(callFrame);
2786         Identifier& ident = callFrame->codeBlock()->identifier(property);
2787         JSValuePtr result = jsBoolean(baseObj->deleteProperty(callFrame, ident));
2788         CHECK_FOR_EXCEPTION();
2789         callFrame[dst] = result;
2790         ++vPC;
2791         NEXT_INSTRUCTION();
2792     }
2793     DEFINE_OPCODE(op_get_by_val) {
2794         /* get_by_val dst(r) base(r) property(r)
2795 
2796            Converts register base to Object, gets the property named
2797            by register property from the object, and puts the result
2798            in register dst. property is nominally converted to string
2799            but numbers are treated more efficiently.
2800         */
2801         int dst = (++vPC)->u.operand;
2802         int base = (++vPC)->u.operand;
2803         int property = (++vPC)->u.operand;
2804 
2805         JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
2806         JSValuePtr subscript = callFrame[property].jsValue(callFrame);
2807 
2808         JSValuePtr result;
2809 
2810         if (LIKELY(subscript.isUInt32Fast())) {
2811             uint32_t i = subscript.getUInt32Fast();
2812             if (isJSArray(baseValue)) {
2813                 JSArray* jsArray = asArray(baseValue);
2814                 if (jsArray->canGetIndex(i))
2815                     result = jsArray->getIndex(i);
2816                 else
2817                     result = jsArray->JSArray::get(callFrame, i);
2818             } else if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
2819                 result = asString(baseValue)->getIndex(&callFrame->globalData(), i);
2820             else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i))
2821                 result = asByteArray(baseValue)->getIndex(callFrame, i);
2822             else
2823                 result = baseValue.get(callFrame, i);
2824         } else {
2825             Identifier property(callFrame, subscript.toString(callFrame));
2826             result = baseValue.get(callFrame, property);
2827         }
2828 
2829         CHECK_FOR_EXCEPTION();
2830         callFrame[dst] = result;
2831         ++vPC;
2832         NEXT_INSTRUCTION();
2833     }
2834     DEFINE_OPCODE(op_put_by_val) {
2835         /* put_by_val base(r) property(r) value(r)
2836 
2837            Sets register value on register base as the property named
2838            by register property. Base is converted to object
2839            first. register property is nominally converted to string
2840            but numbers are treated more efficiently.
2841 
2842            Unlike many opcodes, this one does not write any output to
2843            the register file.
2844         */
2845         int base = (++vPC)->u.operand;
2846         int property = (++vPC)->u.operand;
2847         int value = (++vPC)->u.operand;
2848 
2849         JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
2850         JSValuePtr subscript = callFrame[property].jsValue(callFrame);
2851 
2852         if (LIKELY(subscript.isUInt32Fast())) {
2853             uint32_t i = subscript.getUInt32Fast();
2854             if (isJSArray(baseValue)) {
2855                 JSArray* jsArray = asArray(baseValue);
2856                 if (jsArray->canSetIndex(i))
2857                     jsArray->setIndex(i, callFrame[value].jsValue(callFrame));
2858                 else
2859                     jsArray->JSArray::put(callFrame, i, callFrame[value].jsValue(callFrame));
2860             } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2861                 JSByteArray* jsByteArray = asByteArray(baseValue);
2862                 double dValue = 0;
2863                 JSValuePtr jsValue = callFrame[value].jsValue(callFrame);
2864                 if (jsValue.isInt32Fast())
2865                     jsByteArray->setIndex(i, jsValue.getInt32Fast());
2866                 else if (jsValue.getNumber(dValue))
2867                     jsByteArray->setIndex(i, dValue);
2868                 else
2869                     baseValue.put(callFrame, i, jsValue);
2870             } else
2871                 baseValue.put(callFrame, i, callFrame[value].jsValue(callFrame));
2872         } else {
2873             Identifier property(callFrame, subscript.toString(callFrame));
2874             if (!globalData->exception) { // Don't put to an object if toString threw an exception.
2875                 PutPropertySlot slot;
2876                 baseValue.put(callFrame, property, callFrame[value].jsValue(callFrame), slot);
2877             }
2878         }
2879 
2880         CHECK_FOR_EXCEPTION();
2881         ++vPC;
2882         NEXT_INSTRUCTION();
2883     }
2884     DEFINE_OPCODE(op_del_by_val) {
2885         /* del_by_val dst(r) base(r) property(r)
2886 
2887            Converts register base to Object, deletes the property
2888            named by register property from the object, and writes a
2889            boolean indicating success (if true) or failure (if false)
2890            to register dst.
2891         */
2892         int dst = (++vPC)->u.operand;
2893         int base = (++vPC)->u.operand;
2894         int property = (++vPC)->u.operand;
2895 
2896         JSObject* baseObj = callFrame[base].jsValue(callFrame).toObject(callFrame); // may throw
2897 
2898         JSValuePtr subscript = callFrame[property].jsValue(callFrame);
2899         JSValuePtr result;
2900         uint32_t i;
2901         if (subscript.getUInt32(i))
2902             result = jsBoolean(baseObj->deleteProperty(callFrame, i));
2903         else {
2904             CHECK_FOR_EXCEPTION();
2905             Identifier property(callFrame, subscript.toString(callFrame));
2906             CHECK_FOR_EXCEPTION();
2907             result = jsBoolean(baseObj->deleteProperty(callFrame, property));
2908         }
2909 
2910         CHECK_FOR_EXCEPTION();
2911         callFrame[dst] = result;
2912         ++vPC;
2913         NEXT_INSTRUCTION();
2914     }
2915     DEFINE_OPCODE(op_put_by_index) {
2916         /* put_by_index base(r) property(n) value(r)
2917 
2918            Sets register value on register base as the property named
2919            by the immediate number property. Base is converted to
2920            object first.
2921 
2922            Unlike many opcodes, this one does not write any output to
2923            the register file.
2924 
2925            This opcode is mainly used to initialize array literals.
2926         */
2927         int base = (++vPC)->u.operand;
2928         unsigned property = (++vPC)->u.operand;
2929         int value = (++vPC)->u.operand;
2930 
2931         callFrame[base].jsValue(callFrame).put(callFrame, property, callFrame[value].jsValue(callFrame));
2932 
2933         ++vPC;
2934         NEXT_INSTRUCTION();
2935     }
2936     DEFINE_OPCODE(op_loop) {
2937         /* loop target(offset)
2938 
2939            Jumps unconditionally to offset target from the current
2940            instruction.
2941 
2942            Additionally this loop instruction may terminate JS execution is
2943            the JS timeout is reached.
2944          */
2945 #if ENABLE(OPCODE_STATS)
2946         OpcodeStats::resetLastInstruction();
2947 #endif
2948         int target = (++vPC)->u.operand;
2949         CHECK_FOR_TIMEOUT();
2950         vPC += target;
2951         NEXT_INSTRUCTION();
2952     }
2953     DEFINE_OPCODE(op_jmp) {
2954         /* jmp target(offset)
2955 
2956            Jumps unconditionally to offset target from the current
2957            instruction.
2958         */
2959 #if ENABLE(OPCODE_STATS)
2960         OpcodeStats::resetLastInstruction();
2961 #endif
2962         int target = (++vPC)->u.operand;
2963 
2964         vPC += target;
2965         NEXT_INSTRUCTION();
2966     }
2967     DEFINE_OPCODE(op_loop_if_true) {
2968         /* loop_if_true cond(r) target(offset)
2969 
2970            Jumps to offset target from the current instruction, if and
2971            only if register cond converts to boolean as true.
2972 
2973            Additionally this loop instruction may terminate JS execution is
2974            the JS timeout is reached.
2975          */
2976         int cond = (++vPC)->u.operand;
2977         int target = (++vPC)->u.operand;
2978         if (callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) {
2979             vPC += target;
2980             CHECK_FOR_TIMEOUT();
2981             NEXT_INSTRUCTION();
2982         }
2983 
2984         ++vPC;
2985         NEXT_INSTRUCTION();
2986     }
2987     DEFINE_OPCODE(op_jtrue) {
2988         /* jtrue cond(r) target(offset)
2989 
2990            Jumps to offset target from the current instruction, if and
2991            only if register cond converts to boolean as true.
2992         */
2993         int cond = (++vPC)->u.operand;
2994         int target = (++vPC)->u.operand;
2995         if (callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) {
2996             vPC += target;
2997             NEXT_INSTRUCTION();
2998         }
2999 
3000         ++vPC;
3001         NEXT_INSTRUCTION();
3002     }
3003     DEFINE_OPCODE(op_jfalse) {
3004         /* jfalse cond(r) target(offset)
3005 
3006            Jumps to offset target from the current instruction, if and
3007            only if register cond converts to boolean as false.
3008         */
3009         int cond = (++vPC)->u.operand;
3010         int target = (++vPC)->u.operand;
3011         if (!callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) {
3012             vPC += target;
3013             NEXT_INSTRUCTION();
3014         }
3015 
3016         ++vPC;
3017         NEXT_INSTRUCTION();
3018     }
3019     DEFINE_OPCODE(op_jeq_null) {
3020         /* jeq_null src(r) target(offset)
3021 
3022            Jumps to offset target from the current instruction, if and
3023            only if register src is null.
3024         */
3025         int src = (++vPC)->u.operand;
3026         int target = (++vPC)->u.operand;
3027         JSValuePtr srcValue = callFrame[src].jsValue(callFrame);
3028 
3029         if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
3030             vPC += target;
3031             NEXT_INSTRUCTION();
3032         }
3033 
3034         ++vPC;
3035         NEXT_INSTRUCTION();
3036     }
3037     DEFINE_OPCODE(op_jneq_null) {
3038         /* jneq_null src(r) target(offset)
3039 
3040            Jumps to offset target from the current instruction, if and
3041            only if register src is not null.
3042         */
3043         int src = (++vPC)->u.operand;
3044         int target = (++vPC)->u.operand;
3045         JSValuePtr srcValue = callFrame[src].jsValue(callFrame);
3046 
3047         if (!srcValue.isUndefinedOrNull() || (srcValue.isCell() && !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
3048             vPC += target;
3049             NEXT_INSTRUCTION();
3050         }
3051 
3052         ++vPC;
3053         NEXT_INSTRUCTION();
3054     }
3055     DEFINE_OPCODE(op_loop_if_less) {
3056         /* loop_if_less src1(r) src2(r) target(offset)
3057 
3058            Checks whether register src1 is less than register src2, as
3059            with the ECMAScript '<' operator, and then jumps to offset
3060            target from the current instruction, if and only if the
3061            result of the comparison is true.
3062 
3063            Additionally this loop instruction may terminate JS execution is
3064            the JS timeout is reached.
3065          */
3066         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3067         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3068         int target = (++vPC)->u.operand;
3069 
3070         bool result = jsLess(callFrame, src1, src2);
3071         CHECK_FOR_EXCEPTION();
3072 
3073         if (result) {
3074             vPC += target;
3075             CHECK_FOR_TIMEOUT();
3076             NEXT_INSTRUCTION();
3077         }
3078 
3079         ++vPC;
3080         NEXT_INSTRUCTION();
3081     }
3082     DEFINE_OPCODE(op_loop_if_lesseq) {
3083         /* loop_if_lesseq src1(r) src2(r) target(offset)
3084 
3085            Checks whether register src1 is less than or equal to register
3086            src2, as with the ECMAScript '<=' operator, and then jumps to
3087            offset target from the current instruction, if and only if the
3088            result of the comparison is true.
3089 
3090            Additionally this loop instruction may terminate JS execution is
3091            the JS timeout is reached.
3092         */
3093         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3094         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3095         int target = (++vPC)->u.operand;
3096 
3097         bool result = jsLessEq(callFrame, src1, src2);
3098         CHECK_FOR_EXCEPTION();
3099 
3100         if (result) {
3101             vPC += target;
3102             CHECK_FOR_TIMEOUT();
3103             NEXT_INSTRUCTION();
3104         }
3105 
3106         ++vPC;
3107         NEXT_INSTRUCTION();
3108     }
3109     DEFINE_OPCODE(op_jnless) {
3110         /* jnless src1(r) src2(r) target(offset)
3111 
3112            Checks whether register src1 is less than register src2, as
3113            with the ECMAScript '<' operator, and then jumps to offset
3114            target from the current instruction, if and only if the
3115            result of the comparison is false.
3116         */
3117         JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3118         JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3119         int target = (++vPC)->u.operand;
3120 
3121         bool result = jsLess(callFrame, src1, src2);
3122         CHECK_FOR_EXCEPTION();
3123 
3124         if (!result) {
3125             vPC += target;
3126             NEXT_INSTRUCTION();
3127         }
3128 
3129         ++vPC;
3130         NEXT_INSTRUCTION();
3131     }
3132     DEFINE_OPCODE(op_switch_imm) {
3133         /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
3134 
3135            Performs a range checked switch on the scrutinee value, using
3136            the tableIndex-th immediate switch jump table.  If the scrutinee value
3137            is an immediate number in the range covered by the referenced jump
3138            table, and the value at jumpTable[scrutinee value] is non-zero, then
3139            that value is used as the jump offset, otherwise defaultOffset is used.
3140          */
3141         int tableIndex = (++vPC)->u.operand;
3142         int defaultOffset = (++vPC)->u.operand;
3143         JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3144         if (scrutinee.isInt32Fast())
3145             vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.getInt32Fast(), defaultOffset);
3146         else {
3147             int32_t value;
3148             if (scrutinee.numberToInt32(value))
3149                 vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(value, defaultOffset);
3150             else
3151                 vPC += defaultOffset;
3152         }
3153         NEXT_INSTRUCTION();
3154     }
3155     DEFINE_OPCODE(op_switch_char) {
3156         /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
3157 
3158            Performs a range checked switch on the scrutinee value, using
3159            the tableIndex-th character switch jump table.  If the scrutinee value
3160            is a single character string in the range covered by the referenced jump
3161            table, and the value at jumpTable[scrutinee value] is non-zero, then
3162            that value is used as the jump offset, otherwise defaultOffset is used.
3163          */
3164         int tableIndex = (++vPC)->u.operand;
3165         int defaultOffset = (++vPC)->u.operand;
3166         JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3167         if (!scrutinee.isString())
3168             vPC += defaultOffset;
3169         else {
3170             UString::Rep* value = asString(scrutinee)->value().rep();
3171             if (value->size() != 1)
3172                 vPC += defaultOffset;
3173             else
3174                 vPC += callFrame->codeBlock()->characterSwitchJumpTable(tableIndex).offsetForValue(value->data()[0], defaultOffset);
3175         }
3176         NEXT_INSTRUCTION();
3177     }
3178     DEFINE_OPCODE(op_switch_string) {
3179         /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
3180 
3181            Performs a sparse hashmap based switch on the value in the scrutinee
3182            register, using the tableIndex-th string switch jump table.  If the
3183            scrutinee value is a string that exists as a key in the referenced
3184            jump table, then the value associated with the string is used as the
3185            jump offset, otherwise defaultOffset is used.
3186          */
3187         int tableIndex = (++vPC)->u.operand;
3188         int defaultOffset = (++vPC)->u.operand;
3189         JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3190         if (!scrutinee.isString())
3191             vPC += defaultOffset;
3192         else
3193             vPC += callFrame->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value().rep(), defaultOffset);
3194         NEXT_INSTRUCTION();
3195     }
3196     DEFINE_OPCODE(op_new_func) {
3197         /* new_func dst(r) func(f)
3198 
3199            Constructs a new Function instance from function func and
3200            the current scope chain using the original Function
3201            constructor, using the rules for function declarations, and
3202            puts the result in register dst.
3203         */
3204         int dst = (++vPC)->u.operand;
3205         int func = (++vPC)->u.operand;
3206 
3207         callFrame[dst] = callFrame->codeBlock()->function(func)->makeFunction(callFrame, callFrame->scopeChain());
3208 
3209         ++vPC;
3210         NEXT_INSTRUCTION();
3211     }
3212     DEFINE_OPCODE(op_new_func_exp) {
3213         /* new_func_exp dst(r) func(f)
3214 
3215            Constructs a new Function instance from function func and
3216            the current scope chain using the original Function
3217            constructor, using the rules for function expressions, and
3218            puts the result in register dst.
3219         */
3220         int dst = (++vPC)->u.operand;
3221         int func = (++vPC)->u.operand;
3222 
3223         callFrame[dst] = callFrame->codeBlock()->functionExpression(func)->makeFunction(callFrame, callFrame->scopeChain());
3224 
3225         ++vPC;
3226         NEXT_INSTRUCTION();
3227     }
3228     DEFINE_OPCODE(op_call_eval) {
3229         /* call_eval dst(r) func(r) argCount(n) registerOffset(n)
3230 
3231            Call a function named "eval" with no explicit "this" value
3232            (which may therefore be the eval operator). If register
3233            thisVal is the global object, and register func contains
3234            that global object's original global eval function, then
3235            perform the eval operator in local scope (interpreting
3236            the argument registers as for the "call"
3237            opcode). Otherwise, act exactly as the "call" opcode would.
3238          */
3239 
3240         int dst = vPC[1].u.operand;
3241         int func = vPC[2].u.operand;
3242         int argCount = vPC[3].u.operand;
3243         int registerOffset = vPC[4].u.operand;
3244 
3245         JSValuePtr funcVal = callFrame[func].jsValue(callFrame);
3246 
3247         Register* newCallFrame = callFrame->registers() + registerOffset;
3248         Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
3249         JSValuePtr thisValue = argv[0].jsValue(callFrame);
3250         JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
3251 
3252         if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
3253             JSValuePtr result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
3254             if (exceptionValue)
3255                 goto vm_throw;
3256             callFrame[dst] = result;
3257 
3258             vPC += 5;
3259             NEXT_INSTRUCTION();
3260         }
3261 
3262         // We didn't find the blessed version of eval, so process this
3263         // instruction as a normal function call.
3264         // fall through to op_call
3265     }
3266     DEFINE_OPCODE(op_call) {
3267         /* call dst(r) func(r) argCount(n) registerOffset(n)
3268 
3269            Perform a function call.
3270 
3271            registerOffset is the distance the callFrame pointer should move
3272            before the VM initializes the new call frame's header.
3273 
3274            dst is where op_ret should store its result.
3275          */
3276 
3277         int dst = vPC[1].u.operand;
3278         int func = vPC[2].u.operand;
3279         int argCount = vPC[3].u.operand;
3280         int registerOffset = vPC[4].u.operand;
3281 
3282         JSValuePtr v = callFrame[func].jsValue(callFrame);
3283 
3284         CallData callData;
3285         CallType callType = v.getCallData(callData);
3286 
3287         if (callType == CallTypeJS) {
3288             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
3289             FunctionBodyNode* functionBodyNode = callData.js.functionBody;
3290             CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain);
3291 
3292             CallFrame* previousCallFrame = callFrame;
3293 
3294             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
3295             if (UNLIKELY(!callFrame)) {
3296                 callFrame = previousCallFrame;
3297                 exceptionValue = createStackOverflowError(callFrame);
3298                 goto vm_throw;
3299             }
3300 
3301             callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
3302             vPC = newCodeBlock->instructions().begin();
3303 
3304 #if ENABLE(OPCODE_STATS)
3305             OpcodeStats::resetLastInstruction();
3306 #endif
3307 
3308             NEXT_INSTRUCTION();
3309         }
3310 
3311         if (callType == CallTypeHost) {
3312             ScopeChainNode* scopeChain = callFrame->scopeChain();
3313             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
3314             newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0);
3315 
3316             Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
3317             ArgList args(thisRegister + 1, argCount - 1);
3318 
3319             // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
3320             JSValuePtr thisValue = thisRegister->jsValue(callFrame);
3321             if (thisValue == jsNull())
3322                 thisValue = callFrame->globalThisValue();
3323 
3324             JSValuePtr returnValue;
3325             {
3326                 SamplingTool::HostCallRecord callRecord(m_sampler);
3327                 returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
3328             }
3329             CHECK_FOR_EXCEPTION();
3330 
3331             callFrame[dst] = JSValuePtr(returnValue);
3332 
3333             vPC += 5;
3334             NEXT_INSTRUCTION();
3335         }
3336 
3337         ASSERT(callType == CallTypeNone);
3338 
3339         exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
3340         goto vm_throw;
3341     }
3342     DEFINE_OPCODE(op_tear_off_activation) {
3343         /* tear_off_activation activation(r)
3344 
3345            Copy all locals and parameters to new memory allocated on
3346            the heap, and make the passed activation use this memory
3347            in the future when looking up entries in the symbol table.
3348            If there is an 'arguments' object, then it will also use
3349            this memory for storing the named parameters, but not any
3350            extra arguments.
3351 
3352            This opcode should only be used immediately before op_ret.
3353         */
3354 
3355         int src = (++vPC)->u.operand;
3356         ASSERT(callFrame->codeBlock()->needsFullScopeChain());
3357 
3358         asActivation(callFrame[src].getJSValue())->copyRegisters(callFrame->optionalCalleeArguments());
3359 
3360         ++vPC;
3361         NEXT_INSTRUCTION();
3362     }
3363     DEFINE_OPCODE(op_tear_off_arguments) {
3364         /* tear_off_arguments
3365 
3366            Copy all arguments to new memory allocated on the heap,
3367            and make the 'arguments' object use this memory in the
3368            future when looking up named parameters, but not any
3369            extra arguments. If an activation object exists for the
3370            current function context, then the tear_off_activation
3371            opcode should be used instead.
3372 
3373            This opcode should only be used immediately before op_ret.
3374         */
3375 
3376         ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain());
3377 
3378         callFrame->optionalCalleeArguments()->copyRegisters();
3379 
3380         ++vPC;
3381         NEXT_INSTRUCTION();
3382     }
3383     DEFINE_OPCODE(op_ret) {
3384         /* ret result(r)
3385 
3386            Return register result as the return value of the current
3387            function call, writing it into the caller's expected return
3388            value register. In addition, unwind one call frame and
3389            restore the scope chain, code block instruction pointer and
3390            register base to those of the calling function.
3391         */
3392 
3393         int result = (++vPC)->u.operand;
3394 
3395         if (callFrame->codeBlock()->needsFullScopeChain())
3396             callFrame->scopeChain()->deref();
3397 
3398         JSValuePtr returnValue = callFrame[result].jsValue(callFrame);
3399 
3400         vPC = callFrame->returnPC();
3401         int dst = callFrame->returnValueRegister();
3402         callFrame = callFrame->callerFrame();
3403 
3404         if (callFrame->hasHostCallFrameFlag())
3405             return returnValue;
3406 
3407         callFrame[dst] = JSValuePtr(returnValue);
3408 
3409         NEXT_INSTRUCTION();
3410     }
3411     DEFINE_OPCODE(op_enter) {
3412         /* enter
3413 
3414            Initializes local variables to undefined and fills constant
3415            registers with their values. If the code block requires an
3416            activation, enter_with_activation should be used instead.
3417 
3418            This opcode should only be used at the beginning of a code
3419            block.
3420         */
3421 
3422         size_t i = 0;
3423         CodeBlock* codeBlock = callFrame->codeBlock();
3424 
3425         for (size_t count = codeBlock->m_numVars; i < count; ++i)
3426             callFrame[i] = jsUndefined();
3427 
3428         for (size_t count = codeBlock->numberOfConstantRegisters(), j = 0; j < count; ++i, ++j)
3429             callFrame[i] = codeBlock->constantRegister(j);
3430 
3431         ++vPC;
3432         NEXT_INSTRUCTION();
3433     }
3434     DEFINE_OPCODE(op_enter_with_activation) {
3435         /* enter_with_activation dst(r)
3436 
3437            Initializes local variables to undefined, fills constant
3438            registers with their values, creates an activation object,
3439            and places the new activation both in dst and at the top
3440            of the scope chain. If the code block does not require an
3441            activation, enter should be used instead.
3442 
3443            This opcode should only be used at the beginning of a code
3444            block.
3445         */
3446 
3447         size_t i = 0;
3448         CodeBlock* codeBlock = callFrame->codeBlock();
3449 
3450         for (size_t count = codeBlock->m_numVars; i < count; ++i)
3451             callFrame[i] = jsUndefined();
3452 
3453         for (size_t count = codeBlock->numberOfConstantRegisters(), j = 0; j < count; ++i, ++j)
3454             callFrame[i] = codeBlock->constantRegister(j);
3455 
3456         int dst = (++vPC)->u.operand;
3457         JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionBodyNode*>(codeBlock->ownerNode()));
3458         callFrame[dst] = activation;
3459         callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
3460 
3461         ++vPC;
3462         NEXT_INSTRUCTION();
3463     }
3464     DEFINE_OPCODE(op_convert_this) {
3465         /* convert_this this(r)
3466 
3467            Takes the value in the 'this' register, converts it to a
3468            value that is suitable for use as the 'this' value, and
3469            stores it in the 'this' register. This opcode is emitted
3470            to avoid doing the conversion in the caller unnecessarily.
3471 
3472            This opcode should only be used at the beginning of a code
3473            block.
3474         */
3475 
3476         int thisRegister = (++vPC)->u.operand;
3477         JSValuePtr thisVal = callFrame[thisRegister].getJSValue();
3478         if (thisVal.needsThisConversion())
3479             callFrame[thisRegister] = JSValuePtr(thisVal.toThisObject(callFrame));
3480 
3481         ++vPC;
3482         NEXT_INSTRUCTION();
3483     }
3484     DEFINE_OPCODE(op_create_arguments) {
3485         /* create_arguments
3486 
3487            Creates the 'arguments' object and places it in both the
3488            'arguments' call frame slot and the local 'arguments'
3489            register.
3490 
3491            This opcode should only be used at the beginning of a code
3492            block.
3493         */
3494 
3495         Arguments* arguments = new (globalData) Arguments(callFrame);
3496         callFrame->setCalleeArguments(arguments);
3497         callFrame[RegisterFile::ArgumentsRegister] = arguments;
3498 
3499         ++vPC;
3500         NEXT_INSTRUCTION();
3501     }
3502     DEFINE_OPCODE(op_construct) {
3503         /* construct dst(r) func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r)
3504 
3505            Invoke register "func" as a constructor. For JS
3506            functions, the calling convention is exactly as for the
3507            "call" opcode, except that the "this" value is a newly
3508            created Object. For native constructors, no "this"
3509            value is passed. In either case, the argCount and registerOffset
3510            registers are interpreted as for the "call" opcode.
3511 
3512            Register proto must contain the prototype property of
3513            register func. This is to enable polymorphic inline
3514            caching of this lookup.
3515         */
3516 
3517         int dst = vPC[1].u.operand;
3518         int func = vPC[2].u.operand;
3519         int argCount = vPC[3].u.operand;
3520         int registerOffset = vPC[4].u.operand;
3521         int proto = vPC[5].u.operand;
3522         int thisRegister = vPC[6].u.operand;
3523 
3524         JSValuePtr v = callFrame[func].jsValue(callFrame);
3525 
3526         ConstructData constructData;
3527         ConstructType constructType = v.getConstructData(constructData);
3528 
3529         if (constructType == ConstructTypeJS) {
3530             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
3531             FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
3532             CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain);
3533 
3534             Structure* structure;
3535             JSValuePtr prototype = callFrame[proto].jsValue(callFrame);
3536             if (prototype.isObject())
3537                 structure = asObject(prototype)->inheritorID();
3538             else
3539                 structure = callDataScopeChain->globalObject()->emptyObjectStructure();
3540             JSObject* newObject = new (globalData) JSObject(structure);
3541 
3542             callFrame[thisRegister] = JSValuePtr(newObject); // "this" value
3543 
3544             CallFrame* previousCallFrame = callFrame;
3545 
3546             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
3547             if (UNLIKELY(!callFrame)) {
3548                 callFrame = previousCallFrame;
3549                 exceptionValue = createStackOverflowError(callFrame);
3550                 goto vm_throw;
3551             }
3552 
3553             callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
3554             vPC = newCodeBlock->instructions().begin();
3555 
3556 #if ENABLE(OPCODE_STATS)
3557             OpcodeStats::resetLastInstruction();
3558 #endif
3559 
3560             NEXT_INSTRUCTION();
3561         }
3562 
3563         if (constructType == ConstructTypeHost) {
3564             ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1);
3565 
3566             ScopeChainNode* scopeChain = callFrame->scopeChain();
3567             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
3568             newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0);
3569 
3570             JSValuePtr returnValue;
3571             {
3572                 SamplingTool::HostCallRecord callRecord(m_sampler);
3573                 returnValue = constructData.native.function(newCallFrame, asObject(v), args);
3574             }
3575             CHECK_FOR_EXCEPTION();
3576             callFrame[dst] = JSValuePtr(returnValue);
3577 
3578             vPC += 7;
3579             NEXT_INSTRUCTION();
3580         }
3581 
3582         ASSERT(constructType == ConstructTypeNone);
3583 
3584         exceptionValue = createNotAConstructorError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
3585         goto vm_throw;
3586     }
3587     DEFINE_OPCODE(op_construct_verify) {
3588         /* construct_verify dst(r) override(r)
3589 
3590            Verifies that register dst holds an object. If not, moves
3591            the object in register override to register dst.
3592         */
3593 
3594         int dst = vPC[1].u.operand;;
3595         if (LIKELY(callFrame[dst].jsValue(callFrame).isObject())) {
3596             vPC += 3;
3597             NEXT_INSTRUCTION();
3598         }
3599 
3600         int override = vPC[2].u.operand;
3601         callFrame[dst] = callFrame[override];
3602 
3603         vPC += 3;
3604         NEXT_INSTRUCTION();
3605     }
3606     DEFINE_OPCODE(op_push_scope) {
3607         /* push_scope scope(r)
3608 
3609            Converts register scope to object, and pushes it onto the top
3610            of the current scope chain.  The contents of the register scope
3611            are replaced by the result of toObject conversion of the scope.
3612         */
3613         int scope = (++vPC)->u.operand;
3614         JSValuePtr v = callFrame[scope].jsValue(callFrame);
3615         JSObject* o = v.toObject(callFrame);
3616         CHECK_FOR_EXCEPTION();
3617 
3618         callFrame[scope] = JSValuePtr(o);
3619         callFrame->setScopeChain(callFrame->scopeChain()->push(o));
3620 
3621         ++vPC;
3622         NEXT_INSTRUCTION();
3623     }
3624     DEFINE_OPCODE(op_pop_scope) {
3625         /* pop_scope
3626 
3627            Removes the top item from the current scope chain.
3628         */
3629         callFrame->setScopeChain(callFrame->scopeChain()->pop());
3630 
3631         ++vPC;
3632         NEXT_INSTRUCTION();
3633     }
3634     DEFINE_OPCODE(op_get_pnames) {
3635         /* get_pnames dst(r) base(r)
3636 
3637            Creates a property name list for register base and puts it
3638            in register dst. This is not a true JavaScript value, just
3639            a synthetic value used to keep the iteration state in a
3640            register.
3641         */
3642         int dst = (++vPC)->u.operand;
3643         int base = (++vPC)->u.operand;
3644 
3645         callFrame[dst] = JSPropertyNameIterator::create(callFrame, callFrame[base].jsValue(callFrame));
3646         ++vPC;
3647         NEXT_INSTRUCTION();
3648     }
3649     DEFINE_OPCODE(op_next_pname) {
3650         /* next_pname dst(r) iter(r) target(offset)
3651 
3652            Tries to copies the next name from property name list in
3653            register iter. If there are names left, then copies one to
3654            register dst, and jumps to offset target. If there are none
3655            left, invalidates the iterator and continues to the next
3656            instruction.
3657         */
3658         int dst = (++vPC)->u.operand;
3659         int iter = (++vPC)->u.operand;
3660         int target = (++vPC)->u.operand;
3661 
3662         JSPropertyNameIterator* it = callFrame[iter].propertyNameIterator();
3663         if (JSValuePtr temp = it->next(callFrame)) {
3664             CHECK_FOR_TIMEOUT();
3665             callFrame[dst] = JSValuePtr(temp);
3666             vPC += target;
3667             NEXT_INSTRUCTION();
3668         }
3669         it->invalidate();
3670 
3671         ++vPC;
3672         NEXT_INSTRUCTION();
3673     }
3674     DEFINE_OPCODE(op_jmp_scopes) {
3675         /* jmp_scopes count(n) target(offset)
3676 
3677            Removes the a number of items from the current scope chain
3678            specified by immediate number count, then jumps to offset
3679            target.
3680         */
3681         int count = (++vPC)->u.operand;
3682         int target = (++vPC)->u.operand;
3683 
3684         ScopeChainNode* tmp = callFrame->scopeChain();
3685         while (count--)
3686             tmp = tmp->pop();
3687         callFrame->setScopeChain(tmp);
3688 
3689         vPC += target;
3690         NEXT_INSTRUCTION();
3691     }
3692 #if HAVE(COMPUTED_GOTO)
3693     // Appease GCC
3694     goto *(&&skip_new_scope);
3695 #endif
3696     DEFINE_OPCODE(op_push_new_scope) {
3697         /* new_scope dst(r) property(id) value(r)
3698 
3699            Constructs a new StaticScopeObject with property set to value.  That scope
3700            object is then pushed onto the ScopeChain.  The scope object is then stored
3701            in dst for GC.
3702          */
3703         callFrame->setScopeChain(createExceptionScope(callFrame, vPC));
3704 
3705         vPC += 4;
3706         NEXT_INSTRUCTION();
3707     }
3708 #if HAVE(COMPUTED_GOTO)
3709     skip_new_scope:
3710 #endif
3711     DEFINE_OPCODE(op_catch) {
3712         /* catch ex(r)
3713 
3714            Retrieves the VMs current exception and puts it in register
3715            ex. This is only valid after an exception has been raised,
3716            and usually forms the beginning of an exception handler.
3717         */
3718         ASSERT(exceptionValue);
3719         ASSERT(!globalData->exception);
3720         int ex = (++vPC)->u.operand;
3721         callFrame[ex] = exceptionValue;
3722         exceptionValue = noValue();
3723 
3724         ++vPC;
3725         NEXT_INSTRUCTION();
3726     }
3727     DEFINE_OPCODE(op_throw) {
3728         /* throw ex(r)
3729 
3730            Throws register ex as an exception. This involves three
3731            steps: first, it is set as the current exception in the
3732            VM's internal state, then the stack is unwound until an
3733            exception handler or a native code boundary is found, and
3734            then control resumes at the exception handler if any or
3735            else the script returns control to the nearest native caller.
3736         */
3737 
3738         int ex = (++vPC)->u.operand;
3739         exceptionValue = callFrame[ex].jsValue(callFrame);
3740 
3741         handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), true);
3742         if (!handler) {
3743             *exception = exceptionValue;
3744             return jsNull();
3745         }
3746 
3747         vPC = callFrame->codeBlock()->instructions().begin() + handler->target;
3748         NEXT_INSTRUCTION();
3749     }
3750     DEFINE_OPCODE(op_unexpected_load) {
3751         /* unexpected_load load dst(r) src(k)
3752 
3753            Copies constant src to register dst.
3754         */
3755         int dst = (++vPC)->u.operand;
3756         int src = (++vPC)->u.operand;
3757         callFrame[dst] = JSValuePtr(callFrame->codeBlock()->unexpectedConstant(src));
3758 
3759         ++vPC;
3760         NEXT_INSTRUCTION();
3761     }
3762     DEFINE_OPCODE(op_new_error) {
3763         /* new_error dst(r) type(n) message(k)
3764 
3765            Constructs a new Error instance using the original
3766            constructor, using immediate number n as the type and
3767            constant message as the message string. The result is
3768            written to register dst.
3769         */
3770         int dst = (++vPC)->u.operand;
3771         int type = (++vPC)->u.operand;
3772         int message = (++vPC)->u.operand;
3773 
3774         CodeBlock* codeBlock = callFrame->codeBlock();
3775         callFrame[dst] = JSValuePtr(Error::create(callFrame, (ErrorType)type, codeBlock->unexpectedConstant(message).toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()));
3776 
3777         ++vPC;
3778         NEXT_INSTRUCTION();
3779     }
3780     DEFINE_OPCODE(op_end) {
3781         /* end result(r)
3782 
3783            Return register result as the value of a global or eval
3784            program. Return control to the calling native code.
3785         */
3786 
3787         if (callFrame->codeBlock()->needsFullScopeChain()) {
3788             ScopeChainNode* scopeChain = callFrame->scopeChain();
3789             ASSERT(scopeChain->refCount > 1);
3790             scopeChain->deref();
3791         }
3792         int result = (++vPC)->u.operand;
3793         return callFrame[result].jsValue(callFrame);
3794     }
3795     DEFINE_OPCODE(op_put_getter) {
3796         /* put_getter base(r) property(id) function(r)
3797 
3798            Sets register function on register base as the getter named
3799            by identifier property. Base and function are assumed to be
3800            objects as this op should only be used for getters defined
3801            in object literal form.
3802 
3803            Unlike many opcodes, this one does not write any output to
3804            the register file.
3805         */
3806         int base = (++vPC)->u.operand;
3807         int property = (++vPC)->u.operand;
3808         int function = (++vPC)->u.operand;
3809 
3810         ASSERT(callFrame[base].jsValue(callFrame).isObject());
3811         JSObject* baseObj = asObject(callFrame[base].jsValue(callFrame));
3812         Identifier& ident = callFrame->codeBlock()->identifier(property);
3813         ASSERT(callFrame[function].jsValue(callFrame).isObject());
3814         baseObj->defineGetter(callFrame, ident, asObject(callFrame[function].jsValue(callFrame)));
3815 
3816         ++vPC;
3817         NEXT_INSTRUCTION();
3818     }
3819     DEFINE_OPCODE(op_put_setter) {
3820         /* put_setter base(r) property(id) function(r)
3821 
3822            Sets register function on register base as the setter named
3823            by identifier property. Base and function are assumed to be
3824            objects as this op should only be used for setters defined
3825            in object literal form.
3826 
3827            Unlike many opcodes, this one does not write any output to
3828            the register file.
3829         */
3830         int base = (++vPC)->u.operand;
3831         int property = (++vPC)->u.operand;
3832         int function = (++vPC)->u.operand;
3833 
3834         ASSERT(callFrame[base].jsValue(callFrame).isObject());
3835         JSObject* baseObj = asObject(callFrame[base].jsValue(callFrame));
3836         Identifier& ident = callFrame->codeBlock()->identifier(property);
3837         ASSERT(callFrame[function].jsValue(callFrame).isObject());
3838         baseObj->defineSetter(callFrame, ident, asObject(callFrame[function].jsValue(callFrame)));
3839 
3840         ++vPC;
3841         NEXT_INSTRUCTION();
3842     }
3843     DEFINE_OPCODE(op_jsr) {
3844         /* jsr retAddrDst(r) target(offset)
3845 
3846            Places the address of the next instruction into the retAddrDst
3847            register and jumps to offset target from the current instruction.
3848         */
3849         int retAddrDst = (++vPC)->u.operand;
3850         int target = (++vPC)->u.operand;
3851         callFrame[retAddrDst] = vPC + 1;
3852 
3853         vPC += target;
3854         NEXT_INSTRUCTION();
3855     }
3856     DEFINE_OPCODE(op_sret) {
3857         /* sret retAddrSrc(r)
3858 
3859          Jumps to the address stored in the retAddrSrc register. This
3860          differs from op_jmp because the target address is stored in a
3861          register, not as an immediate.
3862         */
3863         int retAddrSrc = (++vPC)->u.operand;
3864         vPC = callFrame[retAddrSrc].vPC();
3865         NEXT_INSTRUCTION();
3866     }
3867     DEFINE_OPCODE(op_debug) {
3868         /* debug debugHookID(n) firstLine(n) lastLine(n)
3869 
3870          Notifies the debugger of the current state of execution. This opcode
3871          is only generated while the debugger is attached.
3872         */
3873         int debugHookID = (++vPC)->u.operand;
3874         int firstLine = (++vPC)->u.operand;
3875         int lastLine = (++vPC)->u.operand;
3876 
3877         debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
3878 
3879         ++vPC;
3880         NEXT_INSTRUCTION();
3881     }
3882     DEFINE_OPCODE(op_profile_will_call) {
3883         /* op_profile_will_call function(r)
3884 
3885          Notifies the profiler of the beginning of a function call. This opcode
3886          is only generated if developer tools are enabled.
3887         */
3888         int function = vPC[1].u.operand;
3889 
3890         if (*enabledProfilerReference)
3891             (*enabledProfilerReference)->willExecute(callFrame, callFrame[function].jsValue(callFrame));
3892 
3893         vPC += 2;
3894         NEXT_INSTRUCTION();
3895     }
3896     DEFINE_OPCODE(op_profile_did_call) {
3897         /* op_profile_did_call function(r)
3898 
3899          Notifies the profiler of the end of a function call. This opcode
3900          is only generated if developer tools are enabled.
3901         */
3902         int function = vPC[1].u.operand;
3903 
3904         if (*enabledProfilerReference)
3905             (*enabledProfilerReference)->didExecute(callFrame, callFrame[function].jsValue(callFrame));
3906 
3907         vPC += 2;
3908         NEXT_INSTRUCTION();
3909     }
3910     vm_throw: {
3911         globalData->exception = noValue();
3912         if (!tickCount) {
3913             // The exceptionValue is a lie! (GCC produces bad code for reasons I
3914             // cannot fathom if we don't assign to the exceptionValue before branching)
3915             exceptionValue = createInterruptedExecutionException(globalData);
3916         }
3917         handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), false);
3918         if (!handler) {
3919             *exception = exceptionValue;
3920             return jsNull();
3921         }
3922 
3923         vPC = callFrame->codeBlock()->instructions().begin() + handler->target;
3924         NEXT_INSTRUCTION();
3925     }
3926     }
3927 #if !HAVE(COMPUTED_GOTO)
3928     } // iterator loop ends
3929 #endif
3930     #undef NEXT_INSTRUCTION
3931     #undef DEFINE_OPCODE
3932     #undef CHECK_FOR_EXCEPTION
3933     #undef CHECK_FOR_TIMEOUT
3934 }
3935 
retrieveArguments(CallFrame * callFrame,JSFunction * function) const3936 JSValuePtr Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
3937 {
3938     CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
3939     if (!functionCallFrame)
3940         return jsNull();
3941 
3942     CodeBlock* codeBlock = functionCallFrame->codeBlock();
3943     if (codeBlock->usesArguments()) {
3944         ASSERT(codeBlock->codeType() == FunctionCode);
3945         SymbolTable& symbolTable = codeBlock->symbolTable();
3946         int argumentsIndex = symbolTable.get(functionCallFrame->propertyNames().arguments.ustring().rep()).getIndex();
3947         return functionCallFrame[argumentsIndex].jsValue(callFrame);
3948     }
3949 
3950     Arguments* arguments = functionCallFrame->optionalCalleeArguments();
3951     if (!arguments) {
3952         arguments = new (functionCallFrame) Arguments(functionCallFrame);
3953         arguments->copyRegisters();
3954         callFrame->setCalleeArguments(arguments);
3955     }
3956 
3957     return arguments;
3958 }
3959 
retrieveCaller(CallFrame * callFrame,InternalFunction * function) const3960 JSValuePtr Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* function) const
3961 {
3962     CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
3963     if (!functionCallFrame)
3964         return jsNull();
3965 
3966     CallFrame* callerFrame = functionCallFrame->callerFrame();
3967     if (callerFrame->hasHostCallFrameFlag())
3968         return jsNull();
3969 
3970     JSValuePtr caller = callerFrame->callee();
3971     if (!caller)
3972         return jsNull();
3973 
3974     return caller;
3975 }
3976 
retrieveLastCaller(CallFrame * callFrame,int & lineNumber,intptr_t & sourceID,UString & sourceURL,JSValuePtr & function) const3977 void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValuePtr& function) const
3978 {
3979     function = noValue();
3980     lineNumber = -1;
3981     sourceURL = UString();
3982 
3983     CallFrame* callerFrame = callFrame->callerFrame();
3984     if (callerFrame->hasHostCallFrameFlag())
3985         return;
3986 
3987     CodeBlock* callerCodeBlock = callerFrame->codeBlock();
3988     if (!callerCodeBlock)
3989         return;
3990 
3991     unsigned bytecodeOffset = bytecodeOffsetForPC(callerFrame, callerCodeBlock, callFrame->returnPC());
3992     lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(callerFrame, bytecodeOffset - 1);
3993     sourceID = callerCodeBlock->ownerNode()->sourceID();
3994     sourceURL = callerCodeBlock->ownerNode()->sourceURL();
3995     function = callerFrame->callee();
3996 }
3997 
findFunctionCallFrame(CallFrame * callFrame,InternalFunction * function)3998 CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, InternalFunction* function)
3999 {
4000     for (CallFrame* candidate = callFrame; candidate; candidate = candidate->callerFrame()->removeHostCallFrameFlag()) {
4001         if (candidate->callee() == function)
4002             return candidate;
4003     }
4004     return 0;
4005 }
4006 
4007 #if ENABLE(JIT)
4008 
4009 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
4010 
tryCTICachePutByID(CallFrame * callFrame,CodeBlock * codeBlock,void * returnAddress,JSValuePtr baseValue,const PutPropertySlot & slot)4011 NEVER_INLINE void Interpreter::tryCTICachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress, JSValuePtr baseValue, const PutPropertySlot& slot)
4012 {
4013     // The interpreter checks for recursion here; I do not believe this can occur in CTI.
4014 
4015     if (!baseValue.isCell())
4016         return;
4017 
4018     // Uncacheable: give up.
4019     if (!slot.isCacheable()) {
4020         ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic));
4021         return;
4022     }
4023 
4024     JSCell* baseCell = asCell(baseValue);
4025     Structure* structure = baseCell->structure();
4026 
4027     if (structure->isDictionary()) {
4028         ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic));
4029         return;
4030     }
4031 
4032     // If baseCell != base, then baseCell must be a proxy for another object.
4033     if (baseCell != slot.base()) {
4034         ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic));
4035         return;
4036     }
4037 
4038     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);
4039 
4040     // Cache hit: Specialize instruction and ref Structures.
4041 
4042     // Structure transition, cache transition info
4043     if (slot.type() == PutPropertySlot::NewProperty) {
4044         StructureChain* chain = structure->cachedPrototypeChain();
4045         if (!chain) {
4046             chain = cachePrototypeChain(callFrame, structure);
4047             if (!chain) {
4048                 // This happens if someone has manually inserted null into the prototype chain
4049                 stubInfo->opcodeID = op_put_by_id_generic;
4050                 return;
4051             }
4052         }
4053         stubInfo->initPutByIdTransition(structure->previousID(), structure, chain);
4054         JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), chain, returnAddress);
4055         return;
4056     }
4057 
4058     stubInfo->initPutByIdReplace(structure);
4059 
4060 #if USE(CTI_REPATCH_PIC)
4061     UNUSED_PARAM(callFrame);
4062     JIT::patchPutByIdReplace(stubInfo, structure, slot.cachedOffset(), returnAddress);
4063 #else
4064     JIT::compilePutByIdReplace(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
4065 #endif
4066 }
4067 
tryCTICacheGetByID(CallFrame * callFrame,CodeBlock * codeBlock,void * returnAddress,JSValuePtr baseValue,const Identifier & propertyName,const PropertySlot & slot)4068 NEVER_INLINE void Interpreter::tryCTICacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot& slot)
4069 {
4070     // FIXME: Write a test that proves we need to check for recursion here just
4071     // like the interpreter does, then add a check for recursion.
4072 
4073     // FIXME: Cache property access for immediates.
4074     if (!baseValue.isCell()) {
4075         ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic));
4076         return;
4077     }
4078 
4079     if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
4080 #if USE(CTI_REPATCH_PIC)
4081         JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress);
4082 #else
4083         ctiPatchCallByReturnAddress(returnAddress, m_ctiArrayLengthTrampoline);
4084 #endif
4085         return;
4086     }
4087     if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
4088         // The tradeoff of compiling an patched inline string length access routine does not seem
4089         // to pay off, so we currently only do this for arrays.
4090         ctiPatchCallByReturnAddress(returnAddress, m_ctiStringLengthTrampoline);
4091         return;
4092     }
4093 
4094     // Uncacheable: give up.
4095     if (!slot.isCacheable()) {
4096         ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic));
4097         return;
4098     }
4099 
4100     JSCell* baseCell = asCell(baseValue);
4101     Structure* structure = baseCell->structure();
4102 
4103     if (structure->isDictionary()) {
4104         ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic));
4105         return;
4106     }
4107 
4108     // In the interpreter the last structure is trapped here; in CTI we use the
4109     // *_second method to achieve a similar (but not quite the same) effect.
4110 
4111     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);
4112 
4113     // Cache hit: Specialize instruction and ref Structures.
4114 
4115     if (slot.slotBase() == baseValue) {
4116         // set this up, so derefStructures can do it's job.
4117         stubInfo->initGetByIdSelf(structure);
4118 
4119 #if USE(CTI_REPATCH_PIC)
4120         JIT::patchGetByIdSelf(stubInfo, structure, slot.cachedOffset(), returnAddress);
4121 #else
4122         JIT::compileGetByIdSelf(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
4123 #endif
4124         return;
4125     }
4126 
4127     if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
4128         ASSERT(slot.slotBase().isObject());
4129 
4130         JSObject* slotBaseObject = asObject(slot.slotBase());
4131 
4132         // Since we're accessing a prototype in a loop, it's a good bet that it
4133         // should not be treated as a dictionary.
4134         if (slotBaseObject->structure()->isDictionary()) {
4135             RefPtr<Structure> transition = Structure::fromDictionaryTransition(slotBaseObject->structure());
4136             slotBaseObject->setStructure(transition.release());
4137             asCell(baseValue)->structure()->setCachedPrototypeChain(0);
4138         }
4139 
4140         stubInfo->initGetByIdProto(structure, slotBaseObject->structure());
4141 
4142         JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), slot.cachedOffset(), returnAddress);
4143         return;
4144     }
4145 
4146     size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot);
4147     if (!count) {
4148         stubInfo->opcodeID = op_get_by_id_generic;
4149         return;
4150     }
4151 
4152     StructureChain* chain = structure->cachedPrototypeChain();
4153     if (!chain)
4154         chain = cachePrototypeChain(callFrame, structure);
4155     ASSERT(chain);
4156 
4157     stubInfo->initGetByIdChain(structure, chain);
4158 
4159     JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, chain, count, slot.cachedOffset(), returnAddress);
4160 }
4161 
4162 #endif
4163 
4164 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
4165 #define SETUP_VA_LISTL_ARGS va_list vl_args; va_start(vl_args, args)
4166 #else // JIT_STUB_ARGUMENT_REGISTER or JIT_STUB_ARGUMENT_STACK
4167 #define SETUP_VA_LISTL_ARGS
4168 #endif
4169 
4170 #ifndef NDEBUG
4171 
4172 extern "C" {
4173 
jscGeneratedNativeCode()4174 static void jscGeneratedNativeCode()
4175 {
4176     // When executing a CTI function (which might do an allocation), we hack the return address
4177     // to pretend to be executing this function, to keep stack logging tools from blowing out
4178     // memory.
4179 }
4180 
4181 }
4182 
4183 struct StackHack {
StackHackJSC::StackHack4184     ALWAYS_INLINE StackHack(void** location)
4185     {
4186         returnAddressLocation = location;
4187         savedReturnAddress = *returnAddressLocation;
4188         ctiSetReturnAddress(returnAddressLocation, reinterpret_cast<void*>(jscGeneratedNativeCode));
4189     }
~StackHackJSC::StackHack4190     ALWAYS_INLINE ~StackHack()
4191     {
4192         ctiSetReturnAddress(returnAddressLocation, savedReturnAddress);
4193     }
4194 
4195     void** returnAddressLocation;
4196     void* savedReturnAddress;
4197 };
4198 
4199 #define BEGIN_STUB_FUNCTION() SETUP_VA_LISTL_ARGS; StackHack stackHack(&STUB_RETURN_ADDRESS_SLOT)
4200 #define STUB_SET_RETURN_ADDRESS(address) stackHack.savedReturnAddress = address
4201 #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
4202 
4203 #else
4204 
4205 #define BEGIN_STUB_FUNCTION() SETUP_VA_LISTL_ARGS
4206 #define STUB_SET_RETURN_ADDRESS(address) ctiSetReturnAddress(&STUB_RETURN_ADDRESS_SLOT, address);
4207 #define STUB_RETURN_ADDRESS STUB_RETURN_ADDRESS_SLOT
4208 
4209 #endif
4210 
4211 // The reason this is not inlined is to avoid having to do a PIC branch
4212 // to get the address of the ctiVMThrowTrampoline function. It's also
4213 // good to keep the code size down by leaving as much of the exception
4214 // handling code out of line as possible.
returnToThrowTrampoline(JSGlobalData * globalData,void * exceptionLocation,void * & returnAddressSlot)4215 static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot)
4216 {
4217     ASSERT(globalData->exception);
4218     globalData->exceptionLocation = exceptionLocation;
4219     ctiSetReturnAddress(&returnAddressSlot, reinterpret_cast<void*>(ctiVMThrowTrampoline));
4220 }
4221 
throwStackOverflowError(CallFrame * callFrame,JSGlobalData * globalData,void * exceptionLocation,void * & returnAddressSlot)4222 static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot)
4223 {
4224     globalData->exception = createStackOverflowError(callFrame);
4225     returnToThrowTrampoline(globalData, exceptionLocation, returnAddressSlot);
4226 }
4227 
4228 #define VM_THROW_EXCEPTION() \
4229     do { \
4230         VM_THROW_EXCEPTION_AT_END(); \
4231         return 0; \
4232     } while (0)
4233 #define VM_THROW_EXCEPTION_2() \
4234     do { \
4235         VM_THROW_EXCEPTION_AT_END(); \
4236         RETURN_PAIR(0, 0); \
4237     } while (0)
4238 #define VM_THROW_EXCEPTION_AT_END() \
4239     returnToThrowTrampoline(ARG_globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS)
4240 
4241 #define CHECK_FOR_EXCEPTION() \
4242     do { \
4243         if (UNLIKELY(ARG_globalData->exception != noValue())) \
4244             VM_THROW_EXCEPTION(); \
4245     } while (0)
4246 #define CHECK_FOR_EXCEPTION_AT_END() \
4247     do { \
4248         if (UNLIKELY(ARG_globalData->exception != noValue())) \
4249             VM_THROW_EXCEPTION_AT_END(); \
4250     } while (0)
4251 #define CHECK_FOR_EXCEPTION_VOID() \
4252     do { \
4253         if (UNLIKELY(ARG_globalData->exception != noValue())) { \
4254             VM_THROW_EXCEPTION_AT_END(); \
4255             return; \
4256         } \
4257     } while (0)
4258 
cti_op_convert_this(STUB_ARGS)4259 JSObject* Interpreter::cti_op_convert_this(STUB_ARGS)
4260 {
4261     BEGIN_STUB_FUNCTION();
4262 
4263     JSValuePtr v1 = ARG_src1;
4264     CallFrame* callFrame = ARG_callFrame;
4265 
4266     JSObject* result = v1.toThisObject(callFrame);
4267     CHECK_FOR_EXCEPTION_AT_END();
4268     return result;
4269 }
4270 
cti_op_end(STUB_ARGS)4271 void Interpreter::cti_op_end(STUB_ARGS)
4272 {
4273     BEGIN_STUB_FUNCTION();
4274 
4275     ScopeChainNode* scopeChain = ARG_callFrame->scopeChain();
4276     ASSERT(scopeChain->refCount > 1);
4277     scopeChain->deref();
4278 }
4279 
cti_op_add(STUB_ARGS)4280 JSValueEncodedAsPointer* Interpreter::cti_op_add(STUB_ARGS)
4281 {
4282     BEGIN_STUB_FUNCTION();
4283 
4284     JSValuePtr v1 = ARG_src1;
4285     JSValuePtr v2 = ARG_src2;
4286 
4287     double left;
4288     double right = 0.0;
4289 
4290     bool rightIsNumber = v2.getNumber(right);
4291     if (rightIsNumber && v1.getNumber(left))
4292         return JSValuePtr::encode(jsNumber(ARG_globalData, left + right));
4293 
4294     CallFrame* callFrame = ARG_callFrame;
4295 
4296     bool leftIsString = v1.isString();
4297     if (leftIsString && v2.isString()) {
4298         RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep());
4299         if (UNLIKELY(!value)) {
4300             throwOutOfMemoryError(callFrame);
4301             VM_THROW_EXCEPTION();
4302         }
4303 
4304         return JSValuePtr::encode(jsString(ARG_globalData, value.release()));
4305     }
4306 
4307     if (rightIsNumber & leftIsString) {
4308         RefPtr<UString::Rep> value = v2.isInt32Fast() ?
4309             concatenate(asString(v1)->value().rep(), v2.getInt32Fast()) :
4310             concatenate(asString(v1)->value().rep(), right);
4311 
4312         if (UNLIKELY(!value)) {
4313             throwOutOfMemoryError(callFrame);
4314             VM_THROW_EXCEPTION();
4315         }
4316         return JSValuePtr::encode(jsString(ARG_globalData, value.release()));
4317     }
4318 
4319     // All other cases are pretty uncommon
4320     JSValuePtr result = jsAddSlowCase(callFrame, v1, v2);
4321     CHECK_FOR_EXCEPTION_AT_END();
4322     return JSValuePtr::encode(result);
4323 }
4324 
cti_op_pre_inc(STUB_ARGS)4325 JSValueEncodedAsPointer* Interpreter::cti_op_pre_inc(STUB_ARGS)
4326 {
4327     BEGIN_STUB_FUNCTION();
4328 
4329     JSValuePtr v = ARG_src1;
4330 
4331     CallFrame* callFrame = ARG_callFrame;
4332     JSValuePtr result = jsNumber(ARG_globalData, v.toNumber(callFrame) + 1);
4333     CHECK_FOR_EXCEPTION_AT_END();
4334     return JSValuePtr::encode(result);
4335 }
4336 
cti_timeout_check(STUB_ARGS)4337 int Interpreter::cti_timeout_check(STUB_ARGS)
4338 {
4339     BEGIN_STUB_FUNCTION();
4340     Interpreter* interpreter = ARG_globalData->interpreter;
4341 
4342     if (interpreter->checkTimeout(ARG_callFrame->dynamicGlobalObject())) {
4343         ARG_globalData->exception = createInterruptedExecutionException(ARG_globalData);
4344         VM_THROW_EXCEPTION_AT_END();
4345     }
4346 
4347     return interpreter->m_ticksUntilNextTimeoutCheck;
4348 }
4349 
cti_register_file_check(STUB_ARGS)4350 void Interpreter::cti_register_file_check(STUB_ARGS)
4351 {
4352     BEGIN_STUB_FUNCTION();
4353 
4354     if (LIKELY(ARG_registerFile->grow(ARG_callFrame + ARG_callFrame->codeBlock()->m_numCalleeRegisters)))
4355         return;
4356 
4357     // Rewind to the previous call frame because op_call already optimistically
4358     // moved the call frame forward.
4359     CallFrame* oldCallFrame = ARG_callFrame->callerFrame();
4360     ARG_setCallFrame(oldCallFrame);
4361     throwStackOverflowError(oldCallFrame, ARG_globalData, oldCallFrame->returnPC(), STUB_RETURN_ADDRESS);
4362 }
4363 
cti_op_loop_if_less(STUB_ARGS)4364 int Interpreter::cti_op_loop_if_less(STUB_ARGS)
4365 {
4366     BEGIN_STUB_FUNCTION();
4367 
4368     JSValuePtr src1 = ARG_src1;
4369     JSValuePtr src2 = ARG_src2;
4370     CallFrame* callFrame = ARG_callFrame;
4371 
4372     bool result = jsLess(callFrame, src1, src2);
4373     CHECK_FOR_EXCEPTION_AT_END();
4374     return result;
4375 }
4376 
cti_op_loop_if_lesseq(STUB_ARGS)4377 int Interpreter::cti_op_loop_if_lesseq(STUB_ARGS)
4378 {
4379     BEGIN_STUB_FUNCTION();
4380 
4381     JSValuePtr src1 = ARG_src1;
4382     JSValuePtr src2 = ARG_src2;
4383     CallFrame* callFrame = ARG_callFrame;
4384 
4385     bool result = jsLessEq(callFrame, src1, src2);
4386     CHECK_FOR_EXCEPTION_AT_END();
4387     return result;
4388 }
4389 
cti_op_new_object(STUB_ARGS)4390 JSObject* Interpreter::cti_op_new_object(STUB_ARGS)
4391 {
4392     BEGIN_STUB_FUNCTION();
4393 
4394     return constructEmptyObject(ARG_callFrame);
4395 }
4396 
cti_op_put_by_id_generic(STUB_ARGS)4397 void Interpreter::cti_op_put_by_id_generic(STUB_ARGS)
4398 {
4399     BEGIN_STUB_FUNCTION();
4400 
4401     PutPropertySlot slot;
4402     ARG_src1.put(ARG_callFrame, *ARG_id2, ARG_src3, slot);
4403     CHECK_FOR_EXCEPTION_AT_END();
4404 }
4405 
cti_op_get_by_id_generic(STUB_ARGS)4406 JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_generic(STUB_ARGS)
4407 {
4408     BEGIN_STUB_FUNCTION();
4409 
4410     CallFrame* callFrame = ARG_callFrame;
4411     Identifier& ident = *ARG_id2;
4412 
4413     JSValuePtr baseValue = ARG_src1;
4414     PropertySlot slot(baseValue);
4415     JSValuePtr result = baseValue.get(callFrame, ident, slot);
4416 
4417     CHECK_FOR_EXCEPTION_AT_END();
4418     return JSValuePtr::encode(result);
4419 }
4420 
4421 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
4422 
cti_op_put_by_id(STUB_ARGS)4423 void Interpreter::cti_op_put_by_id(STUB_ARGS)
4424 {
4425     BEGIN_STUB_FUNCTION();
4426 
4427     CallFrame* callFrame = ARG_callFrame;
4428     Identifier& ident = *ARG_id2;
4429 
4430     PutPropertySlot slot;
4431     ARG_src1.put(callFrame, ident, ARG_src3, slot);
4432 
4433     ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_id_second));
4434 
4435     CHECK_FOR_EXCEPTION_AT_END();
4436 }
4437 
cti_op_put_by_id_second(STUB_ARGS)4438 void Interpreter::cti_op_put_by_id_second(STUB_ARGS)
4439 {
4440     BEGIN_STUB_FUNCTION();
4441 
4442     PutPropertySlot slot;
4443     ARG_src1.put(ARG_callFrame, *ARG_id2, ARG_src3, slot);
4444     ARG_globalData->interpreter->tryCTICachePutByID(ARG_callFrame, ARG_callFrame->codeBlock(), STUB_RETURN_ADDRESS, ARG_src1, slot);
4445     CHECK_FOR_EXCEPTION_AT_END();
4446 }
4447 
cti_op_put_by_id_fail(STUB_ARGS)4448 void Interpreter::cti_op_put_by_id_fail(STUB_ARGS)
4449 {
4450     BEGIN_STUB_FUNCTION();
4451 
4452     CallFrame* callFrame = ARG_callFrame;
4453     Identifier& ident = *ARG_id2;
4454 
4455     PutPropertySlot slot;
4456     ARG_src1.put(callFrame, ident, ARG_src3, slot);
4457 
4458     CHECK_FOR_EXCEPTION_AT_END();
4459 }
4460 
cti_op_get_by_id(STUB_ARGS)4461 JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id(STUB_ARGS)
4462 {
4463     BEGIN_STUB_FUNCTION();
4464 
4465     CallFrame* callFrame = ARG_callFrame;
4466     Identifier& ident = *ARG_id2;
4467 
4468     JSValuePtr baseValue = ARG_src1;
4469     PropertySlot slot(baseValue);
4470     JSValuePtr result = baseValue.get(callFrame, ident, slot);
4471 
4472     ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_second));
4473 
4474     CHECK_FOR_EXCEPTION_AT_END();
4475     return JSValuePtr::encode(result);
4476 }
4477 
cti_op_get_by_id_second(STUB_ARGS)4478 JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_second(STUB_ARGS)
4479 {
4480     BEGIN_STUB_FUNCTION();
4481 
4482     CallFrame* callFrame = ARG_callFrame;
4483     Identifier& ident = *ARG_id2;
4484 
4485     JSValuePtr baseValue = ARG_src1;
4486     PropertySlot slot(baseValue);
4487     JSValuePtr result = baseValue.get(callFrame, ident, slot);
4488 
4489     ARG_globalData->interpreter->tryCTICacheGetByID(callFrame, callFrame->codeBlock(), STUB_RETURN_ADDRESS, baseValue, ident, slot);
4490 
4491     CHECK_FOR_EXCEPTION_AT_END();
4492     return JSValuePtr::encode(result);
4493 }
4494 
cti_op_get_by_id_self_fail(STUB_ARGS)4495 JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_self_fail(STUB_ARGS)
4496 {
4497     BEGIN_STUB_FUNCTION();
4498 
4499     CallFrame* callFrame = ARG_callFrame;
4500     Identifier& ident = *ARG_id2;
4501 
4502     JSValuePtr baseValue = ARG_src1;
4503     PropertySlot slot(baseValue);
4504     JSValuePtr result = baseValue.get(callFrame, ident, slot);
4505 
4506     CHECK_FOR_EXCEPTION();
4507 
4508     if (baseValue.isCell()
4509         && slot.isCacheable()
4510         && !asCell(baseValue)->structure()->isDictionary()
4511         && slot.slotBase() == baseValue) {
4512 
4513         CodeBlock* codeBlock = callFrame->codeBlock();
4514         StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
4515 
4516         ASSERT(slot.slotBase().isObject());
4517 
4518         PolymorphicAccessStructureList* polymorphicStructureList;
4519         int listIndex = 1;
4520 
4521         if (stubInfo->opcodeID == op_get_by_id_self) {
4522             ASSERT(!stubInfo->stubRoutine);
4523             polymorphicStructureList = new PolymorphicAccessStructureList(0, stubInfo->u.getByIdSelf.baseObjectStructure);
4524             stubInfo->initGetByIdSelfList(polymorphicStructureList, 2);
4525         } else {
4526             polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
4527             listIndex = stubInfo->u.getByIdSelfList.listSize;
4528             stubInfo->u.getByIdSelfList.listSize++;
4529         }
4530 
4531         JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), slot.cachedOffset());
4532 
4533         if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
4534             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic));
4535     } else {
4536         ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic));
4537     }
4538     return JSValuePtr::encode(result);
4539 }
4540 
getPolymorphicAccessStructureListSlot(StructureStubInfo * stubInfo,int & listIndex)4541 static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(StructureStubInfo* stubInfo, int& listIndex)
4542 {
4543     PolymorphicAccessStructureList* prototypeStructureList = 0;
4544     listIndex = 1;
4545 
4546     switch (stubInfo->opcodeID) {
4547     case op_get_by_id_proto:
4548         prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure);
4549         stubInfo->stubRoutine = 0;
4550         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
4551         break;
4552     case op_get_by_id_chain:
4553         prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain);
4554         stubInfo->stubRoutine = 0;
4555         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
4556         break;
4557     case op_get_by_id_proto_list:
4558         prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
4559         listIndex = stubInfo->u.getByIdProtoList.listSize;
4560         stubInfo->u.getByIdProtoList.listSize++;
4561         break;
4562     default:
4563         ASSERT_NOT_REACHED();
4564     }
4565 
4566     ASSERT(listIndex < POLYMORPHIC_LIST_CACHE_SIZE);
4567     return prototypeStructureList;
4568 }
4569 
cti_op_get_by_id_proto_list(STUB_ARGS)4570 JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_list(STUB_ARGS)
4571 {
4572     BEGIN_STUB_FUNCTION();
4573 
4574     CallFrame* callFrame = ARG_callFrame;
4575 
4576     JSValuePtr baseValue = ARG_src1;
4577     PropertySlot slot(baseValue);
4578     JSValuePtr result = baseValue.get(callFrame, *ARG_id2, slot);
4579 
4580     CHECK_FOR_EXCEPTION();
4581 
4582     if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) {
4583         ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail));
4584         return JSValuePtr::encode(result);
4585     }
4586 
4587     Structure* structure = asCell(baseValue)->structure();
4588     CodeBlock* codeBlock = callFrame->codeBlock();
4589     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
4590 
4591     ASSERT(slot.slotBase().isObject());
4592     JSObject* slotBaseObject = asObject(slot.slotBase());
4593 
4594     if (slot.slotBase() == baseValue)
4595         ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail));
4596     else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) {
4597         // Since we're accessing a prototype in a loop, it's a good bet that it
4598         // should not be treated as a dictionary.
4599         if (slotBaseObject->structure()->isDictionary()) {
4600             RefPtr<Structure> transition = Structure::fromDictionaryTransition(slotBaseObject->structure());
4601             slotBaseObject->setStructure(transition.release());
4602             asCell(baseValue)->structure()->setCachedPrototypeChain(0);
4603         }
4604 
4605         int listIndex;
4606         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
4607 
4608         JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), slot.cachedOffset());
4609 
4610         if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
4611             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full));
4612     } else if (size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot)) {
4613         StructureChain* chain = structure->cachedPrototypeChain();
4614         if (!chain)
4615             chain = cachePrototypeChain(callFrame, structure);
4616         ASSERT(chain);
4617 
4618         int listIndex;
4619         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
4620 
4621         JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, chain, count, slot.cachedOffset());
4622 
4623         if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
4624             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full));
4625     } else
4626         ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail));
4627 
4628     return JSValuePtr::encode(result);
4629 }
4630 
cti_op_get_by_id_proto_list_full(STUB_ARGS)4631 JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_list_full(STUB_ARGS)
4632 {
4633     BEGIN_STUB_FUNCTION();
4634 
4635     JSValuePtr baseValue = ARG_src1;
4636     PropertySlot slot(baseValue);
4637     JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot);
4638 
4639     CHECK_FOR_EXCEPTION_AT_END();
4640     return JSValuePtr::encode(result);
4641 }
4642 
cti_op_get_by_id_proto_fail(STUB_ARGS)4643 JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_fail(STUB_ARGS)
4644 {
4645     BEGIN_STUB_FUNCTION();
4646 
4647     JSValuePtr baseValue = ARG_src1;
4648     PropertySlot slot(baseValue);
4649     JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot);
4650 
4651     CHECK_FOR_EXCEPTION_AT_END();
4652     return JSValuePtr::encode(result);
4653 }
4654 
cti_op_get_by_id_array_fail(STUB_ARGS)4655 JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_array_fail(STUB_ARGS)
4656 {
4657     BEGIN_STUB_FUNCTION();
4658 
4659     JSValuePtr baseValue = ARG_src1;
4660     PropertySlot slot(baseValue);
4661     JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot);
4662 
4663     CHECK_FOR_EXCEPTION_AT_END();
4664     return JSValuePtr::encode(result);
4665 }
4666 
cti_op_get_by_id_string_fail(STUB_ARGS)4667 JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_string_fail(STUB_ARGS)
4668 {
4669     BEGIN_STUB_FUNCTION();
4670 
4671     JSValuePtr baseValue = ARG_src1;
4672     PropertySlot slot(baseValue);
4673     JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot);
4674 
4675     CHECK_FOR_EXCEPTION_AT_END();
4676     return JSValuePtr::encode(result);
4677 }
4678 
4679 #endif
4680 
cti_op_instanceof(STUB_ARGS)4681 JSValueEncodedAsPointer* Interpreter::cti_op_instanceof(STUB_ARGS)
4682 {
4683     BEGIN_STUB_FUNCTION();
4684 
4685     CallFrame* callFrame = ARG_callFrame;
4686     JSValuePtr value = ARG_src1;
4687     JSValuePtr baseVal = ARG_src2;
4688     JSValuePtr proto = ARG_src3;
4689 
4690     // at least one of these checks must have failed to get to the slow case
4691     ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell()
4692            || !value.isObject() || !baseVal.isObject() || !proto.isObject()
4693            || (asObject(baseVal)->structure()->typeInfo().flags() & (ImplementsHasInstance | OverridesHasInstance)) != ImplementsHasInstance);
4694 
4695     if (!baseVal.isObject()) {
4696         CallFrame* callFrame = ARG_callFrame;
4697         CodeBlock* codeBlock = callFrame->codeBlock();
4698         unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
4699         ARG_globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal, vPCIndex, codeBlock);
4700         VM_THROW_EXCEPTION();
4701     }
4702 
4703     if (!asObject(baseVal)->structure()->typeInfo().implementsHasInstance())
4704         return JSValuePtr::encode(jsBoolean(false));
4705 
4706     if (!proto.isObject()) {
4707         throwError(callFrame, TypeError, "instanceof called on an object with an invalid prototype property.");
4708         VM_THROW_EXCEPTION();
4709     }
4710 
4711     if (!value.isObject())
4712         return JSValuePtr::encode(jsBoolean(false));
4713 
4714     JSValuePtr result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto));
4715     CHECK_FOR_EXCEPTION_AT_END();
4716 
4717     return JSValuePtr::encode(result);
4718 }
4719 
cti_op_del_by_id(STUB_ARGS)4720 JSValueEncodedAsPointer* Interpreter::cti_op_del_by_id(STUB_ARGS)
4721 {
4722     BEGIN_STUB_FUNCTION();
4723 
4724     CallFrame* callFrame = ARG_callFrame;
4725 
4726     JSObject* baseObj = ARG_src1.toObject(callFrame);
4727 
4728     JSValuePtr result = jsBoolean(baseObj->deleteProperty(callFrame, *ARG_id2));
4729     CHECK_FOR_EXCEPTION_AT_END();
4730     return JSValuePtr::encode(result);
4731 }
4732 
cti_op_mul(STUB_ARGS)4733 JSValueEncodedAsPointer* Interpreter::cti_op_mul(STUB_ARGS)
4734 {
4735     BEGIN_STUB_FUNCTION();
4736 
4737     JSValuePtr src1 = ARG_src1;
4738     JSValuePtr src2 = ARG_src2;
4739 
4740     double left;
4741     double right;
4742     if (src1.getNumber(left) && src2.getNumber(right))
4743         return JSValuePtr::encode(jsNumber(ARG_globalData, left * right));
4744 
4745     CallFrame* callFrame = ARG_callFrame;
4746     JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) * src2.toNumber(callFrame));
4747     CHECK_FOR_EXCEPTION_AT_END();
4748     return JSValuePtr::encode(result);
4749 }
4750 
cti_op_new_func(STUB_ARGS)4751 JSObject* Interpreter::cti_op_new_func(STUB_ARGS)
4752 {
4753     BEGIN_STUB_FUNCTION();
4754 
4755     return ARG_func1->makeFunction(ARG_callFrame, ARG_callFrame->scopeChain());
4756 }
4757 
cti_op_call_JSFunction(STUB_ARGS)4758 void* Interpreter::cti_op_call_JSFunction(STUB_ARGS)
4759 {
4760     BEGIN_STUB_FUNCTION();
4761 
4762 #ifndef NDEBUG
4763     CallData callData;
4764     ASSERT(ARG_src1.getCallData(callData) == CallTypeJS);
4765 #endif
4766 
4767     ScopeChainNode* callDataScopeChain = asFunction(ARG_src1)->m_scopeChain.node();
4768     CodeBlock* newCodeBlock = &asFunction(ARG_src1)->body()->bytecode(callDataScopeChain);
4769 
4770     if (!newCodeBlock->jitCode())
4771         JIT::compile(ARG_globalData, newCodeBlock);
4772 
4773     return newCodeBlock;
4774 }
4775 
cti_op_call_arityCheck(STUB_ARGS)4776 VoidPtrPair Interpreter::cti_op_call_arityCheck(STUB_ARGS)
4777 {
4778     BEGIN_STUB_FUNCTION();
4779 
4780     CallFrame* callFrame = ARG_callFrame;
4781     CodeBlock* newCodeBlock = ARG_codeBlock4;
4782     int argCount = ARG_int3;
4783 
4784     ASSERT(argCount != newCodeBlock->m_numParameters);
4785 
4786     CallFrame* oldCallFrame = callFrame->callerFrame();
4787 
4788     if (argCount > newCodeBlock->m_numParameters) {
4789         size_t numParameters = newCodeBlock->m_numParameters;
4790         Register* r = callFrame->registers() + numParameters;
4791 
4792         Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
4793         for (size_t i = 0; i < numParameters; ++i)
4794             argv[i + argCount] = argv[i];
4795 
4796         callFrame = CallFrame::create(r);
4797         callFrame->setCallerFrame(oldCallFrame);
4798     } else {
4799         size_t omittedArgCount = newCodeBlock->m_numParameters - argCount;
4800         Register* r = callFrame->registers() + omittedArgCount;
4801         Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
4802         if (!ARG_registerFile->grow(newEnd)) {
4803             // Rewind to the previous call frame because op_call already optimistically
4804             // moved the call frame forward.
4805             ARG_setCallFrame(oldCallFrame);
4806             throwStackOverflowError(oldCallFrame, ARG_globalData, ARG_returnAddress2, STUB_RETURN_ADDRESS);
4807             RETURN_PAIR(0, 0);
4808         }
4809 
4810         Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
4811         for (size_t i = 0; i < omittedArgCount; ++i)
4812             argv[i] = jsUndefined();
4813 
4814         callFrame = CallFrame::create(r);
4815         callFrame->setCallerFrame(oldCallFrame);
4816     }
4817 
4818     RETURN_PAIR(newCodeBlock, callFrame);
4819 }
4820 
cti_vm_dontLazyLinkCall(STUB_ARGS)4821 void* Interpreter::cti_vm_dontLazyLinkCall(STUB_ARGS)
4822 {
4823     BEGIN_STUB_FUNCTION();
4824 
4825     JSFunction* callee = asFunction(ARG_src1);
4826     CodeBlock* codeBlock = &callee->body()->bytecode(callee->m_scopeChain.node());
4827     if (!codeBlock->jitCode())
4828         JIT::compile(ARG_globalData, codeBlock);
4829 
4830     ctiPatchCallByReturnAddress(ARG_returnAddress2, ARG_globalData->interpreter->m_ctiVirtualCallLink);
4831 
4832     return codeBlock->jitCode();
4833 }
4834 
cti_vm_lazyLinkCall(STUB_ARGS)4835 void* Interpreter::cti_vm_lazyLinkCall(STUB_ARGS)
4836 {
4837     BEGIN_STUB_FUNCTION();
4838 
4839     JSFunction* callee = asFunction(ARG_src1);
4840     CodeBlock* codeBlock = &callee->body()->bytecode(callee->m_scopeChain.node());
4841     if (!codeBlock->jitCode())
4842         JIT::compile(ARG_globalData, codeBlock);
4843 
4844     CallLinkInfo* callLinkInfo = &ARG_callFrame->callerFrame()->codeBlock()->getCallLinkInfo(ARG_returnAddress2);
4845     JIT::linkCall(callee, codeBlock, codeBlock->jitCode(), callLinkInfo, ARG_int3);
4846 
4847     return codeBlock->jitCode();
4848 }
4849 
cti_op_push_activation(STUB_ARGS)4850 JSObject* Interpreter::cti_op_push_activation(STUB_ARGS)
4851 {
4852     BEGIN_STUB_FUNCTION();
4853 
4854     JSActivation* activation = new (ARG_globalData) JSActivation(ARG_callFrame, static_cast<FunctionBodyNode*>(ARG_callFrame->codeBlock()->ownerNode()));
4855     ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->copy()->push(activation));
4856     return activation;
4857 }
4858 
cti_op_call_NotJSFunction(STUB_ARGS)4859 JSValueEncodedAsPointer* Interpreter::cti_op_call_NotJSFunction(STUB_ARGS)
4860 {
4861     BEGIN_STUB_FUNCTION();
4862 
4863     JSValuePtr funcVal = ARG_src1;
4864 
4865     CallData callData;
4866     CallType callType = funcVal.getCallData(callData);
4867 
4868     ASSERT(callType != CallTypeJS);
4869 
4870     if (callType == CallTypeHost) {
4871         int registerOffset = ARG_int2;
4872         int argCount = ARG_int3;
4873         CallFrame* previousCallFrame = ARG_callFrame;
4874         CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset);
4875 
4876         callFrame->init(0, static_cast<Instruction*>(STUB_RETURN_ADDRESS), previousCallFrame->scopeChain(), previousCallFrame, 0, argCount, 0);
4877         ARG_setCallFrame(callFrame);
4878 
4879         Register* argv = ARG_callFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
4880         ArgList argList(argv + 1, argCount - 1);
4881 
4882         JSValuePtr returnValue;
4883         {
4884             SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
4885 
4886             // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
4887             JSValuePtr thisValue = argv[0].jsValue(callFrame);
4888             if (thisValue == jsNull())
4889                 thisValue = callFrame->globalThisValue();
4890 
4891             returnValue = callData.native.function(callFrame, asObject(funcVal), thisValue, argList);
4892         }
4893         ARG_setCallFrame(previousCallFrame);
4894         CHECK_FOR_EXCEPTION();
4895 
4896         return JSValuePtr::encode(returnValue);
4897     }
4898 
4899     ASSERT(callType == CallTypeNone);
4900 
4901     CallFrame* callFrame = ARG_callFrame;
4902     CodeBlock* codeBlock = callFrame->codeBlock();
4903     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
4904     ARG_globalData->exception = createNotAFunctionError(ARG_callFrame, funcVal, vPCIndex, codeBlock);
4905     VM_THROW_EXCEPTION();
4906 }
4907 
cti_op_create_arguments(STUB_ARGS)4908 void Interpreter::cti_op_create_arguments(STUB_ARGS)
4909 {
4910     BEGIN_STUB_FUNCTION();
4911 
4912     Arguments* arguments = new (ARG_globalData) Arguments(ARG_callFrame);
4913     ARG_callFrame->setCalleeArguments(arguments);
4914     ARG_callFrame[RegisterFile::ArgumentsRegister] = arguments;
4915 }
4916 
cti_op_create_arguments_no_params(STUB_ARGS)4917 void Interpreter::cti_op_create_arguments_no_params(STUB_ARGS)
4918 {
4919     BEGIN_STUB_FUNCTION();
4920 
4921     Arguments* arguments = new (ARG_globalData) Arguments(ARG_callFrame, Arguments::NoParameters);
4922     ARG_callFrame->setCalleeArguments(arguments);
4923     ARG_callFrame[RegisterFile::ArgumentsRegister] = arguments;
4924 }
4925 
cti_op_tear_off_activation(STUB_ARGS)4926 void Interpreter::cti_op_tear_off_activation(STUB_ARGS)
4927 {
4928     BEGIN_STUB_FUNCTION();
4929 
4930     ASSERT(ARG_callFrame->codeBlock()->needsFullScopeChain());
4931     asActivation(ARG_src1)->copyRegisters(ARG_callFrame->optionalCalleeArguments());
4932 }
4933 
cti_op_tear_off_arguments(STUB_ARGS)4934 void Interpreter::cti_op_tear_off_arguments(STUB_ARGS)
4935 {
4936     BEGIN_STUB_FUNCTION();
4937 
4938     ASSERT(ARG_callFrame->codeBlock()->usesArguments() && !ARG_callFrame->codeBlock()->needsFullScopeChain());
4939     ARG_callFrame->optionalCalleeArguments()->copyRegisters();
4940 }
4941 
cti_op_profile_will_call(STUB_ARGS)4942 void Interpreter::cti_op_profile_will_call(STUB_ARGS)
4943 {
4944     BEGIN_STUB_FUNCTION();
4945 
4946     ASSERT(*ARG_profilerReference);
4947     (*ARG_profilerReference)->willExecute(ARG_callFrame, ARG_src1);
4948 }
4949 
cti_op_profile_did_call(STUB_ARGS)4950 void Interpreter::cti_op_profile_did_call(STUB_ARGS)
4951 {
4952     BEGIN_STUB_FUNCTION();
4953 
4954     ASSERT(*ARG_profilerReference);
4955     (*ARG_profilerReference)->didExecute(ARG_callFrame, ARG_src1);
4956 }
4957 
cti_op_ret_scopeChain(STUB_ARGS)4958 void Interpreter::cti_op_ret_scopeChain(STUB_ARGS)
4959 {
4960     BEGIN_STUB_FUNCTION();
4961 
4962     ASSERT(ARG_callFrame->codeBlock()->needsFullScopeChain());
4963     ARG_callFrame->scopeChain()->deref();
4964 }
4965 
cti_op_new_array(STUB_ARGS)4966 JSObject* Interpreter::cti_op_new_array(STUB_ARGS)
4967 {
4968     BEGIN_STUB_FUNCTION();
4969 
4970     ArgList argList(&ARG_callFrame->registers()[ARG_int1], ARG_int2);
4971     return constructArray(ARG_callFrame, argList);
4972 }
4973 
cti_op_resolve(STUB_ARGS)4974 JSValueEncodedAsPointer* Interpreter::cti_op_resolve(STUB_ARGS)
4975 {
4976     BEGIN_STUB_FUNCTION();
4977 
4978     CallFrame* callFrame = ARG_callFrame;
4979     ScopeChainNode* scopeChain = callFrame->scopeChain();
4980 
4981     ScopeChainIterator iter = scopeChain->begin();
4982     ScopeChainIterator end = scopeChain->end();
4983     ASSERT(iter != end);
4984 
4985     Identifier& ident = *ARG_id1;
4986     do {
4987         JSObject* o = *iter;
4988         PropertySlot slot(o);
4989         if (o->getPropertySlot(callFrame, ident, slot)) {
4990             JSValuePtr result = slot.getValue(callFrame, ident);
4991             CHECK_FOR_EXCEPTION_AT_END();
4992             return JSValuePtr::encode(result);
4993         }
4994     } while (++iter != end);
4995 
4996     CodeBlock* codeBlock = callFrame->codeBlock();
4997     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
4998     ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
4999     VM_THROW_EXCEPTION();
5000 }
5001 
cti_op_construct_JSConstruct(STUB_ARGS)5002 JSObject* Interpreter::cti_op_construct_JSConstruct(STUB_ARGS)
5003 {
5004     BEGIN_STUB_FUNCTION();
5005 
5006 #ifndef NDEBUG
5007     ConstructData constructData;
5008     ASSERT(asFunction(ARG_src1)->getConstructData(constructData) == ConstructTypeJS);
5009 #endif
5010 
5011     Structure* structure;
5012     if (ARG_src4.isObject())
5013         structure = asObject(ARG_src4)->inheritorID();
5014     else
5015         structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->emptyObjectStructure();
5016     return new (ARG_globalData) JSObject(structure);
5017 }
5018 
cti_op_construct_NotJSConstruct(STUB_ARGS)5019 JSValueEncodedAsPointer* Interpreter::cti_op_construct_NotJSConstruct(STUB_ARGS)
5020 {
5021     BEGIN_STUB_FUNCTION();
5022 
5023     CallFrame* callFrame = ARG_callFrame;
5024 
5025     JSValuePtr constrVal = ARG_src1;
5026     int argCount = ARG_int3;
5027     int thisRegister = ARG_int5;
5028 
5029     ConstructData constructData;
5030     ConstructType constructType = constrVal.getConstructData(constructData);
5031 
5032     if (constructType == ConstructTypeHost) {
5033         ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1);
5034 
5035         JSValuePtr returnValue;
5036         {
5037             SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
5038             returnValue = constructData.native.function(callFrame, asObject(constrVal), argList);
5039         }
5040         CHECK_FOR_EXCEPTION();
5041 
5042         return JSValuePtr::encode(returnValue);
5043     }
5044 
5045     ASSERT(constructType == ConstructTypeNone);
5046 
5047     CodeBlock* codeBlock = callFrame->codeBlock();
5048     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
5049     ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, vPCIndex, codeBlock);
5050     VM_THROW_EXCEPTION();
5051 }
5052 
cti_op_get_by_val(STUB_ARGS)5053 JSValueEncodedAsPointer* Interpreter::cti_op_get_by_val(STUB_ARGS)
5054 {
5055     BEGIN_STUB_FUNCTION();
5056 
5057     CallFrame* callFrame = ARG_callFrame;
5058     Interpreter* interpreter = ARG_globalData->interpreter;
5059 
5060     JSValuePtr baseValue = ARG_src1;
5061     JSValuePtr subscript = ARG_src2;
5062 
5063     JSValuePtr result;
5064 
5065     if (LIKELY(subscript.isUInt32Fast())) {
5066         uint32_t i = subscript.getUInt32Fast();
5067         if (interpreter->isJSArray(baseValue)) {
5068             JSArray* jsArray = asArray(baseValue);
5069             if (jsArray->canGetIndex(i))
5070                 result = jsArray->getIndex(i);
5071             else
5072                 result = jsArray->JSArray::get(callFrame, i);
5073         } else if (interpreter->isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
5074             result = asString(baseValue)->getIndex(ARG_globalData, i);
5075         else if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
5076             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
5077             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_val_byte_array));
5078             return JSValuePtr::encode(asByteArray(baseValue)->getIndex(callFrame, i));
5079         } else
5080             result = baseValue.get(callFrame, i);
5081     } else {
5082         Identifier property(callFrame, subscript.toString(callFrame));
5083         result = baseValue.get(callFrame, property);
5084     }
5085 
5086     CHECK_FOR_EXCEPTION_AT_END();
5087     return JSValuePtr::encode(result);
5088 }
5089 
cti_op_get_by_val_byte_array(STUB_ARGS)5090 JSValueEncodedAsPointer* Interpreter::cti_op_get_by_val_byte_array(STUB_ARGS)
5091 {
5092     BEGIN_STUB_FUNCTION();
5093 
5094     CallFrame* callFrame = ARG_callFrame;
5095     Interpreter* interpreter = ARG_globalData->interpreter;
5096 
5097     JSValuePtr baseValue = ARG_src1;
5098     JSValuePtr subscript = ARG_src2;
5099 
5100     JSValuePtr result;
5101 
5102     if (LIKELY(subscript.isUInt32Fast())) {
5103         uint32_t i = subscript.getUInt32Fast();
5104         if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
5105             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
5106             return JSValuePtr::encode(asByteArray(baseValue)->getIndex(callFrame, i));
5107         }
5108 
5109         result = baseValue.get(callFrame, i);
5110         if (!interpreter->isJSByteArray(baseValue))
5111             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_val));
5112     } else {
5113         Identifier property(callFrame, subscript.toString(callFrame));
5114         result = baseValue.get(callFrame, property);
5115     }
5116 
5117     CHECK_FOR_EXCEPTION_AT_END();
5118     return JSValuePtr::encode(result);
5119 }
5120 
cti_op_resolve_func(STUB_ARGS)5121 VoidPtrPair Interpreter::cti_op_resolve_func(STUB_ARGS)
5122 {
5123     BEGIN_STUB_FUNCTION();
5124 
5125     CallFrame* callFrame = ARG_callFrame;
5126     ScopeChainNode* scopeChain = callFrame->scopeChain();
5127 
5128     ScopeChainIterator iter = scopeChain->begin();
5129     ScopeChainIterator end = scopeChain->end();
5130 
5131     // FIXME: add scopeDepthIsZero optimization
5132 
5133     ASSERT(iter != end);
5134 
5135     Identifier& ident = *ARG_id1;
5136     JSObject* base;
5137     do {
5138         base = *iter;
5139         PropertySlot slot(base);
5140         if (base->getPropertySlot(callFrame, ident, slot)) {
5141             // ECMA 11.2.3 says that if we hit an activation the this value should be null.
5142             // However, section 10.2.3 says that in the case where the value provided
5143             // by the caller is null, the global object should be used. It also says
5144             // that the section does not apply to internal functions, but for simplicity
5145             // of implementation we use the global object anyway here. This guarantees
5146             // that in host objects you always get a valid object for this.
5147             // We also handle wrapper substitution for the global object at the same time.
5148             JSObject* thisObj = base->toThisObject(callFrame);
5149             JSValuePtr result = slot.getValue(callFrame, ident);
5150             CHECK_FOR_EXCEPTION_AT_END();
5151 
5152             RETURN_PAIR(thisObj, JSValuePtr::encode(result));
5153         }
5154         ++iter;
5155     } while (iter != end);
5156 
5157     CodeBlock* codeBlock = callFrame->codeBlock();
5158     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
5159     ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
5160     VM_THROW_EXCEPTION_2();
5161 }
5162 
cti_op_sub(STUB_ARGS)5163 JSValueEncodedAsPointer* Interpreter::cti_op_sub(STUB_ARGS)
5164 {
5165     BEGIN_STUB_FUNCTION();
5166 
5167     JSValuePtr src1 = ARG_src1;
5168     JSValuePtr src2 = ARG_src2;
5169 
5170     double left;
5171     double right;
5172     if (src1.getNumber(left) && src2.getNumber(right))
5173         return JSValuePtr::encode(jsNumber(ARG_globalData, left - right));
5174 
5175     CallFrame* callFrame = ARG_callFrame;
5176     JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) - src2.toNumber(callFrame));
5177     CHECK_FOR_EXCEPTION_AT_END();
5178     return JSValuePtr::encode(result);
5179 }
5180 
cti_op_put_by_val(STUB_ARGS)5181 void Interpreter::cti_op_put_by_val(STUB_ARGS)
5182 {
5183     BEGIN_STUB_FUNCTION();
5184 
5185     CallFrame* callFrame = ARG_callFrame;
5186     Interpreter* interpreter = ARG_globalData->interpreter;
5187 
5188     JSValuePtr baseValue = ARG_src1;
5189     JSValuePtr subscript = ARG_src2;
5190     JSValuePtr value = ARG_src3;
5191 
5192     if (LIKELY(subscript.isUInt32Fast())) {
5193         uint32_t i = subscript.getUInt32Fast();
5194         if (interpreter->isJSArray(baseValue)) {
5195             JSArray* jsArray = asArray(baseValue);
5196             if (jsArray->canSetIndex(i))
5197                 jsArray->setIndex(i, value);
5198             else
5199                 jsArray->JSArray::put(callFrame, i, value);
5200         } else if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
5201             JSByteArray* jsByteArray = asByteArray(baseValue);
5202             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_val_byte_array));
5203             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
5204             if (value.isInt32Fast()) {
5205                 jsByteArray->setIndex(i, value.getInt32Fast());
5206                 return;
5207             } else {
5208                 double dValue = 0;
5209                 if (value.getNumber(dValue)) {
5210                     jsByteArray->setIndex(i, dValue);
5211                     return;
5212                 }
5213             }
5214 
5215             baseValue.put(callFrame, i, value);
5216         } else
5217             baseValue.put(callFrame, i, value);
5218     } else {
5219         Identifier property(callFrame, subscript.toString(callFrame));
5220         if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception.
5221             PutPropertySlot slot;
5222             baseValue.put(callFrame, property, value, slot);
5223         }
5224     }
5225 
5226     CHECK_FOR_EXCEPTION_AT_END();
5227 }
5228 
cti_op_put_by_val_array(STUB_ARGS)5229 void Interpreter::cti_op_put_by_val_array(STUB_ARGS)
5230 {
5231     BEGIN_STUB_FUNCTION();
5232 
5233     CallFrame* callFrame = ARG_callFrame;
5234 
5235     JSValuePtr baseValue = ARG_src1;
5236     int i = ARG_int2;
5237     JSValuePtr value = ARG_src3;
5238 
5239     ASSERT(ARG_globalData->interpreter->isJSArray(baseValue));
5240 
5241     if (LIKELY(i >= 0))
5242         asArray(baseValue)->JSArray::put(callFrame, i, value);
5243     else {
5244         // This should work since we're re-boxing an immediate unboxed in JIT code.
5245         ASSERT(JSValuePtr::makeInt32Fast(i));
5246         Identifier property(callFrame, JSValuePtr::makeInt32Fast(i).toString(callFrame));
5247         // FIXME: can toString throw an exception here?
5248         if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception.
5249             PutPropertySlot slot;
5250             baseValue.put(callFrame, property, value, slot);
5251         }
5252     }
5253 
5254     CHECK_FOR_EXCEPTION_AT_END();
5255 }
5256 
cti_op_put_by_val_byte_array(STUB_ARGS)5257 void Interpreter::cti_op_put_by_val_byte_array(STUB_ARGS)
5258 {
5259     BEGIN_STUB_FUNCTION();
5260 
5261     CallFrame* callFrame = ARG_callFrame;
5262     Interpreter* interpreter = ARG_globalData->interpreter;
5263 
5264     JSValuePtr baseValue = ARG_src1;
5265     JSValuePtr subscript = ARG_src2;
5266     JSValuePtr value = ARG_src3;
5267 
5268     if (LIKELY(subscript.isUInt32Fast())) {
5269         uint32_t i = subscript.getUInt32Fast();
5270         if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
5271             JSByteArray* jsByteArray = asByteArray(baseValue);
5272 
5273             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
5274             if (value.isInt32Fast()) {
5275                 jsByteArray->setIndex(i, value.getInt32Fast());
5276                 return;
5277             } else {
5278                 double dValue = 0;
5279                 if (value.getNumber(dValue)) {
5280                     jsByteArray->setIndex(i, dValue);
5281                     return;
5282                 }
5283             }
5284         }
5285 
5286         if (!interpreter->isJSByteArray(baseValue))
5287             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_val));
5288         baseValue.put(callFrame, i, value);
5289     } else {
5290         Identifier property(callFrame, subscript.toString(callFrame));
5291         if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception.
5292             PutPropertySlot slot;
5293             baseValue.put(callFrame, property, value, slot);
5294         }
5295     }
5296 
5297     CHECK_FOR_EXCEPTION_AT_END();
5298 }
5299 
cti_op_lesseq(STUB_ARGS)5300 JSValueEncodedAsPointer* Interpreter::cti_op_lesseq(STUB_ARGS)
5301 {
5302     BEGIN_STUB_FUNCTION();
5303 
5304     CallFrame* callFrame = ARG_callFrame;
5305     JSValuePtr result = jsBoolean(jsLessEq(callFrame, ARG_src1, ARG_src2));
5306     CHECK_FOR_EXCEPTION_AT_END();
5307     return JSValuePtr::encode(result);
5308 }
5309 
cti_op_loop_if_true(STUB_ARGS)5310 int Interpreter::cti_op_loop_if_true(STUB_ARGS)
5311 {
5312     BEGIN_STUB_FUNCTION();
5313 
5314     JSValuePtr src1 = ARG_src1;
5315 
5316     CallFrame* callFrame = ARG_callFrame;
5317 
5318     bool result = src1.toBoolean(callFrame);
5319     CHECK_FOR_EXCEPTION_AT_END();
5320     return result;
5321 }
5322 
cti_op_negate(STUB_ARGS)5323 JSValueEncodedAsPointer* Interpreter::cti_op_negate(STUB_ARGS)
5324 {
5325     BEGIN_STUB_FUNCTION();
5326 
5327     JSValuePtr src = ARG_src1;
5328 
5329     double v;
5330     if (src.getNumber(v))
5331         return JSValuePtr::encode(jsNumber(ARG_globalData, -v));
5332 
5333     CallFrame* callFrame = ARG_callFrame;
5334     JSValuePtr result = jsNumber(ARG_globalData, -src.toNumber(callFrame));
5335     CHECK_FOR_EXCEPTION_AT_END();
5336     return JSValuePtr::encode(result);
5337 }
5338 
cti_op_resolve_base(STUB_ARGS)5339 JSValueEncodedAsPointer* Interpreter::cti_op_resolve_base(STUB_ARGS)
5340 {
5341     BEGIN_STUB_FUNCTION();
5342 
5343     return JSValuePtr::encode(inlineResolveBase(ARG_callFrame, *ARG_id1, ARG_callFrame->scopeChain()));
5344 }
5345 
cti_op_resolve_skip(STUB_ARGS)5346 JSValueEncodedAsPointer* Interpreter::cti_op_resolve_skip(STUB_ARGS)
5347 {
5348     BEGIN_STUB_FUNCTION();
5349 
5350     CallFrame* callFrame = ARG_callFrame;
5351     ScopeChainNode* scopeChain = callFrame->scopeChain();
5352 
5353     int skip = ARG_int2;
5354 
5355     ScopeChainIterator iter = scopeChain->begin();
5356     ScopeChainIterator end = scopeChain->end();
5357     ASSERT(iter != end);
5358     while (skip--) {
5359         ++iter;
5360         ASSERT(iter != end);
5361     }
5362     Identifier& ident = *ARG_id1;
5363     do {
5364         JSObject* o = *iter;
5365         PropertySlot slot(o);
5366         if (o->getPropertySlot(callFrame, ident, slot)) {
5367             JSValuePtr result = slot.getValue(callFrame, ident);
5368             CHECK_FOR_EXCEPTION_AT_END();
5369             return JSValuePtr::encode(result);
5370         }
5371     } while (++iter != end);
5372 
5373     CodeBlock* codeBlock = callFrame->codeBlock();
5374     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
5375     ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
5376     VM_THROW_EXCEPTION();
5377 }
5378 
cti_op_resolve_global(STUB_ARGS)5379 JSValueEncodedAsPointer* Interpreter::cti_op_resolve_global(STUB_ARGS)
5380 {
5381     BEGIN_STUB_FUNCTION();
5382 
5383     CallFrame* callFrame = ARG_callFrame;
5384     JSGlobalObject* globalObject = asGlobalObject(ARG_src1);
5385     Identifier& ident = *ARG_id2;
5386     unsigned globalResolveInfoIndex = ARG_int3;
5387     ASSERT(globalObject->isGlobalObject());
5388 
5389     PropertySlot slot(globalObject);
5390     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
5391         JSValuePtr result = slot.getValue(callFrame, ident);
5392         if (slot.isCacheable() && !globalObject->structure()->isDictionary()) {
5393             GlobalResolveInfo& globalResolveInfo = callFrame->codeBlock()->globalResolveInfo(globalResolveInfoIndex);
5394             if (globalResolveInfo.structure)
5395                 globalResolveInfo.structure->deref();
5396             globalObject->structure()->ref();
5397             globalResolveInfo.structure = globalObject->structure();
5398             globalResolveInfo.offset = slot.cachedOffset();
5399             return JSValuePtr::encode(result);
5400         }
5401 
5402         CHECK_FOR_EXCEPTION_AT_END();
5403         return JSValuePtr::encode(result);
5404     }
5405 
5406     unsigned vPCIndex = callFrame->codeBlock()->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
5407     ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, callFrame->codeBlock());
5408     VM_THROW_EXCEPTION();
5409 }
5410 
cti_op_div(STUB_ARGS)5411 JSValueEncodedAsPointer* Interpreter::cti_op_div(STUB_ARGS)
5412 {
5413     BEGIN_STUB_FUNCTION();
5414 
5415     JSValuePtr src1 = ARG_src1;
5416     JSValuePtr src2 = ARG_src2;
5417 
5418     double left;
5419     double right;
5420     if (src1.getNumber(left) && src2.getNumber(right))
5421         return JSValuePtr::encode(jsNumber(ARG_globalData, left / right));
5422 
5423     CallFrame* callFrame = ARG_callFrame;
5424     JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) / src2.toNumber(callFrame));
5425     CHECK_FOR_EXCEPTION_AT_END();
5426     return JSValuePtr::encode(result);
5427 }
5428 
cti_op_pre_dec(STUB_ARGS)5429 JSValueEncodedAsPointer* Interpreter::cti_op_pre_dec(STUB_ARGS)
5430 {
5431     BEGIN_STUB_FUNCTION();
5432 
5433     JSValuePtr v = ARG_src1;
5434 
5435     CallFrame* callFrame = ARG_callFrame;
5436     JSValuePtr result = jsNumber(ARG_globalData, v.toNumber(callFrame) - 1);
5437     CHECK_FOR_EXCEPTION_AT_END();
5438     return JSValuePtr::encode(result);
5439 }
5440 
cti_op_jless(STUB_ARGS)5441 int Interpreter::cti_op_jless(STUB_ARGS)
5442 {
5443     BEGIN_STUB_FUNCTION();
5444 
5445     JSValuePtr src1 = ARG_src1;
5446     JSValuePtr src2 = ARG_src2;
5447     CallFrame* callFrame = ARG_callFrame;
5448 
5449     bool result = jsLess(callFrame, src1, src2);
5450     CHECK_FOR_EXCEPTION_AT_END();
5451     return result;
5452 }
5453 
cti_op_not(STUB_ARGS)5454 JSValueEncodedAsPointer* Interpreter::cti_op_not(STUB_ARGS)
5455 {
5456     BEGIN_STUB_FUNCTION();
5457 
5458     JSValuePtr src = ARG_src1;
5459 
5460     CallFrame* callFrame = ARG_callFrame;
5461 
5462     JSValuePtr result = jsBoolean(!src.toBoolean(callFrame));
5463     CHECK_FOR_EXCEPTION_AT_END();
5464     return JSValuePtr::encode(result);
5465 }
5466 
cti_op_jtrue(STUB_ARGS)5467 int Interpreter::cti_op_jtrue(STUB_ARGS)
5468 {
5469     BEGIN_STUB_FUNCTION();
5470 
5471     JSValuePtr src1 = ARG_src1;
5472 
5473     CallFrame* callFrame = ARG_callFrame;
5474 
5475     bool result = src1.toBoolean(callFrame);
5476     CHECK_FOR_EXCEPTION_AT_END();
5477     return result;
5478 }
5479 
cti_op_post_inc(STUB_ARGS)5480 VoidPtrPair Interpreter::cti_op_post_inc(STUB_ARGS)
5481 {
5482     BEGIN_STUB_FUNCTION();
5483 
5484     JSValuePtr v = ARG_src1;
5485 
5486     CallFrame* callFrame = ARG_callFrame;
5487 
5488     JSValuePtr number = v.toJSNumber(callFrame);
5489     CHECK_FOR_EXCEPTION_AT_END();
5490 
5491     RETURN_PAIR(JSValuePtr::encode(number), JSValuePtr::encode(jsNumber(ARG_globalData, number.uncheckedGetNumber() + 1)));
5492 }
5493 
cti_op_eq(STUB_ARGS)5494 JSValueEncodedAsPointer* Interpreter::cti_op_eq(STUB_ARGS)
5495 {
5496     BEGIN_STUB_FUNCTION();
5497 
5498     JSValuePtr src1 = ARG_src1;
5499     JSValuePtr src2 = ARG_src2;
5500 
5501     CallFrame* callFrame = ARG_callFrame;
5502 
5503     ASSERT(!JSValuePtr::areBothInt32Fast(src1, src2));
5504     JSValuePtr result = jsBoolean(JSValuePtr::equalSlowCaseInline(callFrame, src1, src2));
5505     CHECK_FOR_EXCEPTION_AT_END();
5506     return JSValuePtr::encode(result);
5507 }
5508 
cti_op_lshift(STUB_ARGS)5509 JSValueEncodedAsPointer* Interpreter::cti_op_lshift(STUB_ARGS)
5510 {
5511     BEGIN_STUB_FUNCTION();
5512 
5513     JSValuePtr val = ARG_src1;
5514     JSValuePtr shift = ARG_src2;
5515 
5516     int32_t left;
5517     uint32_t right;
5518     if (JSValuePtr::areBothInt32Fast(val, shift))
5519         return JSValuePtr::encode(jsNumber(ARG_globalData, val.getInt32Fast() << (shift.getInt32Fast() & 0x1f)));
5520     if (val.numberToInt32(left) && shift.numberToUInt32(right))
5521         return JSValuePtr::encode(jsNumber(ARG_globalData, left << (right & 0x1f)));
5522 
5523     CallFrame* callFrame = ARG_callFrame;
5524     JSValuePtr result = jsNumber(ARG_globalData, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
5525     CHECK_FOR_EXCEPTION_AT_END();
5526     return JSValuePtr::encode(result);
5527 }
5528 
cti_op_bitand(STUB_ARGS)5529 JSValueEncodedAsPointer* Interpreter::cti_op_bitand(STUB_ARGS)
5530 {
5531     BEGIN_STUB_FUNCTION();
5532 
5533     JSValuePtr src1 = ARG_src1;
5534     JSValuePtr src2 = ARG_src2;
5535 
5536     int32_t left;
5537     int32_t right;
5538     if (src1.numberToInt32(left) && src2.numberToInt32(right))
5539         return JSValuePtr::encode(jsNumber(ARG_globalData, left & right));
5540 
5541     CallFrame* callFrame = ARG_callFrame;
5542     JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) & src2.toInt32(callFrame));
5543     CHECK_FOR_EXCEPTION_AT_END();
5544     return JSValuePtr::encode(result);
5545 }
5546 
cti_op_rshift(STUB_ARGS)5547 JSValueEncodedAsPointer* Interpreter::cti_op_rshift(STUB_ARGS)
5548 {
5549     BEGIN_STUB_FUNCTION();
5550 
5551     JSValuePtr val = ARG_src1;
5552     JSValuePtr shift = ARG_src2;
5553 
5554     int32_t left;
5555     uint32_t right;
5556     if (JSFastMath::canDoFastRshift(val, shift))
5557         return JSValuePtr::encode(JSFastMath::rightShiftImmediateNumbers(val, shift));
5558     if (val.numberToInt32(left) && shift.numberToUInt32(right))
5559         return JSValuePtr::encode(jsNumber(ARG_globalData, left >> (right & 0x1f)));
5560 
5561     CallFrame* callFrame = ARG_callFrame;
5562     JSValuePtr result = jsNumber(ARG_globalData, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
5563     CHECK_FOR_EXCEPTION_AT_END();
5564     return JSValuePtr::encode(result);
5565 }
5566 
cti_op_bitnot(STUB_ARGS)5567 JSValueEncodedAsPointer* Interpreter::cti_op_bitnot(STUB_ARGS)
5568 {
5569     BEGIN_STUB_FUNCTION();
5570 
5571     JSValuePtr src = ARG_src1;
5572 
5573     int value;
5574     if (src.numberToInt32(value))
5575         return JSValuePtr::encode(jsNumber(ARG_globalData, ~value));
5576 
5577     CallFrame* callFrame = ARG_callFrame;
5578     JSValuePtr result = jsNumber(ARG_globalData, ~src.toInt32(callFrame));
5579     CHECK_FOR_EXCEPTION_AT_END();
5580     return JSValuePtr::encode(result);
5581 }
5582 
cti_op_resolve_with_base(STUB_ARGS)5583 VoidPtrPair Interpreter::cti_op_resolve_with_base(STUB_ARGS)
5584 {
5585     BEGIN_STUB_FUNCTION();
5586 
5587     CallFrame* callFrame = ARG_callFrame;
5588     ScopeChainNode* scopeChain = callFrame->scopeChain();
5589 
5590     ScopeChainIterator iter = scopeChain->begin();
5591     ScopeChainIterator end = scopeChain->end();
5592 
5593     // FIXME: add scopeDepthIsZero optimization
5594 
5595     ASSERT(iter != end);
5596 
5597     Identifier& ident = *ARG_id1;
5598     JSObject* base;
5599     do {
5600         base = *iter;
5601         PropertySlot slot(base);
5602         if (base->getPropertySlot(callFrame, ident, slot)) {
5603             JSValuePtr result = slot.getValue(callFrame, ident);
5604             CHECK_FOR_EXCEPTION_AT_END();
5605 
5606             RETURN_PAIR(base, JSValuePtr::encode(result));
5607         }
5608         ++iter;
5609     } while (iter != end);
5610 
5611     CodeBlock* codeBlock = callFrame->codeBlock();
5612     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
5613     ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
5614     VM_THROW_EXCEPTION_2();
5615 }
5616 
cti_op_new_func_exp(STUB_ARGS)5617 JSObject* Interpreter::cti_op_new_func_exp(STUB_ARGS)
5618 {
5619     BEGIN_STUB_FUNCTION();
5620 
5621     return ARG_funcexp1->makeFunction(ARG_callFrame, ARG_callFrame->scopeChain());
5622 }
5623 
cti_op_mod(STUB_ARGS)5624 JSValueEncodedAsPointer* Interpreter::cti_op_mod(STUB_ARGS)
5625 {
5626     BEGIN_STUB_FUNCTION();
5627 
5628     JSValuePtr dividendValue = ARG_src1;
5629     JSValuePtr divisorValue = ARG_src2;
5630 
5631     CallFrame* callFrame = ARG_callFrame;
5632     double d = dividendValue.toNumber(callFrame);
5633     JSValuePtr result = jsNumber(ARG_globalData, fmod(d, divisorValue.toNumber(callFrame)));
5634     CHECK_FOR_EXCEPTION_AT_END();
5635     return JSValuePtr::encode(result);
5636 }
5637 
cti_op_less(STUB_ARGS)5638 JSValueEncodedAsPointer* Interpreter::cti_op_less(STUB_ARGS)
5639 {
5640     BEGIN_STUB_FUNCTION();
5641 
5642     CallFrame* callFrame = ARG_callFrame;
5643     JSValuePtr result = jsBoolean(jsLess(callFrame, ARG_src1, ARG_src2));
5644     CHECK_FOR_EXCEPTION_AT_END();
5645     return JSValuePtr::encode(result);
5646 }
5647 
cti_op_neq(STUB_ARGS)5648 JSValueEncodedAsPointer* Interpreter::cti_op_neq(STUB_ARGS)
5649 {
5650     BEGIN_STUB_FUNCTION();
5651 
5652     JSValuePtr src1 = ARG_src1;
5653     JSValuePtr src2 = ARG_src2;
5654 
5655     ASSERT(!JSValuePtr::areBothInt32Fast(src1, src2));
5656 
5657     CallFrame* callFrame = ARG_callFrame;
5658     JSValuePtr result = jsBoolean(!JSValuePtr::equalSlowCaseInline(callFrame, src1, src2));
5659     CHECK_FOR_EXCEPTION_AT_END();
5660     return JSValuePtr::encode(result);
5661 }
5662 
cti_op_post_dec(STUB_ARGS)5663 VoidPtrPair Interpreter::cti_op_post_dec(STUB_ARGS)
5664 {
5665     BEGIN_STUB_FUNCTION();
5666 
5667     JSValuePtr v = ARG_src1;
5668 
5669     CallFrame* callFrame = ARG_callFrame;
5670 
5671     JSValuePtr number = v.toJSNumber(callFrame);
5672     CHECK_FOR_EXCEPTION_AT_END();
5673 
5674     RETURN_PAIR(JSValuePtr::encode(number), JSValuePtr::encode(jsNumber(ARG_globalData, number.uncheckedGetNumber() - 1)));
5675 }
5676 
cti_op_urshift(STUB_ARGS)5677 JSValueEncodedAsPointer* Interpreter::cti_op_urshift(STUB_ARGS)
5678 {
5679     BEGIN_STUB_FUNCTION();
5680 
5681     JSValuePtr val = ARG_src1;
5682     JSValuePtr shift = ARG_src2;
5683 
5684     CallFrame* callFrame = ARG_callFrame;
5685 
5686     if (JSFastMath::canDoFastUrshift(val, shift))
5687         return JSValuePtr::encode(JSFastMath::rightShiftImmediateNumbers(val, shift));
5688     else {
5689         JSValuePtr result = jsNumber(ARG_globalData, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
5690         CHECK_FOR_EXCEPTION_AT_END();
5691         return JSValuePtr::encode(result);
5692     }
5693 }
5694 
cti_op_bitxor(STUB_ARGS)5695 JSValueEncodedAsPointer* Interpreter::cti_op_bitxor(STUB_ARGS)
5696 {
5697     BEGIN_STUB_FUNCTION();
5698 
5699     JSValuePtr src1 = ARG_src1;
5700     JSValuePtr src2 = ARG_src2;
5701 
5702     CallFrame* callFrame = ARG_callFrame;
5703 
5704     JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
5705     CHECK_FOR_EXCEPTION_AT_END();
5706     return JSValuePtr::encode(result);
5707 }
5708 
cti_op_new_regexp(STUB_ARGS)5709 JSObject* Interpreter::cti_op_new_regexp(STUB_ARGS)
5710 {
5711     BEGIN_STUB_FUNCTION();
5712 
5713     return new (ARG_globalData) RegExpObject(ARG_callFrame->lexicalGlobalObject()->regExpStructure(), ARG_regexp1);
5714 }
5715 
cti_op_bitor(STUB_ARGS)5716 JSValueEncodedAsPointer* Interpreter::cti_op_bitor(STUB_ARGS)
5717 {
5718     BEGIN_STUB_FUNCTION();
5719 
5720     JSValuePtr src1 = ARG_src1;
5721     JSValuePtr src2 = ARG_src2;
5722 
5723     CallFrame* callFrame = ARG_callFrame;
5724 
5725     JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) | src2.toInt32(callFrame));
5726     CHECK_FOR_EXCEPTION_AT_END();
5727     return JSValuePtr::encode(result);
5728 }
5729 
cti_op_call_eval(STUB_ARGS)5730 JSValueEncodedAsPointer* Interpreter::cti_op_call_eval(STUB_ARGS)
5731 {
5732     BEGIN_STUB_FUNCTION();
5733 
5734     CallFrame* callFrame = ARG_callFrame;
5735     RegisterFile* registerFile = ARG_registerFile;
5736 
5737     Interpreter* interpreter = ARG_globalData->interpreter;
5738 
5739     JSValuePtr funcVal = ARG_src1;
5740     int registerOffset = ARG_int2;
5741     int argCount = ARG_int3;
5742 
5743     Register* newCallFrame = callFrame->registers() + registerOffset;
5744     Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
5745     JSValuePtr thisValue = argv[0].jsValue(callFrame);
5746     JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
5747 
5748     if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
5749         JSValuePtr exceptionValue = noValue();
5750         JSValuePtr result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
5751         if (UNLIKELY(exceptionValue != noValue())) {
5752             ARG_globalData->exception = exceptionValue;
5753             VM_THROW_EXCEPTION_AT_END();
5754         }
5755         return JSValuePtr::encode(result);
5756     }
5757 
5758     return JSValuePtr::encode(jsImpossibleValue());
5759 }
5760 
cti_op_throw(STUB_ARGS)5761 JSValueEncodedAsPointer* Interpreter::cti_op_throw(STUB_ARGS)
5762 {
5763     BEGIN_STUB_FUNCTION();
5764 
5765     CallFrame* callFrame = ARG_callFrame;
5766     CodeBlock* codeBlock = callFrame->codeBlock();
5767 
5768     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
5769 
5770     JSValuePtr exceptionValue = ARG_src1;
5771     ASSERT(exceptionValue);
5772 
5773     HandlerInfo* handler = ARG_globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, true);
5774 
5775     if (!handler) {
5776         *ARG_exception = exceptionValue;
5777         return JSValuePtr::encode(jsNull());
5778     }
5779 
5780     ARG_setCallFrame(callFrame);
5781     void* catchRoutine = handler->nativeCode;
5782     ASSERT(catchRoutine);
5783     STUB_SET_RETURN_ADDRESS(catchRoutine);
5784     return JSValuePtr::encode(exceptionValue);
5785 }
5786 
cti_op_get_pnames(STUB_ARGS)5787 JSPropertyNameIterator* Interpreter::cti_op_get_pnames(STUB_ARGS)
5788 {
5789     BEGIN_STUB_FUNCTION();
5790 
5791     return JSPropertyNameIterator::create(ARG_callFrame, ARG_src1);
5792 }
5793 
cti_op_next_pname(STUB_ARGS)5794 JSValueEncodedAsPointer* Interpreter::cti_op_next_pname(STUB_ARGS)
5795 {
5796     BEGIN_STUB_FUNCTION();
5797 
5798     JSPropertyNameIterator* it = ARG_pni1;
5799     JSValuePtr temp = it->next(ARG_callFrame);
5800     if (!temp)
5801         it->invalidate();
5802     return JSValuePtr::encode(temp);
5803 }
5804 
cti_op_push_scope(STUB_ARGS)5805 JSObject* Interpreter::cti_op_push_scope(STUB_ARGS)
5806 {
5807     BEGIN_STUB_FUNCTION();
5808 
5809     JSObject* o = ARG_src1.toObject(ARG_callFrame);
5810     CHECK_FOR_EXCEPTION();
5811     ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->push(o));
5812     return o;
5813 }
5814 
cti_op_pop_scope(STUB_ARGS)5815 void Interpreter::cti_op_pop_scope(STUB_ARGS)
5816 {
5817     BEGIN_STUB_FUNCTION();
5818 
5819     ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->pop());
5820 }
5821 
cti_op_typeof(STUB_ARGS)5822 JSValueEncodedAsPointer* Interpreter::cti_op_typeof(STUB_ARGS)
5823 {
5824     BEGIN_STUB_FUNCTION();
5825 
5826     return JSValuePtr::encode(jsTypeStringForValue(ARG_callFrame, ARG_src1));
5827 }
5828 
cti_op_is_undefined(STUB_ARGS)5829 JSValueEncodedAsPointer* Interpreter::cti_op_is_undefined(STUB_ARGS)
5830 {
5831     BEGIN_STUB_FUNCTION();
5832 
5833     JSValuePtr v = ARG_src1;
5834     return JSValuePtr::encode(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()));
5835 }
5836 
cti_op_is_boolean(STUB_ARGS)5837 JSValueEncodedAsPointer* Interpreter::cti_op_is_boolean(STUB_ARGS)
5838 {
5839     BEGIN_STUB_FUNCTION();
5840 
5841     return JSValuePtr::encode(jsBoolean(ARG_src1.isBoolean()));
5842 }
5843 
cti_op_is_number(STUB_ARGS)5844 JSValueEncodedAsPointer* Interpreter::cti_op_is_number(STUB_ARGS)
5845 {
5846     BEGIN_STUB_FUNCTION();
5847 
5848     return JSValuePtr::encode(jsBoolean(ARG_src1.isNumber()));
5849 }
5850 
cti_op_is_string(STUB_ARGS)5851 JSValueEncodedAsPointer* Interpreter::cti_op_is_string(STUB_ARGS)
5852 {
5853     BEGIN_STUB_FUNCTION();
5854 
5855     return JSValuePtr::encode(jsBoolean(ARG_globalData->interpreter->isJSString(ARG_src1)));
5856 }
5857 
cti_op_is_object(STUB_ARGS)5858 JSValueEncodedAsPointer* Interpreter::cti_op_is_object(STUB_ARGS)
5859 {
5860     BEGIN_STUB_FUNCTION();
5861 
5862     return JSValuePtr::encode(jsBoolean(jsIsObjectType(ARG_src1)));
5863 }
5864 
cti_op_is_function(STUB_ARGS)5865 JSValueEncodedAsPointer* Interpreter::cti_op_is_function(STUB_ARGS)
5866 {
5867     BEGIN_STUB_FUNCTION();
5868 
5869     return JSValuePtr::encode(jsBoolean(jsIsFunctionType(ARG_src1)));
5870 }
5871 
cti_op_stricteq(STUB_ARGS)5872 JSValueEncodedAsPointer* Interpreter::cti_op_stricteq(STUB_ARGS)
5873 {
5874     BEGIN_STUB_FUNCTION();
5875 
5876     JSValuePtr src1 = ARG_src1;
5877     JSValuePtr src2 = ARG_src2;
5878 
5879     return JSValuePtr::encode(jsBoolean(JSValuePtr::strictEqual(src1, src2)));
5880 }
5881 
cti_op_nstricteq(STUB_ARGS)5882 JSValueEncodedAsPointer* Interpreter::cti_op_nstricteq(STUB_ARGS)
5883 {
5884     BEGIN_STUB_FUNCTION();
5885 
5886     JSValuePtr src1 = ARG_src1;
5887     JSValuePtr src2 = ARG_src2;
5888 
5889     return JSValuePtr::encode(jsBoolean(!JSValuePtr::strictEqual(src1, src2)));
5890 }
5891 
cti_op_to_jsnumber(STUB_ARGS)5892 JSValueEncodedAsPointer* Interpreter::cti_op_to_jsnumber(STUB_ARGS)
5893 {
5894     BEGIN_STUB_FUNCTION();
5895 
5896     JSValuePtr src = ARG_src1;
5897     CallFrame* callFrame = ARG_callFrame;
5898 
5899     JSValuePtr result = src.toJSNumber(callFrame);
5900     CHECK_FOR_EXCEPTION_AT_END();
5901     return JSValuePtr::encode(result);
5902 }
5903 
cti_op_in(STUB_ARGS)5904 JSValueEncodedAsPointer* Interpreter::cti_op_in(STUB_ARGS)
5905 {
5906     BEGIN_STUB_FUNCTION();
5907 
5908     CallFrame* callFrame = ARG_callFrame;
5909     JSValuePtr baseVal = ARG_src2;
5910 
5911     if (!baseVal.isObject()) {
5912         CallFrame* callFrame = ARG_callFrame;
5913         CodeBlock* codeBlock = callFrame->codeBlock();
5914         unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
5915         ARG_globalData->exception = createInvalidParamError(callFrame, "in", baseVal, vPCIndex, codeBlock);
5916         VM_THROW_EXCEPTION();
5917     }
5918 
5919     JSValuePtr propName = ARG_src1;
5920     JSObject* baseObj = asObject(baseVal);
5921 
5922     uint32_t i;
5923     if (propName.getUInt32(i))
5924         return JSValuePtr::encode(jsBoolean(baseObj->hasProperty(callFrame, i)));
5925 
5926     Identifier property(callFrame, propName.toString(callFrame));
5927     CHECK_FOR_EXCEPTION();
5928     return JSValuePtr::encode(jsBoolean(baseObj->hasProperty(callFrame, property)));
5929 }
5930 
cti_op_push_new_scope(STUB_ARGS)5931 JSObject* Interpreter::cti_op_push_new_scope(STUB_ARGS)
5932 {
5933     BEGIN_STUB_FUNCTION();
5934 
5935     JSObject* scope = new (ARG_globalData) JSStaticScopeObject(ARG_callFrame, *ARG_id1, ARG_src2, DontDelete);
5936 
5937     CallFrame* callFrame = ARG_callFrame;
5938     callFrame->setScopeChain(callFrame->scopeChain()->push(scope));
5939     return scope;
5940 }
5941 
cti_op_jmp_scopes(STUB_ARGS)5942 void Interpreter::cti_op_jmp_scopes(STUB_ARGS)
5943 {
5944     BEGIN_STUB_FUNCTION();
5945 
5946     unsigned count = ARG_int1;
5947     CallFrame* callFrame = ARG_callFrame;
5948 
5949     ScopeChainNode* tmp = callFrame->scopeChain();
5950     while (count--)
5951         tmp = tmp->pop();
5952     callFrame->setScopeChain(tmp);
5953 }
5954 
cti_op_put_by_index(STUB_ARGS)5955 void Interpreter::cti_op_put_by_index(STUB_ARGS)
5956 {
5957     BEGIN_STUB_FUNCTION();
5958 
5959     CallFrame* callFrame = ARG_callFrame;
5960     unsigned property = ARG_int2;
5961 
5962     ARG_src1.put(callFrame, property, ARG_src3);
5963 }
5964 
cti_op_switch_imm(STUB_ARGS)5965 void* Interpreter::cti_op_switch_imm(STUB_ARGS)
5966 {
5967     BEGIN_STUB_FUNCTION();
5968 
5969     JSValuePtr scrutinee = ARG_src1;
5970     unsigned tableIndex = ARG_int2;
5971     CallFrame* callFrame = ARG_callFrame;
5972     CodeBlock* codeBlock = callFrame->codeBlock();
5973 
5974     if (scrutinee.isInt32Fast())
5975         return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.getInt32Fast());
5976     else {
5977         int32_t value;
5978         if (scrutinee.numberToInt32(value))
5979             return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(value);
5980         else
5981             return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault;
5982     }
5983 }
5984 
cti_op_switch_char(STUB_ARGS)5985 void* Interpreter::cti_op_switch_char(STUB_ARGS)
5986 {
5987     BEGIN_STUB_FUNCTION();
5988 
5989     JSValuePtr scrutinee = ARG_src1;
5990     unsigned tableIndex = ARG_int2;
5991     CallFrame* callFrame = ARG_callFrame;
5992     CodeBlock* codeBlock = callFrame->codeBlock();
5993 
5994     void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault;
5995 
5996     if (scrutinee.isString()) {
5997         UString::Rep* value = asString(scrutinee)->value().rep();
5998         if (value->size() == 1)
5999             result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]);
6000     }
6001 
6002     return result;
6003 }
6004 
cti_op_switch_string(STUB_ARGS)6005 void* Interpreter::cti_op_switch_string(STUB_ARGS)
6006 {
6007     BEGIN_STUB_FUNCTION();
6008 
6009     JSValuePtr scrutinee = ARG_src1;
6010     unsigned tableIndex = ARG_int2;
6011     CallFrame* callFrame = ARG_callFrame;
6012     CodeBlock* codeBlock = callFrame->codeBlock();
6013 
6014     void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault;
6015 
6016     if (scrutinee.isString()) {
6017         UString::Rep* value = asString(scrutinee)->value().rep();
6018         result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value);
6019     }
6020 
6021     return result;
6022 }
6023 
cti_op_del_by_val(STUB_ARGS)6024 JSValueEncodedAsPointer* Interpreter::cti_op_del_by_val(STUB_ARGS)
6025 {
6026     BEGIN_STUB_FUNCTION();
6027 
6028     CallFrame* callFrame = ARG_callFrame;
6029 
6030     JSValuePtr baseValue = ARG_src1;
6031     JSObject* baseObj = baseValue.toObject(callFrame); // may throw
6032 
6033     JSValuePtr subscript = ARG_src2;
6034     JSValuePtr result;
6035     uint32_t i;
6036     if (subscript.getUInt32(i))
6037         result = jsBoolean(baseObj->deleteProperty(callFrame, i));
6038     else {
6039         CHECK_FOR_EXCEPTION();
6040         Identifier property(callFrame, subscript.toString(callFrame));
6041         CHECK_FOR_EXCEPTION();
6042         result = jsBoolean(baseObj->deleteProperty(callFrame, property));
6043     }
6044 
6045     CHECK_FOR_EXCEPTION_AT_END();
6046     return JSValuePtr::encode(result);
6047 }
6048 
cti_op_put_getter(STUB_ARGS)6049 void Interpreter::cti_op_put_getter(STUB_ARGS)
6050 {
6051     BEGIN_STUB_FUNCTION();
6052 
6053     CallFrame* callFrame = ARG_callFrame;
6054 
6055     ASSERT(ARG_src1.isObject());
6056     JSObject* baseObj = asObject(ARG_src1);
6057     ASSERT(ARG_src3.isObject());
6058     baseObj->defineGetter(callFrame, *ARG_id2, asObject(ARG_src3));
6059 }
6060 
cti_op_put_setter(STUB_ARGS)6061 void Interpreter::cti_op_put_setter(STUB_ARGS)
6062 {
6063     BEGIN_STUB_FUNCTION();
6064 
6065     CallFrame* callFrame = ARG_callFrame;
6066 
6067     ASSERT(ARG_src1.isObject());
6068     JSObject* baseObj = asObject(ARG_src1);
6069     ASSERT(ARG_src3.isObject());
6070     baseObj->defineSetter(callFrame, *ARG_id2, asObject(ARG_src3));
6071 }
6072 
cti_op_new_error(STUB_ARGS)6073 JSObject* Interpreter::cti_op_new_error(STUB_ARGS)
6074 {
6075     BEGIN_STUB_FUNCTION();
6076 
6077     CallFrame* callFrame = ARG_callFrame;
6078     CodeBlock* codeBlock = callFrame->codeBlock();
6079     unsigned type = ARG_int1;
6080     JSValuePtr message = ARG_src2;
6081     unsigned bytecodeOffset = ARG_int3;
6082 
6083     unsigned lineNumber = codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
6084     return Error::create(callFrame, static_cast<ErrorType>(type), message.toString(callFrame), lineNumber, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
6085 }
6086 
cti_op_debug(STUB_ARGS)6087 void Interpreter::cti_op_debug(STUB_ARGS)
6088 {
6089     BEGIN_STUB_FUNCTION();
6090 
6091     CallFrame* callFrame = ARG_callFrame;
6092 
6093     int debugHookID = ARG_int1;
6094     int firstLine = ARG_int2;
6095     int lastLine = ARG_int3;
6096 
6097     ARG_globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
6098 }
6099 
cti_vm_throw(STUB_ARGS)6100 JSValueEncodedAsPointer* Interpreter::cti_vm_throw(STUB_ARGS)
6101 {
6102     BEGIN_STUB_FUNCTION();
6103 
6104     CallFrame* callFrame = ARG_callFrame;
6105     CodeBlock* codeBlock = callFrame->codeBlock();
6106     JSGlobalData* globalData = ARG_globalData;
6107 
6108     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, globalData->exceptionLocation);
6109 
6110     JSValuePtr exceptionValue = globalData->exception;
6111     ASSERT(exceptionValue);
6112     globalData->exception = noValue();
6113 
6114     HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, false);
6115 
6116     if (!handler) {
6117         *ARG_exception = exceptionValue;
6118         return JSValuePtr::encode(jsNull());
6119     }
6120 
6121     ARG_setCallFrame(callFrame);
6122     void* catchRoutine = handler->nativeCode;
6123     ASSERT(catchRoutine);
6124     STUB_SET_RETURN_ADDRESS(catchRoutine);
6125     return JSValuePtr::encode(exceptionValue);
6126 }
6127 
6128 #undef STUB_RETURN_ADDRESS
6129 #undef STUB_SET_RETURN_ADDRESS
6130 #undef BEGIN_STUB_FUNCTION
6131 #undef CHECK_FOR_EXCEPTION
6132 #undef CHECK_FOR_EXCEPTION_AT_END
6133 #undef CHECK_FOR_EXCEPTION_VOID
6134 #undef VM_THROW_EXCEPTION
6135 #undef VM_THROW_EXCEPTION_2
6136 #undef VM_THROW_EXCEPTION_AT_END
6137 
6138 #endif // ENABLE(JIT)
6139 
6140 } // namespace JSC
6141