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