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