]> git.saurik.com Git - apple/javascriptcore.git/blame - interpreter/Interpreter.cpp
JavaScriptCore-1218.35.tar.gz
[apple/javascriptcore.git] / interpreter / Interpreter.cpp
CommitLineData
9dae56ea 1/*
93a37866 2 * Copyright (C) 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
9dae56ea
A
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"
ba379fdc
A
35#include "CallFrame.h"
36#include "CallFrameClosure.h"
9dae56ea 37#include "CodeBlock.h"
14957cd0 38#include "Heap.h"
ba379fdc 39#include "Debugger.h"
9dae56ea 40#include "DebuggerCallFrame.h"
14957cd0 41#include "ErrorInstance.h"
9dae56ea
A
42#include "EvalCodeCache.h"
43#include "ExceptionHelpers.h"
4e4e5a6f 44#include "GetterSetter.h"
9dae56ea
A
45#include "JSActivation.h"
46#include "JSArray.h"
6fe7ccc8 47#include "JSBoundFunction.h"
93a37866 48#include "JSNameScope.h"
9dae56ea
A
49#include "JSNotAnObject.h"
50#include "JSPropertyNameIterator.h"
93a37866 51#include "JSStackInlines.h"
9dae56ea 52#include "JSString.h"
93a37866
A
53#include "JSWithScope.h"
54#include "LLIntCLoop.h"
55#include "LegacyProfiler.h"
56#include "LiteralParser.h"
57#include "NameInstance.h"
9dae56ea 58#include "ObjectPrototype.h"
ba379fdc 59#include "Operations.h"
9dae56ea 60#include "Parser.h"
9dae56ea
A
61#include "RegExpObject.h"
62#include "RegExpPrototype.h"
63#include "Register.h"
9dae56ea 64#include "SamplingTool.h"
14957cd0 65#include "StrictEvalActivation.h"
6fe7ccc8 66#include "StrongInlines.h"
f9bf01c6 67#include <limits.h>
9dae56ea 68#include <stdio.h>
93a37866
A
69#include <wtf/StackStats.h>
70#include <wtf/StringPrintStream.h>
ba379fdc 71#include <wtf/Threading.h>
93a37866 72#include <wtf/WTFThreadData.h>
6fe7ccc8 73#include <wtf/text/StringBuilder.h>
9dae56ea
A
74
75#if ENABLE(JIT)
76#include "JIT.h"
77#endif
78
93a37866 79#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (ENABLE(LLINT) && !defined(__llvm__))
4e4e5a6f 80
9dae56ea
A
81using namespace std;
82
83namespace JSC {
9dae56ea 84
93a37866
A
85Interpreter::ErrorHandlingMode::ErrorHandlingMode(ExecState *exec)
86 : m_interpreter(*exec->interpreter())
4e4e5a6f 87{
93a37866
A
88 if (!m_interpreter.m_errorHandlingModeReentry)
89 m_interpreter.stack().enableErrorStackReserve();
90 m_interpreter.m_errorHandlingModeReentry++;
4e4e5a6f
A
91}
92
93a37866 93Interpreter::ErrorHandlingMode::~ErrorHandlingMode()
9dae56ea 94{
93a37866
A
95 m_interpreter.m_errorHandlingModeReentry--;
96 ASSERT(m_interpreter.m_errorHandlingModeReentry >= 0);
97 if (!m_interpreter.m_errorHandlingModeReentry)
98 m_interpreter.stack().disableErrorStackReserve();
9dae56ea
A
99}
100
9dae56ea 101
93a37866
A
102// The Interpreter::StackPolicy class is used to compute a stack capacity
103// requirement to ensure that we have enough room on the native stack for:
104// 1. the max cumulative stack used by the interpreter and all code
105// paths sub of it up till leaf functions.
106// 2. the max cumulative stack used by the interpreter before it reaches
107// the next checkpoint (execute...() function) in the interpreter.
108//
109// The interpreter can be run on different threads and hence, different
110// native stacks (with different sizes) before exiting out of the first
111// frame. Hence, the required capacity needs to be re-computed on every
112// entry into the interpreter.
113//
114// Currently the requiredStack is computed based on a policy. See comments
115// in StackPolicy::StackPolicy() for details.
116
117Interpreter::StackPolicy::StackPolicy(Interpreter& interpreter, const StackBounds& stack)
118 : m_interpreter(interpreter)
9dae56ea 119{
93a37866 120 const size_t size = stack.size();
9dae56ea 121
93a37866
A
122 // We have two separate stack limits, one for regular JS execution, and one
123 // for when we're handling errors. We need the error stack to be smaller
124 // otherwise there would obviously not be any stack left to execute JS in when
125 // there's a stack overflow.
126 //
127 // These sizes were derived from the stack usage of a number of sites when
128 // layout occurs when we've already consumed most of the C stack.
129 const size_t requiredStack = 256 * KB;
130 const size_t errorModeRequiredStack = 64 * KB;
9dae56ea 131
93a37866 132 size_t requiredCapacity = m_interpreter.m_errorHandlingModeReentry ? errorModeRequiredStack : requiredStack;
4e4e5a6f 133
93a37866 134 RELEASE_ASSERT(size > requiredCapacity);
4e4e5a6f 135
93a37866 136 m_requiredCapacity = requiredCapacity;
9dae56ea
A
137}
138
9dae56ea 139
93a37866 140static CallFrame* getCallerInfo(VM*, CallFrame*, unsigned& bytecodeOffset, CodeBlock*& callerOut);
6fe7ccc8 141
93a37866
A
142// Returns the depth of the scope chain within a given call frame.
143static int depth(CodeBlock* codeBlock, JSScope* sc)
6fe7ccc8 144{
93a37866 145 if (!codeBlock->needsFullScopeChain())
6fe7ccc8 146 return 0;
93a37866 147 return sc->localDepth();
ba379fdc 148}
ba379fdc 149
6fe7ccc8 150JSValue eval(CallFrame* callFrame)
9dae56ea 151{
6fe7ccc8 152 if (!callFrame->argumentCount())
9dae56ea
A
153 return jsUndefined();
154
6fe7ccc8 155 JSValue program = callFrame->argument(0);
9dae56ea
A
156 if (!program.isString())
157 return program;
6fe7ccc8 158
93a37866
A
159 TopCallFrameSetter topCallFrame(callFrame->vm(), callFrame);
160 String programSource = asString(program)->value(callFrame);
4e4e5a6f
A
161 if (callFrame->hadException())
162 return JSValue();
14957cd0 163
6fe7ccc8
A
164 CallFrame* callerFrame = callFrame->callerFrame();
165 CodeBlock* callerCodeBlock = callerFrame->codeBlock();
93a37866 166 JSScope* callerScopeChain = callerFrame->scope();
6fe7ccc8
A
167 EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(callerCodeBlock->isStrictMode(), programSource, callerScopeChain);
168
169 if (!eval) {
170 if (!callerCodeBlock->isStrictMode()) {
171 // FIXME: We can use the preparser in strict mode, we just need additional logic
172 // to prevent duplicates.
173 if (programSource.is8Bit()) {
174 LiteralParser<LChar> preparser(callFrame, programSource.characters8(), programSource.length(), NonStrictJSON);
175 if (JSValue parsedObject = preparser.tryLiteralParse())
176 return parsedObject;
177 } else {
178 LiteralParser<UChar> preparser(callFrame, programSource.characters16(), programSource.length(), NonStrictJSON);
179 if (JSValue parsedObject = preparser.tryLiteralParse())
180 return parsedObject;
181 }
182 }
93a37866
A
183
184 // If the literal parser bailed, it should not have thrown exceptions.
185 ASSERT(!callFrame->vm().exception);
6fe7ccc8
A
186
187 JSValue exceptionValue;
93a37866 188 eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->unlinkedCodeBlock()->codeCacheForEval().get(), callerCodeBlock->ownerExecutable(), callerCodeBlock->isStrictMode(), programSource, callerScopeChain, exceptionValue);
6fe7ccc8
A
189
190 ASSERT(!eval == exceptionValue);
191 if (UNLIKELY(!eval))
192 return throwError(callFrame, exceptionValue);
14957cd0 193 }
f9bf01c6 194
6fe7ccc8
A
195 JSValue thisValue = callerFrame->thisValue();
196 ASSERT(isValidThisObject(thisValue, callFrame));
93a37866
A
197 Interpreter* interpreter = callFrame->vm().interpreter;
198 return interpreter->execute(eval, callFrame, thisValue, callerScopeChain);
6fe7ccc8
A
199}
200
93a37866 201CallFrame* loadVarargs(CallFrame* callFrame, JSStack* stack, JSValue thisValue, JSValue arguments, int firstFreeRegister)
6fe7ccc8
A
202{
203 if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
204 unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
93a37866
A
205 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + argumentCountIncludingThis + JSStack::CallFrameHeaderSize);
206 if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !stack->grow(newCallFrame->registers())) {
207 callFrame->vm().exception = createStackOverflowError(callFrame);
6fe7ccc8
A
208 return 0;
209 }
210
211 newCallFrame->setArgumentCountIncludingThis(argumentCountIncludingThis);
212 newCallFrame->setThisValue(thisValue);
213 for (size_t i = 0; i < callFrame->argumentCount(); ++i)
93a37866 214 newCallFrame->setArgument(i, callFrame->argumentAfterCapture(i));
6fe7ccc8
A
215 return newCallFrame;
216 }
217
218 if (arguments.isUndefinedOrNull()) {
93a37866
A
219 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + 1 + JSStack::CallFrameHeaderSize);
220 if (!stack->grow(newCallFrame->registers())) {
221 callFrame->vm().exception = createStackOverflowError(callFrame);
6fe7ccc8
A
222 return 0;
223 }
224 newCallFrame->setArgumentCountIncludingThis(1);
225 newCallFrame->setThisValue(thisValue);
226 return newCallFrame;
227 }
228
229 if (!arguments.isObject()) {
93a37866 230 callFrame->vm().exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
6fe7ccc8
A
231 return 0;
232 }
9dae56ea 233
6fe7ccc8
A
234 if (asObject(arguments)->classInfo() == &Arguments::s_info) {
235 Arguments* argsObject = asArguments(arguments);
236 unsigned argCount = argsObject->length(callFrame);
237 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
93a37866
A
238 if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) {
239 callFrame->vm().exception = createStackOverflowError(callFrame);
6fe7ccc8
A
240 return 0;
241 }
242 newCallFrame->setArgumentCountIncludingThis(argCount + 1);
243 newCallFrame->setThisValue(thisValue);
244 argsObject->copyToArguments(callFrame, newCallFrame, argCount);
245 return newCallFrame;
246 }
247
248 if (isJSArray(arguments)) {
249 JSArray* array = asArray(arguments);
250 unsigned argCount = array->length();
251 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
93a37866
A
252 if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) {
253 callFrame->vm().exception = createStackOverflowError(callFrame);
6fe7ccc8
A
254 return 0;
255 }
256 newCallFrame->setArgumentCountIncludingThis(argCount + 1);
257 newCallFrame->setThisValue(thisValue);
258 array->copyToArguments(callFrame, newCallFrame, argCount);
259 return newCallFrame;
260 }
9dae56ea 261
6fe7ccc8
A
262 JSObject* argObject = asObject(arguments);
263 unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
264 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
93a37866
A
265 if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) {
266 callFrame->vm().exception = createStackOverflowError(callFrame);
6fe7ccc8
A
267 return 0;
268 }
269 newCallFrame->setArgumentCountIncludingThis(argCount + 1);
270 newCallFrame->setThisValue(thisValue);
271 for (size_t i = 0; i < argCount; ++i) {
272 newCallFrame->setArgument(i, asObject(arguments)->get(callFrame, i));
93a37866 273 if (UNLIKELY(callFrame->vm().exception))
6fe7ccc8
A
274 return 0;
275 }
276 return newCallFrame;
9dae56ea
A
277}
278
93a37866 279Interpreter::Interpreter(VM& vm)
f9bf01c6 280 : m_sampleEntryDepth(0)
93a37866
A
281 , m_stack(vm)
282 , m_errorHandlingModeReentry(0)
6fe7ccc8
A
283#if !ASSERT_DISABLED
284 , m_initialized(false)
285#endif
9dae56ea 286{
6fe7ccc8
A
287}
288
289Interpreter::~Interpreter()
290{
6fe7ccc8
A
291}
292
93a37866 293void Interpreter::initialize(bool canUseJIT)
6fe7ccc8 294{
6fe7ccc8
A
295 UNUSED_PARAM(canUseJIT);
296
93a37866
A
297#if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT)
298 m_opcodeTable = LLInt::opcodeMap();
ba379fdc
A
299 for (int i = 0; i < numOpcodeIDs; ++i)
300 m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
6fe7ccc8 301#endif
93a37866 302
6fe7ccc8
A
303#if !ASSERT_DISABLED
304 m_initialized = true;
305#endif
f9bf01c6
A
306
307#if ENABLE(OPCODE_SAMPLING)
308 enableSampler();
309#endif
9dae56ea
A
310}
311
93a37866
A
312#ifdef NDEBUG
313
314void Interpreter::dumpCallFrame(CallFrame*)
315{
316}
317
318#else
9dae56ea
A
319
320void Interpreter::dumpCallFrame(CallFrame* callFrame)
321{
93a37866 322 callFrame->codeBlock()->dumpBytecode();
9dae56ea
A
323 dumpRegisters(callFrame);
324}
325
326void Interpreter::dumpRegisters(CallFrame* callFrame)
327{
93a37866
A
328 dataLogF("Register frame: \n\n");
329 dataLogF("-----------------------------------------------------------------------------\n");
330 dataLogF(" use | address | value \n");
331 dataLogF("-----------------------------------------------------------------------------\n");
9dae56ea
A
332
333 CodeBlock* codeBlock = callFrame->codeBlock();
9dae56ea
A
334 const Register* it;
335 const Register* end;
336
93a37866
A
337 it = callFrame->registers() - JSStack::CallFrameHeaderSize - callFrame->argumentCountIncludingThis();
338 end = callFrame->registers() - JSStack::CallFrameHeaderSize;
339 while (it < end) {
340 JSValue v = it->jsValue();
341 int registerNumber = it - callFrame->registers();
342 String name = codeBlock->nameForRegister(registerNumber);
343 dataLogF("[r% 3d %14s] | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, toCString(v).data(), (long long)JSValue::encode(v));
344 it++;
9dae56ea 345 }
93a37866
A
346
347 dataLogF("-----------------------------------------------------------------------------\n");
348 dataLogF("[ArgumentCount] | %10p | %lu \n", it, (unsigned long) callFrame->argumentCount());
349 ++it;
350 dataLogF("[CallerFrame] | %10p | %p \n", it, callFrame->callerFrame());
351 ++it;
352 dataLogF("[Callee] | %10p | %p \n", it, callFrame->callee());
353 ++it;
354 dataLogF("[ScopeChain] | %10p | %p \n", it, callFrame->scope());
355 ++it;
356#if ENABLE(JIT)
357 AbstractPC pc = callFrame->abstractReturnPC(callFrame->vm());
358 if (pc.hasJITReturnAddress())
359 dataLogF("[ReturnJITPC] | %10p | %p \n", it, pc.jitReturnAddress().value());
360#endif
361 unsigned bytecodeOffset = 0;
362 int line = 0;
363 CodeBlock* callerCodeBlock = 0;
364 getCallerInfo(&callFrame->vm(), callFrame, bytecodeOffset, callerCodeBlock);
365 line = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset);
366 dataLogF("[ReturnVPC] | %10p | %d (line %d)\n", it, bytecodeOffset, line);
367 ++it;
368 dataLogF("[CodeBlock] | %10p | %p \n", it, callFrame->codeBlock());
369 ++it;
370 dataLogF("-----------------------------------------------------------------------------\n");
9dae56ea
A
371
372 int registerCount = 0;
373
374 end = it + codeBlock->m_numVars;
375 if (it != end) {
376 do {
93a37866
A
377 JSValue v = it->jsValue();
378 int registerNumber = it - callFrame->registers();
379 String name = codeBlock->nameForRegister(registerNumber);
380 dataLogF("[r% 3d %14s] | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, toCString(v).data(), (long long)JSValue::encode(v));
9dae56ea
A
381 ++it;
382 ++registerCount;
383 } while (it != end);
384 }
93a37866 385 dataLogF("-----------------------------------------------------------------------------\n");
9dae56ea 386
ba379fdc 387 end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars;
9dae56ea
A
388 if (it != end) {
389 do {
93a37866
A
390 JSValue v = (*it).jsValue();
391 dataLogF("[r% 3d] | %10p | %-16s 0x%lld \n", registerCount, it, toCString(v).data(), (long long)JSValue::encode(v));
9dae56ea
A
392 ++it;
393 ++registerCount;
394 } while (it != end);
395 }
93a37866 396 dataLogF("-----------------------------------------------------------------------------\n");
9dae56ea
A
397}
398
399#endif
400
401bool Interpreter::isOpcode(Opcode opcode)
402{
93a37866 403#if ENABLE(COMPUTED_GOTO_OPCODES)
6fe7ccc8 404#if !ENABLE(LLINT)
93a37866
A
405 return static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)) <= op_end;
406#else
9dae56ea
A
407 return opcode != HashTraits<Opcode>::emptyValue()
408 && !HashTraits<Opcode>::isDeletedValue(opcode)
409 && m_opcodeIDTable.contains(opcode);
93a37866 410#endif
9dae56ea
A
411#else
412 return opcode >= 0 && opcode <= op_end;
413#endif
414}
415
ba379fdc 416NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
9dae56ea
A
417{
418 CodeBlock* oldCodeBlock = codeBlock;
93a37866 419 JSScope* scope = callFrame->scope();
9dae56ea
A
420
421 if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
422 DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
423 if (callFrame->callee())
93a37866 424 debugger->returnEvent(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine(), 0);
9dae56ea 425 else
93a37866
A
426 debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine(), 0);
427 }
428
429 JSValue activation;
430 if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsActivation()) {
431 activation = callFrame->uncheckedR(oldCodeBlock->activationRegister()).jsValue();
432 if (activation)
433 jsCast<JSActivation*>(activation)->tearOff(*scope->vm());
9dae56ea
A
434 }
435
93a37866
A
436 if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->usesArguments()) {
437 if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) {
438 if (activation)
439 jsCast<Arguments*>(arguments)->didTearOffActivation(callFrame, jsCast<JSActivation*>(activation));
440 else
441 jsCast<Arguments*>(arguments)->tearOff(callFrame);
14957cd0 442 }
14957cd0 443 }
9dae56ea 444
14957cd0 445 CallFrame* callerFrame = callFrame->callerFrame();
93a37866 446 callFrame->vm().topCallFrame = callerFrame;
4e4e5a6f 447 if (callerFrame->hasHostCallFrameFlag())
9dae56ea 448 return false;
93a37866 449 callFrame = getCallerInfo(&callFrame->vm(), callFrame, bytecodeOffset, codeBlock);
9dae56ea
A
450 return true;
451}
452
14957cd0 453static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception, unsigned bytecodeOffset)
9dae56ea 454{
14957cd0
A
455 exception->clearAppendSourceToMessage();
456
457 if (!callFrame->codeBlock()->hasExpressionInfo())
458 return;
459
460 int startOffset = 0;
461 int endOffset = 0;
462 int divotPoint = 0;
93a37866
A
463 unsigned line = 0;
464 unsigned column = 0;
14957cd0
A
465
466 CodeBlock* codeBlock = callFrame->codeBlock();
93a37866 467 codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divotPoint, startOffset, endOffset, line, column);
14957cd0
A
468
469 int expressionStart = divotPoint - startOffset;
470 int expressionStop = divotPoint + endOffset;
471
93a37866
A
472 const String& sourceString = codeBlock->source()->source();
473 if (!expressionStop || expressionStart > static_cast<int>(sourceString.length()))
14957cd0
A
474 return;
475
93a37866
A
476 VM* vm = &callFrame->vm();
477 JSValue jsMessage = exception->getDirect(*vm, vm->propertyNames->message);
14957cd0
A
478 if (!jsMessage || !jsMessage.isString())
479 return;
480
93a37866 481 String message = asString(jsMessage)->value(callFrame);
14957cd0
A
482
483 if (expressionStart < expressionStop)
93a37866 484 message = makeString(message, " (evaluating '", codeBlock->source()->getRange(expressionStart, expressionStop), "')");
14957cd0
A
485 else {
486 // No range information, so give a few characters of context
93a37866
A
487 const StringImpl* data = sourceString.impl();
488 int dataLength = sourceString.length();
14957cd0
A
489 int start = expressionStart;
490 int stop = expressionStart;
491 // Get up to 20 characters of context to the left and right of the divot, clamping to the line.
492 // then strip whitespace.
6fe7ccc8 493 while (start > 0 && (expressionStart - start < 20) && (*data)[start - 1] != '\n')
14957cd0 494 start--;
6fe7ccc8 495 while (start < (expressionStart - 1) && isStrWhiteSpace((*data)[start]))
14957cd0 496 start++;
6fe7ccc8 497 while (stop < dataLength && (stop - expressionStart < 20) && (*data)[stop] != '\n')
14957cd0 498 stop++;
6fe7ccc8 499 while (stop > expressionStart && isStrWhiteSpace((*data)[stop - 1]))
14957cd0 500 stop--;
93a37866 501 message = makeString(message, " (near '...", codeBlock->source()->getRange(start, stop), "...')");
14957cd0
A
502 }
503
93a37866 504 exception->putDirect(*vm, vm->propertyNames->message, jsString(vm, message));
14957cd0 505}
9dae56ea 506
93a37866 507static unsigned getBytecodeOffsetForCallFrame(CallFrame* callFrame)
6fe7ccc8 508{
6fe7ccc8
A
509 callFrame = callFrame->removeHostCallFrameFlag();
510 CodeBlock* codeBlock = callFrame->codeBlock();
511 if (!codeBlock)
93a37866 512 return 0;
6fe7ccc8
A
513#if ENABLE(DFG_JIT)
514 if (codeBlock->getJITType() == JITCode::DFGJIT)
93a37866 515 return codeBlock->codeOrigin(callFrame->codeOriginIndexForDFG()).bytecodeIndex;
6fe7ccc8 516#endif
93a37866 517 return callFrame->bytecodeOffsetForNonDFGCode();
6fe7ccc8
A
518}
519
93a37866 520static CallFrame* getCallerInfo(VM* vm, CallFrame* callFrame, unsigned& bytecodeOffset, CodeBlock*& caller)
6fe7ccc8 521{
93a37866
A
522 ASSERT_UNUSED(vm, vm);
523 bytecodeOffset = 0;
6fe7ccc8 524 ASSERT(!callFrame->hasHostCallFrameFlag());
93a37866
A
525 CallFrame* trueCallerFrame = callFrame->trueCallerFrame();
526 bool wasCalledByHost = callFrame->callerFrame()->hasHostCallFrameFlag();
527 ASSERT(!trueCallerFrame->hasHostCallFrameFlag());
6fe7ccc8 528
93a37866
A
529 if (trueCallerFrame == CallFrame::noCaller() || !trueCallerFrame || !trueCallerFrame->codeBlock()) {
530 caller = 0;
531 return trueCallerFrame;
532 }
6fe7ccc8 533
93a37866 534 CodeBlock* callerCodeBlock = trueCallerFrame->codeBlock();
6fe7ccc8 535
6fe7ccc8 536 if (!callFrame->hasReturnPC())
93a37866 537 wasCalledByHost = true;
6fe7ccc8 538
93a37866 539 if (wasCalledByHost) {
6fe7ccc8
A
540#if ENABLE(DFG_JIT)
541 if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) {
93a37866
A
542 unsigned codeOriginIndex = callFrame->callerFrame()->removeHostCallFrameFlag()->codeOriginIndexForDFG();
543 CodeOrigin origin = callerCodeBlock->codeOrigin(codeOriginIndex);
544 bytecodeOffset = origin.bytecodeIndex;
545 if (InlineCallFrame* inlineCallFrame = origin.inlineCallFrame)
546 callerCodeBlock = inlineCallFrame->baselineCodeBlock();
6fe7ccc8
A
547 } else
548#endif
93a37866 549 bytecodeOffset = trueCallerFrame->bytecodeOffsetForNonDFGCode();
6fe7ccc8 550 } else {
93a37866 551#if ENABLE(DFG_JIT)
6fe7ccc8
A
552 if (callFrame->isInlineCallFrame()) {
553 InlineCallFrame* icf = callFrame->inlineCallFrame();
554 bytecodeOffset = icf->caller.bytecodeIndex;
555 if (InlineCallFrame* parentCallFrame = icf->caller.inlineCallFrame) {
556 FunctionExecutable* executable = static_cast<FunctionExecutable*>(parentCallFrame->executable.get());
557 CodeBlock* newCodeBlock = executable->baselineCodeBlockFor(parentCallFrame->isCall ? CodeForCall : CodeForConstruct);
558 ASSERT(newCodeBlock);
559 ASSERT(newCodeBlock->instructionCount() > bytecodeOffset);
560 callerCodeBlock = newCodeBlock;
561 }
562 } else if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) {
563 CodeOrigin origin;
93a37866
A
564 if (!callerCodeBlock->codeOriginForReturn(callFrame->returnPC(), origin)) {
565 // This should not be possible, but we're seeing cases where it does happen
566 // CallFrame already has robustness against bogus stack walks, so
567 // we'll extend that to here as well.
6fe7ccc8 568 ASSERT_NOT_REACHED();
93a37866
A
569 caller = 0;
570 return 0;
571 }
6fe7ccc8
A
572 bytecodeOffset = origin.bytecodeIndex;
573 if (InlineCallFrame* icf = origin.inlineCallFrame) {
574 FunctionExecutable* executable = static_cast<FunctionExecutable*>(icf->executable.get());
575 CodeBlock* newCodeBlock = executable->baselineCodeBlockFor(icf->isCall ? CodeForCall : CodeForConstruct);
576 ASSERT(newCodeBlock);
577 ASSERT(newCodeBlock->instructionCount() > bytecodeOffset);
578 callerCodeBlock = newCodeBlock;
579 }
580 } else
6fe7ccc8 581#endif
93a37866
A
582 {
583 RELEASE_ASSERT(callerCodeBlock);
584 bytecodeOffset = callerCodeBlock->bytecodeOffset(trueCallerFrame, callFrame->returnPC());
585 }
6fe7ccc8
A
586 }
587
93a37866
A
588 RELEASE_ASSERT(callerCodeBlock);
589 caller = callerCodeBlock;
590 return trueCallerFrame;
6fe7ccc8
A
591}
592
93a37866 593static ALWAYS_INLINE const String getSourceURLFromCallFrame(CallFrame* callFrame)
6fe7ccc8
A
594{
595 ASSERT(!callFrame->hasHostCallFrameFlag());
6fe7ccc8 596 return callFrame->codeBlock()->ownerExecutable()->sourceURL();
6fe7ccc8
A
597}
598
599static StackFrameCodeType getStackFrameCodeType(CallFrame* callFrame)
600{
601 ASSERT(!callFrame->hasHostCallFrameFlag());
602
603 switch (callFrame->codeBlock()->codeType()) {
604 case EvalCode:
605 return StackFrameEvalCode;
606 case FunctionCode:
607 return StackFrameFunctionCode;
608 case GlobalCode:
609 return StackFrameGlobalCode;
610 }
93a37866 611 RELEASE_ASSERT_NOT_REACHED();
6fe7ccc8
A
612 return StackFrameGlobalCode;
613}
614
93a37866 615void StackFrame::computeLineAndColumn(unsigned& line, unsigned& column)
6fe7ccc8 616{
93a37866
A
617 if (!codeBlock) {
618 line = 0;
619 column = 0;
6fe7ccc8 620 return;
93a37866
A
621 }
622
623 int divot = 0;
624 int unusedStartOffset = 0;
625 int unusedEndOffset = 0;
626 unsigned divotLine = 0;
627 unsigned divotColumn = 0;
628 expressionInfo(divot, unusedStartOffset, unusedEndOffset, divotLine, divotColumn);
629
630 line = divotLine + lineOffset;
631 column = divotColumn + (divotLine ? 1 : firstLineColumnOffset);
632}
633
634void StackFrame::expressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
635{
636 codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
637 divot += characterOffset;
638}
639
640String StackFrame::toString(CallFrame* callFrame)
641{
642 StringBuilder traceBuild;
643 String functionName = friendlyFunctionName(callFrame);
644 String sourceURL = friendlySourceURL();
645 traceBuild.append(functionName);
646 if (!sourceURL.isEmpty()) {
647 if (!functionName.isEmpty())
648 traceBuild.append('@');
649 traceBuild.append(sourceURL);
650 if (codeType != StackFrameNativeCode) {
651 unsigned line;
652 unsigned column;
653 computeLineAndColumn(line, column);
654
655 traceBuild.append(':');
656 traceBuild.appendNumber(line);
657 traceBuild.append(':');
658 traceBuild.appendNumber(column);
659 }
660 }
661 return traceBuild.toString().impl();
662}
6fe7ccc8 663
93a37866
A
664void Interpreter::getStackTrace(VM* vm, Vector<StackFrame>& results, size_t maxStackSize)
665{
666 CallFrame* callFrame = vm->topCallFrame->removeHostCallFrameFlag();
667 if (!callFrame || callFrame == CallFrame::noCaller())
668 return;
669 unsigned bytecodeOffset = getBytecodeOffsetForCallFrame(callFrame);
6fe7ccc8 670 callFrame = callFrame->trueCallFrameFromVMCode();
93a37866
A
671 if (!callFrame)
672 return;
673 CodeBlock* callerCodeBlock = callFrame->codeBlock();
6fe7ccc8 674
93a37866
A
675 while (callFrame && callFrame != CallFrame::noCaller() && maxStackSize--) {
676 String sourceURL;
677 if (callerCodeBlock) {
6fe7ccc8 678 sourceURL = getSourceURLFromCallFrame(callFrame);
93a37866
A
679 StackFrame s = {
680 Strong<JSObject>(*vm, callFrame->callee()),
681 getStackFrameCodeType(callFrame),
682 Strong<ExecutableBase>(*vm, callerCodeBlock->ownerExecutable()),
683 Strong<UnlinkedCodeBlock>(*vm, callerCodeBlock->unlinkedCodeBlock()),
684 callerCodeBlock->source(),
685 callerCodeBlock->ownerExecutable()->lineNo(),
686 callerCodeBlock->firstLineColumnOffset(),
687 callerCodeBlock->sourceOffset(),
688 bytecodeOffset,
689 sourceURL
690 };
691
6fe7ccc8
A
692 results.append(s);
693 } else {
93a37866 694 StackFrame s = { Strong<JSObject>(*vm, callFrame->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), Strong<UnlinkedCodeBlock>(), 0, 0, 0, 0, 0, String()};
6fe7ccc8
A
695 results.append(s);
696 }
93a37866 697 callFrame = getCallerInfo(vm, callFrame, bytecodeOffset, callerCodeBlock);
6fe7ccc8
A
698 }
699}
700
93a37866 701void Interpreter::addStackTraceIfNecessary(CallFrame* callFrame, JSValue error)
6fe7ccc8 702{
93a37866
A
703 VM* vm = &callFrame->vm();
704 ASSERT(callFrame == vm->topCallFrame || callFrame == callFrame->lexicalGlobalObject()->globalExec() || callFrame == callFrame->dynamicGlobalObject()->globalExec());
6fe7ccc8
A
705
706 Vector<StackFrame> stackTrace;
93a37866
A
707 getStackTrace(&callFrame->vm(), stackTrace);
708 vm->exceptionStack() = RefCountedArray<StackFrame>(stackTrace);
709 if (stackTrace.isEmpty() || !error.isObject())
6fe7ccc8 710 return;
93a37866
A
711
712 JSObject* errorObject = asObject(error);
6fe7ccc8 713 JSGlobalObject* globalObject = 0;
93a37866
A
714 if (isTerminatedExecutionException(error))
715 globalObject = vm->dynamicGlobalObject;
6fe7ccc8 716 else
93a37866
A
717 globalObject = errorObject->globalObject();
718
719 // FIXME: JSStringJoiner could be more efficient than StringBuilder here.
6fe7ccc8
A
720 StringBuilder builder;
721 for (unsigned i = 0; i < stackTrace.size(); i++) {
722 builder.append(String(stackTrace[i].toString(globalObject->globalExec()).impl()));
723 if (i != stackTrace.size() - 1)
724 builder.append('\n');
725 }
93a37866
A
726
727 if (errorObject->hasProperty(callFrame, vm->propertyNames->stack))
728 return;
729 errorObject->putDirect(*vm, vm->propertyNames->stack, jsString(vm, builder.toString()), ReadOnly | DontDelete);
6fe7ccc8
A
730}
731
14957cd0
A
732NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
733{
9dae56ea 734 CodeBlock* codeBlock = callFrame->codeBlock();
93a37866 735 bool isTermination = false;
14957cd0 736
6fe7ccc8
A
737 ASSERT(!exceptionValue.isEmpty());
738 ASSERT(!exceptionValue.isCell() || exceptionValue.asCell());
739 // This shouldn't be possible (hence the assertions), but we're already in the slowest of
740 // slow cases, so let's harden against it anyway to be safe.
741 if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
742 exceptionValue = jsNull();
743
14957cd0 744 // Set up the exception object
9dae56ea
A
745 if (exceptionValue.isObject()) {
746 JSObject* exception = asObject(exceptionValue);
4e4e5a6f 747
14957cd0
A
748 if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage())
749 appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), bytecodeOffset);
750
6fe7ccc8 751 if (!hasErrorInfo(callFrame, exception)) {
14957cd0
A
752 // FIXME: should only really be adding these properties to VM generated exceptions,
753 // but the inspector currently requires these for all thrown objects.
754 addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source());
9dae56ea 755 }
14957cd0 756
93a37866
A
757 isTermination = isTerminatedExecutionException(exception);
758 } else {
759 if (!callFrame->vm().exceptionStack().size()) {
760 Vector<StackFrame> stack;
761 Interpreter::getStackTrace(&callFrame->vm(), stack);
762 callFrame->vm().exceptionStack() = RefCountedArray<StackFrame>(stack);
763 }
9dae56ea
A
764 }
765
766 if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
767 DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
12899fa2
A
768 bool hasHandler = false;
769 if (!isTermination) {
770 VM* vm = &callFrame->vm();
771 CallFrame* currentFrame = callFrame;
772 CodeBlock* currentCB = codeBlock;
773 unsigned currentOffset = bytecodeOffset;
774 while (currentFrame) {
775 if (currentCB && currentCB->handlerForBytecodeOffset(currentOffset)) {
776 hasHandler = true;
777 break;
778 }
779 currentFrame = getCallerInfo(vm, currentFrame, currentOffset, currentCB);
780 }
781 }
93a37866 782 debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), 0, hasHandler);
9dae56ea
A
783 }
784
785 // Calculate an exception handler vPC, unwinding call frames as necessary.
9dae56ea 786 HandlerInfo* handler = 0;
93a37866 787 while (isTermination || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
14957cd0 788 if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
93a37866 789 if (LegacyProfiler* profiler = callFrame->vm().enabledProfiler())
14957cd0 790 profiler->exceptionUnwind(callFrame);
9dae56ea 791 return 0;
14957cd0 792 }
9dae56ea
A
793 }
794
93a37866 795 if (LegacyProfiler* profiler = callFrame->vm().enabledProfiler())
14957cd0 796 profiler->exceptionUnwind(callFrame);
9dae56ea 797
14957cd0 798 // Unwind the scope chain within the exception handler's call frame.
93a37866 799 JSScope* scope = callFrame->scope();
14957cd0
A
800 int scopeDelta = 0;
801 if (!codeBlock->needsFullScopeChain() || codeBlock->codeType() != FunctionCode
93a37866
A
802 || callFrame->uncheckedR(codeBlock->activationRegister()).jsValue()) {
803 int currentDepth = depth(codeBlock, scope);
804 int targetDepth = handler->scopeDepth;
805 scopeDelta = currentDepth - targetDepth;
806 RELEASE_ASSERT(scopeDelta >= 0);
807 }
9dae56ea 808 while (scopeDelta--)
93a37866
A
809 scope = scope->next();
810 callFrame->setScope(scope);
9dae56ea
A
811
812 return handler;
813}
814
14957cd0
A
815static inline JSValue checkedReturn(JSValue returnValue)
816{
817 ASSERT(returnValue);
818 return returnValue;
819}
820
821static inline JSObject* checkedReturn(JSObject* returnValue)
822{
823 ASSERT(returnValue);
824 return returnValue;
825}
826
93a37866
A
827class SamplingScope {
828public:
829 SamplingScope(Interpreter* interpreter)
830 : m_interpreter(interpreter)
831 {
832 interpreter->startSampling();
833 }
834 ~SamplingScope()
835 {
836 m_interpreter->stopSampling();
837 }
838private:
839 Interpreter* m_interpreter;
840};
841
842JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, JSObject* thisObj)
9dae56ea 843{
93a37866
A
844 SamplingScope samplingScope(this);
845
846 JSScope* scope = callFrame->scope();
847 VM& vm = *scope->vm();
848
6fe7ccc8 849 ASSERT(isValidThisObject(thisObj, callFrame));
93a37866
A
850 ASSERT(!vm.exception);
851 ASSERT(!vm.isCollectorBusy());
852 if (vm.isCollectorBusy())
853 return jsNull();
9dae56ea 854
93a37866
A
855 StackStats::CheckPoint stackCheckPoint;
856 const StackBounds& nativeStack = wtfThreadData().stack();
857 StackPolicy policy(*this, nativeStack);
858 if (!nativeStack.isSafeToRecurse(policy.requiredCapacity()))
14957cd0
A
859 return checkedReturn(throwStackOverflowError(callFrame));
860
93a37866
A
861 // First check if the "program" is actually just a JSON object. If so,
862 // we'll handle the JSON object here. Else, we'll handle real JS code
863 // below at failedJSONP.
864 DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
6fe7ccc8
A
865 Vector<JSONPData> JSONPData;
866 bool parseResult;
93a37866 867 const String programSource = program->source().toString();
6fe7ccc8
A
868 if (programSource.isNull())
869 return jsUndefined();
870 if (programSource.is8Bit()) {
871 LiteralParser<LChar> literalParser(callFrame, programSource.characters8(), programSource.length(), JSONP);
93a37866 872 parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
6fe7ccc8
A
873 } else {
874 LiteralParser<UChar> literalParser(callFrame, programSource.characters16(), programSource.length(), JSONP);
93a37866 875 parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
6fe7ccc8
A
876 }
877
878 if (parseResult) {
93a37866 879 JSGlobalObject* globalObject = scope->globalObject();
14957cd0
A
880 JSValue result;
881 for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
6fe7ccc8 882 Vector<JSONPPathEntry> JSONPPath;
14957cd0
A
883 JSONPPath.swap(JSONPData[entry].m_path);
884 JSValue JSONPValue = JSONPData[entry].m_value.get();
6fe7ccc8 885 if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclare) {
14957cd0
A
886 if (globalObject->hasProperty(callFrame, JSONPPath[0].m_pathEntryName)) {
887 PutPropertySlot slot;
6fe7ccc8 888 globalObject->methodTable()->put(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
14957cd0 889 } else
6fe7ccc8 890 globalObject->methodTable()->putDirectVirtual(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, DontEnum | DontDelete);
14957cd0
A
891 // var declarations return undefined
892 result = jsUndefined();
893 continue;
894 }
895 JSValue baseObject(globalObject);
896 for (unsigned i = 0; i < JSONPPath.size() - 1; i++) {
6fe7ccc8 897 ASSERT(JSONPPath[i].m_type != JSONPPathEntryTypeDeclare);
14957cd0 898 switch (JSONPPath[i].m_type) {
6fe7ccc8 899 case JSONPPathEntryTypeDot: {
14957cd0
A
900 if (i == 0) {
901 PropertySlot slot(globalObject);
902 if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
903 if (entry)
904 return throwError(callFrame, createUndefinedVariableError(globalObject->globalExec(), JSONPPath[i].m_pathEntryName));
905 goto failedJSONP;
906 }
907 baseObject = slot.getValue(callFrame, JSONPPath[i].m_pathEntryName);
908 } else
909 baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathEntryName);
910 if (callFrame->hadException())
911 return jsUndefined();
912 continue;
913 }
6fe7ccc8 914 case JSONPPathEntryTypeLookup: {
14957cd0
A
915 baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
916 if (callFrame->hadException())
917 return jsUndefined();
918 continue;
919 }
920 default:
93a37866 921 RELEASE_ASSERT_NOT_REACHED();
14957cd0
A
922 return jsUndefined();
923 }
924 }
925 PutPropertySlot slot;
926 switch (JSONPPath.last().m_type) {
6fe7ccc8 927 case JSONPPathEntryTypeCall: {
14957cd0
A
928 JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
929 if (callFrame->hadException())
930 return jsUndefined();
931 CallData callData;
932 CallType callType = getCallData(function, callData);
933 if (callType == CallTypeNone)
934 return throwError(callFrame, createNotAFunctionError(callFrame, function));
935 MarkedArgumentBuffer jsonArg;
936 jsonArg.append(JSONPValue);
937 JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined(): baseObject;
938 JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg);
939 if (callFrame->hadException())
940 return jsUndefined();
941 break;
942 }
6fe7ccc8 943 case JSONPPathEntryTypeDot: {
14957cd0
A
944 baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
945 if (callFrame->hadException())
946 return jsUndefined();
947 break;
948 }
6fe7ccc8
A
949 case JSONPPathEntryTypeLookup: {
950 baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
14957cd0
A
951 if (callFrame->hadException())
952 return jsUndefined();
953 break;
954 }
955 default:
93a37866 956 RELEASE_ASSERT_NOT_REACHED();
14957cd0
A
957 return jsUndefined();
958 }
959 result = JSONPValue;
ba379fdc 960 }
14957cd0 961 return result;
9dae56ea 962 }
14957cd0 963failedJSONP:
93a37866
A
964 // If we get here, then we have already proven that the script is not a JSON
965 // object.
966
967 // Compile source to bytecode if necessary:
968 if (JSObject* error = program->initializeGlobalProperties(vm, callFrame, scope))
14957cd0 969 return checkedReturn(throwError(callFrame, error));
9dae56ea 970
93a37866
A
971 if (JSObject* error = program->compile(callFrame, scope))
972 return checkedReturn(throwError(callFrame, error));
973
974 ProgramCodeBlock* codeBlock = &program->generatedBytecode();
975
976 if (UNLIKELY(vm.watchdog.didFire(callFrame)))
977 return throwTerminatedExecutionException(callFrame);
9dae56ea 978
93a37866 979 // Push the call frame for this invocation:
6fe7ccc8 980 ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
93a37866
A
981 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, codeBlock, scope, 1, 0);
982 if (UNLIKELY(!newCallFrame))
983 return checkedReturn(throwStackOverflowError(callFrame));
984
985 // Set the arguments for the callee:
6fe7ccc8 986 newCallFrame->setThisValue(thisObj);
9dae56ea 987
93a37866
A
988 if (LegacyProfiler* profiler = vm.enabledProfiler())
989 profiler->willExecute(callFrame, program->sourceURL(), program->lineNo());
9dae56ea 990
93a37866 991 // Execute the code:
ba379fdc 992 JSValue result;
9dae56ea 993 {
f9bf01c6 994 SamplingTool::CallRecord callRecord(m_sampler.get());
93a37866 995 Watchdog::Scope watchdogScope(vm.watchdog);
9dae56ea 996
93a37866
A
997#if ENABLE(LLINT_C_LOOP)
998 result = LLInt::CLoop::execute(newCallFrame, llint_program_prologue);
999#elif ENABLE(JIT)
1000 result = program->generatedJITCode().execute(&m_stack, newCallFrame, &vm);
1001#endif // ENABLE(JIT)
9dae56ea
A
1002 }
1003
93a37866
A
1004 if (LegacyProfiler* profiler = vm.enabledProfiler())
1005 profiler->didExecute(callFrame, program->sourceURL(), program->lineNo());
9dae56ea 1006
93a37866 1007 m_stack.popFrame(newCallFrame);
9dae56ea 1008
14957cd0 1009 return checkedReturn(result);
9dae56ea
A
1010}
1011
14957cd0 1012JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
9dae56ea 1013{
93a37866 1014 VM& vm = callFrame->vm();
6fe7ccc8 1015 ASSERT(isValidThisObject(thisValue, callFrame));
14957cd0 1016 ASSERT(!callFrame->hadException());
93a37866
A
1017 ASSERT(!vm.isCollectorBusy());
1018 if (vm.isCollectorBusy())
14957cd0 1019 return jsNull();
9dae56ea 1020
93a37866
A
1021 StackStats::CheckPoint stackCheckPoint;
1022 const StackBounds& nativeStack = wtfThreadData().stack();
1023 StackPolicy policy(*this, nativeStack);
1024 if (!nativeStack.isSafeToRecurse(policy.requiredCapacity()))
14957cd0 1025 return checkedReturn(throwStackOverflowError(callFrame));
9dae56ea 1026
93a37866
A
1027 bool isJSCall = (callType == CallTypeJS);
1028 JSScope* scope;
1029 CodeBlock* newCodeBlock;
1030 size_t argsCount = 1 + args.size(); // implicit "this" parameter
14957cd0 1031
93a37866
A
1032 if (isJSCall)
1033 scope = callData.js.scope;
1034 else {
1035 ASSERT(callType == CallTypeHost);
1036 scope = callFrame->scope();
1037 }
1038 DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
14957cd0 1039
93a37866
A
1040 if (isJSCall) {
1041 // Compile the callee:
1042 JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, scope);
14957cd0 1043 if (UNLIKELY(!!compileError)) {
14957cd0
A
1044 return checkedReturn(throwError(callFrame, compileError));
1045 }
93a37866
A
1046 newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
1047 ASSERT(!!newCodeBlock);
1048 } else
1049 newCodeBlock = 0;
14957cd0 1050
93a37866
A
1051 if (UNLIKELY(vm.watchdog.didFire(callFrame)))
1052 return throwTerminatedExecutionException(callFrame);
14957cd0 1053
93a37866
A
1054 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, newCodeBlock, scope, argsCount, function);
1055 if (UNLIKELY(!newCallFrame))
1056 return checkedReturn(throwStackOverflowError(callFrame));
6fe7ccc8 1057
93a37866
A
1058 // Set the arguments for the callee:
1059 newCallFrame->setThisValue(thisValue);
1060 for (size_t i = 0; i < args.size(); ++i)
1061 newCallFrame->setArgument(i, args.at(i));
9dae56ea 1062
93a37866
A
1063 if (LegacyProfiler* profiler = vm.enabledProfiler())
1064 profiler->willExecute(callFrame, function);
9dae56ea 1065
ba379fdc 1066 JSValue result;
9dae56ea 1067 {
93a37866
A
1068 SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSCall);
1069 Watchdog::Scope watchdogScope(vm.watchdog);
1070
1071 // Execute the code:
1072 if (isJSCall) {
1073#if ENABLE(LLINT_C_LOOP)
1074 result = LLInt::CLoop::execute(newCallFrame, llint_function_for_call_prologue);
1075#elif ENABLE(JIT)
1076 result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_stack, newCallFrame, &vm);
1077#endif // ENABLE(JIT)
1078 } else
1079 result = JSValue::decode(callData.native.function(newCallFrame));
14957cd0 1080 }
9dae56ea 1081
93a37866
A
1082 if (LegacyProfiler* profiler = vm.enabledProfiler())
1083 profiler->didExecute(callFrame, function);
14957cd0 1084
93a37866 1085 m_stack.popFrame(newCallFrame);
14957cd0
A
1086 return checkedReturn(result);
1087}
1088
1089JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
1090{
93a37866 1091 VM& vm = callFrame->vm();
14957cd0 1092 ASSERT(!callFrame->hadException());
93a37866 1093 ASSERT(!vm.isCollectorBusy());
14957cd0
A
1094 // We throw in this case because we have to return something "valid" but we're
1095 // already in an invalid state.
93a37866 1096 if (vm.isCollectorBusy())
14957cd0
A
1097 return checkedReturn(throwStackOverflowError(callFrame));
1098
93a37866
A
1099 StackStats::CheckPoint stackCheckPoint;
1100 const StackBounds& nativeStack = wtfThreadData().stack();
1101 StackPolicy policy(*this, nativeStack);
1102 if (!nativeStack.isSafeToRecurse(policy.requiredCapacity()))
14957cd0
A
1103 return checkedReturn(throwStackOverflowError(callFrame));
1104
93a37866
A
1105 bool isJSConstruct = (constructType == ConstructTypeJS);
1106 JSScope* scope;
1107 CodeBlock* newCodeBlock;
1108 size_t argsCount = 1 + args.size(); // implicit "this" parameter
14957cd0 1109
93a37866
A
1110 if (isJSConstruct)
1111 scope = constructData.js.scope;
1112 else {
1113 ASSERT(constructType == ConstructTypeHost);
1114 scope = callFrame->scope();
1115 }
14957cd0 1116
93a37866 1117 DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
14957cd0 1118
93a37866
A
1119 if (isJSConstruct) {
1120 // Compile the callee:
1121 JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, scope);
14957cd0 1122 if (UNLIKELY(!!compileError)) {
14957cd0
A
1123 return checkedReturn(throwError(callFrame, compileError));
1124 }
93a37866
A
1125 newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
1126 ASSERT(!!newCodeBlock);
1127 } else
1128 newCodeBlock = 0;
14957cd0 1129
93a37866
A
1130 if (UNLIKELY(vm.watchdog.didFire(callFrame)))
1131 return throwTerminatedExecutionException(callFrame);
14957cd0 1132
93a37866
A
1133 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, newCodeBlock, scope, argsCount, constructor);
1134 if (UNLIKELY(!newCallFrame))
1135 return checkedReturn(throwStackOverflowError(callFrame));
6fe7ccc8 1136
93a37866
A
1137 // Set the arguments for the callee:
1138 newCallFrame->setThisValue(jsUndefined());
1139 for (size_t i = 0; i < args.size(); ++i)
1140 newCallFrame->setArgument(i, args.at(i));
14957cd0 1141
93a37866
A
1142 if (LegacyProfiler* profiler = vm.enabledProfiler())
1143 profiler->willExecute(callFrame, constructor);
14957cd0
A
1144
1145 JSValue result;
1146 {
93a37866
A
1147 SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSConstruct);
1148 Watchdog::Scope watchdogScope(vm.watchdog);
1149
1150 // Execute the code.
1151 if (isJSConstruct) {
1152#if ENABLE(LLINT_C_LOOP)
1153 result = LLInt::CLoop::execute(newCallFrame, llint_function_for_construct_prologue);
1154#elif ENABLE(JIT)
1155 result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_stack, newCallFrame, &vm);
1156#endif // ENABLE(JIT)
1157 } else
1158 result = JSValue::decode(constructData.native.function(newCallFrame));
14957cd0
A
1159 }
1160
93a37866
A
1161 if (LegacyProfiler* profiler = vm.enabledProfiler())
1162 profiler->didExecute(callFrame, constructor);
1163
1164 m_stack.popFrame(newCallFrame);
9dae56ea 1165
14957cd0
A
1166 if (callFrame->hadException())
1167 return 0;
1168 ASSERT(result.isObject());
1169 return checkedReturn(asObject(result));
9dae56ea
A
1170}
1171
93a37866 1172CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, int argumentCountIncludingThis, JSScope* scope)
ba379fdc 1173{
93a37866
A
1174 VM& vm = *scope->vm();
1175 ASSERT(!vm.exception);
ba379fdc 1176
93a37866 1177 if (vm.isCollectorBusy())
6fe7ccc8
A
1178 return CallFrameClosure();
1179
93a37866
A
1180 StackStats::CheckPoint stackCheckPoint;
1181 const StackBounds& nativeStack = wtfThreadData().stack();
1182 StackPolicy policy(*this, nativeStack);
1183 if (!nativeStack.isSafeToRecurse(policy.requiredCapacity())) {
6fe7ccc8
A
1184 throwStackOverflowError(callFrame);
1185 return CallFrameClosure();
ba379fdc 1186 }
6fe7ccc8 1187
93a37866
A
1188 // Compile the callee:
1189 JSObject* error = functionExecutable->compileForCall(callFrame, scope);
1190 if (error) {
1191 throwError(callFrame, error);
ba379fdc
A
1192 return CallFrameClosure();
1193 }
93a37866 1194 CodeBlock* newCodeBlock = &functionExecutable->generatedBytecodeForCall();
ba379fdc 1195
93a37866
A
1196 size_t argsCount = argumentCountIncludingThis;
1197
1198 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, newCodeBlock, scope, argsCount, function);
1199 if (UNLIKELY(!newCallFrame)) {
1200 throwStackOverflowError(callFrame);
14957cd0
A
1201 return CallFrameClosure();
1202 }
14957cd0 1203
ba379fdc 1204 if (UNLIKELY(!newCallFrame)) {
14957cd0 1205 throwStackOverflowError(callFrame);
ba379fdc
A
1206 return CallFrameClosure();
1207 }
93a37866
A
1208
1209 // Return the successful closure:
1210 CallFrameClosure result = { callFrame, newCallFrame, function, functionExecutable, &vm, scope, newCodeBlock->numParameters(), argumentCountIncludingThis };
ba379fdc
A
1211 return result;
1212}
1213
14957cd0 1214JSValue Interpreter::execute(CallFrameClosure& closure)
ba379fdc 1215{
93a37866
A
1216 VM& vm = *closure.vm;
1217 SamplingScope samplingScope(this);
1218
1219 ASSERT(!vm.isCollectorBusy());
1220 if (vm.isCollectorBusy())
14957cd0 1221 return jsNull();
93a37866
A
1222
1223 StackStats::CheckPoint stackCheckPoint;
1224 m_stack.validateFence(closure.newCallFrame, "BEFORE");
ba379fdc 1225 closure.resetCallFrame();
93a37866
A
1226 m_stack.validateFence(closure.newCallFrame, "STEP 1");
1227
1228 if (LegacyProfiler* profiler = vm.enabledProfiler())
1229 profiler->willExecute(closure.oldCallFrame, closure.function);
1230
1231 if (UNLIKELY(vm.watchdog.didFire(closure.oldCallFrame)))
1232 return throwTerminatedExecutionException(closure.oldCallFrame);
6fe7ccc8 1233
93a37866
A
1234 // The code execution below may push more frames and point the topCallFrame
1235 // to those newer frames, or it may pop to the top frame to the caller of
1236 // the current repeat frame, or it may leave the top frame pointing to the
1237 // current repeat frame.
1238 //
1239 // Hence, we need to preserve the topCallFrame here ourselves before
1240 // repeating this call on a second callback function.
6fe7ccc8 1241
93a37866
A
1242 TopCallFrameSetter topCallFrame(vm, closure.newCallFrame);
1243
1244 // Execute the code:
ba379fdc
A
1245 JSValue result;
1246 {
f9bf01c6 1247 SamplingTool::CallRecord callRecord(m_sampler.get());
93a37866
A
1248 Watchdog::Scope watchdogScope(vm.watchdog);
1249
1250#if ENABLE(LLINT_C_LOOP)
1251 result = LLInt::CLoop::execute(closure.newCallFrame, llint_function_for_call_prologue);
1252#elif ENABLE(JIT)
1253 result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_stack, closure.newCallFrame, &vm);
1254#endif // ENABLE(JIT)
ba379fdc 1255 }
6fe7ccc8 1256
93a37866
A
1257 if (LegacyProfiler* profiler = vm.enabledProfiler())
1258 profiler->didExecute(closure.oldCallFrame, closure.function);
1259
1260 m_stack.validateFence(closure.newCallFrame, "AFTER");
14957cd0 1261 return checkedReturn(result);
ba379fdc
A
1262}
1263
1264void Interpreter::endRepeatCall(CallFrameClosure& closure)
1265{
93a37866 1266 m_stack.popFrame(closure.newCallFrame);
ba379fdc
A
1267}
1268
93a37866 1269JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, JSScope* scope)
9dae56ea 1270{
93a37866
A
1271 VM& vm = *scope->vm();
1272 SamplingScope samplingScope(this);
1273
1274 ASSERT(scope->vm() == &callFrame->vm());
6fe7ccc8 1275 ASSERT(isValidThisObject(thisValue, callFrame));
93a37866
A
1276 ASSERT(!vm.exception);
1277 ASSERT(!vm.isCollectorBusy());
1278 if (vm.isCollectorBusy())
14957cd0 1279 return jsNull();
9dae56ea 1280
93a37866 1281 DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
9dae56ea 1282
93a37866
A
1283 StackStats::CheckPoint stackCheckPoint;
1284 const StackBounds& nativeStack = wtfThreadData().stack();
1285 StackPolicy policy(*this, nativeStack);
1286 if (!nativeStack.isSafeToRecurse(policy.requiredCapacity()))
14957cd0 1287 return checkedReturn(throwStackOverflowError(callFrame));
9dae56ea 1288
93a37866
A
1289 // Compile the callee:
1290 JSObject* compileError = eval->compile(callFrame, scope);
14957cd0
A
1291 if (UNLIKELY(!!compileError))
1292 return checkedReturn(throwError(callFrame, compileError));
1293 EvalCodeBlock* codeBlock = &eval->generatedBytecode();
9dae56ea 1294
14957cd0 1295 JSObject* variableObject;
93a37866
A
1296 for (JSScope* node = scope; ; node = node->next()) {
1297 RELEASE_ASSERT(node);
1298 if (node->isVariableObject() && !node->isNameScopeObject()) {
1299 variableObject = node;
9dae56ea
A
1300 break;
1301 }
1302 }
1303
4e4e5a6f
A
1304 unsigned numVariables = codeBlock->numVariables();
1305 int numFunctions = codeBlock->numberOfFunctionDecls();
1306 if (numVariables || numFunctions) {
14957cd0 1307 if (codeBlock->isStrictMode()) {
93a37866
A
1308 scope = StrictEvalActivation::create(callFrame);
1309 variableObject = scope;
14957cd0 1310 }
4e4e5a6f 1311 // Scope for BatchedTransitionOptimizer
93a37866 1312 BatchedTransitionOptimizer optimizer(vm, variableObject);
9dae56ea 1313
f9bf01c6
A
1314 for (unsigned i = 0; i < numVariables; ++i) {
1315 const Identifier& ident = codeBlock->variable(i);
9dae56ea
A
1316 if (!variableObject->hasProperty(callFrame, ident)) {
1317 PutPropertySlot slot;
6fe7ccc8 1318 variableObject->methodTable()->put(variableObject, callFrame, ident, jsUndefined(), slot);
9dae56ea
A
1319 }
1320 }
1321
f9bf01c6
A
1322 for (int i = 0; i < numFunctions; ++i) {
1323 FunctionExecutable* function = codeBlock->functionDecl(i);
9dae56ea 1324 PutPropertySlot slot;
93a37866 1325 variableObject->methodTable()->put(variableObject, callFrame, function->name(), JSFunction::create(callFrame, function, scope), slot);
9dae56ea 1326 }
9dae56ea
A
1327 }
1328
93a37866
A
1329 if (UNLIKELY(vm.watchdog.didFire(callFrame)))
1330 return throwTerminatedExecutionException(callFrame);
6fe7ccc8 1331
93a37866 1332 // Push the frame:
6fe7ccc8 1333 ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
93a37866
A
1334 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, codeBlock, scope, 1, 0);
1335 if (UNLIKELY(!newCallFrame))
1336 return checkedReturn(throwStackOverflowError(callFrame));
9dae56ea 1337
93a37866
A
1338 // Set the arguments for the callee:
1339 newCallFrame->setThisValue(thisValue);
9dae56ea 1340
93a37866
A
1341 if (LegacyProfiler* profiler = vm.enabledProfiler())
1342 profiler->willExecute(callFrame, eval->sourceURL(), eval->lineNo());
9dae56ea 1343
93a37866 1344 // Execute the code:
ba379fdc 1345 JSValue result;
9dae56ea 1346 {
f9bf01c6 1347 SamplingTool::CallRecord callRecord(m_sampler.get());
93a37866 1348 Watchdog::Scope watchdogScope(vm.watchdog);
9dae56ea 1349
93a37866
A
1350#if ENABLE(LLINT_C_LOOP)
1351 result = LLInt::CLoop::execute(newCallFrame, llint_eval_prologue);
1352#elif ENABLE(JIT)
1353 result = eval->generatedJITCode().execute(&m_stack, newCallFrame, &vm);
1354#endif // ENABLE(JIT)
9dae56ea
A
1355 }
1356
93a37866
A
1357 if (LegacyProfiler* profiler = vm.enabledProfiler())
1358 profiler->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
9dae56ea 1359
93a37866 1360 m_stack.popFrame(newCallFrame);
14957cd0 1361 return checkedReturn(result);
9dae56ea
A
1362}
1363
93a37866 1364NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine, int column)
9dae56ea
A
1365{
1366 Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
1367 if (!debugger)
1368 return;
1369
1370 switch (debugHookID) {
1371 case DidEnterCallFrame:
93a37866 1372 debugger->callEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column);
9dae56ea
A
1373 return;
1374 case WillLeaveCallFrame:
93a37866 1375 debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column);
9dae56ea
A
1376 return;
1377 case WillExecuteStatement:
93a37866 1378 debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column);
9dae56ea
A
1379 return;
1380 case WillExecuteProgram:
93a37866 1381 debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column);
9dae56ea
A
1382 return;
1383 case DidExecuteProgram:
93a37866 1384 debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column);
9dae56ea
A
1385 return;
1386 case DidReachBreakpoint:
93a37866 1387 debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column);
9dae56ea
A
1388 return;
1389 }
1390}
9dae56ea 1391
93a37866 1392JSValue Interpreter::retrieveArgumentsFromVMCode(CallFrame* callFrame, JSFunction* function) const
9dae56ea 1393{
93a37866
A
1394 CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function);
1395 if (!functionCallFrame)
1396 return jsNull();
9dae56ea 1397
93a37866
A
1398 Arguments* arguments = Arguments::create(functionCallFrame->vm(), functionCallFrame);
1399 arguments->tearOff(functionCallFrame);
1400 return JSValue(arguments);
9dae56ea
A
1401}
1402
93a37866 1403JSValue Interpreter::retrieveCallerFromVMCode(CallFrame* callFrame, JSFunction* function) const
9dae56ea 1404{
93a37866 1405 CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function);
9dae56ea 1406
93a37866
A
1407 if (!functionCallFrame)
1408 return jsNull();
9dae56ea 1409
93a37866
A
1410 unsigned bytecodeOffset;
1411 CodeBlock* unusedCallerCodeBlock = 0;
1412 CallFrame* callerFrame = getCallerInfo(&callFrame->vm(), functionCallFrame, bytecodeOffset, unusedCallerCodeBlock);
1413 if (!callerFrame)
1414 return jsNull();
1415 JSValue caller = callerFrame->callee();
1416 if (!caller)
1417 return jsNull();
f9bf01c6 1418
93a37866
A
1419 // Skip over function bindings.
1420 ASSERT(caller.isObject());
1421 while (asObject(caller)->inherits(&JSBoundFunction::s_info)) {
1422 callerFrame = getCallerInfo(&callFrame->vm(), callerFrame, bytecodeOffset, unusedCallerCodeBlock);
1423 if (!callerFrame)
1424 return jsNull();
1425 caller = callerFrame->callee();
1426 if (!caller)
1427 return jsNull();
9dae56ea
A
1428 }
1429
93a37866 1430 return caller;
9dae56ea
A
1431}
1432
93a37866 1433void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, String& sourceURL, JSValue& function) const
9dae56ea 1434{
93a37866
A
1435 function = JSValue();
1436 lineNumber = -1;
1437 sourceURL = String();
ba379fdc 1438
93a37866
A
1439 CallFrame* callerFrame = callFrame->callerFrame();
1440 if (callerFrame->hasHostCallFrameFlag())
9dae56ea 1441 return;
9dae56ea 1442
93a37866
A
1443 CodeBlock* callerCodeBlock = callerFrame->codeBlock();
1444 if (!callerCodeBlock)
9dae56ea 1445 return;
4e4e5a6f 1446 unsigned bytecodeOffset = 0;
6fe7ccc8 1447 bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
14957cd0 1448 lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
f9bf01c6
A
1449 sourceID = callerCodeBlock->ownerExecutable()->sourceID();
1450 sourceURL = callerCodeBlock->ownerExecutable()->sourceURL();
9dae56ea
A
1451 function = callerFrame->callee();
1452}
1453
6fe7ccc8 1454CallFrame* Interpreter::findFunctionCallFrameFromVMCode(CallFrame* callFrame, JSFunction* function)
9dae56ea 1455{
6fe7ccc8 1456 for (CallFrame* candidate = callFrame->trueCallFrameFromVMCode(); candidate; candidate = candidate->trueCallerFrame()) {
9dae56ea
A
1457 if (candidate->callee() == function)
1458 return candidate;
1459 }
1460 return 0;
1461}
1462
f9bf01c6
A
1463void Interpreter::enableSampler()
1464{
1465#if ENABLE(OPCODE_SAMPLING)
1466 if (!m_sampler) {
6fe7ccc8 1467 m_sampler = adoptPtr(new SamplingTool(this));
f9bf01c6
A
1468 m_sampler->setup();
1469 }
1470#endif
1471}
1472void Interpreter::dumpSampleData(ExecState* exec)
1473{
1474#if ENABLE(OPCODE_SAMPLING)
1475 if (m_sampler)
1476 m_sampler->dump(exec);
1477#else
1478 UNUSED_PARAM(exec);
1479#endif
1480}
1481void Interpreter::startSampling()
1482{
1483#if ENABLE(SAMPLING_THREAD)
1484 if (!m_sampleEntryDepth)
1485 SamplingThread::start();
1486
1487 m_sampleEntryDepth++;
1488#endif
1489}
1490void Interpreter::stopSampling()
1491{
1492#if ENABLE(SAMPLING_THREAD)
1493 m_sampleEntryDepth--;
1494 if (!m_sampleEntryDepth)
1495 SamplingThread::stop();
1496#endif
1497}
1498
9dae56ea 1499} // namespace JSC