2 * Copyright (C) 2008, 2009, 2010, 2012, 2013, 2014 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 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 "CallFrameClosure.h"
36 #include "CallFrameInlines.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 "LLIntThunks.h"
56 #include "LegacyProfiler.h"
57 #include "LiteralParser.h"
58 #include "NameInstance.h"
59 #include "ObjectPrototype.h"
60 #include "JSCInlines.h"
62 #include "ProtoCallFrame.h"
63 #include "RegExpObject.h"
64 #include "RegExpPrototype.h"
66 #include "SamplingTool.h"
67 #include "StackAlignment.h"
68 #include "StackVisitor.h"
69 #include "StrictEvalActivation.h"
70 #include "StrongInlines.h"
71 #include "VMEntryScope.h"
72 #include "VirtualRegister.h"
76 #include <wtf/StackStats.h>
77 #include <wtf/StdLibExtras.h>
78 #include <wtf/StringPrintStream.h>
79 #include <wtf/Threading.h>
80 #include <wtf/WTFThreadData.h>
81 #include <wtf/text/StringBuilder.h>
87 #define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (!defined(__llvm__))
93 JSValue
eval(CallFrame
* callFrame
)
95 if (!callFrame
->argumentCount())
98 JSValue program
= callFrame
->argument(0);
99 if (!program
.isString())
102 TopCallFrameSetter
topCallFrame(callFrame
->vm(), callFrame
);
103 String programSource
= asString(program
)->value(callFrame
);
104 if (callFrame
->hadException())
107 CallFrame
* callerFrame
= callFrame
->callerFrame();
108 CodeBlock
* callerCodeBlock
= callerFrame
->codeBlock();
109 JSScope
* callerScopeChain
= callerFrame
->scope();
110 EvalExecutable
* eval
= callerCodeBlock
->evalCodeCache().tryGet(callerCodeBlock
->isStrictMode(), programSource
, callerScopeChain
);
113 if (!callerCodeBlock
->isStrictMode()) {
114 // FIXME: We can use the preparser in strict mode, we just need additional logic
115 // to prevent duplicates.
116 if (programSource
.is8Bit()) {
117 LiteralParser
<LChar
> preparser(callFrame
, programSource
.characters8(), programSource
.length(), NonStrictJSON
);
118 if (JSValue parsedObject
= preparser
.tryLiteralParse())
121 LiteralParser
<UChar
> preparser(callFrame
, programSource
.characters16(), programSource
.length(), NonStrictJSON
);
122 if (JSValue parsedObject
= preparser
.tryLiteralParse())
127 // If the literal parser bailed, it should not have thrown exceptions.
128 ASSERT(!callFrame
->vm().exception());
130 eval
= callerCodeBlock
->evalCodeCache().getSlow(callFrame
, callerCodeBlock
->ownerExecutable(), callerCodeBlock
->isStrictMode(), programSource
, callerScopeChain
);
132 return jsUndefined();
135 JSValue thisValue
= callerFrame
->thisValue();
136 Interpreter
* interpreter
= callFrame
->vm().interpreter
;
137 return interpreter
->execute(eval
, callFrame
, thisValue
, callerScopeChain
);
140 CallFrame
* sizeFrameForVarargs(CallFrame
* callFrame
, JSStack
* stack
, JSValue arguments
, int firstFreeRegister
, uint32_t firstVarArgOffset
)
142 if (!arguments
) { // f.apply(x, arguments), with arguments unmodified.
143 unsigned argumentCountIncludingThis
= callFrame
->argumentCountIncludingThis();
144 if (argumentCountIncludingThis
> firstVarArgOffset
)
145 argumentCountIncludingThis
-= firstVarArgOffset
;
147 argumentCountIncludingThis
= 1;
148 unsigned paddedCalleeFrameOffset
= WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister
+ argumentCountIncludingThis
+ JSStack::CallFrameHeaderSize
+ 1);
149 CallFrame
* newCallFrame
= CallFrame::create(callFrame
->registers() - paddedCalleeFrameOffset
);
150 if (argumentCountIncludingThis
> Arguments::MaxArguments
+ 1 || !stack
->ensureCapacityFor(newCallFrame
->registers())) {
151 throwStackOverflowError(callFrame
);
157 if (arguments
.isUndefinedOrNull()) {
158 unsigned argumentCountIncludingThis
= 1;
159 unsigned paddedCalleeFrameOffset
= WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister
+ argumentCountIncludingThis
+ JSStack::CallFrameHeaderSize
+ 1);
160 CallFrame
* newCallFrame
= CallFrame::create(callFrame
->registers() - paddedCalleeFrameOffset
);
161 if (!stack
->ensureCapacityFor(newCallFrame
->registers())) {
162 throwStackOverflowError(callFrame
);
168 if (!arguments
.isObject()) {
169 callFrame
->vm().throwException(callFrame
, createInvalidParameterError(callFrame
, "Function.prototype.apply", arguments
));
173 if (asObject(arguments
)->classInfo() == Arguments::info()) {
174 Arguments
* argsObject
= asArguments(arguments
);
175 unsigned argCount
= argsObject
->length(callFrame
);
176 callFrame
->vm().varargsLength
= argCount
;
177 if (argCount
>= firstVarArgOffset
)
178 argCount
-= firstVarArgOffset
;
181 unsigned paddedCalleeFrameOffset
= WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister
+ CallFrame::offsetFor(argCount
+ 1));
182 CallFrame
* newCallFrame
= CallFrame::create(callFrame
->registers() - paddedCalleeFrameOffset
);
183 if (argCount
> Arguments::MaxArguments
|| !stack
->ensureCapacityFor(newCallFrame
->registers())) {
184 throwStackOverflowError(callFrame
);
190 if (isJSArray(arguments
)) {
191 JSArray
* array
= asArray(arguments
);
192 unsigned argCount
= array
->length();
193 if (argCount
>= firstVarArgOffset
)
194 argCount
-= firstVarArgOffset
;
197 unsigned paddedCalleeFrameOffset
= WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister
+ CallFrame::offsetFor(argCount
+ 1));
198 CallFrame
* newCallFrame
= CallFrame::create(callFrame
->registers() - paddedCalleeFrameOffset
);
199 if (argCount
> Arguments::MaxArguments
|| !stack
->ensureCapacityFor(newCallFrame
->registers())) {
200 throwStackOverflowError(callFrame
);
206 JSObject
* argObject
= asObject(arguments
);
207 unsigned argCount
= argObject
->get(callFrame
, callFrame
->propertyNames().length
).toUInt32(callFrame
);
208 callFrame
->vm().varargsLength
= argCount
;
209 if (argCount
>= firstVarArgOffset
)
210 argCount
-= firstVarArgOffset
;
213 unsigned paddedCalleeFrameOffset
= WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister
+ CallFrame::offsetFor(argCount
+ 1));
214 CallFrame
* newCallFrame
= CallFrame::create(callFrame
->registers() - paddedCalleeFrameOffset
);
215 if (argCount
> Arguments::MaxArguments
|| !stack
->ensureCapacityFor(newCallFrame
->registers())) {
216 throwStackOverflowError(callFrame
);
222 void loadVarargs(CallFrame
* callFrame
, CallFrame
* newCallFrame
, JSValue thisValue
, JSValue arguments
, uint32_t firstVarArgOffset
)
224 if (!arguments
) { // f.apply(x, arguments), with arguments unmodified.
225 unsigned argumentCountIncludingThis
= callFrame
->argumentCountIncludingThis();
226 if (argumentCountIncludingThis
> firstVarArgOffset
)
227 argumentCountIncludingThis
-= firstVarArgOffset
;
229 argumentCountIncludingThis
= 1;
230 newCallFrame
->setArgumentCountIncludingThis(argumentCountIncludingThis
);
231 newCallFrame
->setThisValue(thisValue
);
232 for (size_t i
= firstVarArgOffset
; i
< callFrame
->argumentCount(); ++i
)
233 newCallFrame
->setArgument(i
- firstVarArgOffset
, callFrame
->argumentAfterCapture(i
));
237 if (arguments
.isUndefinedOrNull()) {
238 newCallFrame
->setArgumentCountIncludingThis(1);
239 newCallFrame
->setThisValue(thisValue
);
243 if (asObject(arguments
)->classInfo() == Arguments::info()) {
244 Arguments
* argsObject
= asArguments(arguments
);
245 unsigned argCount
= callFrame
->vm().varargsLength
;
246 callFrame
->vm().varargsLength
= 0;
247 if (argCount
>= firstVarArgOffset
) {
248 argCount
-= firstVarArgOffset
;
249 newCallFrame
->setArgumentCountIncludingThis(argCount
+ 1);
250 argsObject
->copyToArguments(callFrame
, newCallFrame
, argCount
, firstVarArgOffset
);
252 newCallFrame
->setArgumentCountIncludingThis(1);
253 newCallFrame
->setThisValue(thisValue
);
257 if (isJSArray(arguments
)) {
258 JSArray
* array
= asArray(arguments
);
259 unsigned argCount
= array
->length();
260 if (argCount
>= firstVarArgOffset
) {
261 argCount
-= firstVarArgOffset
;
262 newCallFrame
->setArgumentCountIncludingThis(argCount
+ 1);
263 array
->copyToArguments(callFrame
, newCallFrame
, argCount
, firstVarArgOffset
);
265 newCallFrame
->setArgumentCountIncludingThis(1);
266 newCallFrame
->setThisValue(thisValue
);
270 unsigned argCount
= callFrame
->vm().varargsLength
;
271 if (argCount
>= firstVarArgOffset
) {
272 argCount
-= firstVarArgOffset
;
273 newCallFrame
->setArgumentCountIncludingThis(argCount
+ 1);
275 newCallFrame
->setArgumentCountIncludingThis(1);
277 newCallFrame
->setThisValue(thisValue
);
278 for (size_t i
= 0; i
< argCount
; ++i
) {
279 newCallFrame
->setArgument(i
, asObject(arguments
)->get(callFrame
, i
+ firstVarArgOffset
));
280 if (UNLIKELY(callFrame
->vm().exception()))
285 Interpreter::Interpreter(VM
& vm
)
286 : m_sampleEntryDepth(0)
289 , m_errorHandlingModeReentry(0)
291 , m_initialized(false)
296 Interpreter::~Interpreter()
300 void Interpreter::initialize(bool canUseJIT
)
302 UNUSED_PARAM(canUseJIT
);
304 #if ENABLE(COMPUTED_GOTO_OPCODES)
305 m_opcodeTable
= LLInt::opcodeMap();
306 for (int i
= 0; i
< numOpcodeIDs
; ++i
)
307 m_opcodeIDTable
.add(m_opcodeTable
[i
], static_cast<OpcodeID
>(i
));
311 m_initialized
= true;
314 #if ENABLE(OPCODE_SAMPLING)
321 void Interpreter::dumpCallFrame(CallFrame
*)
327 void Interpreter::dumpCallFrame(CallFrame
* callFrame
)
329 callFrame
->codeBlock()->dumpBytecode();
330 dumpRegisters(callFrame
);
333 class DumpRegisterFunctor
{
335 DumpRegisterFunctor(const Register
*& it
)
336 : m_hasSkippedFirstFrame(false)
341 StackVisitor::Status
operator()(StackVisitor
& visitor
)
343 if (!m_hasSkippedFirstFrame
) {
344 m_hasSkippedFirstFrame
= true;
345 return StackVisitor::Continue
;
349 unsigned unusedColumn
= 0;
350 visitor
->computeLineAndColumn(line
, unusedColumn
);
351 dataLogF("[ReturnVPC] | %10p | %d (line %d)\n", m_it
, visitor
->bytecodeOffset(), line
);
353 return StackVisitor::Done
;
357 bool m_hasSkippedFirstFrame
;
358 const Register
*& m_it
;
361 void Interpreter::dumpRegisters(CallFrame
* callFrame
)
363 dataLogF("Register frame: \n\n");
364 dataLogF("-----------------------------------------------------------------------------\n");
365 dataLogF(" use | address | value \n");
366 dataLogF("-----------------------------------------------------------------------------\n");
368 CodeBlock
* codeBlock
= callFrame
->codeBlock();
372 it
= callFrame
->registers() + JSStack::ThisArgument
+ callFrame
->argumentCount();
373 end
= callFrame
->registers() + JSStack::ThisArgument
- 1;
375 JSValue v
= it
->jsValue();
376 int registerNumber
= it
- callFrame
->registers();
377 String name
= codeBlock
->nameForRegister(VirtualRegister(registerNumber
));
378 dataLogF("[r% 3d %14s] | %10p | %-16s 0x%lld \n", registerNumber
, name
.ascii().data(), it
, toCString(v
).data(), (long long)JSValue::encode(v
));
382 dataLogF("-----------------------------------------------------------------------------\n");
383 dataLogF("[ArgumentCount] | %10p | %lu \n", it
, (unsigned long) callFrame
->argumentCount());
385 dataLogF("[CallerFrame] | %10p | %p \n", it
, callFrame
->callerFrame());
387 dataLogF("[Callee] | %10p | %p \n", it
, callFrame
->callee());
389 dataLogF("[ScopeChain] | %10p | %p \n", it
, callFrame
->scope());
392 AbstractPC pc
= callFrame
->abstractReturnPC(callFrame
->vm());
393 if (pc
.hasJITReturnAddress())
394 dataLogF("[ReturnJITPC] | %10p | %p \n", it
, pc
.jitReturnAddress().value());
397 DumpRegisterFunctor
functor(it
);
398 callFrame
->iterate(functor
);
400 dataLogF("[CodeBlock] | %10p | %p \n", it
, callFrame
->codeBlock());
402 dataLogF("-----------------------------------------------------------------------------\n");
404 end
= it
- codeBlock
->m_numVars
;
407 JSValue v
= it
->jsValue();
408 int registerNumber
= it
- callFrame
->registers();
409 String name
= codeBlock
->nameForRegister(VirtualRegister(registerNumber
));
410 dataLogF("[r% 3d %14s] | %10p | %-16s 0x%lld \n", registerNumber
, name
.ascii().data(), it
, toCString(v
).data(), (long long)JSValue::encode(v
));
414 dataLogF("-----------------------------------------------------------------------------\n");
416 end
= it
- codeBlock
->m_numCalleeRegisters
+ codeBlock
->m_numVars
;
419 JSValue v
= (*it
).jsValue();
420 int registerNumber
= it
- callFrame
->registers();
421 dataLogF("[r% 3d] | %10p | %-16s 0x%lld \n", registerNumber
, it
, toCString(v
).data(), (long long)JSValue::encode(v
));
425 dataLogF("-----------------------------------------------------------------------------\n");
430 bool Interpreter::isOpcode(Opcode opcode
)
432 #if ENABLE(COMPUTED_GOTO_OPCODES)
433 return opcode
!= HashTraits
<Opcode
>::emptyValue()
434 && !HashTraits
<Opcode
>::isDeletedValue(opcode
)
435 && m_opcodeIDTable
.contains(opcode
);
437 return opcode
>= 0 && opcode
<= op_end
;
441 static bool unwindCallFrame(StackVisitor
& visitor
)
443 CallFrame
* callFrame
= visitor
->callFrame();
444 CodeBlock
* codeBlock
= visitor
->codeBlock();
445 JSScope
* scope
= callFrame
->scope();
447 if (Debugger
* debugger
= callFrame
->vmEntryGlobalObject()->debugger()) {
448 ClearExceptionScope
scope(&callFrame
->vm());
449 if (callFrame
->callee())
450 debugger
->returnEvent(callFrame
);
452 debugger
->didExecuteProgram(callFrame
);
453 ASSERT(!callFrame
->hadException());
457 if (codeBlock
->codeType() == FunctionCode
&& codeBlock
->needsActivation()) {
459 RELEASE_ASSERT(!visitor
->isInlinedFrame());
461 activation
= callFrame
->uncheckedActivation();
462 // Protect against the activation not being created, or the variable still being
463 // initialized to Undefined inside op_enter.
464 if (activation
&& activation
.isCell()) {
465 JSActivation
* activationObject
= jsCast
<JSActivation
*>(activation
);
466 // Protect against throwing exceptions after tear-off.
467 if (!activationObject
->isTornOff())
468 activationObject
->tearOff(*scope
->vm());
472 if (codeBlock
->codeType() == FunctionCode
&& codeBlock
->usesArguments()) {
473 if (Arguments
* arguments
= visitor
->existingArguments()) {
474 if (activation
&& activation
.isCell())
475 arguments
->didTearOffActivation(callFrame
, jsCast
<JSActivation
*>(activation
));
477 else if (visitor
->isInlinedFrame())
478 arguments
->tearOff(callFrame
, visitor
->inlineCallFrame());
481 arguments
->tearOff(callFrame
);
485 CallFrame
* callerFrame
= callFrame
->callerFrame();
486 return !callerFrame
->isVMEntrySentinel();
489 static StackFrameCodeType
getStackFrameCodeType(StackVisitor
& visitor
)
491 switch (visitor
->codeType()) {
492 case StackVisitor::Frame::Eval
:
493 return StackFrameEvalCode
;
494 case StackVisitor::Frame::Function
:
495 return StackFrameFunctionCode
;
496 case StackVisitor::Frame::Global
:
497 return StackFrameGlobalCode
;
498 case StackVisitor::Frame::Native
:
499 ASSERT_NOT_REACHED();
500 return StackFrameNativeCode
;
502 RELEASE_ASSERT_NOT_REACHED();
503 return StackFrameGlobalCode
;
506 void StackFrame::computeLineAndColumn(unsigned& line
, unsigned& column
)
515 int unusedStartOffset
= 0;
516 int unusedEndOffset
= 0;
517 unsigned divotLine
= 0;
518 unsigned divotColumn
= 0;
519 expressionInfo(divot
, unusedStartOffset
, unusedEndOffset
, divotLine
, divotColumn
);
521 line
= divotLine
+ lineOffset
;
522 column
= divotColumn
+ (divotLine
? 1 : firstLineColumnOffset
);
525 void StackFrame::expressionInfo(int& divot
, int& startOffset
, int& endOffset
, unsigned& line
, unsigned& column
)
527 codeBlock
->expressionRangeForBytecodeOffset(bytecodeOffset
, divot
, startOffset
, endOffset
, line
, column
);
528 divot
+= characterOffset
;
531 String
StackFrame::toString(CallFrame
* callFrame
)
533 StringBuilder traceBuild
;
534 String functionName
= friendlyFunctionName(callFrame
);
535 String sourceURL
= friendlySourceURL();
536 traceBuild
.append(functionName
);
537 if (!sourceURL
.isEmpty()) {
538 if (!functionName
.isEmpty())
539 traceBuild
.append('@');
540 traceBuild
.append(sourceURL
);
541 if (codeType
!= StackFrameNativeCode
) {
544 computeLineAndColumn(line
, column
);
546 traceBuild
.append(':');
547 traceBuild
.appendNumber(line
);
548 traceBuild
.append(':');
549 traceBuild
.appendNumber(column
);
552 return traceBuild
.toString().impl();
555 class GetStackTraceFunctor
{
557 GetStackTraceFunctor(VM
& vm
, Vector
<StackFrame
>& results
, size_t remainingCapacity
)
560 , m_remainingCapacityForFrameCapture(remainingCapacity
)
564 StackVisitor::Status
operator()(StackVisitor
& visitor
)
567 if (m_remainingCapacityForFrameCapture
) {
568 if (visitor
->isJSFrame() && !visitor
->codeBlock()->unlinkedCodeBlock()->isBuiltinFunction()) {
569 CodeBlock
* codeBlock
= visitor
->codeBlock();
571 Strong
<JSObject
>(vm
, visitor
->callee()),
572 getStackFrameCodeType(visitor
),
573 Strong
<ExecutableBase
>(vm
, codeBlock
->ownerExecutable()),
574 Strong
<UnlinkedCodeBlock
>(vm
, codeBlock
->unlinkedCodeBlock()),
576 codeBlock
->ownerExecutable()->lineNo(),
577 codeBlock
->firstLineColumnOffset(),
578 codeBlock
->sourceOffset(),
579 visitor
->bytecodeOffset(),
584 StackFrame s
= { Strong
<JSObject
>(vm
, visitor
->callee()), StackFrameNativeCode
, Strong
<ExecutableBase
>(), Strong
<UnlinkedCodeBlock
>(), 0, 0, 0, 0, 0, String()};
588 m_remainingCapacityForFrameCapture
--;
589 return StackVisitor::Continue
;
591 return StackVisitor::Done
;
596 Vector
<StackFrame
>& m_results
;
597 size_t m_remainingCapacityForFrameCapture
;
600 void Interpreter::getStackTrace(Vector
<StackFrame
>& results
, size_t maxStackSize
)
603 ASSERT(!vm
.topCallFrame
->isVMEntrySentinel());
604 CallFrame
* callFrame
= vm
.topCallFrame
;
608 GetStackTraceFunctor
functor(vm
, results
, maxStackSize
);
609 callFrame
->iterate(functor
);
612 JSString
* Interpreter::stackTraceAsString(ExecState
* exec
, Vector
<StackFrame
> stackTrace
)
614 // FIXME: JSStringJoiner could be more efficient than StringBuilder here.
615 StringBuilder builder
;
616 for (unsigned i
= 0; i
< stackTrace
.size(); i
++) {
617 builder
.append(String(stackTrace
[i
].toString(exec
)));
618 if (i
!= stackTrace
.size() - 1)
619 builder
.append('\n');
621 return jsString(&exec
->vm(), builder
.toString());
624 class GetExceptionHandlerFunctor
{
626 GetExceptionHandlerFunctor()
631 HandlerInfo
* handler() { return m_handler
; }
633 StackVisitor::Status
operator()(StackVisitor
& visitor
)
635 CodeBlock
* codeBlock
= visitor
->codeBlock();
637 return StackVisitor::Continue
;
639 unsigned bytecodeOffset
= visitor
->bytecodeOffset();
640 m_handler
= codeBlock
->handlerForBytecodeOffset(bytecodeOffset
);
642 return StackVisitor::Done
;
644 return StackVisitor::Continue
;
648 HandlerInfo
* m_handler
;
651 class UnwindFunctor
{
653 UnwindFunctor(CallFrame
*& callFrame
, bool isTermination
, CodeBlock
*& codeBlock
, HandlerInfo
*& handler
)
654 : m_callFrame(callFrame
)
655 , m_isTermination(isTermination
)
656 , m_codeBlock(codeBlock
)
661 StackVisitor::Status
operator()(StackVisitor
& visitor
)
663 VM
& vm
= m_callFrame
->vm();
664 m_callFrame
= visitor
->callFrame();
665 m_codeBlock
= visitor
->codeBlock();
666 unsigned bytecodeOffset
= visitor
->bytecodeOffset();
668 if (m_isTermination
|| !(m_handler
= m_codeBlock
->handlerForBytecodeOffset(bytecodeOffset
))) {
669 if (!unwindCallFrame(visitor
)) {
670 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
671 profiler
->exceptionUnwind(m_callFrame
);
672 return StackVisitor::Done
;
675 return StackVisitor::Done
;
677 return StackVisitor::Continue
;
681 CallFrame
*& m_callFrame
;
682 bool m_isTermination
;
683 CodeBlock
*& m_codeBlock
;
684 HandlerInfo
*& m_handler
;
687 NEVER_INLINE HandlerInfo
* Interpreter::unwind(CallFrame
*& callFrame
, JSValue
& exceptionValue
)
689 if (callFrame
->isVMEntrySentinel()) {
690 // This happens when we throw stack overflow in a function that is called
691 // directly from callToJavaScript. Stack overflow throws the exception in the
692 // context of the caller. In that case the caller is the sentinel frame. The
693 // right thing to do is to pretend that the exception is uncaught so that we
694 // go to the uncaught exception handler, which returns through callToJavaScript.
698 CodeBlock
* codeBlock
= callFrame
->codeBlock();
700 bool isTermination
= false;
702 ASSERT(!exceptionValue
.isEmpty());
703 ASSERT(!exceptionValue
.isCell() || exceptionValue
.asCell());
704 // This shouldn't be possible (hence the assertions), but we're already in the slowest of
705 // slow cases, so let's harden against it anyway to be safe.
706 if (exceptionValue
.isEmpty() || (exceptionValue
.isCell() && !exceptionValue
.asCell()))
707 exceptionValue
= jsNull();
709 if (exceptionValue
.isObject())
710 isTermination
= isTerminatedExecutionException(asObject(exceptionValue
));
712 ASSERT(callFrame
->vm().exceptionStack().size());
714 Debugger
* debugger
= callFrame
->vmEntryGlobalObject()->debugger();
715 if (debugger
&& debugger
->needsExceptionCallbacks()) {
716 // We need to clear the exception and the exception stack here in order to see if a new exception happens.
717 // Afterwards, the values are put back to continue processing this error.
718 ClearExceptionScope
scope(&callFrame
->vm());
719 // This code assumes that if the debugger is enabled then there is no inlining.
720 // If that assumption turns out to be false then we'll ignore the inlined call
722 // https://bugs.webkit.org/show_bug.cgi?id=121754
728 GetExceptionHandlerFunctor functor
;
729 callFrame
->iterate(functor
);
730 hasHandler
= !!functor
.handler();
733 debugger
->exception(callFrame
, exceptionValue
, hasHandler
);
734 ASSERT(!callFrame
->hadException());
737 // Calculate an exception handler vPC, unwinding call frames as necessary.
738 HandlerInfo
* handler
= 0;
739 VM
& vm
= callFrame
->vm();
740 ASSERT(callFrame
== vm
.topCallFrame
);
741 UnwindFunctor
functor(callFrame
, isTermination
, codeBlock
, handler
);
742 callFrame
->iterate(functor
);
746 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
747 profiler
->exceptionUnwind(callFrame
);
749 // Unwind the scope chain within the exception handler's call frame.
750 int targetScopeDepth
= handler
->scopeDepth
;
751 if (codeBlock
->needsActivation() && callFrame
->hasActivation())
754 JSScope
* scope
= callFrame
->scope();
755 int scopeDelta
= scope
->depth() - targetScopeDepth
;
756 RELEASE_ASSERT(scopeDelta
>= 0);
759 scope
= scope
->next();
760 callFrame
->setScope(scope
);
765 static inline JSValue
checkedReturn(JSValue returnValue
)
771 static inline JSObject
* checkedReturn(JSObject
* returnValue
)
777 class SamplingScope
{
779 SamplingScope(Interpreter
* interpreter
)
780 : m_interpreter(interpreter
)
782 interpreter
->startSampling();
786 m_interpreter
->stopSampling();
789 Interpreter
* m_interpreter
;
792 JSValue
Interpreter::execute(ProgramExecutable
* program
, CallFrame
* callFrame
, JSObject
* thisObj
)
794 SamplingScope
samplingScope(this);
796 JSScope
* scope
= callFrame
->scope();
797 VM
& vm
= *scope
->vm();
799 ASSERT(!vm
.exception());
800 ASSERT(!vm
.isCollectorBusy());
801 RELEASE_ASSERT(vm
.currentThreadIsHoldingAPILock());
802 if (vm
.isCollectorBusy())
805 if (!vm
.isSafeToRecurse())
806 return checkedReturn(throwStackOverflowError(callFrame
));
808 // First check if the "program" is actually just a JSON object. If so,
809 // we'll handle the JSON object here. Else, we'll handle real JS code
810 // below at failedJSONP.
812 Vector
<JSONPData
> JSONPData
;
814 const String programSource
= program
->source().toString();
815 if (programSource
.isNull())
816 return jsUndefined();
817 if (programSource
.is8Bit()) {
818 LiteralParser
<LChar
> literalParser(callFrame
, programSource
.characters8(), programSource
.length(), JSONP
);
819 parseResult
= literalParser
.tryJSONPParse(JSONPData
, scope
->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope
->globalObject()));
821 LiteralParser
<UChar
> literalParser(callFrame
, programSource
.characters16(), programSource
.length(), JSONP
);
822 parseResult
= literalParser
.tryJSONPParse(JSONPData
, scope
->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope
->globalObject()));
826 JSGlobalObject
* globalObject
= scope
->globalObject();
828 for (unsigned entry
= 0; entry
< JSONPData
.size(); entry
++) {
829 Vector
<JSONPPathEntry
> JSONPPath
;
830 JSONPPath
.swap(JSONPData
[entry
].m_path
);
831 JSValue JSONPValue
= JSONPData
[entry
].m_value
.get();
832 if (JSONPPath
.size() == 1 && JSONPPath
[0].m_type
== JSONPPathEntryTypeDeclare
) {
833 globalObject
->addVar(callFrame
, JSONPPath
[0].m_pathEntryName
);
834 PutPropertySlot
slot(globalObject
);
835 globalObject
->methodTable()->put(globalObject
, callFrame
, JSONPPath
[0].m_pathEntryName
, JSONPValue
, slot
);
836 result
= jsUndefined();
839 JSValue
baseObject(globalObject
);
840 for (unsigned i
= 0; i
< JSONPPath
.size() - 1; i
++) {
841 ASSERT(JSONPPath
[i
].m_type
!= JSONPPathEntryTypeDeclare
);
842 switch (JSONPPath
[i
].m_type
) {
843 case JSONPPathEntryTypeDot
: {
845 PropertySlot
slot(globalObject
);
846 if (!globalObject
->getPropertySlot(callFrame
, JSONPPath
[i
].m_pathEntryName
, slot
)) {
848 return callFrame
->vm().throwException(callFrame
, createUndefinedVariableError(globalObject
->globalExec(), JSONPPath
[i
].m_pathEntryName
));
851 baseObject
= slot
.getValue(callFrame
, JSONPPath
[i
].m_pathEntryName
);
853 baseObject
= baseObject
.get(callFrame
, JSONPPath
[i
].m_pathEntryName
);
854 if (callFrame
->hadException())
855 return jsUndefined();
858 case JSONPPathEntryTypeLookup
: {
859 baseObject
= baseObject
.get(callFrame
, JSONPPath
[i
].m_pathIndex
);
860 if (callFrame
->hadException())
861 return jsUndefined();
865 RELEASE_ASSERT_NOT_REACHED();
866 return jsUndefined();
869 PutPropertySlot
slot(baseObject
);
870 switch (JSONPPath
.last().m_type
) {
871 case JSONPPathEntryTypeCall
: {
872 JSValue function
= baseObject
.get(callFrame
, JSONPPath
.last().m_pathEntryName
);
873 if (callFrame
->hadException())
874 return jsUndefined();
876 CallType callType
= getCallData(function
, callData
);
877 if (callType
== CallTypeNone
)
878 return callFrame
->vm().throwException(callFrame
, createNotAFunctionError(callFrame
, function
));
879 MarkedArgumentBuffer jsonArg
;
880 jsonArg
.append(JSONPValue
);
881 JSValue thisValue
= JSONPPath
.size() == 1 ? jsUndefined(): baseObject
;
882 JSONPValue
= JSC::call(callFrame
, function
, callType
, callData
, thisValue
, jsonArg
);
883 if (callFrame
->hadException())
884 return jsUndefined();
887 case JSONPPathEntryTypeDot
: {
888 baseObject
.put(callFrame
, JSONPPath
.last().m_pathEntryName
, JSONPValue
, slot
);
889 if (callFrame
->hadException())
890 return jsUndefined();
893 case JSONPPathEntryTypeLookup
: {
894 baseObject
.putByIndex(callFrame
, JSONPPath
.last().m_pathIndex
, JSONPValue
, slot
.isStrictMode());
895 if (callFrame
->hadException())
896 return jsUndefined();
900 RELEASE_ASSERT_NOT_REACHED();
901 return jsUndefined();
908 // If we get here, then we have already proven that the script is not a JSON
911 VMEntryScope
entryScope(vm
, scope
->globalObject());
913 // Compile source to bytecode if necessary:
914 if (JSObject
* error
= program
->initializeGlobalProperties(vm
, callFrame
, scope
))
915 return checkedReturn(callFrame
->vm().throwException(callFrame
, error
));
917 if (JSObject
* error
= program
->prepareForExecution(callFrame
, nullptr, &scope
, CodeForCall
))
918 return checkedReturn(callFrame
->vm().throwException(callFrame
, error
));
920 ProgramCodeBlock
* codeBlock
= program
->codeBlock();
922 if (UNLIKELY(vm
.watchdog
&& vm
.watchdog
->didFire(callFrame
)))
923 return throwTerminatedExecutionException(callFrame
);
925 ASSERT(codeBlock
->numParameters() == 1); // 1 parameter for 'this'.
927 ProtoCallFrame protoCallFrame
;
928 protoCallFrame
.init(codeBlock
, scope
, 0, thisObj
, 1);
930 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
931 profiler
->willExecute(callFrame
, program
->sourceURL(), program
->lineNo(), program
->startColumn());
936 SamplingTool::CallRecord
callRecord(m_sampler
.get());
937 Watchdog::Scope
watchdogScope(vm
.watchdog
.get());
939 result
= program
->generatedJITCode()->execute(&vm
, &protoCallFrame
);
942 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
943 profiler
->didExecute(callFrame
, program
->sourceURL(), program
->lineNo(), program
->startColumn());
945 return checkedReturn(result
);
948 JSValue
Interpreter::executeCall(CallFrame
* callFrame
, JSObject
* function
, CallType callType
, const CallData
& callData
, JSValue thisValue
, const ArgList
& args
)
950 VM
& vm
= callFrame
->vm();
951 ASSERT(!callFrame
->hadException());
952 ASSERT(!vm
.isCollectorBusy());
953 if (vm
.isCollectorBusy())
956 bool isJSCall
= (callType
== CallTypeJS
);
958 CodeBlock
* newCodeBlock
;
959 size_t argsCount
= 1 + args
.size(); // implicit "this" parameter
962 scope
= callData
.js
.scope
;
964 ASSERT(callType
== CallTypeHost
);
965 scope
= callFrame
->scope();
968 VMEntryScope
entryScope(vm
, scope
->globalObject());
969 if (!vm
.isSafeToRecurse())
970 return checkedReturn(throwStackOverflowError(callFrame
));
973 // Compile the callee:
974 JSObject
* compileError
= callData
.js
.functionExecutable
->prepareForExecution(callFrame
, jsCast
<JSFunction
*>(function
), &scope
, CodeForCall
);
975 if (UNLIKELY(!!compileError
)) {
976 return checkedReturn(callFrame
->vm().throwException(callFrame
, compileError
));
978 newCodeBlock
= callData
.js
.functionExecutable
->codeBlockForCall();
979 ASSERT(!!newCodeBlock
);
980 newCodeBlock
->m_shouldAlwaysBeInlined
= false;
984 if (UNLIKELY(vm
.watchdog
&& vm
.watchdog
->didFire(callFrame
)))
985 return throwTerminatedExecutionException(callFrame
);
987 ProtoCallFrame protoCallFrame
;
988 protoCallFrame
.init(newCodeBlock
, scope
, function
, thisValue
, argsCount
, args
.data());
990 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
991 profiler
->willExecute(callFrame
, function
);
995 SamplingTool::CallRecord
callRecord(m_sampler
.get(), !isJSCall
);
996 Watchdog::Scope
watchdogScope(vm
.watchdog
.get());
1000 result
= callData
.js
.functionExecutable
->generatedJITCodeForCall()->execute(&vm
, &protoCallFrame
);
1002 result
= JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(callData
.native
.function
), &vm
, &protoCallFrame
));
1003 if (callFrame
->hadException())
1008 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
1009 profiler
->didExecute(callFrame
, function
);
1011 return checkedReturn(result
);
1014 JSObject
* Interpreter::executeConstruct(CallFrame
* callFrame
, JSObject
* constructor
, ConstructType constructType
, const ConstructData
& constructData
, const ArgList
& args
)
1016 VM
& vm
= callFrame
->vm();
1017 ASSERT(!callFrame
->hadException());
1018 ASSERT(!vm
.isCollectorBusy());
1019 // We throw in this case because we have to return something "valid" but we're
1020 // already in an invalid state.
1021 if (vm
.isCollectorBusy())
1022 return checkedReturn(throwStackOverflowError(callFrame
));
1024 bool isJSConstruct
= (constructType
== ConstructTypeJS
);
1026 CodeBlock
* newCodeBlock
;
1027 size_t argsCount
= 1 + args
.size(); // implicit "this" parameter
1030 scope
= constructData
.js
.scope
;
1032 ASSERT(constructType
== ConstructTypeHost
);
1033 scope
= callFrame
->scope();
1036 VMEntryScope
entryScope(vm
, scope
->globalObject());
1037 if (!vm
.isSafeToRecurse())
1038 return checkedReturn(throwStackOverflowError(callFrame
));
1040 if (isJSConstruct
) {
1041 // Compile the callee:
1042 JSObject
* compileError
= constructData
.js
.functionExecutable
->prepareForExecution(callFrame
, jsCast
<JSFunction
*>(constructor
), &scope
, CodeForConstruct
);
1043 if (UNLIKELY(!!compileError
)) {
1044 return checkedReturn(callFrame
->vm().throwException(callFrame
, compileError
));
1046 newCodeBlock
= constructData
.js
.functionExecutable
->codeBlockForConstruct();
1047 ASSERT(!!newCodeBlock
);
1048 newCodeBlock
->m_shouldAlwaysBeInlined
= false;
1052 if (UNLIKELY(vm
.watchdog
&& vm
.watchdog
->didFire(callFrame
)))
1053 return throwTerminatedExecutionException(callFrame
);
1055 ProtoCallFrame protoCallFrame
;
1056 protoCallFrame
.init(newCodeBlock
, scope
, constructor
, jsUndefined(), argsCount
, args
.data());
1058 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
1059 profiler
->willExecute(callFrame
, constructor
);
1063 SamplingTool::CallRecord
callRecord(m_sampler
.get(), !isJSConstruct
);
1064 Watchdog::Scope
watchdogScope(vm
.watchdog
.get());
1066 // Execute the code.
1068 result
= constructData
.js
.functionExecutable
->generatedJITCodeForConstruct()->execute(&vm
, &protoCallFrame
);
1070 result
= JSValue::decode(callToNativeFunction(reinterpret_cast<void*>(constructData
.native
.function
), &vm
, &protoCallFrame
));
1072 if (!callFrame
->hadException())
1073 RELEASE_ASSERT(result
.isObject());
1077 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
1078 profiler
->didExecute(callFrame
, constructor
);
1080 if (callFrame
->hadException())
1082 ASSERT(result
.isObject());
1083 return checkedReturn(asObject(result
));
1086 CallFrameClosure
Interpreter::prepareForRepeatCall(FunctionExecutable
* functionExecutable
, CallFrame
* callFrame
, ProtoCallFrame
* protoCallFrame
, JSFunction
* function
, int argumentCountIncludingThis
, JSScope
* scope
, JSValue
* args
)
1088 VM
& vm
= *scope
->vm();
1089 ASSERT(!vm
.exception());
1091 if (vm
.isCollectorBusy())
1092 return CallFrameClosure();
1094 // Compile the callee:
1095 JSObject
* error
= functionExecutable
->prepareForExecution(callFrame
, function
, &scope
, CodeForCall
);
1097 callFrame
->vm().throwException(callFrame
, error
);
1098 return CallFrameClosure();
1100 CodeBlock
* newCodeBlock
= functionExecutable
->codeBlockForCall();
1101 newCodeBlock
->m_shouldAlwaysBeInlined
= false;
1103 size_t argsCount
= argumentCountIncludingThis
;
1105 protoCallFrame
->init(newCodeBlock
, scope
, function
, jsUndefined(), argsCount
, args
);
1106 // Return the successful closure:
1107 CallFrameClosure result
= { callFrame
, protoCallFrame
, function
, functionExecutable
, &vm
, scope
, newCodeBlock
->numParameters(), argumentCountIncludingThis
};
1111 JSValue
Interpreter::execute(CallFrameClosure
& closure
)
1113 VM
& vm
= *closure
.vm
;
1114 SamplingScope
samplingScope(this);
1116 ASSERT(!vm
.isCollectorBusy());
1117 RELEASE_ASSERT(vm
.currentThreadIsHoldingAPILock());
1118 if (vm
.isCollectorBusy())
1121 StackStats::CheckPoint stackCheckPoint
;
1122 closure
.resetCallFrame();
1124 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
1125 profiler
->willExecute(closure
.oldCallFrame
, closure
.function
);
1127 if (UNLIKELY(vm
.watchdog
&& vm
.watchdog
->didFire(closure
.oldCallFrame
)))
1128 return throwTerminatedExecutionException(closure
.oldCallFrame
);
1130 // Execute the code:
1133 SamplingTool::CallRecord
callRecord(m_sampler
.get());
1134 Watchdog::Scope
watchdogScope(vm
.watchdog
.get());
1136 result
= closure
.functionExecutable
->generatedJITCodeForCall()->execute(&vm
, closure
.protoCallFrame
);
1139 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
1140 profiler
->didExecute(closure
.oldCallFrame
, closure
.function
);
1142 return checkedReturn(result
);
1145 JSValue
Interpreter::execute(EvalExecutable
* eval
, CallFrame
* callFrame
, JSValue thisValue
, JSScope
* scope
)
1147 VM
& vm
= *scope
->vm();
1148 SamplingScope
samplingScope(this);
1150 ASSERT(scope
->vm() == &callFrame
->vm());
1151 ASSERT(!vm
.exception());
1152 ASSERT(!vm
.isCollectorBusy());
1153 RELEASE_ASSERT(vm
.currentThreadIsHoldingAPILock());
1154 if (vm
.isCollectorBusy())
1157 VMEntryScope
entryScope(vm
, scope
->globalObject());
1158 if (!vm
.isSafeToRecurse())
1159 return checkedReturn(throwStackOverflowError(callFrame
));
1161 unsigned numVariables
= eval
->numVariables();
1162 int numFunctions
= eval
->numberOfFunctionDecls();
1164 JSScope
* variableObject
;
1165 if ((numVariables
|| numFunctions
) && eval
->isStrictMode()) {
1166 scope
= StrictEvalActivation::create(callFrame
);
1167 variableObject
= scope
;
1169 for (JSScope
* node
= scope
; ; node
= node
->next()) {
1170 RELEASE_ASSERT(node
);
1171 if (node
->isVariableObject() && !node
->isNameScopeObject()) {
1172 variableObject
= node
;
1178 JSObject
* compileError
= eval
->prepareForExecution(callFrame
, nullptr, &scope
, CodeForCall
);
1179 if (UNLIKELY(!!compileError
))
1180 return checkedReturn(callFrame
->vm().throwException(callFrame
, compileError
));
1181 EvalCodeBlock
* codeBlock
= eval
->codeBlock();
1183 if (numVariables
|| numFunctions
) {
1184 BatchedTransitionOptimizer
optimizer(vm
, variableObject
);
1185 if (variableObject
->next())
1186 variableObject
->globalObject()->varInjectionWatchpoint()->fireAll();
1188 for (unsigned i
= 0; i
< numVariables
; ++i
) {
1189 const Identifier
& ident
= codeBlock
->variable(i
);
1190 if (!variableObject
->hasProperty(callFrame
, ident
)) {
1191 PutPropertySlot
slot(variableObject
);
1192 variableObject
->methodTable()->put(variableObject
, callFrame
, ident
, jsUndefined(), slot
);
1196 for (int i
= 0; i
< numFunctions
; ++i
) {
1197 FunctionExecutable
* function
= codeBlock
->functionDecl(i
);
1198 PutPropertySlot
slot(variableObject
);
1199 variableObject
->methodTable()->put(variableObject
, callFrame
, function
->name(), JSFunction::create(vm
, function
, scope
), slot
);
1203 if (UNLIKELY(vm
.watchdog
&& vm
.watchdog
->didFire(callFrame
)))
1204 return throwTerminatedExecutionException(callFrame
);
1206 ASSERT(codeBlock
->numParameters() == 1); // 1 parameter for 'this'.
1208 ProtoCallFrame protoCallFrame
;
1209 protoCallFrame
.init(codeBlock
, scope
, 0, thisValue
, 1);
1211 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
1212 profiler
->willExecute(callFrame
, eval
->sourceURL(), eval
->lineNo(), eval
->startColumn());
1214 // Execute the code:
1217 SamplingTool::CallRecord
callRecord(m_sampler
.get());
1218 Watchdog::Scope
watchdogScope(vm
.watchdog
.get());
1220 result
= eval
->generatedJITCode()->execute(&vm
, &protoCallFrame
);
1223 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
1224 profiler
->didExecute(callFrame
, eval
->sourceURL(), eval
->lineNo(), eval
->startColumn());
1226 return checkedReturn(result
);
1229 NEVER_INLINE
void Interpreter::debug(CallFrame
* callFrame
, DebugHookID debugHookID
)
1231 Debugger
* debugger
= callFrame
->vmEntryGlobalObject()->debugger();
1235 ASSERT(callFrame
->codeBlock()->hasDebuggerRequests());
1236 ASSERT(!callFrame
->hadException());
1238 switch (debugHookID
) {
1239 case DidEnterCallFrame
:
1240 debugger
->callEvent(callFrame
);
1242 case WillLeaveCallFrame
:
1243 debugger
->returnEvent(callFrame
);
1245 case WillExecuteStatement
:
1246 debugger
->atStatement(callFrame
);
1248 case WillExecuteProgram
:
1249 debugger
->willExecuteProgram(callFrame
);
1251 case DidExecuteProgram
:
1252 debugger
->didExecuteProgram(callFrame
);
1254 case DidReachBreakpoint
:
1255 debugger
->didReachBreakpoint(callFrame
);
1258 ASSERT(!callFrame
->hadException());
1261 void Interpreter::enableSampler()
1263 #if ENABLE(OPCODE_SAMPLING)
1265 m_sampler
= adoptPtr(new SamplingTool(this));
1270 void Interpreter::dumpSampleData(ExecState
* exec
)
1272 #if ENABLE(OPCODE_SAMPLING)
1274 m_sampler
->dump(exec
);
1279 void Interpreter::startSampling()
1281 #if ENABLE(SAMPLING_THREAD)
1282 if (!m_sampleEntryDepth
)
1283 SamplingThread::start();
1285 m_sampleEntryDepth
++;
1288 void Interpreter::stopSampling()
1290 #if ENABLE(SAMPLING_THREAD)
1291 m_sampleEntryDepth
--;
1292 if (!m_sampleEntryDepth
)
1293 SamplingThread::stop();