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