2 * Copyright (C) 2008, 2009, 2010, 2012, 2013 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 "CallFrameInlines.h"
38 #include "CodeBlock.h"
41 #include "DebuggerCallFrame.h"
42 #include "ErrorInstance.h"
43 #include "EvalCodeCache.h"
44 #include "ExceptionHelpers.h"
45 #include "GetterSetter.h"
46 #include "JSActivation.h"
48 #include "JSBoundFunction.h"
49 #include "JSNameScope.h"
50 #include "JSNotAnObject.h"
51 #include "JSPropertyNameIterator.h"
52 #include "JSStackInlines.h"
54 #include "JSWithScope.h"
55 #include "LLIntCLoop.h"
56 #include "LegacyProfiler.h"
57 #include "LiteralParser.h"
58 #include "NameInstance.h"
59 #include "ObjectPrototype.h"
60 #include "Operations.h"
62 #include "RegExpObject.h"
63 #include "RegExpPrototype.h"
65 #include "SamplingTool.h"
66 #include "StackIterator.h"
67 #include "StrictEvalActivation.h"
68 #include "StrongInlines.h"
69 #include "VMStackBounds.h"
72 #include <wtf/StackStats.h>
73 #include <wtf/StringPrintStream.h>
74 #include <wtf/Threading.h>
75 #include <wtf/WTFThreadData.h>
76 #include <wtf/text/StringBuilder.h>
82 #define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (ENABLE(LLINT) && !defined(__llvm__))
88 Interpreter::ErrorHandlingMode::ErrorHandlingMode(ExecState *exec)
89 : m_interpreter(*exec->interpreter())
91 if (!m_interpreter.m_errorHandlingModeReentry)
92 m_interpreter.stack().enableErrorStackReserve();
93 m_interpreter.m_errorHandlingModeReentry++;
96 Interpreter::ErrorHandlingMode::~ErrorHandlingMode()
98 m_interpreter.m_errorHandlingModeReentry--;
99 ASSERT(m_interpreter.m_errorHandlingModeReentry >= 0);
100 if (!m_interpreter.m_errorHandlingModeReentry)
101 m_interpreter.stack().disableErrorStackReserve();
104 JSValue eval(CallFrame* callFrame)
106 if (!callFrame->argumentCount())
107 return jsUndefined();
109 JSValue program = callFrame->argument(0);
110 if (!program.isString())
113 TopCallFrameSetter topCallFrame(callFrame->vm(), callFrame);
114 String programSource = asString(program)->value(callFrame);
115 if (callFrame->hadException())
118 CallFrame* callerFrame = callFrame->callerFrame();
119 CodeBlock* callerCodeBlock = callerFrame->codeBlock();
120 JSScope* callerScopeChain = callerFrame->scope();
121 EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(callerCodeBlock->isStrictMode(), programSource, callerScopeChain);
124 if (!callerCodeBlock->isStrictMode()) {
125 // FIXME: We can use the preparser in strict mode, we just need additional logic
126 // to prevent duplicates.
127 if (programSource.is8Bit()) {
128 LiteralParser<LChar> preparser(callFrame, programSource.characters8(), programSource.length(), NonStrictJSON);
129 if (JSValue parsedObject = preparser.tryLiteralParse())
132 LiteralParser<UChar> preparser(callFrame, programSource.characters16(), programSource.length(), NonStrictJSON);
133 if (JSValue parsedObject = preparser.tryLiteralParse())
138 // If the literal parser bailed, it should not have thrown exceptions.
139 ASSERT(!callFrame->vm().exception());
141 eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->ownerExecutable(), callerCodeBlock->isStrictMode(), programSource, callerScopeChain);
143 return jsUndefined();
146 JSValue thisValue = callerFrame->thisValue();
147 Interpreter* interpreter = callFrame->vm().interpreter;
148 return interpreter->execute(eval, callFrame, thisValue, callerScopeChain);
151 CallFrame* loadVarargs(CallFrame* callFrame, JSStack* stack, JSValue thisValue, JSValue arguments, int firstFreeRegister)
153 if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
154 unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
155 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + argumentCountIncludingThis + JSStack::CallFrameHeaderSize);
156 if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !stack->grow(newCallFrame->registers())) {
157 callFrame->vm().throwException(callFrame, createStackOverflowError(callFrame));
161 newCallFrame->setArgumentCountIncludingThis(argumentCountIncludingThis);
162 newCallFrame->setThisValue(thisValue);
163 for (size_t i = 0; i < callFrame->argumentCount(); ++i)
164 newCallFrame->setArgument(i, callFrame->argumentAfterCapture(i));
168 if (arguments.isUndefinedOrNull()) {
169 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + 1 + JSStack::CallFrameHeaderSize);
170 if (!stack->grow(newCallFrame->registers())) {
171 callFrame->vm().throwException(callFrame, createStackOverflowError(callFrame));
174 newCallFrame->setArgumentCountIncludingThis(1);
175 newCallFrame->setThisValue(thisValue);
179 if (!arguments.isObject()) {
180 callFrame->vm().throwException(callFrame, createInvalidParameterError(callFrame, "Function.prototype.apply", arguments));
184 if (asObject(arguments)->classInfo() == Arguments::info()) {
185 Arguments* argsObject = asArguments(arguments);
186 unsigned argCount = argsObject->length(callFrame);
187 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
188 if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) {
189 callFrame->vm().throwException(callFrame, createStackOverflowError(callFrame));
192 newCallFrame->setArgumentCountIncludingThis(argCount + 1);
193 newCallFrame->setThisValue(thisValue);
194 argsObject->copyToArguments(callFrame, newCallFrame, argCount);
198 if (isJSArray(arguments)) {
199 JSArray* array = asArray(arguments);
200 unsigned argCount = array->length();
201 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
202 if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) {
203 callFrame->vm().throwException(callFrame, createStackOverflowError(callFrame));
206 newCallFrame->setArgumentCountIncludingThis(argCount + 1);
207 newCallFrame->setThisValue(thisValue);
208 array->copyToArguments(callFrame, newCallFrame, argCount);
212 JSObject* argObject = asObject(arguments);
213 unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
214 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
215 if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) {
216 callFrame->vm().throwException(callFrame, createStackOverflowError(callFrame));
219 newCallFrame->setArgumentCountIncludingThis(argCount + 1);
220 newCallFrame->setThisValue(thisValue);
221 for (size_t i = 0; i < argCount; ++i) {
222 newCallFrame->setArgument(i, asObject(arguments)->get(callFrame, i));
223 if (UNLIKELY(callFrame->vm().exception()))
229 Interpreter::Interpreter(VM& vm)
230 : m_sampleEntryDepth(0)
233 , m_errorHandlingModeReentry(0)
235 , m_initialized(false)
240 Interpreter::~Interpreter()
244 void Interpreter::initialize(bool canUseJIT)
246 UNUSED_PARAM(canUseJIT);
248 #if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT)
249 m_opcodeTable = LLInt::opcodeMap();
250 for (int i = 0; i < numOpcodeIDs; ++i)
251 m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
255 m_initialized = true;
258 #if ENABLE(OPCODE_SAMPLING)
265 void Interpreter::dumpCallFrame(CallFrame*)
271 void Interpreter::dumpCallFrame(CallFrame* callFrame)
273 callFrame->codeBlock()->dumpBytecode();
274 dumpRegisters(callFrame);
277 void Interpreter::dumpRegisters(CallFrame* callFrame)
279 dataLogF("Register frame: \n\n");
280 dataLogF("-----------------------------------------------------------------------------\n");
281 dataLogF(" use | address | value \n");
282 dataLogF("-----------------------------------------------------------------------------\n");
284 CodeBlock* codeBlock = callFrame->codeBlock();
288 it = callFrame->registers() - JSStack::CallFrameHeaderSize - callFrame->argumentCountIncludingThis();
289 end = callFrame->registers() - JSStack::CallFrameHeaderSize;
291 JSValue v = it->jsValue();
292 int registerNumber = it - callFrame->registers();
293 String name = codeBlock->nameForRegister(registerNumber);
294 dataLogF("[r% 3d %14s] | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, toCString(v).data(), (long long)JSValue::encode(v));
298 dataLogF("-----------------------------------------------------------------------------\n");
299 dataLogF("[ArgumentCount] | %10p | %lu \n", it, (unsigned long) callFrame->argumentCount());
301 dataLogF("[CallerFrame] | %10p | %p \n", it, callFrame->callerFrame());
303 dataLogF("[Callee] | %10p | %p \n", it, callFrame->callee());
305 dataLogF("[ScopeChain] | %10p | %p \n", it, callFrame->scope());
308 AbstractPC pc = callFrame->abstractReturnPC(callFrame->vm());
309 if (pc.hasJITReturnAddress())
310 dataLogF("[ReturnJITPC] | %10p | %p \n", it, pc.jitReturnAddress().value());
312 StackIterator iter = callFrame->begin();
314 if (iter != callFrame->end()) {
316 unsigned unusedColumn = 0;
317 iter->computeLineAndColumn(line, unusedColumn);
318 dataLogF("[ReturnVPC] | %10p | %d (line %d)\n", it, iter->bytecodeOffset(), line);
321 dataLogF("[CodeBlock] | %10p | %p \n", it, callFrame->codeBlock());
323 dataLogF("-----------------------------------------------------------------------------\n");
325 int registerCount = 0;
327 end = it + codeBlock->m_numVars;
330 JSValue v = it->jsValue();
331 int registerNumber = it - callFrame->registers();
332 String name = codeBlock->nameForRegister(registerNumber);
333 dataLogF("[r% 3d %14s] | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, toCString(v).data(), (long long)JSValue::encode(v));
338 dataLogF("-----------------------------------------------------------------------------\n");
340 end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars;
343 JSValue v = (*it).jsValue();
344 dataLogF("[r% 3d] | %10p | %-16s 0x%lld \n", registerCount, it, toCString(v).data(), (long long)JSValue::encode(v));
349 dataLogF("-----------------------------------------------------------------------------\n");
354 bool Interpreter::isOpcode(Opcode opcode)
356 #if ENABLE(COMPUTED_GOTO_OPCODES)
358 return static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)) <= op_end;
360 return opcode != HashTraits<Opcode>::emptyValue()
361 && !HashTraits<Opcode>::isDeletedValue(opcode)
362 && m_opcodeIDTable.contains(opcode);
365 return opcode >= 0 && opcode <= op_end;
369 NEVER_INLINE bool Interpreter::unwindCallFrame(StackIterator& iter, JSValue exceptionValue)
371 CallFrame* callFrame = iter->callFrame();
372 CodeBlock* codeBlock = iter->codeBlock();
373 CodeBlock* oldCodeBlock = codeBlock;
374 JSScope* scope = callFrame->scope();
376 if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
377 DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
378 if (callFrame->callee())
379 debugger->returnEvent(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine(), 0);
381 debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine(), 0);
385 if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsActivation()) {
386 activation = callFrame->uncheckedR(oldCodeBlock->activationRegister()).jsValue();
388 jsCast<JSActivation*>(activation)->tearOff(*scope->vm());
391 if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->usesArguments()) {
392 if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) {
394 jsCast<Arguments*>(arguments)->didTearOffActivation(callFrame, jsCast<JSActivation*>(activation));
396 jsCast<Arguments*>(arguments)->tearOff(callFrame);
400 CallFrame* callerFrame = callFrame->callerFrame();
401 callFrame->vm().topCallFrame = callerFrame->removeHostCallFrameFlag();
402 return !callerFrame->hasHostCallFrameFlag();
405 static ALWAYS_INLINE const String getSourceURLFromCallFrame(CallFrame* callFrame)
407 ASSERT(!callFrame->hasHostCallFrameFlag());
408 return callFrame->codeBlock()->ownerExecutable()->sourceURL();
411 static StackFrameCodeType getStackFrameCodeType(StackIterator iter)
413 switch (iter->codeType()) {
414 case StackIterator::Frame::Eval:
415 return StackFrameEvalCode;
416 case StackIterator::Frame::Function:
417 return StackFrameFunctionCode;
418 case StackIterator::Frame::Global:
419 return StackFrameGlobalCode;
420 case StackIterator::Frame::Native:
421 ASSERT_NOT_REACHED();
422 return StackFrameNativeCode;
424 RELEASE_ASSERT_NOT_REACHED();
425 return StackFrameGlobalCode;
428 void StackFrame::computeLineAndColumn(unsigned& line, unsigned& column)
437 int unusedStartOffset = 0;
438 int unusedEndOffset = 0;
439 unsigned divotLine = 0;
440 unsigned divotColumn = 0;
441 expressionInfo(divot, unusedStartOffset, unusedEndOffset, divotLine, divotColumn);
443 line = divotLine + lineOffset;
444 column = divotColumn + (divotLine ? 1 : firstLineColumnOffset);
447 void StackFrame::expressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
449 codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
450 divot += characterOffset;
453 String StackFrame::toString(CallFrame* callFrame)
455 StringBuilder traceBuild;
456 String functionName = friendlyFunctionName(callFrame);
457 String sourceURL = friendlySourceURL();
458 traceBuild.append(functionName);
459 if (!sourceURL.isEmpty()) {
460 if (!functionName.isEmpty())
461 traceBuild.append('@');
462 traceBuild.append(sourceURL);
463 if (codeType != StackFrameNativeCode) {
466 computeLineAndColumn(line, column);
468 traceBuild.append(':');
469 traceBuild.appendNumber(line);
470 traceBuild.append(':');
471 traceBuild.appendNumber(column);
474 return traceBuild.toString().impl();
477 void Interpreter::getStackTrace(Vector<StackFrame>& results, size_t maxStackSize)
480 ASSERT(!vm.topCallFrame->hasHostCallFrameFlag());
481 CallFrame* callFrame = vm.topCallFrame;
484 StackIterator iter = callFrame->begin();
485 for (; iter != callFrame->end() && maxStackSize--; ++iter) {
486 if (iter->isJSFrame()) {
487 CodeBlock* codeBlock = iter->codeBlock();
489 Strong<JSObject>(vm, iter->callee()),
490 getStackFrameCodeType(iter),
491 Strong<ExecutableBase>(vm, codeBlock->ownerExecutable()),
492 Strong<UnlinkedCodeBlock>(vm, codeBlock->unlinkedCodeBlock()),
494 codeBlock->ownerExecutable()->lineNo(),
495 codeBlock->firstLineColumnOffset(),
496 codeBlock->sourceOffset(),
497 iter->bytecodeOffset(),
502 StackFrame s = { Strong<JSObject>(vm, iter->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), Strong<UnlinkedCodeBlock>(), 0, 0, 0, 0, 0, String()};
507 JSString* Interpreter:: stackTraceAsString(ExecState* exec, Vector<StackFrame> stackTrace)
509 // FIXME: JSStringJoiner could be more efficient than StringBuilder here.
510 StringBuilder builder;
511 for (unsigned i = 0; i < stackTrace.size(); i++) {
512 builder.append(String(stackTrace[i].toString(exec)));
513 if (i != stackTrace.size() - 1)
514 builder.append('\n');
516 return jsString(&exec->vm(), builder.toString());
519 NEVER_INLINE HandlerInfo* Interpreter::unwind(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
521 CodeBlock* codeBlock = callFrame->codeBlock();
522 bool isTermination = false;
524 ASSERT(!exceptionValue.isEmpty());
525 ASSERT(!exceptionValue.isCell() || exceptionValue.asCell());
526 // This shouldn't be possible (hence the assertions), but we're already in the slowest of
527 // slow cases, so let's harden against it anyway to be safe.
528 if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
529 exceptionValue = jsNull();
531 if (exceptionValue.isObject()) {
532 isTermination = isTerminatedExecutionException(asObject(exceptionValue));
535 ASSERT(callFrame->vm().exceptionStack().size());
536 ASSERT(!exceptionValue.isObject() || asObject(exceptionValue)->hasProperty(callFrame, callFrame->vm().propertyNames->stack));
538 if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
539 // We need to clear the exception and the exception stack here in order to see if a new exception happens.
540 // Afterwards, the values are put back to continue processing this error.
541 ClearExceptionScope scope(&callFrame->vm());
543 DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
544 bool hasHandler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
545 debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), 0, hasHandler);
548 // Calculate an exception handler vPC, unwinding call frames as necessary.
549 HandlerInfo* handler = 0;
550 VM& vm = callFrame->vm();
551 ASSERT(callFrame == vm.topCallFrame);
552 for (StackIterator iter = callFrame->begin(); iter != callFrame->end(); ++iter) {
553 callFrame = iter->callFrame();
554 codeBlock = iter->codeBlock();
555 bytecodeOffset = iter->bytecodeOffset();
557 if (isTermination || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
558 if (!unwindCallFrame(iter, exceptionValue)) {
559 if (LegacyProfiler* profiler = vm.enabledProfiler())
560 profiler->exceptionUnwind(callFrame);
567 if (LegacyProfiler* profiler = callFrame->vm().enabledProfiler())
568 profiler->exceptionUnwind(callFrame);
570 // Unwind the scope chain within the exception handler's call frame.
571 int targetScopeDepth = handler->scopeDepth;
572 if (codeBlock->needsActivation() && callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
575 JSScope* scope = callFrame->scope();
576 int scopeDelta = scope->depth() - targetScopeDepth;
577 RELEASE_ASSERT(scopeDelta >= 0);
580 scope = scope->next();
581 callFrame->setScope(scope);
586 static inline JSValue checkedReturn(JSValue returnValue)
592 static inline JSObject* checkedReturn(JSObject* returnValue)
598 class SamplingScope {
600 SamplingScope(Interpreter* interpreter)
601 : m_interpreter(interpreter)
603 interpreter->startSampling();
607 m_interpreter->stopSampling();
610 Interpreter* m_interpreter;
613 JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, JSObject* thisObj)
615 SamplingScope samplingScope(this);
617 JSScope* scope = callFrame->scope();
618 VM& vm = *scope->vm();
620 ASSERT(!vm.exception());
621 ASSERT(!vm.isCollectorBusy());
622 if (vm.isCollectorBusy())
625 StackStats::CheckPoint stackCheckPoint;
626 const VMStackBounds vmStackBounds(vm, wtfThreadData().stack());
627 if (!vmStackBounds.isSafeToRecurse())
628 return checkedReturn(throwStackOverflowError(callFrame));
630 // First check if the "program" is actually just a JSON object. If so,
631 // we'll handle the JSON object here. Else, we'll handle real JS code
632 // below at failedJSONP.
633 DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
634 Vector<JSONPData> JSONPData;
636 const String programSource = program->source().toString();
637 if (programSource.isNull())
638 return jsUndefined();
639 if (programSource.is8Bit()) {
640 LiteralParser<LChar> literalParser(callFrame, programSource.characters8(), programSource.length(), JSONP);
641 parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
643 LiteralParser<UChar> literalParser(callFrame, programSource.characters16(), programSource.length(), JSONP);
644 parseResult = literalParser.tryJSONPParse(JSONPData, scope->globalObject()->globalObjectMethodTable()->supportsRichSourceInfo(scope->globalObject()));
648 JSGlobalObject* globalObject = scope->globalObject();
650 for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
651 Vector<JSONPPathEntry> JSONPPath;
652 JSONPPath.swap(JSONPData[entry].m_path);
653 JSValue JSONPValue = JSONPData[entry].m_value.get();
654 if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclare) {
655 globalObject->addVar(callFrame, JSONPPath[0].m_pathEntryName);
656 PutPropertySlot slot;
657 globalObject->methodTable()->put(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
658 result = jsUndefined();
661 JSValue baseObject(globalObject);
662 for (unsigned i = 0; i < JSONPPath.size() - 1; i++) {
663 ASSERT(JSONPPath[i].m_type != JSONPPathEntryTypeDeclare);
664 switch (JSONPPath[i].m_type) {
665 case JSONPPathEntryTypeDot: {
667 PropertySlot slot(globalObject);
668 if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
670 return callFrame->vm().throwException(callFrame, createUndefinedVariableError(globalObject->globalExec(), JSONPPath[i].m_pathEntryName));
673 baseObject = slot.getValue(callFrame, JSONPPath[i].m_pathEntryName);
675 baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathEntryName);
676 if (callFrame->hadException())
677 return jsUndefined();
680 case JSONPPathEntryTypeLookup: {
681 baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
682 if (callFrame->hadException())
683 return jsUndefined();
687 RELEASE_ASSERT_NOT_REACHED();
688 return jsUndefined();
691 PutPropertySlot slot;
692 switch (JSONPPath.last().m_type) {
693 case JSONPPathEntryTypeCall: {
694 JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
695 if (callFrame->hadException())
696 return jsUndefined();
698 CallType callType = getCallData(function, callData);
699 if (callType == CallTypeNone)
700 return callFrame->vm().throwException(callFrame, createNotAFunctionError(callFrame, function));
701 MarkedArgumentBuffer jsonArg;
702 jsonArg.append(JSONPValue);
703 JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined(): baseObject;
704 JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg);
705 if (callFrame->hadException())
706 return jsUndefined();
709 case JSONPPathEntryTypeDot: {
710 baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
711 if (callFrame->hadException())
712 return jsUndefined();
715 case JSONPPathEntryTypeLookup: {
716 baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
717 if (callFrame->hadException())
718 return jsUndefined();
722 RELEASE_ASSERT_NOT_REACHED();
723 return jsUndefined();
730 // If we get here, then we have already proven that the script is not a JSON
733 // Compile source to bytecode if necessary:
734 if (JSObject* error = program->initializeGlobalProperties(vm, callFrame, scope))
735 return checkedReturn(callFrame->vm().throwException(callFrame, error));
737 if (JSObject* error = program->compile(callFrame, scope))
738 return checkedReturn(callFrame->vm().throwException(callFrame, error));
740 ProgramCodeBlock* codeBlock = &program->generatedBytecode();
742 if (UNLIKELY(vm.watchdog.didFire(callFrame)))
743 return throwTerminatedExecutionException(callFrame);
745 // Push the call frame for this invocation:
746 ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
747 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, codeBlock, scope, 1, 0);
748 if (UNLIKELY(!newCallFrame))
749 return checkedReturn(throwStackOverflowError(callFrame));
751 // Set the arguments for the callee:
752 newCallFrame->setThisValue(thisObj);
754 if (LegacyProfiler* profiler = vm.enabledProfiler())
755 profiler->willExecute(callFrame, program->sourceURL(), program->lineNo());
760 SamplingTool::CallRecord callRecord(m_sampler.get());
761 Watchdog::Scope watchdogScope(vm.watchdog);
763 #if ENABLE(LLINT_C_LOOP)
764 result = LLInt::CLoop::execute(newCallFrame, llint_program_prologue);
766 result = program->generatedJITCode()->execute(&m_stack, newCallFrame, &vm);
767 #endif // ENABLE(JIT)
770 if (LegacyProfiler* profiler = vm.enabledProfiler())
771 profiler->didExecute(callFrame, program->sourceURL(), program->lineNo());
773 m_stack.popFrame(newCallFrame);
775 return checkedReturn(result);
778 JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
780 VM& vm = callFrame->vm();
781 ASSERT(!callFrame->hadException());
782 ASSERT(!vm.isCollectorBusy());
783 if (vm.isCollectorBusy())
786 StackStats::CheckPoint stackCheckPoint;
787 const VMStackBounds vmStackBounds(vm, wtfThreadData().stack());
788 if (!vmStackBounds.isSafeToRecurse())
789 return checkedReturn(throwStackOverflowError(callFrame));
791 bool isJSCall = (callType == CallTypeJS);
793 CodeBlock* newCodeBlock;
794 size_t argsCount = 1 + args.size(); // implicit "this" parameter
797 scope = callData.js.scope;
799 ASSERT(callType == CallTypeHost);
800 scope = callFrame->scope();
802 DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
805 // Compile the callee:
806 JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, scope);
807 if (UNLIKELY(!!compileError)) {
808 return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
810 newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
811 ASSERT(!!newCodeBlock);
812 newCodeBlock->m_shouldAlwaysBeInlined = false;
816 if (UNLIKELY(vm.watchdog.didFire(callFrame)))
817 return throwTerminatedExecutionException(callFrame);
819 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, newCodeBlock, scope, argsCount, function);
820 if (UNLIKELY(!newCallFrame))
821 return checkedReturn(throwStackOverflowError(callFrame));
823 // Set the arguments for the callee:
824 newCallFrame->setThisValue(thisValue);
825 for (size_t i = 0; i < args.size(); ++i)
826 newCallFrame->setArgument(i, args.at(i));
828 if (LegacyProfiler* profiler = vm.enabledProfiler())
829 profiler->willExecute(callFrame, function);
833 SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSCall);
834 Watchdog::Scope watchdogScope(vm.watchdog);
838 #if ENABLE(LLINT_C_LOOP)
839 result = LLInt::CLoop::execute(newCallFrame, llint_function_for_call_prologue);
841 result = callData.js.functionExecutable->generatedJITCodeForCall()->execute(&m_stack, newCallFrame, &vm);
842 #endif // ENABLE(JIT)
844 result = JSValue::decode(callData.native.function(newCallFrame));
847 if (LegacyProfiler* profiler = vm.enabledProfiler())
848 profiler->didExecute(callFrame, function);
850 m_stack.popFrame(newCallFrame);
851 return checkedReturn(result);
854 JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
856 VM& vm = callFrame->vm();
857 ASSERT(!callFrame->hadException());
858 ASSERT(!vm.isCollectorBusy());
859 // We throw in this case because we have to return something "valid" but we're
860 // already in an invalid state.
861 if (vm.isCollectorBusy())
862 return checkedReturn(throwStackOverflowError(callFrame));
864 StackStats::CheckPoint stackCheckPoint;
865 const VMStackBounds vmStackBounds(vm, wtfThreadData().stack());
866 if (!vmStackBounds.isSafeToRecurse())
867 return checkedReturn(throwStackOverflowError(callFrame));
869 bool isJSConstruct = (constructType == ConstructTypeJS);
871 CodeBlock* newCodeBlock;
872 size_t argsCount = 1 + args.size(); // implicit "this" parameter
875 scope = constructData.js.scope;
877 ASSERT(constructType == ConstructTypeHost);
878 scope = callFrame->scope();
881 DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
884 // Compile the callee:
885 JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, scope);
886 if (UNLIKELY(!!compileError)) {
887 return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
889 newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
890 ASSERT(!!newCodeBlock);
891 newCodeBlock->m_shouldAlwaysBeInlined = false;
895 if (UNLIKELY(vm.watchdog.didFire(callFrame)))
896 return throwTerminatedExecutionException(callFrame);
898 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, newCodeBlock, scope, argsCount, constructor);
899 if (UNLIKELY(!newCallFrame))
900 return checkedReturn(throwStackOverflowError(callFrame));
902 // Set the arguments for the callee:
903 newCallFrame->setThisValue(jsUndefined());
904 for (size_t i = 0; i < args.size(); ++i)
905 newCallFrame->setArgument(i, args.at(i));
907 if (LegacyProfiler* profiler = vm.enabledProfiler())
908 profiler->willExecute(callFrame, constructor);
912 SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSConstruct);
913 Watchdog::Scope watchdogScope(vm.watchdog);
917 #if ENABLE(LLINT_C_LOOP)
918 result = LLInt::CLoop::execute(newCallFrame, llint_function_for_construct_prologue);
920 result = constructData.js.functionExecutable->generatedJITCodeForConstruct()->execute(&m_stack, newCallFrame, &vm);
921 #endif // ENABLE(JIT)
923 result = JSValue::decode(constructData.native.function(newCallFrame));
924 if (!callFrame->hadException()) {
925 ASSERT_WITH_MESSAGE(result.isObject(), "Host constructor returned non object.");
926 if (!result.isObject())
927 throwTypeError(newCallFrame);
932 if (LegacyProfiler* profiler = vm.enabledProfiler())
933 profiler->didExecute(callFrame, constructor);
935 m_stack.popFrame(newCallFrame);
937 if (callFrame->hadException())
939 ASSERT(result.isObject());
940 return checkedReturn(asObject(result));
943 CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, int argumentCountIncludingThis, JSScope* scope)
945 VM& vm = *scope->vm();
946 ASSERT(!vm.exception());
948 if (vm.isCollectorBusy())
949 return CallFrameClosure();
951 StackStats::CheckPoint stackCheckPoint;
952 const VMStackBounds vmStackBounds(vm, wtfThreadData().stack());
953 if (!vmStackBounds.isSafeToRecurse()) {
954 throwStackOverflowError(callFrame);
955 return CallFrameClosure();
958 // Compile the callee:
959 JSObject* error = functionExecutable->compileForCall(callFrame, scope);
961 callFrame->vm().throwException(callFrame, error);
962 return CallFrameClosure();
964 CodeBlock* newCodeBlock = &functionExecutable->generatedBytecodeForCall();
965 newCodeBlock->m_shouldAlwaysBeInlined = false;
967 size_t argsCount = argumentCountIncludingThis;
969 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, newCodeBlock, scope, argsCount, function);
970 if (UNLIKELY(!newCallFrame)) {
971 throwStackOverflowError(callFrame);
972 return CallFrameClosure();
975 if (UNLIKELY(!newCallFrame)) {
976 throwStackOverflowError(callFrame);
977 return CallFrameClosure();
980 // Return the successful closure:
981 CallFrameClosure result = { callFrame, newCallFrame, function, functionExecutable, &vm, scope, newCodeBlock->numParameters(), argumentCountIncludingThis };
985 JSValue Interpreter::execute(CallFrameClosure& closure)
987 VM& vm = *closure.vm;
988 SamplingScope samplingScope(this);
990 ASSERT(!vm.isCollectorBusy());
991 if (vm.isCollectorBusy())
994 StackStats::CheckPoint stackCheckPoint;
995 m_stack.validateFence(closure.newCallFrame, "BEFORE");
996 closure.resetCallFrame();
997 m_stack.validateFence(closure.newCallFrame, "STEP 1");
999 if (LegacyProfiler* profiler = vm.enabledProfiler())
1000 profiler->willExecute(closure.oldCallFrame, closure.function);
1002 if (UNLIKELY(vm.watchdog.didFire(closure.oldCallFrame)))
1003 return throwTerminatedExecutionException(closure.oldCallFrame);
1005 // The code execution below may push more frames and point the topCallFrame
1006 // to those newer frames, or it may pop to the top frame to the caller of
1007 // the current repeat frame, or it may leave the top frame pointing to the
1008 // current repeat frame.
1010 // Hence, we need to preserve the topCallFrame here ourselves before
1011 // repeating this call on a second callback function.
1013 TopCallFrameSetter topCallFrame(vm, closure.newCallFrame);
1015 // Execute the code:
1018 SamplingTool::CallRecord callRecord(m_sampler.get());
1019 Watchdog::Scope watchdogScope(vm.watchdog);
1021 #if ENABLE(LLINT_C_LOOP)
1022 result = LLInt::CLoop::execute(closure.newCallFrame, llint_function_for_call_prologue);
1024 result = closure.functionExecutable->generatedJITCodeForCall()->execute(&m_stack, closure.newCallFrame, &vm);
1025 #endif // ENABLE(JIT)
1028 if (LegacyProfiler* profiler = vm.enabledProfiler())
1029 profiler->didExecute(closure.oldCallFrame, closure.function);
1031 m_stack.validateFence(closure.newCallFrame, "AFTER");
1032 return checkedReturn(result);
1035 void Interpreter::endRepeatCall(CallFrameClosure& closure)
1037 m_stack.popFrame(closure.newCallFrame);
1040 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, JSScope* scope)
1042 VM& vm = *scope->vm();
1043 SamplingScope samplingScope(this);
1045 ASSERT(scope->vm() == &callFrame->vm());
1046 ASSERT(!vm.exception());
1047 ASSERT(!vm.isCollectorBusy());
1048 if (vm.isCollectorBusy())
1051 DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
1053 StackStats::CheckPoint stackCheckPoint;
1054 const VMStackBounds vmStackBounds(vm, wtfThreadData().stack());
1055 if (!vmStackBounds.isSafeToRecurse())
1056 return checkedReturn(throwStackOverflowError(callFrame));
1058 unsigned numVariables = eval->numVariables();
1059 int numFunctions = eval->numberOfFunctionDecls();
1061 JSScope* variableObject;
1062 if ((numVariables || numFunctions) && eval->isStrictMode()) {
1063 scope = StrictEvalActivation::create(callFrame);
1064 variableObject = scope;
1066 for (JSScope* node = scope; ; node = node->next()) {
1067 RELEASE_ASSERT(node);
1068 if (node->isVariableObject() && !node->isNameScopeObject()) {
1069 variableObject = node;
1075 JSObject* compileError = eval->compile(callFrame, scope);
1076 if (UNLIKELY(!!compileError))
1077 return checkedReturn(callFrame->vm().throwException(callFrame, compileError));
1078 EvalCodeBlock* codeBlock = &eval->generatedBytecode();
1080 if (numVariables || numFunctions) {
1081 BatchedTransitionOptimizer optimizer(vm, variableObject);
1082 if (variableObject->next())
1083 variableObject->globalObject()->varInjectionWatchpoint()->notifyWrite();
1085 for (unsigned i = 0; i < numVariables; ++i) {
1086 const Identifier& ident = codeBlock->variable(i);
1087 if (!variableObject->hasProperty(callFrame, ident)) {
1088 PutPropertySlot slot;
1089 variableObject->methodTable()->put(variableObject, callFrame, ident, jsUndefined(), slot);
1093 for (int i = 0; i < numFunctions; ++i) {
1094 FunctionExecutable* function = codeBlock->functionDecl(i);
1095 PutPropertySlot slot;
1096 variableObject->methodTable()->put(variableObject, callFrame, function->name(), JSFunction::create(callFrame, function, scope), slot);
1100 if (UNLIKELY(vm.watchdog.didFire(callFrame)))
1101 return throwTerminatedExecutionException(callFrame);
1104 ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
1105 CallFrame* newCallFrame = m_stack.pushFrame(callFrame, codeBlock, scope, 1, 0);
1106 if (UNLIKELY(!newCallFrame))
1107 return checkedReturn(throwStackOverflowError(callFrame));
1109 // Set the arguments for the callee:
1110 newCallFrame->setThisValue(thisValue);
1112 if (LegacyProfiler* profiler = vm.enabledProfiler())
1113 profiler->willExecute(callFrame, eval->sourceURL(), eval->lineNo());
1115 // Execute the code:
1118 SamplingTool::CallRecord callRecord(m_sampler.get());
1119 Watchdog::Scope watchdogScope(vm.watchdog);
1121 #if ENABLE(LLINT_C_LOOP)
1122 result = LLInt::CLoop::execute(newCallFrame, llint_eval_prologue);
1124 result = eval->generatedJITCode()->execute(&m_stack, newCallFrame, &vm);
1125 #endif // ENABLE(JIT)
1128 if (LegacyProfiler* profiler = vm.enabledProfiler())
1129 profiler->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
1131 m_stack.popFrame(newCallFrame);
1132 return checkedReturn(result);
1135 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine, int column)
1137 Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
1141 switch (debugHookID) {
1142 case DidEnterCallFrame:
1143 debugger->callEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column);
1145 case WillLeaveCallFrame:
1146 debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column);
1148 case WillExecuteStatement:
1149 debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column);
1151 case WillExecuteProgram:
1152 debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column);
1154 case DidExecuteProgram:
1155 debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column);
1157 case DidReachBreakpoint:
1158 debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column);
1163 void Interpreter::enableSampler()
1165 #if ENABLE(OPCODE_SAMPLING)
1167 m_sampler = adoptPtr(new SamplingTool(this));
1172 void Interpreter::dumpSampleData(ExecState* exec)
1174 #if ENABLE(OPCODE_SAMPLING)
1176 m_sampler->dump(exec);
1181 void Interpreter::startSampling()
1183 #if ENABLE(SAMPLING_THREAD)
1184 if (!m_sampleEntryDepth)
1185 SamplingThread::start();
1187 m_sampleEntryDepth++;
1190 void Interpreter::stopSampling()
1192 #if ENABLE(SAMPLING_THREAD)
1193 m_sampleEntryDepth--;
1194 if (!m_sampleEntryDepth)
1195 SamplingThread::stop();