2
* Copyright (C) 2008, 2009, 2010, 2012 Apple Inc. All rights reserved.
3
* Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
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.
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.
31
#include "Interpreter.h"
33
#include "Arguments.h"
34
#include "BatchedTransitionOptimizer.h"
35
#include "CallFrame.h"
36
#include "CallFrameClosure.h"
37
#include "CodeBlock.h"
40
#include "DebuggerCallFrame.h"
41
#include "ErrorInstance.h"
42
#include "EvalCodeCache.h"
43
#include "ExceptionHelpers.h"
44
#include "GetterSetter.h"
45
#include "JSActivation.h"
47
#include "JSBoundFunction.h"
48
#include "JSNameScope.h"
49
#include "JSNotAnObject.h"
50
#include "JSPropertyNameIterator.h"
51
#include "JSStackInlines.h"
53
#include "JSWithScope.h"
54
#include "LLIntCLoop.h"
55
#include "LiteralParser.h"
56
#include "NameInstance.h"
57
#include "ObjectPrototype.h"
58
#include "Operations.h"
61
#include "RegExpObject.h"
62
#include "RegExpPrototype.h"
64
#include "SamplingTool.h"
65
#include "StrictEvalActivation.h"
66
#include "StrongInlines.h"
69
#include <wtf/StackStats.h>
70
#include <wtf/Threading.h>
71
#include <wtf/WTFThreadData.h>
72
#include <wtf/text/StringBuilder.h>
78
#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (ENABLE(LLINT) && !defined(__llvm__))
84
Interpreter::ErrorHandlingMode::ErrorHandlingMode(ExecState *exec)
85
: m_interpreter(*exec->interpreter())
87
if (!m_interpreter.m_errorHandlingModeReentry)
88
m_interpreter.stack().enableErrorStackReserve();
89
m_interpreter.m_errorHandlingModeReentry++;
92
Interpreter::ErrorHandlingMode::~ErrorHandlingMode()
94
m_interpreter.m_errorHandlingModeReentry--;
95
ASSERT(m_interpreter.m_errorHandlingModeReentry >= 0);
96
if (!m_interpreter.m_errorHandlingModeReentry)
97
m_interpreter.stack().disableErrorStackReserve();
101
// The Interpreter::StackPolicy class is used to compute a stack capacity
102
// requirement to ensure that we have enough room on the native stack for:
103
// 1. the max cumulative stack used by the interpreter and all code
104
// paths sub of it up till leaf functions.
105
// 2. the max cumulative stack used by the interpreter before it reaches
106
// the next checkpoint (execute...() function) in the interpreter.
108
// The interpreter can be run on different threads and hence, different
109
// native stacks (with different sizes) before exiting out of the first
110
// frame. Hence, the required capacity needs to be re-computed on every
111
// entry into the interpreter.
113
// Currently the requiredStack is computed based on a policy. See comments
114
// in StackPolicy::StackPolicy() for details.
116
Interpreter::StackPolicy::StackPolicy(Interpreter& interpreter, const StackBounds& stack)
117
: m_interpreter(interpreter)
119
const size_t size = stack.size();
121
const size_t DEFAULT_REQUIRED_STACK = 1024 * 1024;
122
const size_t DEFAULT_MINIMUM_USEABLE_STACK = 128 * 1024;
123
const size_t DEFAULT_ERROR_MODE_REQUIRED_STACK = 32 * 1024;
125
// Here's the policy in a nutshell:
127
// 1. If we have a large stack, let JS use as much stack as possible
128
// but require that we have at least DEFAULT_REQUIRED_STACK capacity
129
// remaining on the stack:
131
// stack grows this way -->
132
// ---------------------------------------------------------
133
// | ... | <-- DEFAULT_REQUIRED_STACK --> | ...
134
// ---------------------------------------------------------
138
// 2. In event that we're re-entering the interpreter to handle
139
// exceptions (in error mode), we'll be a little more generous and
140
// require less stack capacity for the interpreter to be re-entered.
142
// This is needed because we may have just detected an eminent stack
143
// overflow based on the normally computed required stack capacity.
144
// However, the normal required capacity far exceeds what is needed
145
// for exception handling work. Hence, in error mode, we only require
146
// DEFAULT_ERROR_MODE_REQUIRED_STACK capacity.
148
// stack grows this way -->
149
// -----------------------------------------------------------------
150
// | ... | <-- DEFAULT_ERROR_MODE_REQUIRED_STACK --> | ...
151
// -----------------------------------------------------------------
155
// This smaller required capacity also means that we won't re-trigger
156
// a stack overflow for processing the exception caused by the original
157
// StackOverflowError.
159
// 3. If the stack is not large enough, give JS at least a minimum
160
// amount of useable stack:
162
// stack grows this way -->
163
// --------------------------------------------------------------------
164
// | <-- DEFAULT_MINIMUM_USEABLE_STACK --> | <-- requiredCapacity --> |
165
// --------------------------------------------------------------------
169
// The minimum useable capacity is DEFAULT_MINIMUM_USEABLE_STACK.
170
// In this case, the requiredCapacity is whatever is left of the
171
// total stack capacity after we have give JS its minimum stack
172
// i.e. requiredCapacity can even be 0 if there's not enough stack.
175
// Policy 1: Normal mode: required = DEFAULT_REQUIRED_STACK.
176
// Policy 2: Error mode: required = DEFAULT_ERROR_MODE_REQUIRED_STACK.
177
size_t requiredCapacity = !m_interpreter.m_errorHandlingModeReentry ?
178
DEFAULT_REQUIRED_STACK : DEFAULT_ERROR_MODE_REQUIRED_STACK;
180
size_t useableStack = (requiredCapacity <= size) ?
181
size - requiredCapacity : DEFAULT_MINIMUM_USEABLE_STACK;
183
// Policy 3: Ensure the useable stack is not too small:
184
if (useableStack < DEFAULT_MINIMUM_USEABLE_STACK)
185
useableStack = DEFAULT_MINIMUM_USEABLE_STACK;
187
// Sanity check: Make sure we do not use more space than the stack's
189
if (useableStack > size)
192
// Re-compute the requiredCapacity based on the adjusted useable stack
194
requiredCapacity = size - useableStack;
195
ASSERT(requiredCapacity < size);
197
m_requiredCapacity = requiredCapacity;
201
static CallFrame* getCallerInfo(JSGlobalData*, CallFrame*, int& lineNumber, unsigned& bytecodeOffset);
203
// Returns the depth of the scope chain within a given call frame.
204
static int depth(CodeBlock* codeBlock, JSScope* sc)
206
if (!codeBlock->needsFullScopeChain())
208
return sc->localDepth();
211
JSValue eval(CallFrame* callFrame)
213
if (!callFrame->argumentCount())
214
return jsUndefined();
216
JSValue program = callFrame->argument(0);
217
if (!program.isString())
220
TopCallFrameSetter topCallFrame(callFrame->globalData(), callFrame);
221
String programSource = asString(program)->value(callFrame);
222
if (callFrame->hadException())
225
CallFrame* callerFrame = callFrame->callerFrame();
226
CodeBlock* callerCodeBlock = callerFrame->codeBlock();
227
JSScope* callerScopeChain = callerFrame->scope();
228
EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(callerCodeBlock->isStrictMode(), programSource, callerScopeChain);
231
if (!callerCodeBlock->isStrictMode()) {
232
// FIXME: We can use the preparser in strict mode, we just need additional logic
233
// to prevent duplicates.
234
if (programSource.is8Bit()) {
235
LiteralParser<LChar> preparser(callFrame, programSource.characters8(), programSource.length(), NonStrictJSON);
236
if (JSValue parsedObject = preparser.tryLiteralParse())
239
LiteralParser<UChar> preparser(callFrame, programSource.characters16(), programSource.length(), NonStrictJSON);
240
if (JSValue parsedObject = preparser.tryLiteralParse())
245
// If the literal parser bailed, it should not have thrown exceptions.
246
ASSERT(!callFrame->globalData().exception);
248
JSValue exceptionValue;
249
eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->ownerExecutable(), callerCodeBlock->isStrictMode(), programSource, callerScopeChain, exceptionValue);
251
ASSERT(!eval == exceptionValue);
253
return throwError(callFrame, exceptionValue);
256
JSValue thisValue = callerFrame->thisValue();
257
ASSERT(isValidThisObject(thisValue, callFrame));
258
Interpreter* interpreter = callFrame->globalData().interpreter;
259
return interpreter->execute(eval, callFrame, thisValue, callerScopeChain);
262
CallFrame* loadVarargs(CallFrame* callFrame, JSStack* stack, JSValue thisValue, JSValue arguments, int firstFreeRegister)
264
if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
265
unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
266
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + argumentCountIncludingThis + JSStack::CallFrameHeaderSize);
267
if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !stack->grow(newCallFrame->registers())) {
268
callFrame->globalData().exception = createStackOverflowError(callFrame);
272
newCallFrame->setArgumentCountIncludingThis(argumentCountIncludingThis);
273
newCallFrame->setThisValue(thisValue);
274
for (size_t i = 0; i < callFrame->argumentCount(); ++i)
275
newCallFrame->setArgument(i, callFrame->argumentAfterCapture(i));
279
if (arguments.isUndefinedOrNull()) {
280
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + 1 + JSStack::CallFrameHeaderSize);
281
if (!stack->grow(newCallFrame->registers())) {
282
callFrame->globalData().exception = createStackOverflowError(callFrame);
285
newCallFrame->setArgumentCountIncludingThis(1);
286
newCallFrame->setThisValue(thisValue);
290
if (!arguments.isObject()) {
291
callFrame->globalData().exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
295
if (asObject(arguments)->classInfo() == &Arguments::s_info) {
296
Arguments* argsObject = asArguments(arguments);
297
unsigned argCount = argsObject->length(callFrame);
298
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
299
if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) {
300
callFrame->globalData().exception = createStackOverflowError(callFrame);
303
newCallFrame->setArgumentCountIncludingThis(argCount + 1);
304
newCallFrame->setThisValue(thisValue);
305
argsObject->copyToArguments(callFrame, newCallFrame, argCount);
309
if (isJSArray(arguments)) {
310
JSArray* array = asArray(arguments);
311
unsigned argCount = array->length();
312
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
313
if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) {
314
callFrame->globalData().exception = createStackOverflowError(callFrame);
317
newCallFrame->setArgumentCountIncludingThis(argCount + 1);
318
newCallFrame->setThisValue(thisValue);
319
array->copyToArguments(callFrame, newCallFrame, argCount);
323
JSObject* argObject = asObject(arguments);
324
unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
325
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
326
if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) {
327
callFrame->globalData().exception = createStackOverflowError(callFrame);
330
newCallFrame->setArgumentCountIncludingThis(argCount + 1);
331
newCallFrame->setThisValue(thisValue);
332
for (size_t i = 0; i < argCount; ++i) {
333
newCallFrame->setArgument(i, asObject(arguments)->get(callFrame, i));
334
if (UNLIKELY(callFrame->globalData().exception))
340
Interpreter::Interpreter(JSGlobalData& globalData)
341
: m_sampleEntryDepth(0)
342
, m_stack(globalData)
343
, m_errorHandlingModeReentry(0)
345
, m_initialized(false)
350
Interpreter::~Interpreter()
354
void Interpreter::initialize(bool canUseJIT)
356
UNUSED_PARAM(canUseJIT);
358
#if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT)
359
m_opcodeTable = LLInt::opcodeMap();
360
for (int i = 0; i < numOpcodeIDs; ++i)
361
m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
365
m_initialized = true;
368
#if ENABLE(OPCODE_SAMPLING)
375
void Interpreter::dumpCallFrame(CallFrame*)
381
void Interpreter::dumpCallFrame(CallFrame* callFrame)
383
callFrame->codeBlock()->dumpBytecode();
384
dumpRegisters(callFrame);
387
void Interpreter::dumpRegisters(CallFrame* callFrame)
389
dataLogF("Register frame: \n\n");
390
dataLogF("-----------------------------------------------------------------------------\n");
391
dataLogF(" use | address | value \n");
392
dataLogF("-----------------------------------------------------------------------------\n");
394
CodeBlock* codeBlock = callFrame->codeBlock();
398
it = callFrame->registers() - JSStack::CallFrameHeaderSize - callFrame->argumentCountIncludingThis();
399
end = callFrame->registers() - JSStack::CallFrameHeaderSize;
401
JSValue v = it->jsValue();
402
int registerNumber = it - callFrame->registers();
403
String name = codeBlock->nameForRegister(registerNumber);
404
dataLogF("[r% 3d %14s] | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, v.description(), (long long)JSValue::encode(v));
408
dataLogF("-----------------------------------------------------------------------------\n");
409
dataLogF("[ArgumentCount] | %10p | %lu \n", it, (unsigned long) callFrame->argumentCount());
411
dataLogF("[CallerFrame] | %10p | %p \n", it, callFrame->callerFrame());
413
dataLogF("[Callee] | %10p | %p \n", it, callFrame->callee());
415
dataLogF("[ScopeChain] | %10p | %p \n", it, callFrame->scope());
418
AbstractPC pc = callFrame->abstractReturnPC(callFrame->globalData());
419
if (pc.hasJITReturnAddress())
420
dataLogF("[ReturnJITPC] | %10p | %p \n", it, pc.jitReturnAddress().value());
422
unsigned bytecodeOffset = 0;
424
getCallerInfo(&callFrame->globalData(), callFrame, line, bytecodeOffset);
425
dataLogF("[ReturnVPC] | %10p | %d (line %d)\n", it, bytecodeOffset, line);
427
dataLogF("[CodeBlock] | %10p | %p \n", it, callFrame->codeBlock());
429
dataLogF("-----------------------------------------------------------------------------\n");
431
int registerCount = 0;
433
end = it + codeBlock->m_numVars;
436
JSValue v = it->jsValue();
437
int registerNumber = it - callFrame->registers();
438
String name = codeBlock->nameForRegister(registerNumber);
439
dataLogF("[r% 3d %14s] | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, v.description(), (long long)JSValue::encode(v));
444
dataLogF("-----------------------------------------------------------------------------\n");
446
end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars;
449
JSValue v = (*it).jsValue();
450
dataLogF("[r% 3d] | %10p | %-16s 0x%lld \n", registerCount, it, v.description(), (long long)JSValue::encode(v));
455
dataLogF("-----------------------------------------------------------------------------\n");
460
bool Interpreter::isOpcode(Opcode opcode)
462
#if ENABLE(COMPUTED_GOTO_OPCODES)
464
return static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)) <= op_end;
466
return opcode != HashTraits<Opcode>::emptyValue()
467
&& !HashTraits<Opcode>::isDeletedValue(opcode)
468
&& m_opcodeIDTable.contains(opcode);
471
return opcode >= 0 && opcode <= op_end;
475
NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
477
CodeBlock* oldCodeBlock = codeBlock;
478
JSScope* scope = callFrame->scope();
480
if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
481
DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
482
if (callFrame->callee())
483
debugger->returnEvent(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine(), 0);
485
debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine(), 0);
489
if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsActivation()) {
490
activation = callFrame->uncheckedR(oldCodeBlock->activationRegister()).jsValue();
492
jsCast<JSActivation*>(activation)->tearOff(*scope->globalData());
495
if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->usesArguments()) {
496
if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) {
498
jsCast<Arguments*>(arguments)->didTearOffActivation(callFrame, jsCast<JSActivation*>(activation));
500
jsCast<Arguments*>(arguments)->tearOff(callFrame);
504
CallFrame* callerFrame = callFrame->callerFrame();
505
callFrame->globalData().topCallFrame = callerFrame;
506
if (callerFrame->hasHostCallFrameFlag())
509
codeBlock = callerFrame->codeBlock();
511
// Because of how the JIT records call site->bytecode offset
512
// information the JIT reports the bytecodeOffset for the returnPC
513
// to be at the beginning of the opcode that has caused the call.
514
#if ENABLE(JIT) || ENABLE(LLINT)
515
bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
518
callFrame = callerFrame;
522
static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception, unsigned bytecodeOffset)
524
exception->clearAppendSourceToMessage();
526
if (!callFrame->codeBlock()->hasExpressionInfo())
533
CodeBlock* codeBlock = callFrame->codeBlock();
534
codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divotPoint, startOffset, endOffset);
536
int expressionStart = divotPoint - startOffset;
537
int expressionStop = divotPoint + endOffset;
539
const String& sourceString = codeBlock->source()->source();
540
if (!expressionStop || expressionStart > static_cast<int>(sourceString.length()))
543
JSGlobalData* globalData = &callFrame->globalData();
544
JSValue jsMessage = exception->getDirect(*globalData, globalData->propertyNames->message);
545
if (!jsMessage || !jsMessage.isString())
548
String message = asString(jsMessage)->value(callFrame);
550
if (expressionStart < expressionStop)
551
message = makeString(message, " (evaluating '", codeBlock->source()->getRange(expressionStart, expressionStop), "')");
553
// No range information, so give a few characters of context
554
const StringImpl* data = sourceString.impl();
555
int dataLength = sourceString.length();
556
int start = expressionStart;
557
int stop = expressionStart;
558
// Get up to 20 characters of context to the left and right of the divot, clamping to the line.
559
// then strip whitespace.
560
while (start > 0 && (expressionStart - start < 20) && (*data)[start - 1] != '\n')
562
while (start < (expressionStart - 1) && isStrWhiteSpace((*data)[start]))
564
while (stop < dataLength && (stop - expressionStart < 20) && (*data)[stop] != '\n')
566
while (stop > expressionStart && isStrWhiteSpace((*data)[stop - 1]))
568
message = makeString(message, " (near '...", codeBlock->source()->getRange(start, stop), "...')");
571
exception->putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message));
574
static int getLineNumberForCallFrame(JSGlobalData* globalData, CallFrame* callFrame)
576
UNUSED_PARAM(globalData);
577
callFrame = callFrame->removeHostCallFrameFlag();
578
CodeBlock* codeBlock = callFrame->codeBlock();
581
#if ENABLE(JIT) || ENABLE(LLINT)
583
if (codeBlock->getJITType() == JITCode::DFGJIT)
584
return codeBlock->lineNumberForBytecodeOffset(codeBlock->codeOrigin(callFrame->codeOriginIndexForDFG()).bytecodeIndex);
586
return codeBlock->lineNumberForBytecodeOffset(callFrame->bytecodeOffsetForNonDFGCode());
590
static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, int& lineNumber, unsigned& bytecodeOffset)
592
UNUSED_PARAM(globalData);
595
ASSERT(!callFrame->hasHostCallFrameFlag());
596
CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : callFrame->callerFrame()->removeHostCallFrameFlag();
597
bool callframeIsHost = callerFrame->addHostCallFrameFlag() == callFrame->callerFrame();
598
ASSERT(!callerFrame->hasHostCallFrameFlag());
600
if (callerFrame == CallFrame::noCaller() || !callerFrame || !callerFrame->codeBlock())
603
CodeBlock* callerCodeBlock = callerFrame->codeBlock();
605
#if ENABLE(JIT) || ENABLE(LLINT)
606
if (!callFrame->hasReturnPC())
607
callframeIsHost = true;
610
if (callFrame->isInlineCallFrame())
611
callframeIsHost = false;
614
if (callframeIsHost) {
615
// Don't need to deal with inline callframes here as by definition we haven't
616
// inlined a call with an intervening native call frame.
617
#if ENABLE(JIT) || ENABLE(LLINT)
619
if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) {
620
unsigned codeOriginIndex = callerFrame->codeOriginIndexForDFG();
621
bytecodeOffset = callerCodeBlock->codeOrigin(codeOriginIndex).bytecodeIndex;
624
bytecodeOffset = callerFrame->bytecodeOffsetForNonDFGCode();
627
#if ENABLE(JIT) || ENABLE(LLINT)
629
if (callFrame->isInlineCallFrame()) {
630
InlineCallFrame* icf = callFrame->inlineCallFrame();
631
bytecodeOffset = icf->caller.bytecodeIndex;
632
if (InlineCallFrame* parentCallFrame = icf->caller.inlineCallFrame) {
633
FunctionExecutable* executable = static_cast<FunctionExecutable*>(parentCallFrame->executable.get());
634
CodeBlock* newCodeBlock = executable->baselineCodeBlockFor(parentCallFrame->isCall ? CodeForCall : CodeForConstruct);
635
ASSERT(newCodeBlock);
636
ASSERT(newCodeBlock->instructionCount() > bytecodeOffset);
637
callerCodeBlock = newCodeBlock;
639
} else if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) {
641
if (!callerCodeBlock->codeOriginForReturn(callFrame->returnPC(), origin))
642
ASSERT_NOT_REACHED();
643
bytecodeOffset = origin.bytecodeIndex;
644
if (InlineCallFrame* icf = origin.inlineCallFrame) {
645
FunctionExecutable* executable = static_cast<FunctionExecutable*>(icf->executable.get());
646
CodeBlock* newCodeBlock = executable->baselineCodeBlockFor(icf->isCall ? CodeForCall : CodeForConstruct);
647
ASSERT(newCodeBlock);
648
ASSERT(newCodeBlock->instructionCount() > bytecodeOffset);
649
callerCodeBlock = newCodeBlock;
653
bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
657
lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset);
661
static ALWAYS_INLINE const String getSourceURLFromCallFrame(CallFrame* callFrame)
663
ASSERT(!callFrame->hasHostCallFrameFlag());
664
return callFrame->codeBlock()->ownerExecutable()->sourceURL();
667
static StackFrameCodeType getStackFrameCodeType(CallFrame* callFrame)
669
ASSERT(!callFrame->hasHostCallFrameFlag());
671
switch (callFrame->codeBlock()->codeType()) {
673
return StackFrameEvalCode;
675
return StackFrameFunctionCode;
677
return StackFrameGlobalCode;
679
ASSERT_NOT_REACHED();
680
return StackFrameGlobalCode;
683
void Interpreter::getStackTrace(JSGlobalData* globalData, Vector<StackFrame>& results)
685
CallFrame* callFrame = globalData->topCallFrame->removeHostCallFrameFlag();
686
if (!callFrame || callFrame == CallFrame::noCaller())
688
int line = getLineNumberForCallFrame(globalData, callFrame);
690
callFrame = callFrame->trueCallFrameFromVMCode();
692
while (callFrame && callFrame != CallFrame::noCaller()) {
694
if (callFrame->codeBlock()) {
695
sourceURL = getSourceURLFromCallFrame(callFrame);
696
StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), getStackFrameCodeType(callFrame), Strong<ExecutableBase>(*globalData, callFrame->codeBlock()->ownerExecutable()), line, sourceURL};
699
StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), -1, String()};
702
unsigned unusedBytecodeOffset = 0;
703
callFrame = getCallerInfo(globalData, callFrame, line, unusedBytecodeOffset);
707
void Interpreter::addStackTraceIfNecessary(CallFrame* callFrame, JSObject* error)
709
JSGlobalData* globalData = &callFrame->globalData();
710
ASSERT(callFrame == globalData->topCallFrame || callFrame == callFrame->lexicalGlobalObject()->globalExec() || callFrame == callFrame->dynamicGlobalObject()->globalExec());
711
if (error->hasProperty(callFrame, globalData->propertyNames->stack))
714
Vector<StackFrame> stackTrace;
715
getStackTrace(&callFrame->globalData(), stackTrace);
717
if (stackTrace.isEmpty())
720
JSGlobalObject* globalObject = 0;
721
if (isTerminatedExecutionException(error) || isInterruptedExecutionException(error))
722
globalObject = globalData->dynamicGlobalObject;
724
globalObject = error->globalObject();
726
// FIXME: JSStringJoiner could be more efficient than StringBuilder here.
727
StringBuilder builder;
728
for (unsigned i = 0; i < stackTrace.size(); i++) {
729
builder.append(String(stackTrace[i].toString(globalObject->globalExec()).impl()));
730
if (i != stackTrace.size() - 1)
731
builder.append('\n');
734
error->putDirect(*globalData, globalData->propertyNames->stack, jsString(globalData, builder.toString()), ReadOnly | DontDelete);
737
NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
739
CodeBlock* codeBlock = callFrame->codeBlock();
740
bool isInterrupt = false;
742
ASSERT(!exceptionValue.isEmpty());
743
ASSERT(!exceptionValue.isCell() || exceptionValue.asCell());
744
// This shouldn't be possible (hence the assertions), but we're already in the slowest of
745
// slow cases, so let's harden against it anyway to be safe.
746
if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
747
exceptionValue = jsNull();
749
// Set up the exception object
750
if (exceptionValue.isObject()) {
751
JSObject* exception = asObject(exceptionValue);
753
if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage())
754
appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), bytecodeOffset);
756
if (!hasErrorInfo(callFrame, exception)) {
757
// FIXME: should only really be adding these properties to VM generated exceptions,
758
// but the inspector currently requires these for all thrown objects.
759
addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source());
762
isInterrupt = isInterruptedExecutionException(exception) || isTerminatedExecutionException(exception);
765
if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
766
DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
767
bool hasHandler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
768
debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), 0, hasHandler);
771
// Calculate an exception handler vPC, unwinding call frames as necessary.
772
HandlerInfo* handler = 0;
773
while (isInterrupt || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
774
if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
775
if (Profiler* profiler = callFrame->globalData().enabledProfiler())
776
profiler->exceptionUnwind(callFrame);
781
if (Profiler* profiler = callFrame->globalData().enabledProfiler())
782
profiler->exceptionUnwind(callFrame);
784
// Unwind the scope chain within the exception handler's call frame.
785
JSScope* scope = callFrame->scope();
787
if (!codeBlock->needsFullScopeChain() || codeBlock->codeType() != FunctionCode
788
|| callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
789
scopeDelta = depth(codeBlock, scope) - handler->scopeDepth;
790
ASSERT(scopeDelta >= 0);
792
scope = scope->next();
793
callFrame->setScope(scope);
798
static inline JSValue checkedReturn(JSValue returnValue)
804
static inline JSObject* checkedReturn(JSObject* returnValue)
810
class SamplingScope {
812
SamplingScope(Interpreter* interpreter)
813
: m_interpreter(interpreter)
815
interpreter->startSampling();
819
m_interpreter->stopSampling();
822
Interpreter* m_interpreter;
825
JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, JSObject* thisObj)
827
SamplingScope samplingScope(this);
829
JSScope* scope = callFrame->scope();
830
JSGlobalData& globalData = *scope->globalData();
832
ASSERT(isValidThisObject(thisObj, callFrame));
833
ASSERT(!globalData.exception);
834
ASSERT(!globalData.isCollectorBusy());
835
if (globalData.isCollectorBusy())
838
StackStats::CheckPoint stackCheckPoint;
839
const StackBounds& nativeStack = wtfThreadData().stack();
840
StackPolicy policy(*this, nativeStack);
841
if (!nativeStack.isSafeToRecurse(policy.requiredCapacity()))
842
return checkedReturn(throwStackOverflowError(callFrame));
844
// First check if the "program" is actually just a JSON object. If so,
845
// we'll handle the JSON object here. Else, we'll handle real JS code
846
// below at failedJSONP.
847
DynamicGlobalObjectScope globalObjectScope(globalData, scope->globalObject());
848
Vector<JSONPData> JSONPData;
850
const String programSource = program->source().toString();
851
if (programSource.isNull())
852
return jsUndefined();
853
if (programSource.is8Bit()) {
854
LiteralParser<LChar> literalParser(callFrame, programSource.characters8(), programSource.length(), JSONP);
855
parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
857
LiteralParser<UChar> literalParser(callFrame, programSource.characters16(), programSource.length(), JSONP);
858
parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
862
JSGlobalObject* globalObject = scope->globalObject();
864
for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
865
Vector<JSONPPathEntry> JSONPPath;
866
JSONPPath.swap(JSONPData[entry].m_path);
867
JSValue JSONPValue = JSONPData[entry].m_value.get();
868
if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclare) {
869
if (globalObject->hasProperty(callFrame, JSONPPath[0].m_pathEntryName)) {
870
PutPropertySlot slot;
871
globalObject->methodTable()->put(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
873
globalObject->methodTable()->putDirectVirtual(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, DontEnum | DontDelete);
874
// var declarations return undefined
875
result = jsUndefined();
878
JSValue baseObject(globalObject);
879
for (unsigned i = 0; i < JSONPPath.size() - 1; i++) {
880
ASSERT(JSONPPath[i].m_type != JSONPPathEntryTypeDeclare);
881
switch (JSONPPath[i].m_type) {
882
case JSONPPathEntryTypeDot: {
884
PropertySlot slot(globalObject);
885
if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
887
return throwError(callFrame, createUndefinedVariableError(globalObject->globalExec(), JSONPPath[i].m_pathEntryName));
890
baseObject = slot.getValue(callFrame, JSONPPath[i].m_pathEntryName);
892
baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathEntryName);
893
if (callFrame->hadException())
894
return jsUndefined();
897
case JSONPPathEntryTypeLookup: {
898
baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
899
if (callFrame->hadException())
900
return jsUndefined();
904
ASSERT_NOT_REACHED();
905
return jsUndefined();
908
PutPropertySlot slot;
909
switch (JSONPPath.last().m_type) {
910
case JSONPPathEntryTypeCall: {
911
JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
912
if (callFrame->hadException())
913
return jsUndefined();
915
CallType callType = getCallData(function, callData);
916
if (callType == CallTypeNone)
917
return throwError(callFrame, createNotAFunctionError(callFrame, function));
918
MarkedArgumentBuffer jsonArg;
919
jsonArg.append(JSONPValue);
920
JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined(): baseObject;
921
JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg);
922
if (callFrame->hadException())
923
return jsUndefined();
926
case JSONPPathEntryTypeDot: {
927
baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
928
if (callFrame->hadException())
929
return jsUndefined();
932
case JSONPPathEntryTypeLookup: {
933
baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
934
if (callFrame->hadException())
935
return jsUndefined();
939
ASSERT_NOT_REACHED();
940
return jsUndefined();
947
// If we get here, then we have already proven that the script is not a JSON
950
// Compile source to bytecode if necessary:
951
if (JSObject* error = program->initalizeGlobalProperties(globalData, callFrame, scope))
952
return checkedReturn(throwError(callFrame, error));
954
if (JSObject* error = program->compile(callFrame, scope))
955
return checkedReturn(throwError(callFrame, error));
957
ProgramCodeBlock* codeBlock = &program->generatedBytecode();
959
// Push the call frame for this invocation:
960
ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
961
CallFrame* newCallFrame = m_stack.pushFrame(callFrame, codeBlock, scope, 1, 0);
962
if (UNLIKELY(!newCallFrame))
963
return checkedReturn(throwStackOverflowError(callFrame));
965
// Set the arguments for the callee:
966
newCallFrame->setThisValue(thisObj);
968
if (Profiler* profiler = globalData.enabledProfiler())
969
profiler->willExecute(callFrame, program->sourceURL(), program->lineNo());
974
SamplingTool::CallRecord callRecord(m_sampler.get());
976
#if ENABLE(LLINT_C_LOOP)
977
result = LLInt::CLoop::execute(newCallFrame, llint_program_prologue);
979
result = program->generatedJITCode().execute(&m_stack, newCallFrame, &globalData);
980
#endif // ENABLE(JIT)
983
if (Profiler* profiler = globalData.enabledProfiler())
984
profiler->didExecute(callFrame, program->sourceURL(), program->lineNo());
986
m_stack.popFrame(newCallFrame);
988
return checkedReturn(result);
991
JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
993
JSGlobalData& globalData = callFrame->globalData();
994
ASSERT(isValidThisObject(thisValue, callFrame));
995
ASSERT(!callFrame->hadException());
996
ASSERT(!globalData.isCollectorBusy());
997
if (globalData.isCollectorBusy())
1000
StackStats::CheckPoint stackCheckPoint;
1001
const StackBounds& nativeStack = wtfThreadData().stack();
1002
StackPolicy policy(*this, nativeStack);
1003
if (!nativeStack.isSafeToRecurse(policy.requiredCapacity()))
1004
return checkedReturn(throwStackOverflowError(callFrame));
1006
bool isJSCall = (callType == CallTypeJS);
1008
CodeBlock* newCodeBlock;
1009
size_t argsCount = 1 + args.size(); // implicit "this" parameter
1012
scope = callData.js.scope;
1014
ASSERT(callType == CallTypeHost);
1015
scope = callFrame->scope();
1017
DynamicGlobalObjectScope globalObjectScope(globalData, scope->globalObject());
1020
// Compile the callee:
1021
JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, scope);
1022
if (UNLIKELY(!!compileError)) {
1023
return checkedReturn(throwError(callFrame, compileError));
1025
newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
1026
ASSERT(!!newCodeBlock);
1030
CallFrame* newCallFrame = m_stack.pushFrame(callFrame, newCodeBlock, scope, argsCount, function);
1031
if (UNLIKELY(!newCallFrame))
1032
return checkedReturn(throwStackOverflowError(callFrame));
1034
// Set the arguments for the callee:
1035
newCallFrame->setThisValue(thisValue);
1036
for (size_t i = 0; i < args.size(); ++i)
1037
newCallFrame->setArgument(i, args.at(i));
1039
if (Profiler* profiler = globalData.enabledProfiler())
1040
profiler->willExecute(callFrame, function);
1044
SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSCall);
1046
// Execute the code:
1048
#if ENABLE(LLINT_C_LOOP)
1049
result = LLInt::CLoop::execute(newCallFrame, llint_function_for_call_prologue);
1051
result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_stack, newCallFrame, &globalData);
1052
#endif // ENABLE(JIT)
1054
result = JSValue::decode(callData.native.function(newCallFrame));
1057
if (Profiler* profiler = globalData.enabledProfiler())
1058
profiler->didExecute(callFrame, function);
1060
m_stack.popFrame(newCallFrame);
1061
return checkedReturn(result);
1064
JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
1066
JSGlobalData& globalData = callFrame->globalData();
1067
ASSERT(!callFrame->hadException());
1068
ASSERT(!globalData.isCollectorBusy());
1069
// We throw in this case because we have to return something "valid" but we're
1070
// already in an invalid state.
1071
if (globalData.isCollectorBusy())
1072
return checkedReturn(throwStackOverflowError(callFrame));
1074
StackStats::CheckPoint stackCheckPoint;
1075
const StackBounds& nativeStack = wtfThreadData().stack();
1076
StackPolicy policy(*this, nativeStack);
1077
if (!nativeStack.isSafeToRecurse(policy.requiredCapacity()))
1078
return checkedReturn(throwStackOverflowError(callFrame));
1080
bool isJSConstruct = (constructType == ConstructTypeJS);
1082
CodeBlock* newCodeBlock;
1083
size_t argsCount = 1 + args.size(); // implicit "this" parameter
1086
scope = constructData.js.scope;
1088
ASSERT(constructType == ConstructTypeHost);
1089
scope = callFrame->scope();
1092
DynamicGlobalObjectScope globalObjectScope(globalData, scope->globalObject());
1094
if (isJSConstruct) {
1095
// Compile the callee:
1096
JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, scope);
1097
if (UNLIKELY(!!compileError)) {
1098
return checkedReturn(throwError(callFrame, compileError));
1100
newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
1101
ASSERT(!!newCodeBlock);
1105
CallFrame* newCallFrame = m_stack.pushFrame(callFrame, newCodeBlock, scope, argsCount, constructor);
1106
if (UNLIKELY(!newCallFrame))
1107
return checkedReturn(throwStackOverflowError(callFrame));
1109
// Set the arguments for the callee:
1110
newCallFrame->setThisValue(jsUndefined());
1111
for (size_t i = 0; i < args.size(); ++i)
1112
newCallFrame->setArgument(i, args.at(i));
1114
if (Profiler* profiler = globalData.enabledProfiler())
1115
profiler->willExecute(callFrame, constructor);
1119
SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSConstruct);
1121
// Execute the code.
1122
if (isJSConstruct) {
1123
#if ENABLE(LLINT_C_LOOP)
1124
result = LLInt::CLoop::execute(newCallFrame, llint_function_for_construct_prologue);
1126
result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_stack, newCallFrame, &globalData);
1127
#endif // ENABLE(JIT)
1129
result = JSValue::decode(constructData.native.function(newCallFrame));
1133
if (Profiler* profiler = globalData.enabledProfiler())
1134
profiler->didExecute(callFrame, constructor);
1136
m_stack.popFrame(newCallFrame);
1138
if (callFrame->hadException())
1140
ASSERT(result.isObject());
1141
return checkedReturn(asObject(result));
1144
CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, int argumentCountIncludingThis, JSScope* scope)
1146
JSGlobalData& globalData = *scope->globalData();
1147
ASSERT(!globalData.exception);
1149
if (globalData.isCollectorBusy())
1150
return CallFrameClosure();
1152
StackStats::CheckPoint stackCheckPoint;
1153
const StackBounds& nativeStack = wtfThreadData().stack();
1154
StackPolicy policy(*this, nativeStack);
1155
if (!nativeStack.isSafeToRecurse(policy.requiredCapacity())) {
1156
throwStackOverflowError(callFrame);
1157
return CallFrameClosure();
1160
// Compile the callee:
1161
JSObject* error = functionExecutable->compileForCall(callFrame, scope);
1163
throwError(callFrame, error);
1164
return CallFrameClosure();
1166
CodeBlock* newCodeBlock = &functionExecutable->generatedBytecodeForCall();
1168
size_t argsCount = argumentCountIncludingThis;
1170
CallFrame* newCallFrame = m_stack.pushFrame(callFrame, newCodeBlock, scope, argsCount, function);
1171
if (UNLIKELY(!newCallFrame)) {
1172
throwStackOverflowError(callFrame);
1173
return CallFrameClosure();
1176
if (UNLIKELY(!newCallFrame)) {
1177
throwStackOverflowError(callFrame);
1178
return CallFrameClosure();
1181
// Return the successful closure:
1182
CallFrameClosure result = { callFrame, newCallFrame, function, functionExecutable, &globalData, scope, newCodeBlock->numParameters(), argumentCountIncludingThis };
1186
JSValue Interpreter::execute(CallFrameClosure& closure)
1188
JSGlobalData& globalData = *closure.globalData;
1189
SamplingScope samplingScope(this);
1191
ASSERT(!globalData.isCollectorBusy());
1192
if (globalData.isCollectorBusy())
1195
StackStats::CheckPoint stackCheckPoint;
1196
m_stack.validateFence(closure.newCallFrame, "BEFORE");
1197
closure.resetCallFrame();
1198
m_stack.validateFence(closure.newCallFrame, "STEP 1");
1200
if (Profiler* profiler = globalData.enabledProfiler())
1201
profiler->willExecute(closure.oldCallFrame, closure.function);
1203
// The code execution below may push more frames and point the topCallFrame
1204
// to those newer frames, or it may pop to the top frame to the caller of
1205
// the current repeat frame, or it may leave the top frame pointing to the
1206
// current repeat frame.
1208
// Hence, we need to preserve the topCallFrame here ourselves before
1209
// repeating this call on a second callback function.
1211
TopCallFrameSetter topCallFrame(globalData, closure.newCallFrame);
1213
// Execute the code:
1216
SamplingTool::CallRecord callRecord(m_sampler.get());
1218
#if ENABLE(LLINT_C_LOOP)
1219
result = LLInt::CLoop::execute(closure.newCallFrame, llint_function_for_call_prologue);
1221
result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_stack, closure.newCallFrame, &globalData);
1222
#endif // ENABLE(JIT)
1225
if (Profiler* profiler = globalData.enabledProfiler())
1226
profiler->didExecute(closure.oldCallFrame, closure.function);
1228
m_stack.validateFence(closure.newCallFrame, "AFTER");
1229
return checkedReturn(result);
1232
void Interpreter::endRepeatCall(CallFrameClosure& closure)
1234
m_stack.popFrame(closure.newCallFrame);
1237
JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, JSScope* scope)
1239
JSGlobalData& globalData = *scope->globalData();
1240
SamplingScope samplingScope(this);
1242
ASSERT(scope->globalData() == &callFrame->globalData());
1243
ASSERT(isValidThisObject(thisValue, callFrame));
1244
ASSERT(!globalData.exception);
1245
ASSERT(!globalData.isCollectorBusy());
1246
if (globalData.isCollectorBusy())
1249
DynamicGlobalObjectScope globalObjectScope(globalData, scope->globalObject());
1251
StackStats::CheckPoint stackCheckPoint;
1252
const StackBounds& nativeStack = wtfThreadData().stack();
1253
StackPolicy policy(*this, nativeStack);
1254
if (!nativeStack.isSafeToRecurse(policy.requiredCapacity()))
1255
return checkedReturn(throwStackOverflowError(callFrame));
1257
// Compile the callee:
1258
JSObject* compileError = eval->compile(callFrame, scope);
1259
if (UNLIKELY(!!compileError))
1260
return checkedReturn(throwError(callFrame, compileError));
1261
EvalCodeBlock* codeBlock = &eval->generatedBytecode();
1263
JSObject* variableObject;
1264
for (JSScope* node = scope; ; node = node->next()) {
1266
if (node->isVariableObject() && !node->isNameScopeObject()) {
1267
variableObject = node;
1272
unsigned numVariables = codeBlock->numVariables();
1273
int numFunctions = codeBlock->numberOfFunctionDecls();
1274
if (numVariables || numFunctions) {
1275
if (codeBlock->isStrictMode()) {
1276
scope = StrictEvalActivation::create(callFrame);
1277
variableObject = scope;
1279
// Scope for BatchedTransitionOptimizer
1280
BatchedTransitionOptimizer optimizer(globalData, variableObject);
1282
for (unsigned i = 0; i < numVariables; ++i) {
1283
const Identifier& ident = codeBlock->variable(i);
1284
if (!variableObject->hasProperty(callFrame, ident)) {
1285
PutPropertySlot slot;
1286
variableObject->methodTable()->put(variableObject, callFrame, ident, jsUndefined(), slot);
1290
for (int i = 0; i < numFunctions; ++i) {
1291
FunctionExecutable* function = codeBlock->functionDecl(i);
1292
PutPropertySlot slot;
1293
variableObject->methodTable()->put(variableObject, callFrame, function->name(), JSFunction::create(callFrame, function, scope), slot);
1298
ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1299
CallFrame* newCallFrame = m_stack.pushFrame(callFrame, codeBlock, scope, 1, 0);
1300
if (UNLIKELY(!newCallFrame))
1301
return checkedReturn(throwStackOverflowError(callFrame));
1303
// Set the arguments for the callee:
1304
newCallFrame->setThisValue(thisValue);
1306
if (Profiler* profiler = globalData.enabledProfiler())
1307
profiler->willExecute(callFrame, eval->sourceURL(), eval->lineNo());
1309
// Execute the code:
1312
SamplingTool::CallRecord callRecord(m_sampler.get());
1314
#if ENABLE(LLINT_C_LOOP)
1315
result = LLInt::CLoop::execute(newCallFrame, llint_eval_prologue);
1317
result = eval->generatedJITCode().execute(&m_stack, newCallFrame, &globalData);
1318
#endif // ENABLE(JIT)
1321
if (Profiler* profiler = globalData.enabledProfiler())
1322
profiler->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
1324
m_stack.popFrame(newCallFrame);
1325
return checkedReturn(result);
1328
NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine, int column)
1330
Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
1334
switch (debugHookID) {
1335
case DidEnterCallFrame:
1336
debugger->callEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column);
1338
case WillLeaveCallFrame:
1339
debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column);
1341
case WillExecuteStatement:
1342
debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column);
1344
case WillExecuteProgram:
1345
debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column);
1347
case DidExecuteProgram:
1348
debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column);
1350
case DidReachBreakpoint:
1351
debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column);
1356
JSValue Interpreter::retrieveArgumentsFromVMCode(CallFrame* callFrame, JSFunction* function) const
1358
CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function);
1359
if (!functionCallFrame)
1362
Arguments* arguments = Arguments::create(functionCallFrame->globalData(), functionCallFrame);
1363
arguments->tearOff(functionCallFrame);
1364
return JSValue(arguments);
1367
JSValue Interpreter::retrieveCallerFromVMCode(CallFrame* callFrame, JSFunction* function) const
1369
CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function);
1371
if (!functionCallFrame)
1375
unsigned bytecodeOffset;
1376
CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, lineNumber, bytecodeOffset);
1379
JSValue caller = callerFrame->callee();
1383
// Skip over function bindings.
1384
ASSERT(caller.isObject());
1385
while (asObject(caller)->inherits(&JSBoundFunction::s_info)) {
1386
callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, lineNumber, bytecodeOffset);
1389
caller = callerFrame->callee();
1397
void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, String& sourceURL, JSValue& function) const
1399
function = JSValue();
1401
sourceURL = String();
1403
CallFrame* callerFrame = callFrame->callerFrame();
1404
if (callerFrame->hasHostCallFrameFlag())
1407
CodeBlock* callerCodeBlock = callerFrame->codeBlock();
1408
if (!callerCodeBlock)
1410
unsigned bytecodeOffset = 0;
1411
bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
1412
lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
1413
sourceID = callerCodeBlock->ownerExecutable()->sourceID();
1414
sourceURL = callerCodeBlock->ownerExecutable()->sourceURL();
1415
function = callerFrame->callee();
1418
CallFrame* Interpreter::findFunctionCallFrameFromVMCode(CallFrame* callFrame, JSFunction* function)
1420
for (CallFrame* candidate = callFrame->trueCallFrameFromVMCode(); candidate; candidate = candidate->trueCallerFrame()) {
1421
if (candidate->callee() == function)
1427
void Interpreter::enableSampler()
1429
#if ENABLE(OPCODE_SAMPLING)
1431
m_sampler = adoptPtr(new SamplingTool(this));
1436
void Interpreter::dumpSampleData(ExecState* exec)
1438
#if ENABLE(OPCODE_SAMPLING)
1440
m_sampler->dump(exec);
1445
void Interpreter::startSampling()
1447
#if ENABLE(SAMPLING_THREAD)
1448
if (!m_sampleEntryDepth)
1449
SamplingThread::start();
1451
m_sampleEntryDepth++;
1454
void Interpreter::stopSampling()
1456
#if ENABLE(SAMPLING_THREAD)
1457
m_sampleEntryDepth--;
1458
if (!m_sampleEntryDepth)
1459
SamplingThread::stop();