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