Title: [93755] trunk/Source/_javascript_Core
Revision
93755
Author
commit-qu...@webkit.org
Date
2011-08-24 18:25:38 -0700 (Wed, 24 Aug 2011)

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

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

Reply via email to