فهرست منبع

TTD -- Correct behavior around unhandled exception & debugger

Mark Marron 8 سال پیش
والد
کامیت
e36bb50cf3
3فایلهای تغییر یافته به همراه26 افزوده شده و 5 حذف شده
  1. 19 3
      lib/Runtime/Debug/TTExecutionInfo.cpp
  2. 6 1
      lib/Runtime/Debug/TTExecutionInfo.h
  3. 1 1
      lib/Runtime/Language/InterpreterStackFrame.cpp

+ 19 - 3
lib/Runtime/Debug/TTExecutionInfo.cpp

@@ -417,7 +417,7 @@ namespace TTD
     ExecutionInfoManager::ExecutionInfoManager()
         : m_topLevelCallbackEventTime(-1), m_runningFunctionTimeCtr(0), m_callStack(&HeapAllocator::Instance),
         m_debuggerNotifiedTopLevelBodies(&HeapAllocator::Instance),
-        m_lastReturnLocation(),
+        m_lastReturnLocation(), m_lastExceptionPropagating(false), m_lastExceptionLocation(),
         m_breakOnFirstUserCode(false),
         m_pendingTTDBP(), m_pendingTTDMoveMode(-1), m_activeBPId(-1), m_shouldRemoveWhenDone(false), m_activeTTDBP(),
         m_hitContinueSearchBP(false), m_continueBreakPoint(),
@@ -537,6 +537,12 @@ namespace TTD
             this->m_lastReturnLocation.SetExceptionLocation(this->m_callStack.Last());
         }
 
+        if(!m_lastExceptionPropagating)
+        {
+            this->m_lastExceptionLocation.SetLocationFromFrame(this->m_topLevelCallbackEventTime, this->m_callStack.Last());
+            this->m_lastExceptionPropagating = true;
+        }
+
         this->m_runningFunctionTimeCtr++;
         this->m_callStack.RemoveAtEnd();
 
@@ -545,9 +551,11 @@ namespace TTD
 #endif
     }
 
-    void ExecutionInfoManager::ClearExceptionFrames()
+    void ExecutionInfoManager::ProcessCatchInfoForLastExecutedStatements()
     {
         this->m_lastReturnLocation.Clear();
+
+        this->m_lastExceptionPropagating = false;
     }
 
     void ExecutionInfoManager::SetBreakOnFirstUserCode()
@@ -579,7 +587,8 @@ namespace TTD
 
     void ExecutionInfoManager::SetPendingTTDUnhandledException()
     {
-        this->GetLastExecutedTimeAndPositionForDebugger(this->m_pendingTTDBP);
+        this->GetLastExceptionTimeAndPositionForDebugger(this->m_pendingTTDBP);
+        this->m_lastExceptionPropagating = false;
 
         this->m_pendingTTDMoveMode = 0;
     }
@@ -928,6 +937,12 @@ namespace TTD
         }
     }
 
+    void ExecutionInfoManager::GetLastExceptionTimeAndPositionForDebugger(TTDebuggerSourceLocation& sourceLocation) const
+    {
+        //If no exception then this will also clear sourceLocation
+        sourceLocation.SetLocationCopy(this->m_lastExceptionLocation);
+    }
+
     void ExecutionInfoManager::ResetCallStackForTopLevelCall(int64 topLevelCallbackEventTime)
     {
         TTDAssert(this->m_callStack.Count() == 0, "We should be at the top-level entry!!!");
@@ -936,6 +951,7 @@ namespace TTD
 
         this->m_runningFunctionTimeCtr = 0;
         this->m_lastReturnLocation.Clear();
+        this->m_lastExceptionLocation.Clear();
     }
 
     void ExecutionInfoManager::SetBPInfoForActiveSegmentContinueScan(ThreadContextTTD* ttdThreadContext)

+ 6 - 1
lib/Runtime/Debug/TTExecutionInfo.h

@@ -185,6 +185,10 @@ namespace TTD
         // - Step back *into* possible if either case is true
         TTLastReturnLocationInfo m_lastReturnLocation;
 
+        //Always keep the last exception location as well -- even if it is caught
+        bool m_lastExceptionPropagating;
+        TTDebuggerSourceLocation m_lastExceptionLocation; 
+
         //A flag indicating if we want to break on the entry to the user code 
         bool m_breakOnFirstUserCode;
 
@@ -237,7 +241,7 @@ namespace TTD
         void PopCallEvent(Js::JavascriptFunction* function, Js::Var result);
         void PopCallEventException(Js::JavascriptFunction* function);
 
-        void ClearExceptionFrames();
+        void ProcessCatchInfoForLastExecutedStatements();
 
         //Set that we want to break on the execution of the first user code
         void SetBreakOnFirstUserCode();
@@ -295,6 +299,7 @@ namespace TTD
         //Get the last (uncaught or just caught) exception time/position for the debugger -- if the last return action was an exception and we have not made any additional calls
         //Otherwise get the last statement executed call time/position for the debugger
         void GetLastExecutedTimeAndPositionForDebugger(TTDebuggerSourceLocation& sourceLocation) const;
+        void GetLastExceptionTimeAndPositionForDebugger(TTDebuggerSourceLocation& sourceLocation) const;
 
         //Ensure the call stack is clear and counters are zeroed appropriately
         void ResetCallStackForTopLevelCall(int64 topLevelCallbackEventTime);

+ 1 - 1
lib/Runtime/Language/InterpreterStackFrame.cpp

@@ -6645,7 +6645,7 @@ const byte * InterpreterStackFrame::OP_ProfiledLoopBodyStart(const byte * ip)
         //Clear any previous Exception Info
         if(SHOULD_DO_TTD_STACK_STMT_OP(this->scriptContext))
         {
-            this->scriptContext->GetThreadContext()->TTDExecutionInfo->ClearExceptionFrames();
+            this->scriptContext->GetThreadContext()->TTDExecutionInfo->ProcessCatchInfoForLastExecutedStatements();
         }
 #endif