Add some RELEASE_ASSERTs to catch JSLock bugs earlier
[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     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
764     if (vm.isCollectorBusy())
765         return jsNull();
766
767     if (!vm.isSafeToRecurse())
768         return checkedReturn(throwStackOverflowError(callFrame));
769
770     // First check if the "program" is actually just a JSON object. If so,
771     // we'll handle the JSON object here. Else, we'll handle real JS code
772     // below at failedJSONP.
773
774     Vector<JSONPData> JSONPData;
775     bool parseResult;
776     const String programSource = program->source().toString();
777     if (programSource.isNull())
778         return jsUndefined();
779     if (programSource.is8Bit()) {
780         LiteralParser<LChar> literalParser(callFrame, programSource.characters8(), programSource.length(), JSONP);
781         parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
782     } else {
783         LiteralParser<UChar> literalParser(callFrame, programSource.characters16(), programSource.length(), JSONP);
784         parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
785     }
786
787     if (parseResult) {
788         JSGlobalObject* globalObject = scope->globalObject();
789         JSValue result;
790         for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
791             Vector<JSONPPathEntry> JSONPPath;
792             JSONPPath.swap(JSONPData[entry].m_path);
793             JSValue JSONPValue = JSONPData[entry].m_value.get();
794             if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclare) {
795                 globalObject->addVar(callFrame, JSONPPath[0].m_pathEntryName);
796                 PutPropertySlot slot(globalObject);
797                 globalObject->methodTable()->put(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
798                 result = jsUndefined();
799                 continue;
800             }
801             JSValue baseObject(globalObject);
802             for (unsigned i = 0; i < JSONPPath.size() - 1; i++) {
803                 ASSERT(JSONPPath[i].m_type != JSONPPathEntryTypeDeclare);
804                 switch (JSONPPath[i].m_type) {
805                 case JSONPPathEntryTypeDot: {
806                     if (i == 0) {
807                         PropertySlot slot(globalObject);
808                         if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
809                             if (entry)
810                                 return callFrame->vm().throwException(callFrame, createUndefinedVariableError(globalObject->globalExec(), JSONPPath[i].m_pathEntryName));
811                             goto failedJSONP;
812                         }
813                         baseObject = slot.getValue(callFrame, JSONPPath[i].m_pathEntryName);
814                     } else
815                         baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathEntryName);
816                     if (callFrame->hadException())
817                         return jsUndefined();
818                     continue;
819                 }
820                 case JSONPPathEntryTypeLookup: {
821                     baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
822                     if (callFrame->hadException())
823                         return jsUndefined();
824                     continue;
825                 }
826                 default:
827                     RELEASE_ASSERT_NOT_REACHED();
828                     return jsUndefined();
829                 }
830             }
831             PutPropertySlot slot(baseObject);
832             switch (JSONPPath.last().m_type) {
833             case JSONPPathEntryTypeCall: {
834                 JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
835                 if (callFrame->hadException())
836                     return jsUndefined();
837                 CallData callData;
838                 CallType callType = getCallData(function, callData);
839                 if (callType == CallTypeNone)
840                     return callFrame->vm().throwException(callFrame, createNotAFunctionError(callFrame, function));
841                 MarkedArgumentBuffer jsonArg;
842                 jsonArg.append(JSONPValue);
843                 JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined(): baseObject;
844                 JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg);
845                 if (callFrame->hadException())
846                     return jsUndefined();
847                 break;
848             }
849             case JSONPPathEntryTypeDot: {
850                 baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
851                 if (callFrame->hadException())
852                     return jsUndefined();
853                 break;
854             }
855             case JSONPPathEntryTypeLookup: {
856                 baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
857                 if (callFrame->hadException())
858                     return jsUndefined();
859                 break;
860             }
861             default:
862                 RELEASE_ASSERT_NOT_REACHED();
863                     return jsUndefined();
864             }
865             result = JSONPValue;
866         }
867         return result;
868     }
869 failedJSONP:
870     // If we get here, then we have already proven that the script is not a JSON
871     // object.
872
873     VMEntryScope entryScope(vm, scope->globalObject());
874
875     // Compile source to bytecode if necessary:
876     if (JSObject* error = program->initializeGlobalProperties(vm, callFrame, scope))
877         return checkedReturn(callFrame->vm().throwException(callFrame, error));
878
879     if (JSObject* error = program->prepareForExecution(callFrame, nullptr, &scope, CodeForCall))
880         return checkedReturn(callFrame->vm().throwException(callFrame, error));
881
882     ProgramCodeBlock* codeBlock = program->codeBlock();
883
884     if (UNLIKELY(vm.watchdog.didFire(callFrame)))
885         return throwTerminatedExecutionException(callFrame);
886
887     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
888
889     ProtoCallFrame protoCallFrame;
890     protoCallFrame.init(codeBlock, scope, 0, thisObj, 1);
891
892     if (LegacyProfiler* profiler = vm.enabledProfiler())
893         profiler->willExecute(callFrame, program->sourceURL(), program->lineNo(), program->startColumn());
894
895     // Execute the code:
896     JSValue result;
897     {
898         SamplingTool::CallRecord callRecord(m_sampler.get());
899         Watchdog::Scope watchdogScope(vm.watchdog);
900
901         result = program->generatedJITCode()->execute(&vm, &protoCallFrame);
902     }
903
904     if (LegacyProfiler* profiler = vm.enabledProfiler())
905         profiler->didExecute(callFrame, program->sourceURL(), program->lineNo(), program->startColumn());
906
907     return checkedReturn(result);
908 }
909
910 JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
911 {
912     VM& vm = callFrame->vm();
913     ASSERT(!callFrame->hadException());
914     ASSERT(!vm.isCollectorBusy());
915     if (vm.isCollectorBusy())
916         return jsNull();
917
918     bool isJSCall = (callType == CallTypeJS);
919     JSScope* scope;
920     CodeBlock* newCodeBlock;
921     size_t argsCount = 1 + args.size(); // implicit "this" parameter
922
923     if (isJSCall)
924         scope = callData.js.scope;
925     else {
926         ASSERT(callType == CallTypeHost);
927         scope = callFrame->scope();
928     }
929
930     VMEntryScope entryScope(vm, scope->globalObject());
931     if (!vm.isSafeToRecurse())
932         return checkedReturn(throwStackOverflowError(callFrame));
933
934     if (isJSCall) {
935         // Compile the callee:
936         JSObject* compileError = callData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(function), &scope, CodeForCall);
937         if (UNLIKELY(!!compileError)) {
938             return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
939         }
940         newCodeBlock = callData.js.functionExecutable->codeBlockForCall();
941         ASSERT(!!newCodeBlock);
942         newCodeBlock->m_shouldAlwaysBeInlined = false;
943     } else
944         newCodeBlock = 0;
945
946     if (UNLIKELY(vm.watchdog.didFire(callFrame)))
947         return throwTerminatedExecutionException(callFrame);
948
949     ProtoCallFrame protoCallFrame;
950     protoCallFrame.init(newCodeBlock, scope, function, thisValue, argsCount, args.data());
951
952     if (LegacyProfiler* profiler = vm.enabledProfiler())
953         profiler->willExecute(callFrame, function);
954
955     JSValue result;
956     {
957         SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSCall);
958         Watchdog::Scope watchdogScope(vm.watchdog);
959
960         // Execute the code:
961         if (isJSCall)
962             result = callData.js.functionExecutable->generatedJITCodeForCall()->execute(&vm, &protoCallFrame);
963         else {
964             result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(callData.native.function), &vm, &protoCallFrame));
965             if (callFrame->hadException())
966                 result = jsNull();
967         }
968     }
969
970     if (LegacyProfiler* profiler = vm.enabledProfiler())
971         profiler->didExecute(callFrame, function);
972
973     return checkedReturn(result);
974 }
975
976 JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
977 {
978     VM& vm = callFrame->vm();
979     ASSERT(!callFrame->hadException());
980     ASSERT(!vm.isCollectorBusy());
981     // We throw in this case because we have to return something "valid" but we're
982     // already in an invalid state.
983     if (vm.isCollectorBusy())
984         return checkedReturn(throwStackOverflowError(callFrame));
985
986     bool isJSConstruct = (constructType == ConstructTypeJS);
987     JSScope* scope;
988     CodeBlock* newCodeBlock;
989     size_t argsCount = 1 + args.size(); // implicit "this" parameter
990
991     if (isJSConstruct)
992         scope = constructData.js.scope;
993     else {
994         ASSERT(constructType == ConstructTypeHost);
995         scope = callFrame->scope();
996     }
997
998     VMEntryScope entryScope(vm, scope->globalObject());
999     if (!vm.isSafeToRecurse())
1000         return checkedReturn(throwStackOverflowError(callFrame));
1001
1002     if (isJSConstruct) {
1003         // Compile the callee:
1004         JSObject* compileError = constructData.js.functionExecutable->prepareForExecution(callFrame, jsCast<JSFunction*>(constructor), &scope, CodeForConstruct);
1005         if (UNLIKELY(!!compileError)) {
1006             return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
1007         }
1008         newCodeBlock = constructData.js.functionExecutable->codeBlockForConstruct();
1009         ASSERT(!!newCodeBlock);
1010         newCodeBlock->m_shouldAlwaysBeInlined = false;
1011     } else
1012         newCodeBlock = 0;
1013
1014     if (UNLIKELY(vm.watchdog.didFire(callFrame)))
1015         return throwTerminatedExecutionException(callFrame);
1016
1017     ProtoCallFrame protoCallFrame;
1018     protoCallFrame.init(newCodeBlock, scope, constructor, jsUndefined(), argsCount, args.data());
1019
1020     if (LegacyProfiler* profiler = vm.enabledProfiler())
1021         profiler->willExecute(callFrame, constructor);
1022
1023     JSValue result;
1024     {
1025         SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSConstruct);
1026         Watchdog::Scope watchdogScope(vm.watchdog);
1027
1028         // Execute the code.
1029         if (isJSConstruct)
1030             result = constructData.js.functionExecutable->generatedJITCodeForConstruct()->execute(&vm, &protoCallFrame);
1031         else {
1032             result = JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(constructData.native.function), &vm, &protoCallFrame));
1033
1034             if (!callFrame->hadException())
1035                 RELEASE_ASSERT(result.isObject());
1036         }
1037     }
1038
1039     if (LegacyProfiler* profiler = vm.enabledProfiler())
1040         profiler->didExecute(callFrame, constructor);
1041
1042     if (callFrame->hadException())
1043         return 0;
1044     ASSERT(result.isObject());
1045     return checkedReturn(asObject(result));
1046 }
1047
1048 CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, ProtoCallFrame* protoCallFrame, JSFunction* function, int argumentCountIncludingThis, JSScope* scope, JSValue* args)
1049 {
1050     VM& vm = *scope->vm();
1051     ASSERT(!vm.exception());
1052     
1053     if (vm.isCollectorBusy())
1054         return CallFrameClosure();
1055
1056     // Compile the callee:
1057     JSObject* error = functionExecutable->prepareForExecution(callFrame, function, &scope, CodeForCall);
1058     if (error) {
1059         callFrame->vm().throwException(callFrame, error);
1060         return CallFrameClosure();
1061     }
1062     CodeBlock* newCodeBlock = functionExecutable->codeBlockForCall();
1063     newCodeBlock->m_shouldAlwaysBeInlined = false;
1064
1065     size_t argsCount = argumentCountIncludingThis;
1066
1067     protoCallFrame->init(newCodeBlock, scope, function, jsUndefined(), argsCount, args);
1068     // Return the successful closure:
1069     CallFrameClosure result = { callFrame, protoCallFrame, function, functionExecutable, &vm, scope, newCodeBlock->numParameters(), argumentCountIncludingThis };
1070     return result;
1071 }
1072
1073 JSValue Interpreter::execute(CallFrameClosure& closure) 
1074 {
1075     VM& vm = *closure.vm;
1076     SamplingScope samplingScope(this);
1077     
1078     ASSERT(!vm.isCollectorBusy());
1079     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
1080     if (vm.isCollectorBusy())
1081         return jsNull();
1082
1083     StackStats::CheckPoint stackCheckPoint;
1084     closure.resetCallFrame();
1085
1086     if (LegacyProfiler* profiler = vm.enabledProfiler())
1087         profiler->willExecute(closure.oldCallFrame, closure.function);
1088
1089     if (UNLIKELY(vm.watchdog.didFire(closure.oldCallFrame)))
1090         return throwTerminatedExecutionException(closure.oldCallFrame);
1091
1092     // Execute the code:
1093     JSValue result;
1094     {
1095         SamplingTool::CallRecord callRecord(m_sampler.get());
1096         Watchdog::Scope watchdogScope(vm.watchdog);
1097
1098         result = closure.functionExecutable->generatedJITCodeForCall()->execute(&vm, closure.protoCallFrame);
1099     }
1100
1101     if (LegacyProfiler* profiler = vm.enabledProfiler())
1102         profiler->didExecute(closure.oldCallFrame, closure.function);
1103
1104     return checkedReturn(result);
1105 }
1106
1107 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, JSScope* scope)
1108 {
1109     VM& vm = *scope->vm();
1110     SamplingScope samplingScope(this);
1111     
1112     ASSERT(scope->vm() == &callFrame->vm());
1113     ASSERT(!vm.exception());
1114     ASSERT(!vm.isCollectorBusy());
1115     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
1116     if (vm.isCollectorBusy())
1117         return jsNull();
1118
1119     VMEntryScope entryScope(vm, scope->globalObject());
1120     if (!vm.isSafeToRecurse())
1121         return checkedReturn(throwStackOverflowError(callFrame));        
1122
1123     unsigned numVariables = eval->numVariables();
1124     int numFunctions = eval->numberOfFunctionDecls();
1125
1126     JSScope* variableObject;
1127     if ((numVariables || numFunctions) && eval->isStrictMode()) {
1128         scope = StrictEvalActivation::create(callFrame);
1129         variableObject = scope;
1130     } else {
1131         for (JSScope* node = scope; ; node = node->next()) {
1132             RELEASE_ASSERT(node);
1133             if (node->isVariableObject() && !node->isNameScopeObject()) {
1134                 variableObject = node;
1135                 break;
1136             }
1137         }
1138     }
1139
1140     JSObject* compileError = eval->prepareForExecution(callFrame, nullptr, &scope, CodeForCall);
1141     if (UNLIKELY(!!compileError))
1142         return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
1143     EvalCodeBlock* codeBlock = eval->codeBlock();
1144
1145     if (numVariables || numFunctions) {
1146         BatchedTransitionOptimizer optimizer(vm, variableObject);
1147         if (variableObject->next())
1148             variableObject->globalObject()->varInjectionWatchpoint()->fireAll();
1149
1150         for (unsigned i = 0; i < numVariables; ++i) {
1151             const Identifier& ident = codeBlock->variable(i);
1152             if (!variableObject->hasProperty(callFrame, ident)) {
1153                 PutPropertySlot slot(variableObject);
1154                 variableObject->methodTable()->put(variableObject, callFrame, ident, jsUndefined(), slot);
1155             }
1156         }
1157
1158         for (int i = 0; i < numFunctions; ++i) {
1159             FunctionExecutable* function = codeBlock->functionDecl(i);
1160             PutPropertySlot slot(variableObject);
1161             variableObject->methodTable()->put(variableObject, callFrame, function->name(), JSFunction::create(vm, function, scope), slot);
1162         }
1163     }
1164
1165     if (UNLIKELY(vm.watchdog.didFire(callFrame)))
1166         return throwTerminatedExecutionException(callFrame);
1167
1168     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1169
1170     ProtoCallFrame protoCallFrame;
1171     protoCallFrame.init(codeBlock, scope, 0, thisValue, 1);
1172
1173     if (LegacyProfiler* profiler = vm.enabledProfiler())
1174         profiler->willExecute(callFrame, eval->sourceURL(), eval->lineNo(), eval->startColumn());
1175
1176     // Execute the code:
1177     JSValue result;
1178     {
1179         SamplingTool::CallRecord callRecord(m_sampler.get());
1180         Watchdog::Scope watchdogScope(vm.watchdog);
1181
1182         result = eval->generatedJITCode()->execute(&vm, &protoCallFrame);
1183     }
1184
1185     if (LegacyProfiler* profiler = vm.enabledProfiler())
1186         profiler->didExecute(callFrame, eval->sourceURL(), eval->lineNo(), eval->startColumn());
1187
1188     return checkedReturn(result);
1189 }
1190
1191 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID)
1192 {
1193     Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger();
1194     if (!debugger)
1195         return;
1196     ASSERT(callFrame->codeBlock()->hasDebuggerRequests() || callFrame->hadException());
1197
1198     switch (debugHookID) {
1199         case DidEnterCallFrame:
1200             debugger->callEvent(callFrame);
1201             return;
1202         case WillLeaveCallFrame:
1203             debugger->returnEvent(callFrame);
1204             return;
1205         case WillExecuteStatement:
1206             debugger->atStatement(callFrame);
1207             return;
1208         case WillExecuteProgram:
1209             debugger->willExecuteProgram(callFrame);
1210             return;
1211         case DidExecuteProgram:
1212             debugger->didExecuteProgram(callFrame);
1213             return;
1214         case DidReachBreakpoint:
1215             debugger->didReachBreakpoint(callFrame);
1216             return;
1217     }
1218 }    
1219
1220 void Interpreter::enableSampler()
1221 {
1222 #if ENABLE(OPCODE_SAMPLING)
1223     if (!m_sampler) {
1224         m_sampler = adoptPtr(new SamplingTool(this));
1225         m_sampler->setup();
1226     }
1227 #endif
1228 }
1229 void Interpreter::dumpSampleData(ExecState* exec)
1230 {
1231 #if ENABLE(OPCODE_SAMPLING)
1232     if (m_sampler)
1233         m_sampler->dump(exec);
1234 #else
1235     UNUSED_PARAM(exec);
1236 #endif
1237 }
1238 void Interpreter::startSampling()
1239 {
1240 #if ENABLE(SAMPLING_THREAD)
1241     if (!m_sampleEntryDepth)
1242         SamplingThread::start();
1243
1244     m_sampleEntryDepth++;
1245 #endif
1246 }
1247 void Interpreter::stopSampling()
1248 {
1249 #if ENABLE(SAMPLING_THREAD)
1250     m_sampleEntryDepth--;
1251     if (!m_sampleEntryDepth)
1252         SamplingThread::stop();
1253 #endif
1254 }
1255
1256 } // namespace JSC