Log Message
Keep track of topCallFrame for Stack traces https://bugs.webkit.org/show_bug.cgi?id=66571
Patch by Juan C. Montemayor <jm...@apple.com> on 2011-08-24 Reviewed by Geoffrey Garen. This patch adds a TopCallFrame to JSC in order to have that information when an error is thrown to create a stack trace. The TopCallFrame is updated throughout select points in the Interpreter and the JSC. * interpreter/Interpreter.cpp: (JSC::Interpreter::unwindCallFrame): (JSC::Interpreter::throwException): (JSC::Interpreter::execute): (JSC::Interpreter::executeCall): (JSC::Interpreter::executeConstruct): (JSC::Interpreter::privateExecute): * interpreter/Interpreter.h: (JSC::TopCallFrameSetter::TopCallFrameSetter): (JSC::TopCallFrameSetter::~TopCallFrameSetter): * jit/JIT.h: * jit/JITInlineMethods.h: (JSC::JIT::updateTopCallFrame): * jit/JITStubCall.h: (JSC::JITStubCall::call): * jit/JITStubs.cpp: (JSC::throwExceptionFromOpCall): (JSC::DEFINE_STUB_FUNCTION): (JSC::arityCheckFor): * runtime/JSGlobalData.cpp: (JSC::JSGlobalData::JSGlobalData): * runtime/JSGlobalData.h:
Modified Paths
- trunk/Source/_javascript_Core/ChangeLog
- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp
- trunk/Source/_javascript_Core/interpreter/Interpreter.h
- trunk/Source/_javascript_Core/jit/JIT.h
- trunk/Source/_javascript_Core/jit/JITInlineMethods.h
- trunk/Source/_javascript_Core/jit/JITStubCall.h
- trunk/Source/_javascript_Core/jit/JITStubs.cpp
- trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp
- trunk/Source/_javascript_Core/runtime/JSGlobalData.h
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (93754 => 93755)
--- trunk/Source/_javascript_Core/ChangeLog 2011-08-25 01:23:43 UTC (rev 93754)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-08-25 01:25:38 UTC (rev 93755)
@@ -1,3 +1,37 @@
+2011-08-24 Juan C. Montemayor <jm...@apple.com>
+
+ Keep track of topCallFrame for Stack traces
+ https://bugs.webkit.org/show_bug.cgi?id=66571
+
+ Reviewed by Geoffrey Garen.
+
+ This patch adds a TopCallFrame to JSC in order to have that information
+ when an error is thrown to create a stack trace. The TopCallFrame is
+ updated throughout select points in the Interpreter and the JSC.
+
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::unwindCallFrame):
+ (JSC::Interpreter::throwException):
+ (JSC::Interpreter::execute):
+ (JSC::Interpreter::executeCall):
+ (JSC::Interpreter::executeConstruct):
+ (JSC::Interpreter::privateExecute):
+ * interpreter/Interpreter.h:
+ (JSC::TopCallFrameSetter::TopCallFrameSetter):
+ (JSC::TopCallFrameSetter::~TopCallFrameSetter):
+ * jit/JIT.h:
+ * jit/JITInlineMethods.h:
+ (JSC::JIT::updateTopCallFrame):
+ * jit/JITStubCall.h:
+ (JSC::JITStubCall::call):
+ * jit/JITStubs.cpp:
+ (JSC::throwExceptionFromOpCall):
+ (JSC::DEFINE_STUB_FUNCTION):
+ (JSC::arityCheckFor):
+ * runtime/JSGlobalData.cpp:
+ (JSC::JSGlobalData::JSGlobalData):
+ * runtime/JSGlobalData.h:
+
2011-08-24 Filip Pizlo <fpi...@apple.com>
ErrorInstance::create sometimes has two heap object constructions
Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (93754 => 93755)
--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2011-08-25 01:23:43 UTC (rev 93754)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2011-08-25 01:25:38 UTC (rev 93755)
@@ -608,6 +608,7 @@
}
CallFrame* callerFrame = callFrame->callerFrame();
+ callFrame->globalData().topCallFrame = callerFrame;
if (callerFrame->hasHostCallFrameFlag())
return false;
@@ -881,6 +882,7 @@
ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'.
newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), codeBlock->m_numParameters, 0);
newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = JSValue(thisObj);
+ TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
Profiler** profiler = Profiler::enabledProfilerReference();
if (*profiler)
@@ -954,6 +956,8 @@
newCallFrame->init(newCodeBlock, 0, callDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
+ TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
+
Profiler** profiler = Profiler::enabledProfilerReference();
if (*profiler)
(*profiler)->willExecute(callFrame, function);
@@ -984,6 +988,8 @@
newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);
newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
+ TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
+
DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
Profiler** profiler = Profiler::enabledProfilerReference();
@@ -1048,6 +1054,8 @@
newCallFrame->init(newCodeBlock, 0, constructDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
+ TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
+
Profiler** profiler = Profiler::enabledProfilerReference();
if (*profiler)
(*profiler)->willExecute(callFrame, constructor);
@@ -1081,6 +1089,8 @@
newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);
newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
+ TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
+
DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
Profiler** profiler = Profiler::enabledProfilerReference();
@@ -1143,6 +1153,7 @@
return CallFrameClosure();
}
newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), argc, function);
+ scopeChain->globalData->topCallFrame = newCallFrame;
CallFrameClosure result = { callFrame, newCallFrame, function, FunctionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
return result;
}
@@ -1156,7 +1167,9 @@
Profiler** profiler = Profiler::enabledProfilerReference();
if (*profiler)
(*profiler)->willExecute(closure.oldCallFrame, closure.function);
-
+
+ TopCallFrameSetter topCallFrame(*closure.globalData, closure.newCallFrame);
+
JSValue result;
{
SamplingTool::CallRecord callRecord(m_sampler.get());
@@ -1176,7 +1189,7 @@
#endif
m_reentryDepth--;
}
-
+
if (*profiler)
(*profiler)->didExecute(closure.oldCallFrame, closure.function);
return checkedReturn(result);
@@ -1184,6 +1197,7 @@
void Interpreter::endRepeatCall(CallFrameClosure& closure)
{
+ closure.globalData->topCallFrame = closure.oldCallFrame;
m_registerFile.shrink(closure.oldEnd);
}
@@ -1263,6 +1277,8 @@
newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), codeBlock->m_numParameters, 0);
newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = thisValue;
+ TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
+
Profiler** profiler = Profiler::enabledProfilerReference();
if (*profiler)
(*profiler)->willExecute(callFrame, eval->sourceURL(), eval->lineNo());
@@ -1589,9 +1605,12 @@
return JSValue();
#else
+ ASSERT(callFrame->globalData().topCallFrame == callFrame);
+
JSGlobalData* globalData = &callFrame->globalData();
JSValue exceptionValue;
HandlerInfo* handler = 0;
+ CallFrame** topCallFrameSlot = &globalData->topCallFrame;
CodeBlock* codeBlock = callFrame->codeBlock();
Instruction* vPC = codeBlock->instructions().begin();
@@ -4205,6 +4224,7 @@
callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
codeBlock = newCodeBlock;
ASSERT(codeBlock == callFrame->codeBlock());
+ *topCallFrameSlot = callFrame;
vPC = newCodeBlock->instructions().begin();
#if ENABLE(OPCODE_STATS)
@@ -4223,11 +4243,12 @@
}
newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call), scopeChain, callFrame, argCount, asObject(v));
-
JSValue returnValue;
{
+ *topCallFrameSlot = newCallFrame;
SamplingTool::HostCallRecord callRecord(m_sampler.get());
returnValue = JSValue::decode(callData.native.function(newCallFrame));
+ *topCallFrameSlot = callFrame;
}
CHECK_FOR_EXCEPTION();
@@ -4373,6 +4394,7 @@
callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call_varargs), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
codeBlock = newCodeBlock;
ASSERT(codeBlock == callFrame->codeBlock());
+ *topCallFrameSlot = callFrame;
vPC = newCodeBlock->instructions().begin();
#if ENABLE(OPCODE_STATS)
@@ -4393,8 +4415,10 @@
JSValue returnValue;
{
+ *topCallFrameSlot = newCallFrame;
SamplingTool::HostCallRecord callRecord(m_sampler.get());
returnValue = JSValue::decode(callData.native.function(newCallFrame));
+ *topCallFrameSlot = callFrame;
}
CHECK_FOR_EXCEPTION();
@@ -4476,10 +4500,11 @@
vPC = callFrame->returnVPC();
callFrame = callFrame->callerFrame();
-
+
if (callFrame->hasHostCallFrameFlag())
return returnValue;
+ *topCallFrameSlot = callFrame;
functionReturnValue = returnValue;
codeBlock = callFrame->codeBlock();
ASSERT(codeBlock == callFrame->codeBlock());
@@ -4521,6 +4546,7 @@
if (callFrame->hasHostCallFrameFlag())
return returnValue;
+ *topCallFrameSlot = callFrame;
functionReturnValue = returnValue;
codeBlock = callFrame->codeBlock();
ASSERT(codeBlock == callFrame->codeBlock());
@@ -4694,6 +4720,7 @@
callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_construct), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
codeBlock = newCodeBlock;
+ *topCallFrameSlot = callFrame;
vPC = newCodeBlock->instructions().begin();
#if ENABLE(OPCODE_STATS)
OpcodeStats::resetLastInstruction();
@@ -4713,8 +4740,10 @@
JSValue returnValue;
{
+ *topCallFrameSlot = newCallFrame;
SamplingTool::HostCallRecord callRecord(m_sampler.get());
returnValue = JSValue::decode(constructData.native.function(newCallFrame));
+ *topCallFrameSlot = callFrame;
}
CHECK_FOR_EXCEPTION();
functionReturnValue = returnValue;
Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.h (93754 => 93755)
--- trunk/Source/_javascript_Core/interpreter/Interpreter.h 2011-08-25 01:23:43 UTC (rev 93754)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.h 2011-08-25 01:25:38 UTC (rev 93755)
@@ -62,6 +62,24 @@
WillExecuteStatement
};
+ class TopCallFrameSetter {
+ public:
+ TopCallFrameSetter(JSGlobalData& global, CallFrame* callFrame)
+ : globalData(global)
+ , oldCallFrame(global.topCallFrame)
+ {
+ global.topCallFrame = callFrame;
+ }
+
+ ~TopCallFrameSetter()
+ {
+ globalData.topCallFrame = oldCallFrame;
+ }
+ private:
+ JSGlobalData& globalData;
+ CallFrame* oldCallFrame;
+ };
+
enum { MaxLargeThreadReentryDepth = 256, MaxSmallThreadReentryDepth = 32 };
class Interpreter {
Modified: trunk/Source/_javascript_Core/jit/JIT.h (93754 => 93755)
--- trunk/Source/_javascript_Core/jit/JIT.h 2011-08-25 01:23:43 UTC (rev 93754)
+++ trunk/Source/_javascript_Core/jit/JIT.h 2011-08-25 01:25:38 UTC (rev 93755)
@@ -370,7 +370,7 @@
#if ENABLE(OPCODE_SAMPLING)
static const int patchOffsetGetByIdSlowCaseCall = 37;
#else
- static const int patchOffsetGetByIdSlowCaseCall = 27;
+ static const int patchOffsetGetByIdSlowCaseCall = 33;
#endif
static const int patchOffsetOpCallCompareToJump = 6;
@@ -428,7 +428,7 @@
#if ENABLE(OPCODE_SAMPLING)
#error "OPCODE_SAMPLING is not yet supported"
#else
- static const int patchOffsetGetByIdSlowCaseCall = 30;
+ static const int patchOffsetGetByIdSlowCaseCall = 40;
#endif
static const int patchOffsetOpCallCompareToJump = 16;
@@ -606,7 +606,7 @@
#if ENABLE(OPCODE_SAMPLING)
static const int patchOffsetGetByIdSlowCaseCall = 64;
#else
- static const int patchOffsetGetByIdSlowCaseCall = 41;
+ static const int patchOffsetGetByIdSlowCaseCall = 54;
#endif
static const int patchOffsetOpCallCompareToJump = 9;
@@ -961,6 +961,7 @@
void restoreArgumentReference();
void restoreArgumentReferenceForTrampoline();
+ void updateTopCallFrame();
Call emitNakedCall(CodePtr function = CodePtr());
Modified: trunk/Source/_javascript_Core/jit/JITInlineMethods.h (93754 => 93755)
--- trunk/Source/_javascript_Core/jit/JITInlineMethods.h 2011-08-25 01:23:43 UTC (rev 93754)
+++ trunk/Source/_javascript_Core/jit/JITInlineMethods.h 2011-08-25 01:25:38 UTC (rev 93755)
@@ -253,6 +253,11 @@
poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
}
+ALWAYS_INLINE void JIT::updateTopCallFrame()
+{
+ storePtr(callFrameRegister, &m_globalData->topCallFrame);
+}
+
ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline()
{
#if CPU(X86)
Modified: trunk/Source/_javascript_Core/jit/JITStubCall.h (93754 => 93755)
--- trunk/Source/_javascript_Core/jit/JITStubCall.h 2011-08-25 01:23:43 UTC (rev 93754)
+++ trunk/Source/_javascript_Core/jit/JITStubCall.h 2011-08-25 01:25:38 UTC (rev 93755)
@@ -172,6 +172,7 @@
#endif
m_jit->restoreArgumentReference();
+ m_jit->updateTopCallFrame();
JIT::Call call = m_jit->call();
m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeOffset, m_stub.value()));
Modified: trunk/Source/_javascript_Core/jit/JITStubs.cpp (93754 => 93755)
--- trunk/Source/_javascript_Core/jit/JITStubs.cpp 2011-08-25 01:23:43 UTC (rev 93754)
+++ trunk/Source/_javascript_Core/jit/JITStubs.cpp 2011-08-25 01:25:38 UTC (rev 93755)
@@ -1046,6 +1046,15 @@
return exceptionHandler;
}
+// Helper function for JIT stubs that may throw an exception in the middle of
+// processing a function call. This function rolls back the register file to
+// our caller, so exception processing can proceed from a valid state.
+static ALWAYS_INLINE ExceptionHandler throwExceptionFromOpCall(CallFrame* oldCallFrame, CallFrame* newCallFrame)
+{
+ oldCallFrame->globalData().topCallFrame = oldCallFrame;
+ return jitThrow(&oldCallFrame->globalData(), oldCallFrame, createStackOverflowError(oldCallFrame), ReturnAddressPtr(newCallFrame->returnPC()));
+}
+
#if CPU(ARM_THUMB2) && COMPILER(GCC)
#define DEFINE_STUB_FUNCTION(rtype, op) \
@@ -1350,10 +1359,7 @@
CallFrame* callFrame = stackFrame.callFrame;
if (UNLIKELY(!stackFrame.registerFile->grow(&callFrame->registers()[callFrame->codeBlock()->m_numCalleeRegisters]))) {
- // Rewind to the previous call frame because op_call already optimistically
- // moved the call frame forward.
- CallFrame* oldCallFrame = callFrame->callerFrame();
- ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), ReturnAddressPtr(callFrame->returnPC()));
+ ExceptionHandler handler = throwExceptionFromOpCall(callFrame->callerFrame(), callFrame);
STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
callFrame = handler.callFrame;
}
@@ -1950,9 +1956,7 @@
r = callFrame->registers() + numParameters;
Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
if (!stackFrame.registerFile->grow(newEnd)) {
- // Rewind to the previous call frame because op_call already optimistically
- // moved the call frame forward.
- ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc);
+ ExceptionHandler handler = throwExceptionFromOpCall(oldCallFrame, callFrame);
stubReturnAddress = ReturnAddressPtr(handler.catchRoutine);
return handler.callFrame;
}
@@ -1965,9 +1969,7 @@
r = callFrame->registers() + omittedArgCount;
Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
if (!stackFrame.registerFile->grow(newEnd)) {
- // Rewind to the previous call frame because op_call already optimistically
- // moved the call frame forward.
- ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc);
+ ExceptionHandler handler = throwExceptionFromOpCall(oldCallFrame, callFrame);
stubReturnAddress = ReturnAddressPtr(handler.catchRoutine);
return handler.callFrame;
}
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp (93754 => 93755)
--- trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp 2011-08-25 01:23:43 UTC (rev 93754)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp 2011-08-25 01:25:38 UTC (rev 93755)
@@ -162,6 +162,7 @@
JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapSize heapSize)
: globalDataType(globalDataType)
, clientData(0)
+ , topCallFrame(CallFrame::noCaller())
, arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable))
, arrayPrototypeTable(fastNew<HashTable>(JSC::arrayPrototypeTable))
, booleanPrototypeTable(fastNew<HashTable>(JSC::booleanPrototypeTable))
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalData.h (93754 => 93755)
--- trunk/Source/_javascript_Core/runtime/JSGlobalData.h 2011-08-25 01:23:43 UTC (rev 93754)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalData.h 2011-08-25 01:25:38 UTC (rev 93755)
@@ -135,6 +135,7 @@
GlobalDataType globalDataType;
ClientData* clientData;
+ CallFrame* topCallFrame;
const HashTable* arrayConstructorTable;
const HashTable* arrayPrototypeTable;
_______________________________________________ webkit-changes mailing list webkit-changes@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes