1/*
2 * Copyright (C) 2008, 2009, 2010, 2012, 2013, 2014 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 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 "CallFrameClosure.h"
36#include "CallFrameInlines.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 "JSBoundFunction.h"
48#include "JSNameScope.h"
49#include "JSNotAnObject.h"
50#include "JSPropertyNameIterator.h"
51#include "JSStackInlines.h"
52#include "JSString.h"
53#include "JSWithScope.h"
54#include "LLIntCLoop.h"
55#include "LLIntThunks.h"
56#include "LegacyProfiler.h"
57#include "LiteralParser.h"
58#include "NameInstance.h"
59#include "ObjectPrototype.h"
60#include "JSCInlines.h"
61#include "Parser.h"
62#include "ProtoCallFrame.h"
63#include "RegExpObject.h"
64#include "RegExpPrototype.h"
65#include "Register.h"
66#include "SamplingTool.h"
67#include "StackAlignment.h"
68#include "StackVisitor.h"
69#include "StrictEvalActivation.h"
70#include "StrongInlines.h"
71#include "VMEntryScope.h"
72#include "VirtualRegister.h"
73
74#include <limits.h>
75#include <stdio.h>
76#include <wtf/StackStats.h>
77#include <wtf/StdLibExtras.h>
78#include <wtf/StringPrintStream.h>
79#include <wtf/Threading.h>
80#include <wtf/WTFThreadData.h>
81#include <wtf/text/StringBuilder.h>
82
83#if ENABLE(JIT)
84#include "JIT.h"
85#endif
86
87#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (!defined(__llvm__))
88
89using namespace std;
90
91namespace JSC {
92
93JSValue eval(CallFrame* callFrame)
94{
95    if (!callFrame->argumentCount())
96        return jsUndefined();
97
98    JSValue program = callFrame->argument(0);
99    if (!program.isString())
100        return program;
101
102    TopCallFrameSetter topCallFrame(callFrame->vm(), callFrame);
103    String programSource = asString(program)->value(callFrame);
104    if (callFrame->hadException())
105        return JSValue();
106
107    CallFrame* callerFrame = callFrame->callerFrame();
108    CodeBlock* callerCodeBlock = callerFrame->codeBlock();
109    JSScope* callerScopeChain = callerFrame->scope();
110    EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(callerCodeBlock->isStrictMode(), programSource, callerScopeChain);
111
112    if (!eval) {
113        if (!callerCodeBlock->isStrictMode()) {
114            // FIXME: We can use the preparser in strict mode, we just need additional logic
115            // to prevent duplicates.
116            if (programSource.is8Bit()) {
117                LiteralParser<LChar> preparser(callFrame, programSource.characters8(), programSource.length(), NonStrictJSON);
118                if (JSValue parsedObject = preparser.tryLiteralParse())
119                    return parsedObject;
120            } else {
121                LiteralParser<UChar> preparser(callFrame, programSource.characters16(), programSource.length(), NonStrictJSON);
122                if (JSValue parsedObject = preparser.tryLiteralParse())
123                    return parsedObject;
124            }
125        }
126
127        // If the literal parser bailed, it should not have thrown exceptions.
128        ASSERT(!callFrame->vm().exception());
129
130        eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->ownerExecutable(), callerCodeBlock->isStrictMode(), programSource, callerScopeChain);
131        if (!eval)
132            return jsUndefined();
133    }
134
135    JSValue thisValue = callerFrame->thisValue();
136    Interpreter* interpreter = callFrame->vm().interpreter;
137    return interpreter->execute(eval, callFrame, thisValue, callerScopeChain);
138}
139
140CallFrame* sizeFrameForVarargs(CallFrame* callFrame, JSStack* stack, JSValue arguments, int firstFreeRegister, uint32_t firstVarArgOffset)
141{
142    if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
143        unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
144        if (argumentCountIncludingThis > firstVarArgOffset)
145            argumentCountIncludingThis -= firstVarArgOffset;
146        else
147            argumentCountIncludingThis = 1;
148        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + argumentCountIncludingThis + JSStack::CallFrameHeaderSize + 1);
149        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
150        if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !stack->ensureCapacityFor(newCallFrame->registers())) {
151            throwStackOverflowError(callFrame);
152            return 0;
153        }
154        return newCallFrame;
155    }
156
157    if (arguments.isUndefinedOrNull()) {
158        unsigned argumentCountIncludingThis = 1;
159        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(),  -firstFreeRegister + argumentCountIncludingThis + JSStack::CallFrameHeaderSize + 1);
160        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
161        if (!stack->ensureCapacityFor(newCallFrame->registers())) {
162            throwStackOverflowError(callFrame);
163            return 0;
164        }
165        return newCallFrame;
166    }
167
168    if (!arguments.isObject()) {
169        callFrame->vm().throwException(callFrame, createInvalidParameterError(callFrame, "Function.prototype.apply", arguments));
170        return 0;
171    }
172
173    if (asObject(arguments)->classInfo() == Arguments::info()) {
174        Arguments* argsObject = asArguments(arguments);
175        unsigned argCount = argsObject->length(callFrame);
176        if (argCount >= firstVarArgOffset)
177            argCount -= firstVarArgOffset;
178        else
179            argCount = 0;
180        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + CallFrame::offsetFor(argCount + 1));
181        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
182        if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
183            throwStackOverflowError(callFrame);
184            return 0;
185        }
186        return newCallFrame;
187    }
188
189    if (isJSArray(arguments)) {
190        JSArray* array = asArray(arguments);
191        unsigned argCount = array->length();
192        if (argCount >= firstVarArgOffset)
193            argCount -= firstVarArgOffset;
194        else
195            argCount = 0;
196        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + CallFrame::offsetFor(argCount + 1));
197        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
198        if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
199            throwStackOverflowError(callFrame);
200            return 0;
201        }
202        return newCallFrame;
203    }
204
205    JSObject* argObject = asObject(arguments);
206    unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
207    if (argCount >= firstVarArgOffset)
208        argCount -= firstVarArgOffset;
209    else
210        argCount = 0;
211    unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + CallFrame::offsetFor(argCount + 1));
212    CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
213    if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
214        throwStackOverflowError(callFrame);
215        return 0;
216    }
217    return newCallFrame;
218}
219
220void loadVarargs(CallFrame* callFrame, CallFrame* newCallFrame, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset)
221{
222    if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
223        unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
224        if (argumentCountIncludingThis > firstVarArgOffset)
225            argumentCountIncludingThis -= firstVarArgOffset;
226        else
227            argumentCountIncludingThis = 1;
228        newCallFrame->setArgumentCountIncludingThis(argumentCountIncludingThis);
229        newCallFrame->setThisValue(thisValue);
230        for (size_t i = firstVarArgOffset; i < callFrame->argumentCount(); ++i)
231            newCallFrame->setArgument(i - firstVarArgOffset, callFrame->argumentAfterCapture(i));
232        return;
233    }
234
235    if (arguments.isUndefinedOrNull()) {
236        newCallFrame->setArgumentCountIncludingThis(1);
237        newCallFrame->setThisValue(thisValue);
238        return;
239    }
240
241    if (asObject(arguments)->classInfo() == Arguments::info()) {
242        Arguments* argsObject = asArguments(arguments);
243        unsigned argCount = argsObject->length(callFrame);
244        if (argCount >= firstVarArgOffset) {
245            argCount -= firstVarArgOffset;
246            newCallFrame->setArgumentCountIncludingThis(argCount + 1);
247            argsObject->copyToArguments(callFrame, newCallFrame, argCount, firstVarArgOffset);
248        } else
249            newCallFrame->setArgumentCountIncludingThis(1);
250        newCallFrame->setThisValue(thisValue);
251        return;
252    }
253
254    if (isJSArray(arguments)) {
255        JSArray* array = asArray(arguments);
256        unsigned argCount = array->length();
257        if (argCount >= firstVarArgOffset) {
258            argCount -= firstVarArgOffset;
259            newCallFrame->setArgumentCountIncludingThis(argCount + 1);
260            array->copyToArguments(callFrame, newCallFrame, argCount, firstVarArgOffset);
261        } else
262            newCallFrame->setArgumentCountIncludingThis(1);
263        newCallFrame->setThisValue(thisValue);
264        return;
265    }
266
267    JSObject* argObject = asObject(arguments);
268    unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
269    if (argCount >= firstVarArgOffset) {
270        argCount -= firstVarArgOffset;
271        newCallFrame->setArgumentCountIncludingThis(argCount + 1);
272    } else
273        newCallFrame->setArgumentCountIncludingThis(1);
274
275    newCallFrame->setThisValue(thisValue);
276    for (size_t i = 0; i < argCount; ++i) {
277        newCallFrame->setArgument(i, asObject(arguments)->get(callFrame, i + firstVarArgOffset));
278        if (UNLIKELY(callFrame->vm().exception()))
279            return;
280    }
281}
282
283Interpreter::Interpreter(VM& vm)
284    : m_sampleEntryDepth(0)
285    , m_vm(vm)
286    , m_stack(vm)
287    , m_errorHandlingModeReentry(0)
288#if !ASSERT_DISABLED
289    , m_initialized(false)
290#endif
291{
292}
293
294Interpreter::~Interpreter()
295{
296}
297
298void Interpreter::initialize(bool canUseJIT)
299{
300    UNUSED_PARAM(canUseJIT);
301
302#if ENABLE(COMPUTED_GOTO_OPCODES)
303    m_opcodeTable = LLInt::opcodeMap();
304    for (int i = 0; i < numOpcodeIDs; ++i)
305        m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
306#endif
307
308#if !ASSERT_DISABLED
309    m_initialized = true;
310#endif
311
312#if ENABLE(OPCODE_SAMPLING)
313    enableSampler();
314#endif
315}
316
317#ifdef NDEBUG
318
319void Interpreter::dumpCallFrame(CallFrame*)
320{
321}
322
323#else
324
325void Interpreter::dumpCallFrame(CallFrame* callFrame)
326{
327    callFrame->codeBlock()->dumpBytecode();
328    dumpRegisters(callFrame);
329}
330
331class DumpRegisterFunctor {
332public:
333    DumpRegisterFunctor(const Register*& it)
334        : m_hasSkippedFirstFrame(false)
335        , m_it(it)
336    {
337    }
338
339    StackVisitor::Status operator()(StackVisitor& visitor)
340    {
341        if (!m_hasSkippedFirstFrame) {
342            m_hasSkippedFirstFrame = true;
343            return StackVisitor::Continue;
344        }
345
346        unsigned line = 0;
347        unsigned unusedColumn = 0;
348        visitor->computeLineAndColumn(line, unusedColumn);
349        dataLogF("[ReturnVPC]                | %10p | %d (line %d)\n", m_it, visitor->bytecodeOffset(), line);
350        --m_it;
351        return StackVisitor::Done;
352    }
353
354private:
355    bool m_hasSkippedFirstFrame;
356    const Register*& m_it;
357};
358
359void Interpreter::dumpRegisters(CallFrame* callFrame)
360{
361    dataLogF("Register frame: \n\n");
362    dataLogF("-----------------------------------------------------------------------------\n");
363    dataLogF("            use            |   address  |                value               \n");
364    dataLogF("-----------------------------------------------------------------------------\n");
365
366    CodeBlock* codeBlock = callFrame->codeBlock();
367    const Register* it;
368    const Register* end;
369
370    it = callFrame->registers() + JSStack::ThisArgument + callFrame->argumentCount();
371    end = callFrame->registers() + JSStack::ThisArgument - 1;
372    while (it > end) {
373        JSValue v = it->jsValue();
374        int registerNumber = it - callFrame->registers();
375        String name = codeBlock->nameForRegister(VirtualRegister(registerNumber));
376        dataLogF("[r% 3d %14s]      | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, toCString(v).data(), (long long)JSValue::encode(v));
377        --it;
378    }
379
380    dataLogF("-----------------------------------------------------------------------------\n");
381    dataLogF("[ArgumentCount]            | %10p | %lu \n", it, (unsigned long) callFrame->argumentCount());
382    --it;
383    dataLogF("[CallerFrame]              | %10p | %p \n", it, callFrame->callerFrame());
384    --it;
385    dataLogF("[Callee]                   | %10p | %p \n", it, callFrame->callee());
386    --it;
387    dataLogF("[ScopeChain]               | %10p | %p \n", it, callFrame->scope());
388    --it;
389#if ENABLE(JIT)
390    AbstractPC pc = callFrame->abstractReturnPC(callFrame->vm());
391    if (pc.hasJITReturnAddress())
392        dataLogF("[ReturnJITPC]              | %10p | %p \n", it, pc.jitReturnAddress().value());
393#endif
394
395    DumpRegisterFunctor functor(it);
396    callFrame->iterate(functor);
397
398    dataLogF("[CodeBlock]                | %10p | %p \n", it, callFrame->codeBlock());
399    --it;
400    dataLogF("-----------------------------------------------------------------------------\n");
401
402    end = it - codeBlock->m_numVars;
403    if (it != end) {
404        do {
405            JSValue v = it->jsValue();
406            int registerNumber = it - callFrame->registers();
407            String name = codeBlock->nameForRegister(VirtualRegister(registerNumber));
408            dataLogF("[r% 3d %14s]      | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, toCString(v).data(), (long long)JSValue::encode(v));
409            --it;
410        } while (it != end);
411    }
412    dataLogF("-----------------------------------------------------------------------------\n");
413
414    end = it - codeBlock->m_numCalleeRegisters + codeBlock->m_numVars;
415    if (it != end) {
416        do {
417            JSValue v = (*it).jsValue();
418            int registerNumber = it - callFrame->registers();
419            dataLogF("[r% 3d]                     | %10p | %-16s 0x%lld \n", registerNumber, it, toCString(v).data(), (long long)JSValue::encode(v));
420            --it;
421        } while (it != end);
422    }
423    dataLogF("-----------------------------------------------------------------------------\n");
424}
425
426#endif
427
428bool Interpreter::isOpcode(Opcode opcode)
429{
430#if ENABLE(COMPUTED_GOTO_OPCODES)
431    return opcode != HashTraits<Opcode>::emptyValue()
432        && !HashTraits<Opcode>::isDeletedValue(opcode)
433        && m_opcodeIDTable.contains(opcode);
434#else
435    return opcode >= 0 && opcode <= op_end;
436#endif
437}
438
439static bool unwindCallFrame(StackVisitor& visitor)
440{
441    CallFrame* callFrame = visitor->callFrame();
442    CodeBlock* codeBlock = visitor->codeBlock();
443    JSScope* scope = callFrame->scope();
444
445    if (Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger()) {
446        ClearExceptionScope scope(&callFrame->vm());
447        if (callFrame->callee())
448            debugger->returnEvent(callFrame);
449        else
450            debugger->didExecuteProgram(callFrame);
451        ASSERT(!callFrame->hadException());
452    }
453
454    JSValue activation;
455    if (codeBlock->codeType() == FunctionCode && codeBlock->needsActivation()) {
456#if ENABLE(DFG_JIT)
457        RELEASE_ASSERT(!visitor->isInlinedFrame());
458#endif
459        activation = callFrame->uncheckedActivation();
460        // Protect against the activation not being created, or the variable still being
461        // initialized to Undefined inside op_enter.
462        if (activation && activation.isCell()) {
463            JSActivation* activationObject = jsCast<JSActivation*>(activation);
464            // Protect against throwing exceptions after tear-off.
465            if (!activationObject->isTornOff())
466                activationObject->tearOff(*scope->vm());
467        }
468    }
469
470    if (codeBlock->codeType() == FunctionCode && codeBlock->usesArguments()) {
471        if (Arguments* arguments = visitor->existingArguments()) {
472            if (activation && activation.isCell())
473                arguments->didTearOffActivation(callFrame, jsCast<JSActivation*>(activation));
474#if ENABLE(DFG_JIT)
475            else if (visitor->isInlinedFrame())
476                arguments->tearOff(callFrame, visitor->inlineCallFrame());
477#endif
478            else
479                arguments->tearOff(callFrame);
480        }
481    }
482
483    CallFrame* callerFrame = callFrame->callerFrame();
484    return !callerFrame->isVMEntrySentinel();
485}
486
487static StackFrameCodeType getStackFrameCodeType(StackVisitor& visitor)
488{
489    switch (visitor->codeType()) {
490    case StackVisitor::Frame::Eval:
491        return StackFrameEvalCode;
492    case StackVisitor::Frame::Function:
493        return StackFrameFunctionCode;
494    case StackVisitor::Frame::Global:
495        return StackFrameGlobalCode;
496    case StackVisitor::Frame::Native:
497        ASSERT_NOT_REACHED();
498        return StackFrameNativeCode;
499    }
500    RELEASE_ASSERT_NOT_REACHED();
501    return StackFrameGlobalCode;
502}
503
504void StackFrame::computeLineAndColumn(unsigned& line, unsigned& column)
505{
506    if (!codeBlock) {
507        line = 0;
508        column = 0;
509        return;
510    }
511
512    int divot = 0;
513    int unusedStartOffset = 0;
514    int unusedEndOffset = 0;
515    unsigned divotLine = 0;
516    unsigned divotColumn = 0;
517    expressionInfo(divot, unusedStartOffset, unusedEndOffset, divotLine, divotColumn);
518
519    line = divotLine + lineOffset;
520    column = divotColumn + (divotLine ? 1 : firstLineColumnOffset);
521}
522
523void StackFrame::expressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
524{
525    codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
526    divot += characterOffset;
527}
528
529String StackFrame::toString(CallFrame* callFrame)
530{
531    StringBuilder traceBuild;
532    String functionName = friendlyFunctionName(callFrame);
533    String sourceURL = friendlySourceURL();
534    traceBuild.append(functionName);
535    if (!sourceURL.isEmpty()) {
536        if (!functionName.isEmpty())
537            traceBuild.append('@');
538        traceBuild.append(sourceURL);
539        if (codeType != StackFrameNativeCode) {
540            unsigned line;
541            unsigned column;
542            computeLineAndColumn(line, column);
543
544            traceBuild.append(':');
545            traceBuild.appendNumber(line);
546            traceBuild.append(':');
547            traceBuild.appendNumber(column);
548        }
549    }
550    return traceBuild.toString().impl();
551}
552
553class GetStackTraceFunctor {
554public:
555    GetStackTraceFunctor(VM& vm, Vector<StackFrame>& results, size_t remainingCapacity)
556        : m_vm(vm)
557        , m_results(results)
558        , m_remainingCapacityForFrameCapture(remainingCapacity)
559    {
560    }
561
562    StackVisitor::Status operator()(StackVisitor& visitor)
563    {
564        VM& vm = m_vm;
565        if (m_remainingCapacityForFrameCapture) {
566            if (visitor->isJSFrame() && !visitor->codeBlock()->unlinkedCodeBlock()->isBuiltinFunction()) {
567                CodeBlock* codeBlock = visitor->codeBlock();
568                StackFrame s = {
569                    Strong<JSObject>(vm, visitor->callee()),
570                    getStackFrameCodeType(visitor),
571                    Strong<ExecutableBase>(vm, codeBlock->ownerExecutable()),
572                    Strong<UnlinkedCodeBlock>(vm, codeBlock->unlinkedCodeBlock()),
573                    codeBlock->source(),
574                    codeBlock->ownerExecutable()->lineNo(),
575                    codeBlock->firstLineColumnOffset(),
576                    codeBlock->sourceOffset(),
577                    visitor->bytecodeOffset(),
578                    visitor->sourceURL()
579                };
580                m_results.append(s);
581            } else {
582                StackFrame s = { Strong<JSObject>(vm, visitor->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), Strong<UnlinkedCodeBlock>(), 0, 0, 0, 0, 0, String()};
583                m_results.append(s);
584            }
585
586            m_remainingCapacityForFrameCapture--;
587            return StackVisitor::Continue;
588        }
589        return StackVisitor::Done;
590    }
591
592private:
593    VM& m_vm;
594    Vector<StackFrame>& m_results;
595    size_t m_remainingCapacityForFrameCapture;
596};
597
598void Interpreter::getStackTrace(Vector<StackFrame>& results, size_t maxStackSize)
599{
600    VM& vm = m_vm;
601    ASSERT(!vm.topCallFrame->isVMEntrySentinel());
602    CallFrame* callFrame = vm.topCallFrame;
603    if (!callFrame)
604        return;
605
606    GetStackTraceFunctor functor(vm, results, maxStackSize);
607    callFrame->iterate(functor);
608}
609
610JSString* Interpreter::stackTraceAsString(ExecState* exec, Vector<StackFrame> stackTrace)
611{
612    // FIXME: JSStringJoiner could be more efficient than StringBuilder here.
613    StringBuilder builder;
614    for (unsigned i = 0; i < stackTrace.size(); i++) {
615        builder.append(String(stackTrace[i].toString(exec)));
616        if (i != stackTrace.size() - 1)
617            builder.append('\n');
618    }
619    return jsString(&exec->vm(), builder.toString());
620}
621
622class GetExceptionHandlerFunctor {
623public:
624    GetExceptionHandlerFunctor()
625        : m_handler(0)
626    {
627    }
628
629    HandlerInfo* handler() { return m_handler; }
630
631    StackVisitor::Status operator()(StackVisitor& visitor)
632    {
633        CodeBlock* codeBlock = visitor->codeBlock();
634        if (!codeBlock)
635            return StackVisitor::Continue;
636
637        unsigned bytecodeOffset = visitor->bytecodeOffset();
638        m_handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
639        if (m_handler)
640            return StackVisitor::Done;
641
642        return StackVisitor::Continue;
643    }
644
645private:
646    HandlerInfo* m_handler;
647};
648
649class UnwindFunctor {
650public:
651    UnwindFunctor(CallFrame*& callFrame, bool isTermination, CodeBlock*& codeBlock, HandlerInfo*& handler)
652        : m_callFrame(callFrame)
653        , m_isTermination(isTermination)
654        , m_codeBlock(codeBlock)
655        , m_handler(handler)
656    {
657    }
658
659    StackVisitor::Status operator()(StackVisitor& visitor)
660    {
661        VM& vm = m_callFrame->vm();
662        m_callFrame = visitor->callFrame();
663        m_codeBlock = visitor->codeBlock();
664        unsigned bytecodeOffset = visitor->bytecodeOffset();
665
666        if (m_isTermination || !(m_handler = m_codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
667            if (!unwindCallFrame(visitor)) {
668                if (LegacyProfiler* profiler = vm.enabledProfiler())
669                    profiler->exceptionUnwind(m_callFrame);
670                return StackVisitor::Done;
671            }
672        } else
673            return StackVisitor::Done;
674
675        return StackVisitor::Continue;
676    }
677
678private:
679    CallFrame*& m_callFrame;
680    bool m_isTermination;
681    CodeBlock*& m_codeBlock;
682    HandlerInfo*& m_handler;
683};
684
685NEVER_INLINE HandlerInfo* Interpreter::unwind(CallFrame*& callFrame, JSValue& exceptionValue)
686{
687    if (callFrame->isVMEntrySentinel()) {
688        // This happens when we throw stack overflow in a function that is called
689        // directly from callToJavaScript. Stack overflow throws the exception in the
690        // context of the caller. In that case the caller is the sentinel frame. The
691        // right thing to do is to pretend that the exception is uncaught so that we
692        // go to the uncaught exception handler, which returns through callToJavaScript.
693        return 0;
694    }
695
696    CodeBlock* codeBlock = callFrame->codeBlock();
697    ASSERT(codeBlock);
698    bool isTermination = false;
699
700    ASSERT(!exceptionValue.isEmpty());
701    ASSERT(!exceptionValue.isCell() || exceptionValue.asCell());
702    // This shouldn't be possible (hence the assertions), but we're already in the slowest of
703    // slow cases, so let's harden against it anyway to be safe.
704    if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
705        exceptionValue = jsNull();
706
707    if (exceptionValue.isObject())
708        isTermination = isTerminatedExecutionException(asObject(exceptionValue));
709
710    ASSERT(callFrame->vm().exceptionStack().size());
711
712    Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger();
713    if (debugger && debugger->needsExceptionCallbacks()) {
714        // We need to clear the exception and the exception stack here in order to see if a new exception happens.
715        // Afterwards, the values are put back to continue processing this error.
716        ClearExceptionScope scope(&callFrame->vm());
717        // This code assumes that if the debugger is enabled then there is no inlining.
718        // If that assumption turns out to be false then we'll ignore the inlined call
719        // frames.
720        // https://bugs.webkit.org/show_bug.cgi?id=121754
721
722        bool hasHandler;
723        if (isTermination)
724            hasHandler = false;
725        else {
726            GetExceptionHandlerFunctor functor;
727            callFrame->iterate(functor);
728            hasHandler = !!functor.handler();
729        }
730
731        debugger->exception(callFrame, exceptionValue, hasHandler);
732        ASSERT(!callFrame->hadException());
733    }
734
735    // Calculate an exception handler vPC, unwinding call frames as necessary.
736    HandlerInfo* handler = 0;
737    VM& vm = callFrame->vm();
738    ASSERT(callFrame == vm.topCallFrame);
739    UnwindFunctor functor(callFrame, isTermination, codeBlock, handler);
740    callFrame->iterate(functor);
741    if (!handler)
742        return 0;
743
744    if (LegacyProfiler* profiler = vm.enabledProfiler())
745        profiler->exceptionUnwind(callFrame);
746
747    // Unwind the scope chain within the exception handler's call frame.
748    int targetScopeDepth = handler->scopeDepth;
749    if (codeBlock->needsActivation() && callFrame->hasActivation())
750        ++targetScopeDepth;
751
752    JSScope* scope = callFrame->scope();
753    int scopeDelta = scope->depth() - targetScopeDepth;
754    RELEASE_ASSERT(scopeDelta >= 0);
755
756    while (scopeDelta--)
757        scope = scope->next();
758    callFrame->setScope(scope);
759
760    return handler;
761}
762
763static inline JSValue checkedReturn(JSValue returnValue)
764{
765    ASSERT(returnValue);
766    return returnValue;
767}
768
769static inline JSObject* checkedReturn(JSObject* returnValue)
770{
771    ASSERT(returnValue);
772    return returnValue;
773}
774
775class SamplingScope {
776public:
777    SamplingScope(Interpreter* interpreter)
778        : m_interpreter(interpreter)
779    {
780        interpreter->startSampling();
781    }
782    ~SamplingScope()
783    {
784        m_interpreter->stopSampling();
785    }
786private:
787    Interpreter* m_interpreter;
788};
789
790JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, JSObject* thisObj)
791{
792    SamplingScope samplingScope(this);
793
794    JSScope* scope = callFrame->scope();
795    VM& vm = *scope->vm();
796
797    ASSERT(!vm.exception());
798    ASSERT(!vm.isCollectorBusy());
799    RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
800    if (vm.isCollectorBusy())
801        return jsNull();
802
803    if (!vm.isSafeToRecurse())
804        return checkedReturn(throwStackOverflowError(callFrame));
805
806    // First check if the "program" is actually just a JSON object. If so,
807    // we'll handle the JSON object here. Else, we'll handle real JS code
808    // below at failedJSONP.
809
810    Vector<JSONPData> JSONPData;
811    bool parseResult;
812    const String programSource = program->source().toString();
813    if (programSource.isNull())
814        return jsUndefined();
815    if (programSource.is8Bit()) {
816        LiteralParser<LChar> literalParser(callFrame, programSource.characters8(), programSource.length(), JSONP);
817        parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
818    } else {
819        LiteralParser<UChar> literalParser(callFrame, programSource.characters16(), programSource.length(), JSONP);
820        parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
821    }
822
823    if (parseResult) {
824        JSGlobalObject* globalObject = scope->globalObject();
825        JSValue result;
826        for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
827            Vector<JSONPPathEntry> JSONPPath;
828            JSONPPath.swap(JSONPData[entry].m_path);
829            JSValue JSONPValue = JSONPData[entry].m_value.get();
830            if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclare) {
831                globalObject->addVar(callFrame, JSONPPath[0].m_pathEntryName);
832                PutPropertySlot slot(globalObject);
833                globalObject->methodTable()->put(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
834                result = jsUndefined();
835                continue;
836            }
837            JSValue baseObject(globalObject);
838            for (unsigned i = 0; i < JSONPPath.size() - 1; i++) {
839                ASSERT(JSONPPath[i].m_type != JSONPPathEntryTypeDeclare);
840                switch (JSONPPath[i].m_type) {
841                case JSONPPathEntryTypeDot: {
842                    if (i == 0) {
843                        PropertySlot slot(globalObject);
844                        if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
845                            if (entry)
846                                return callFrame->vm().throwException(callFrame, createUndefinedVariableError(globalObject->globalExec(), JSONPPath[i].m_pathEntryName));
847                            goto failedJSONP;
848                        }
849                        baseObject = slot.getValue(callFrame, JSONPPath[i].m_pathEntryName);
850                    } else
851                        baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathEntryName);
852                    if (callFrame->hadException())
853                        return jsUndefined();
854                    continue;
855                }
856                case JSONPPathEntryTypeLookup: {
857                    baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
858                    if (callFrame->hadException())
859                        return jsUndefined();
860                    continue;
861                }
862                default:
863                    RELEASE_ASSERT_NOT_REACHED();
864                    return jsUndefined();
865                }
866            }
867            PutPropertySlot slot(baseObject);
868            switch (JSONPPath.last().m_type) {
869            case JSONPPathEntryTypeCall: {
870                JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
871                if (callFrame->hadException())
872                    return jsUndefined();
873                CallData callData;
874                CallType callType = getCallData(function, callData);
875                if (callType == CallTypeNone)
876                    return callFrame->vm().throwException(callFrame, createNotAFunctionError(callFrame, function));
877                MarkedArgumentBuffer jsonArg;
878                jsonArg.append(JSONPValue);
879                JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined(): baseObject;
880                JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg);
881                if (callFrame->hadException())
882                    return jsUndefined();
883                break;
884            }
885            case JSONPPathEntryTypeDot: {
886                baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
887                if (callFrame->hadException())
888                    return jsUndefined();
889                break;
890            }
891            case JSONPPathEntryTypeLookup: {
892                baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
893                if (callFrame->hadException())
894                    return jsUndefined();
895                break;
896            }
897            default:
898                RELEASE_ASSERT_NOT_REACHED();
899                    return jsUndefined();
900            }
901            result = JSONPValue;
902        }
903        return result;
904    }
905failedJSONP:
906    // If we get here, then we have already proven that the script is not a JSON
907    // object.
908
909    VMEntryScope entryScope(vm, scope->globalObject());
910
911    // Compile source to bytecode if necessary:
912    if (JSObject* error = program->initializeGlobalProperties(vm, callFrame, scope))
913        return checkedReturn(callFrame->vm().throwException(callFrame, error));
914
915    if (JSObject* error = program->prepareForExecution(callFrame, nullptr, &scope, CodeForCall))
916        return checkedReturn(callFrame->vm().throwException(callFrame, error));
917
918    ProgramCodeBlock* codeBlock = program->codeBlock();
919
920    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
921        return throwTerminatedExecutionException(callFrame);
922
923    ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
924
925    ProtoCallFrame protoCallFrame;
926    protoCallFrame.init(codeBlock, scope, 0, thisObj, 1);
927
928    if (LegacyProfiler* profiler = vm.enabledProfiler())
929        profiler->willExecute(callFrame, program->sourceURL(), program->lineNo(), program->startColumn());
930
931    // Execute the code:
932    JSValue result;
933    {
934        SamplingTool::CallRecord callRecord(m_sampler.get());
935        Watchdog::Scope watchdogScope(vm.watchdog.get());
936
937        result = program->generatedJITCode()->execute(&vm, &protoCallFrame);
938    }
939
940    if (LegacyProfiler* profiler = vm.enabledProfiler())
941        profiler->didExecute(callFrame, program->sourceURL(), program->lineNo(), program->startColumn());
942
943    return checkedReturn(result);
944}
945
946JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
947{
948    VM& vm = callFrame->vm();
949    ASSERT(!callFrame->hadException());
950    ASSERT(!vm.isCollectorBusy());
951    if (vm.isCollectorBusy())
952        return jsNull();
953
954    bool isJSCall = (callType == CallTypeJS);
955    JSScope* scope;
956    CodeBlock* newCodeBlock;
957    size_t argsCount = 1 + args.size(); // implicit "this" parameter
958
959    if (isJSCall)
960        scope = callData.js.scope;
961    else {
962        ASSERT(callType == CallTypeHost);
963        scope = callFrame->scope();
964    }
965
966    VMEntryScope entryScope(vm, scope->globalObject());
967    if (!vm.isSafeToRecurse())
968        return checkedReturn(throwStackOverflowError(callFrame));
969
970    if (isJSCall) {
971        // Compile the callee:
972        JSObject* compileError = callData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(function), &scope, CodeForCall);
973        if (UNLIKELY(!!compileError)) {
974            return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
975        }
976        newCodeBlock = callData.js.functionExecutable->codeBlockForCall();
977        ASSERT(!!newCodeBlock);
978        newCodeBlock->m_shouldAlwaysBeInlined = false;
979    } else
980        newCodeBlock = 0;
981
982    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
983        return throwTerminatedExecutionException(callFrame);
984
985    ProtoCallFrame protoCallFrame;
986    protoCallFrame.init(newCodeBlock, scope, function, thisValue, argsCount, args.data());
987
988    if (LegacyProfiler* profiler = vm.enabledProfiler())
989        profiler->willExecute(callFrame, function);
990
991    JSValue result;
992    {
993        SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSCall);
994        Watchdog::Scope watchdogScope(vm.watchdog.get());
995
996        // Execute the code:
997        if (isJSCall)
998            result = callData.js.functionExecutable->generatedJITCodeForCall()->execute(&vm, &protoCallFrame);
999        else {
1000            result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(callData.native.function), &vm, &protoCallFrame));
1001            if (callFrame->hadException())
1002                result = jsNull();
1003        }
1004    }
1005
1006    if (LegacyProfiler* profiler = vm.enabledProfiler())
1007        profiler->didExecute(callFrame, function);
1008
1009    return checkedReturn(result);
1010}
1011
1012JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
1013{
1014    VM& vm = callFrame->vm();
1015    ASSERT(!callFrame->hadException());
1016    ASSERT(!vm.isCollectorBusy());
1017    // We throw in this case because we have to return something "valid" but we're
1018    // already in an invalid state.
1019    if (vm.isCollectorBusy())
1020        return checkedReturn(throwStackOverflowError(callFrame));
1021
1022    bool isJSConstruct = (constructType == ConstructTypeJS);
1023    JSScope* scope;
1024    CodeBlock* newCodeBlock;
1025    size_t argsCount = 1 + args.size(); // implicit "this" parameter
1026
1027    if (isJSConstruct)
1028        scope = constructData.js.scope;
1029    else {
1030        ASSERT(constructType == ConstructTypeHost);
1031        scope = callFrame->scope();
1032    }
1033
1034    VMEntryScope entryScope(vm, scope->globalObject());
1035    if (!vm.isSafeToRecurse())
1036        return checkedReturn(throwStackOverflowError(callFrame));
1037
1038    if (isJSConstruct) {
1039        // Compile the callee:
1040        JSObject* compileError = constructData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(constructor), &scope, CodeForConstruct);
1041        if (UNLIKELY(!!compileError)) {
1042            return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
1043        }
1044        newCodeBlock = constructData.js.functionExecutable->codeBlockForConstruct();
1045        ASSERT(!!newCodeBlock);
1046        newCodeBlock->m_shouldAlwaysBeInlined = false;
1047    } else
1048        newCodeBlock = 0;
1049
1050    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
1051        return throwTerminatedExecutionException(callFrame);
1052
1053    ProtoCallFrame protoCallFrame;
1054    protoCallFrame.init(newCodeBlock, scope, constructor, jsUndefined(), argsCount, args.data());
1055
1056    if (LegacyProfiler* profiler = vm.enabledProfiler())
1057        profiler->willExecute(callFrame, constructor);
1058
1059    JSValue result;
1060    {
1061        SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSConstruct);
1062        Watchdog::Scope watchdogScope(vm.watchdog.get());
1063
1064        // Execute the code.
1065        if (isJSConstruct)
1066            result = constructData.js.functionExecutable->generatedJITCodeForConstruct()->execute(&vm, &protoCallFrame);
1067        else {
1068            result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(constructData.native.function), &vm, &protoCallFrame));
1069
1070            if (!callFrame->hadException())
1071                RELEASE_ASSERT(result.isObject());
1072        }
1073    }
1074
1075    if (LegacyProfiler* profiler = vm.enabledProfiler())
1076        profiler->didExecute(callFrame, constructor);
1077
1078    if (callFrame->hadException())
1079        return 0;
1080    ASSERT(result.isObject());
1081    return checkedReturn(asObject(result));
1082}
1083
1084CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, ProtoCallFrame* protoCallFrame, JSFunction* function, int argumentCountIncludingThis, JSScope* scope, JSValue* args)
1085{
1086    VM& vm = *scope->vm();
1087    ASSERT(!vm.exception());
1088
1089    if (vm.isCollectorBusy())
1090        return CallFrameClosure();
1091
1092    // Compile the callee:
1093    JSObject* error = functionExecutable->prepareForExecution(callFrame, function, &scope, CodeForCall);
1094    if (error) {
1095        callFrame->vm().throwException(callFrame, error);
1096        return CallFrameClosure();
1097    }
1098    CodeBlock* newCodeBlock = functionExecutable->codeBlockForCall();
1099    newCodeBlock->m_shouldAlwaysBeInlined = false;
1100
1101    size_t argsCount = argumentCountIncludingThis;
1102
1103    protoCallFrame->init(newCodeBlock, scope, function, jsUndefined(), argsCount, args);
1104    // Return the successful closure:
1105    CallFrameClosure result = { callFrame, protoCallFrame, function, functionExecutable, &vm, scope, newCodeBlock->numParameters(), argumentCountIncludingThis };
1106    return result;
1107}
1108
1109JSValue Interpreter::execute(CallFrameClosure& closure)
1110{
1111    VM& vm = *closure.vm;
1112    SamplingScope samplingScope(this);
1113
1114    ASSERT(!vm.isCollectorBusy());
1115    RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
1116    if (vm.isCollectorBusy())
1117        return jsNull();
1118
1119    StackStats::CheckPoint stackCheckPoint;
1120    closure.resetCallFrame();
1121
1122    if (LegacyProfiler* profiler = vm.enabledProfiler())
1123        profiler->willExecute(closure.oldCallFrame, closure.function);
1124
1125    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(closure.oldCallFrame)))
1126        return throwTerminatedExecutionException(closure.oldCallFrame);
1127
1128    // Execute the code:
1129    JSValue result;
1130    {
1131        SamplingTool::CallRecord callRecord(m_sampler.get());
1132        Watchdog::Scope watchdogScope(vm.watchdog.get());
1133
1134        result = closure.functionExecutable->generatedJITCodeForCall()->execute(&vm, closure.protoCallFrame);
1135    }
1136
1137    if (LegacyProfiler* profiler = vm.enabledProfiler())
1138        profiler->didExecute(closure.oldCallFrame, closure.function);
1139
1140    return checkedReturn(result);
1141}
1142
1143JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, JSScope* scope)
1144{
1145    VM& vm = *scope->vm();
1146    SamplingScope samplingScope(this);
1147
1148    ASSERT(scope->vm() == &callFrame->vm());
1149    ASSERT(!vm.exception());
1150    ASSERT(!vm.isCollectorBusy());
1151    RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
1152    if (vm.isCollectorBusy())
1153        return jsNull();
1154
1155    VMEntryScope entryScope(vm, scope->globalObject());
1156    if (!vm.isSafeToRecurse())
1157        return checkedReturn(throwStackOverflowError(callFrame));
1158
1159    unsigned numVariables = eval->numVariables();
1160    int numFunctions = eval->numberOfFunctionDecls();
1161
1162    JSScope* variableObject;
1163    if ((numVariables || numFunctions) && eval->isStrictMode()) {
1164        scope = StrictEvalActivation::create(callFrame);
1165        variableObject = scope;
1166    } else {
1167        for (JSScope* node = scope; ; node = node->next()) {
1168            RELEASE_ASSERT(node);
1169            if (node->isVariableObject() && !node->isNameScopeObject()) {
1170                variableObject = node;
1171                break;
1172            }
1173        }
1174    }
1175
1176    JSObject* compileError = eval->prepareForExecution(callFrame, nullptr, &scope, CodeForCall);
1177    if (UNLIKELY(!!compileError))
1178        return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
1179    EvalCodeBlock* codeBlock = eval->codeBlock();
1180
1181    if (numVariables || numFunctions) {
1182        BatchedTransitionOptimizer optimizer(vm, variableObject);
1183        if (variableObject->next())
1184            variableObject->globalObject()->varInjectionWatchpoint()->fireAll();
1185
1186        for (unsigned i = 0; i < numVariables; ++i) {
1187            const Identifier& ident = codeBlock->variable(i);
1188            if (!variableObject->hasProperty(callFrame, ident)) {
1189                PutPropertySlot slot(variableObject);
1190                variableObject->methodTable()->put(variableObject, callFrame, ident, jsUndefined(), slot);
1191            }
1192        }
1193
1194        for (int i = 0; i < numFunctions; ++i) {
1195            FunctionExecutable* function = codeBlock->functionDecl(i);
1196            PutPropertySlot slot(variableObject);
1197            variableObject->methodTable()->put(variableObject, callFrame, function->name(), JSFunction::create(vm, function, scope), slot);
1198        }
1199    }
1200
1201    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
1202        return throwTerminatedExecutionException(callFrame);
1203
1204    ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1205
1206    ProtoCallFrame protoCallFrame;
1207    protoCallFrame.init(codeBlock, scope, 0, thisValue, 1);
1208
1209    if (LegacyProfiler* profiler = vm.enabledProfiler())
1210        profiler->willExecute(callFrame, eval->sourceURL(), eval->lineNo(), eval->startColumn());
1211
1212    // Execute the code:
1213    JSValue result;
1214    {
1215        SamplingTool::CallRecord callRecord(m_sampler.get());
1216        Watchdog::Scope watchdogScope(vm.watchdog.get());
1217
1218        result = eval->generatedJITCode()->execute(&vm, &protoCallFrame);
1219    }
1220
1221    if (LegacyProfiler* profiler = vm.enabledProfiler())
1222        profiler->didExecute(callFrame, eval->sourceURL(), eval->lineNo(), eval->startColumn());
1223
1224    return checkedReturn(result);
1225}
1226
1227NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID)
1228{
1229    Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger();
1230    if (!debugger)
1231        return;
1232
1233    ASSERT(callFrame->codeBlock()->hasDebuggerRequests());
1234    ASSERT(!callFrame->hadException());
1235
1236    switch (debugHookID) {
1237        case DidEnterCallFrame:
1238            debugger->callEvent(callFrame);
1239            break;
1240        case WillLeaveCallFrame:
1241            debugger->returnEvent(callFrame);
1242            break;
1243        case WillExecuteStatement:
1244            debugger->atStatement(callFrame);
1245            break;
1246        case WillExecuteProgram:
1247            debugger->willExecuteProgram(callFrame);
1248            break;
1249        case DidExecuteProgram:
1250            debugger->didExecuteProgram(callFrame);
1251            break;
1252        case DidReachBreakpoint:
1253            debugger->didReachBreakpoint(callFrame);
1254            break;
1255    }
1256    ASSERT(!callFrame->hadException());
1257}
1258
1259void Interpreter::enableSampler()
1260{
1261#if ENABLE(OPCODE_SAMPLING)
1262    if (!m_sampler) {
1263        m_sampler = adoptPtr(new SamplingTool(this));
1264        m_sampler->setup();
1265    }
1266#endif
1267}
1268void Interpreter::dumpSampleData(ExecState* exec)
1269{
1270#if ENABLE(OPCODE_SAMPLING)
1271    if (m_sampler)
1272        m_sampler->dump(exec);
1273#else
1274    UNUSED_PARAM(exec);
1275#endif
1276}
1277void Interpreter::startSampling()
1278{
1279#if ENABLE(SAMPLING_THREAD)
1280    if (!m_sampleEntryDepth)
1281        SamplingThread::start();
1282
1283    m_sampleEntryDepth++;
1284#endif
1285}
1286void Interpreter::stopSampling()
1287{
1288#if ENABLE(SAMPLING_THREAD)
1289    m_sampleEntryDepth--;
1290    if (!m_sampleEntryDepth)
1291        SamplingThread::stop();
1292#endif
1293}
1294
1295} // namespace JSC
1296