TTExecutionInfo.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeDebugPch.h"
  6. #if ENABLE_TTD
  7. namespace TTD
  8. {
  9. TTDebuggerAbortException::TTDebuggerAbortException(uint32 abortCode, int64 optEventTime, int64 optMoveMode, const char16* staticAbortMessage)
  10. : m_abortCode(abortCode), m_optEventTime(optEventTime), m_optMoveMode(optMoveMode), m_staticAbortMessage(staticAbortMessage)
  11. {
  12. ;
  13. }
  14. TTDebuggerAbortException::~TTDebuggerAbortException()
  15. {
  16. ;
  17. }
  18. TTDebuggerAbortException TTDebuggerAbortException::CreateAbortEndOfLog(const char16* staticMessage)
  19. {
  20. return TTDebuggerAbortException(1, -1, 0, staticMessage);
  21. }
  22. TTDebuggerAbortException TTDebuggerAbortException::CreateTopLevelAbortRequest(int64 targetEventTime, int64 moveMode, const char16* staticMessage)
  23. {
  24. return TTDebuggerAbortException(2, targetEventTime, moveMode, staticMessage);
  25. }
  26. TTDebuggerAbortException TTDebuggerAbortException::CreateUncaughtExceptionAbortRequest(int64 targetEventTime, const char16* staticMessage)
  27. {
  28. return TTDebuggerAbortException(3, targetEventTime, 0, staticMessage);
  29. }
  30. bool TTDebuggerAbortException::IsEndOfLog() const
  31. {
  32. return this->m_abortCode == 1;
  33. }
  34. bool TTDebuggerAbortException::IsEventTimeMove() const
  35. {
  36. return this->m_abortCode == 2;
  37. }
  38. bool TTDebuggerAbortException::IsTopLevelException() const
  39. {
  40. return this->m_abortCode == 3;
  41. }
  42. int64 TTDebuggerAbortException::GetTargetEventTime() const
  43. {
  44. return this->m_optEventTime;
  45. }
  46. int64 TTDebuggerAbortException::GetMoveMode() const
  47. {
  48. return this->m_optMoveMode;
  49. }
  50. const char16* TTDebuggerAbortException::GetStaticAbortMessage() const
  51. {
  52. return this->m_staticAbortMessage;
  53. }
  54. Js::FunctionBody* TTDebuggerSourceLocation::UpdatePostInflateFunctionBody_Helper(Js::FunctionBody* rootBody) const
  55. {
  56. for(uint32 i = 0; i < rootBody->GetNestedCount(); ++i)
  57. {
  58. Js::ParseableFunctionInfo* ipfi = rootBody->GetNestedFunctionForExecution(i);
  59. Js::FunctionBody* ifb = JsSupport::ForceAndGetFunctionBody(ipfi);
  60. if(this->m_functionLine == ifb->GetLineNumber() && this->m_functionColumn == ifb->GetColumnNumber())
  61. {
  62. return ifb;
  63. }
  64. else
  65. {
  66. Js::FunctionBody* found = this->UpdatePostInflateFunctionBody_Helper(ifb);
  67. if(found != nullptr)
  68. {
  69. return found;
  70. }
  71. }
  72. }
  73. return nullptr;
  74. }
  75. TTDebuggerSourceLocation::TTDebuggerSourceLocation()
  76. : m_sourceScriptLogId(TTD_INVALID_LOG_PTR_ID), m_bpId(-1),
  77. m_etime(-1), m_ftime(0), m_ltime(0),
  78. m_topLevelBodyId(0), m_functionLine(0), m_functionColumn(0), m_line(0), m_column(0)
  79. {
  80. ;
  81. }
  82. TTDebuggerSourceLocation::TTDebuggerSourceLocation(const TTDebuggerSourceLocation& other)
  83. : m_sourceScriptLogId(other.m_sourceScriptLogId), m_bpId(other.m_bpId),
  84. m_etime(other.m_etime), m_ftime(other.m_ftime), m_ltime(other.m_ltime),
  85. m_topLevelBodyId(other.m_topLevelBodyId), m_functionLine(other.m_functionLine), m_functionColumn(other.m_functionColumn), m_line(other.m_line), m_column(other.m_column)
  86. {
  87. ;
  88. }
  89. TTDebuggerSourceLocation::~TTDebuggerSourceLocation()
  90. {
  91. this->Clear();
  92. }
  93. TTDebuggerSourceLocation& TTDebuggerSourceLocation::operator= (const TTDebuggerSourceLocation& other)
  94. {
  95. if(this != &other)
  96. {
  97. this->SetLocationCopy(other);
  98. }
  99. return *this;
  100. }
  101. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  102. void TTDebuggerSourceLocation::PrintToConsole() const
  103. {
  104. if(!this->HasValue())
  105. {
  106. wprintf(_u("undef"));
  107. }
  108. else
  109. {
  110. wprintf(_u("BP: { bpId: %I64i, ctx: %I64u, topId: %I32u, fline: %I32u, fcolumn: %I32u, line: %I32u, column: %I32u }"), this->m_bpId, this->m_sourceScriptLogId, this->m_topLevelBodyId, this->m_functionLine, this->m_functionColumn, this->m_line, this->m_column);
  111. if(this->m_etime != -1)
  112. {
  113. wprintf(_u(" TTDTime: { etime: %I64i, ftime: %I64i, ltime: %I64i }"), this->m_etime, this->m_ftime, this->m_ltime);
  114. }
  115. }
  116. }
  117. #endif
  118. void TTDebuggerSourceLocation::Initialize()
  119. {
  120. this->m_sourceScriptLogId = TTD_INVALID_LOG_PTR_ID;
  121. this->m_bpId = -1;
  122. this->m_etime = -1;
  123. this->m_ftime = 0;
  124. this->m_ltime = 0;
  125. this->m_topLevelBodyId = 0;
  126. this->m_functionLine = 0;
  127. this->m_functionColumn = 0;
  128. this->m_line = 0;
  129. this->m_column = 0;
  130. }
  131. bool TTDebuggerSourceLocation::HasValue() const
  132. {
  133. return this->m_sourceScriptLogId != TTD_INVALID_LOG_PTR_ID;
  134. }
  135. bool TTDebuggerSourceLocation::HasTTDTimeValue() const
  136. {
  137. return this->m_etime != -1;
  138. }
  139. void TTDebuggerSourceLocation::Clear()
  140. {
  141. this->m_sourceScriptLogId = TTD_INVALID_LOG_PTR_ID;
  142. this->m_bpId = -1;
  143. this->m_etime = -1;
  144. this->m_ftime = 0;
  145. this->m_ltime = 0;
  146. this->m_topLevelBodyId = 0;
  147. this->m_functionLine = 0;
  148. this->m_functionColumn = 0;
  149. this->m_line = 0;
  150. this->m_column = 0;
  151. }
  152. void TTDebuggerSourceLocation::SetLocationCopy(const TTDebuggerSourceLocation& other)
  153. {
  154. this->m_sourceScriptLogId = other.m_sourceScriptLogId;
  155. this->m_bpId = other.m_bpId;
  156. this->m_etime = other.m_etime;
  157. this->m_ftime = other.m_ftime;
  158. this->m_ltime = other.m_ltime;
  159. this->m_topLevelBodyId = other.m_topLevelBodyId;
  160. this->m_functionLine = other.m_functionLine;
  161. this->m_functionColumn = other.m_functionColumn;
  162. this->m_line = other.m_line;
  163. this->m_column = other.m_column;
  164. }
  165. void TTDebuggerSourceLocation::SetLocationFromFrame(int64 topLevelETime, const SingleCallCounter& callFrame)
  166. {
  167. ULONG srcLine = 0;
  168. LONG srcColumn = -1;
  169. uint32 startOffset = callFrame.Function->GetStatementStartOffset(callFrame.CurrentStatementIndex);
  170. callFrame.Function->GetSourceLineFromStartOffset_TTD(startOffset, &srcLine, &srcColumn);
  171. this->SetLocationFull(topLevelETime, callFrame.FunctionTime, callFrame.LoopTime, callFrame.Function, (uint32)srcLine, (uint32)srcColumn);
  172. }
  173. void TTDebuggerSourceLocation::SetLocationFromFunctionEntryAnyTime(int64 topLevelETime, Js::FunctionBody* body)
  174. {
  175. ULONG srcLine = 0;
  176. LONG srcColumn = -1;
  177. uint32 startOffset = body->GetStatementStartOffset(0);
  178. body->GetSourceLineFromStartOffset_TTD(startOffset, &srcLine, &srcColumn);
  179. this->SetLocationFull(topLevelETime, -1, -1, body, (uint32)srcLine, (uint32)srcColumn);
  180. }
  181. void TTDebuggerSourceLocation::SetLocationFull(int64 etime, int64 ftime, int64 ltime, Js::FunctionBody* body, ULONG line, LONG column)
  182. {
  183. this->m_sourceScriptLogId = body->GetScriptContext()->ScriptContextLogTag;
  184. this->m_bpId = -1;
  185. this->m_etime = etime;
  186. this->m_ftime = ftime;
  187. this->m_ltime = ltime;
  188. this->m_topLevelBodyId = body->GetScriptContext()->TTDContextInfo->FindTopLevelCtrForBody(body);
  189. this->m_functionLine = body->GetLineNumber();
  190. this->m_functionColumn = body->GetColumnNumber();
  191. this->m_line = (uint32)line;
  192. this->m_column = (uint32)column;
  193. }
  194. void TTDebuggerSourceLocation::SetLocationFullRaw(TTD_LOG_PTR_ID sourceScriptLogId, int64 etime, int64 ftime, int64 ltime, uint32 topLevelBodyId, uint32 functionLine, uint32 functionColumn, ULONG line, LONG column)
  195. {
  196. this->m_sourceScriptLogId = sourceScriptLogId;
  197. this->m_bpId = -1;
  198. this->m_etime = etime;
  199. this->m_ftime = ftime;
  200. this->m_ltime = ltime;
  201. this->m_topLevelBodyId = topLevelBodyId;
  202. this->m_functionLine = functionLine;
  203. this->m_functionColumn = functionColumn;
  204. this->m_line = (uint32)line;
  205. this->m_column = (uint32)column;
  206. }
  207. void TTDebuggerSourceLocation::SetLocationWithBP(int64 bpId, Js::FunctionBody* body, ULONG line, LONG column)
  208. {
  209. this->m_sourceScriptLogId = body->GetScriptContext()->ScriptContextLogTag;
  210. this->m_bpId = bpId;
  211. this->m_etime = -1;
  212. this->m_ftime = -1;
  213. this->m_ltime = -1;
  214. this->m_topLevelBodyId = body->GetScriptContext()->TTDContextInfo->FindTopLevelCtrForBody(body);
  215. this->m_functionLine = body->GetLineNumber();
  216. this->m_functionColumn = body->GetColumnNumber();
  217. this->m_line = (uint32)line;
  218. this->m_column = (uint32)column;
  219. }
  220. int64 TTDebuggerSourceLocation::GetRootEventTime() const
  221. {
  222. return this->m_etime;
  223. }
  224. int64 TTDebuggerSourceLocation::GetFunctionTime() const
  225. {
  226. return this->m_ftime;
  227. }
  228. int64 TTDebuggerSourceLocation::GetLoopTime() const
  229. {
  230. return this->m_ltime;
  231. }
  232. TTD_LOG_PTR_ID TTDebuggerSourceLocation::GetScriptLogTagId() const
  233. {
  234. return this->m_sourceScriptLogId;
  235. }
  236. Js::FunctionBody* TTDebuggerSourceLocation::LoadFunctionBodyIfPossible(Js::ScriptContext* inCtx) const
  237. {
  238. Js::FunctionBody* rootBody = inCtx->TTDContextInfo->FindRootBodyByTopLevelCtr(this->m_topLevelBodyId);
  239. if(rootBody == nullptr)
  240. {
  241. return nullptr;
  242. }
  243. if(this->m_functionLine == rootBody->GetLineNumber() && this->m_functionColumn == rootBody->GetColumnNumber())
  244. {
  245. return rootBody;
  246. }
  247. else
  248. {
  249. return this->UpdatePostInflateFunctionBody_Helper(rootBody);
  250. }
  251. }
  252. int64 TTDebuggerSourceLocation::GetBPId() const
  253. {
  254. return this->m_bpId;
  255. }
  256. uint32 TTDebuggerSourceLocation::GetTopLevelBodyId() const
  257. {
  258. return this->m_topLevelBodyId;
  259. }
  260. uint32 TTDebuggerSourceLocation::GetFunctionSourceLine() const
  261. {
  262. return this->m_functionLine;
  263. }
  264. uint32 TTDebuggerSourceLocation::GetFunctionSourceColumn() const
  265. {
  266. return this->m_functionColumn;
  267. }
  268. uint32 TTDebuggerSourceLocation::GetSourceLine() const
  269. {
  270. return this->m_line;
  271. }
  272. uint32 TTDebuggerSourceLocation::GetSourceColumn() const
  273. {
  274. return this->m_column;
  275. }
  276. bool TTDebuggerSourceLocation::AreSameLocations(const TTDebuggerSourceLocation& sl1, const TTDebuggerSourceLocation& sl2)
  277. {
  278. //first check the code locations
  279. if(sl1.m_topLevelBodyId != sl2.m_topLevelBodyId || sl1.m_line != sl2.m_line || sl1.m_column != sl2.m_column)
  280. {
  281. return false;
  282. }
  283. //next check the time values
  284. if(sl1.m_etime != sl2.m_etime || sl1.m_ftime != sl2.m_ftime || sl1.m_ltime != sl2.m_ltime)
  285. {
  286. return false;
  287. }
  288. return true;
  289. }
  290. bool TTDebuggerSourceLocation::AreSameLocations_PlaceOnly(const TTDebuggerSourceLocation& sl1, const TTDebuggerSourceLocation& sl2)
  291. {
  292. return (sl1.m_topLevelBodyId == sl2.m_topLevelBodyId && sl1.m_line == sl2.m_line && sl1.m_column == sl2.m_column);
  293. }
  294. TTLastReturnLocationInfo::TTLastReturnLocationInfo()
  295. : m_isExceptionFrame(false)
  296. {
  297. this->m_lastFrame = { 0 };
  298. }
  299. void TTLastReturnLocationInfo::SetReturnLocation(const SingleCallCounter& cframe)
  300. {
  301. this->m_isExceptionFrame = false;
  302. this->m_lastFrame = cframe;
  303. }
  304. void TTLastReturnLocationInfo::SetExceptionLocation(const SingleCallCounter& cframe)
  305. {
  306. this->m_isExceptionFrame = true;
  307. this->m_lastFrame = cframe;
  308. }
  309. bool TTLastReturnLocationInfo::IsDefined() const
  310. {
  311. return this->m_lastFrame.Function != nullptr;
  312. }
  313. bool TTLastReturnLocationInfo::IsReturnLocation() const
  314. {
  315. return this->IsDefined() && !this->m_isExceptionFrame;
  316. }
  317. bool TTLastReturnLocationInfo::IsExceptionLocation() const
  318. {
  319. return this->IsDefined() && this->m_isExceptionFrame;
  320. }
  321. const SingleCallCounter& TTLastReturnLocationInfo::GetLocation() const
  322. {
  323. TTDAssert(this->IsDefined(), "Should check this!");
  324. return this->m_lastFrame;
  325. }
  326. void TTLastReturnLocationInfo::Clear()
  327. {
  328. if(this->IsDefined())
  329. {
  330. this->m_isExceptionFrame = false;
  331. this->m_lastFrame = { 0 };
  332. }
  333. }
  334. void TTLastReturnLocationInfo::ClearReturnOnly()
  335. {
  336. if(this->IsDefined() && !this->m_isExceptionFrame)
  337. {
  338. this->Clear();
  339. }
  340. }
  341. void TTLastReturnLocationInfo::ClearExceptionOnly()
  342. {
  343. if(this->IsDefined() && this->m_isExceptionFrame)
  344. {
  345. this->Clear();
  346. }
  347. }
  348. TTInnerLoopLastStatementInfo::TTInnerLoopLastStatementInfo()
  349. : m_eventTime(-1), m_functionTime(0), m_loopTime(0), m_line(0), m_column(0)
  350. {
  351. ;
  352. }
  353. TTInnerLoopLastStatementInfo::TTInnerLoopLastStatementInfo(const TTInnerLoopLastStatementInfo& lsi)
  354. : m_eventTime(lsi.m_eventTime), m_functionTime(lsi.m_functionTime), m_loopTime(lsi.m_loopTime), m_line(lsi.m_line), m_column(lsi.m_column)
  355. {
  356. ;
  357. }
  358. bool TTInnerLoopLastStatementInfo::IsEnabled() const
  359. {
  360. return this->m_eventTime != -1;
  361. }
  362. void TTInnerLoopLastStatementInfo::SetLastLine(int64 etime, int64 ftime, int64 ltime, uint32 line, uint32 column)
  363. {
  364. this->m_eventTime = etime;
  365. this->m_functionTime = ftime;
  366. this->m_loopTime = ltime;
  367. this->m_line = line;
  368. this->m_column = column;
  369. }
  370. bool TTInnerLoopLastStatementInfo::CheckLastTimeMatch(int64 etime, int64 ftime, int64 ltime) const
  371. {
  372. return (this->m_eventTime == etime) & (this->m_functionTime == ftime) & (this->m_loopTime == ltime);
  373. }
  374. bool TTInnerLoopLastStatementInfo::CheckLineColumnMatch(uint32 line, uint32 column) const
  375. {
  376. return (this->m_line == line) & (this->m_column == column);
  377. }
  378. //////////////////
  379. bool ExecutionInfoManager::ShouldSuppressBreakpointsForTimeTravelMove(TTDMode mode)
  380. {
  381. return (mode & TTD::TTDMode::DebuggerSuppressBreakpoints) == TTD::TTDMode::DebuggerSuppressBreakpoints;
  382. }
  383. bool ExecutionInfoManager::ShouldRecordBreakpointsDuringTimeTravelScan(TTDMode mode)
  384. {
  385. return (mode & TTD::TTDMode::DebuggerLogBreakpoints) == TTD::TTDMode::DebuggerLogBreakpoints;
  386. }
  387. ExecutionInfoManager::ExecutionInfoManager(const TTInnerLoopLastStatementInfo& lsi)
  388. : m_topLevelCallbackEventTime(-1), m_runningFunctionTimeCtr(0), m_callStack(&HeapAllocator::Instance),
  389. m_debuggerNotifiedTopLevelBodies(&HeapAllocator::Instance),
  390. m_lastReturnLocation(), m_lastExceptionPropagating(false), m_lastExceptionLocation(),
  391. m_breakOnFirstUserCode(false),
  392. m_pendingTTDBP(), m_pendingTTDMoveMode(-1), m_activeBPId(-1), m_shouldRemoveWhenDone(false), m_activeTTDBP(),
  393. m_hitContinueSearchBP(false), m_continueBreakPoint(),
  394. m_unRestoredBreakpoints(&HeapAllocator::Instance),
  395. m_innerloopLastLocation(lsi)
  396. {
  397. ;
  398. }
  399. ExecutionInfoManager::~ExecutionInfoManager()
  400. {
  401. if(this->m_unRestoredBreakpoints.Count() != 0)
  402. {
  403. for(int32 i = 0; i < this->m_unRestoredBreakpoints.Count(); ++i)
  404. {
  405. HeapDelete(this->m_unRestoredBreakpoints.Item(i));
  406. }
  407. }
  408. }
  409. #if ENABLE_BASIC_TRACE || ENABLE_FULL_BC_TRACE
  410. TraceLogger* ExecutionInfoManager::GetTraceLogger()
  411. {
  412. return &(this->m_diagnosticLogger);
  413. }
  414. #endif
  415. const SingleCallCounter& ExecutionInfoManager::GetTopCallCounter() const
  416. {
  417. TTDAssert(this->m_callStack.Count() != 0, "Empty stack!");
  418. return this->m_callStack.Item(this->m_callStack.Count() - 1);
  419. }
  420. SingleCallCounter& ExecutionInfoManager::GetTopCallCounter()
  421. {
  422. TTDAssert(this->m_callStack.Count() != 0, "Empty stack!");
  423. return this->m_callStack.Item(this->m_callStack.Count() - 1);
  424. }
  425. bool ExecutionInfoManager::TryGetTopCallCallerCounter(SingleCallCounter& caller) const
  426. {
  427. if(this->m_callStack.Count() < 2)
  428. {
  429. return false;
  430. }
  431. else
  432. {
  433. caller = this->m_callStack.Item(this->m_callStack.Count() - 2);
  434. return true;
  435. }
  436. }
  437. void ExecutionInfoManager::PushCallEvent(Js::JavascriptFunction* function, uint32 argc, Js::Var* argv, bool isInFinally)
  438. {
  439. //Clear any previous last return frame info
  440. this->m_lastReturnLocation.ClearReturnOnly();
  441. this->m_runningFunctionTimeCtr++;
  442. SingleCallCounter cfinfo;
  443. cfinfo.Function = function->GetFunctionBody();
  444. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  445. cfinfo.Name = cfinfo.Function->GetExternalDisplayName();
  446. #endif
  447. cfinfo.FunctionTime = this->m_runningFunctionTimeCtr;
  448. cfinfo.LoopTime = 0;
  449. cfinfo.CurrentStatementIndex = -1;
  450. cfinfo.CurrentStatementLoopTime = 0;
  451. cfinfo.LastStatementIndex = -1;
  452. cfinfo.LastStatementLoopTime = 0;
  453. cfinfo.CurrentStatementBytecodeMin = UINT32_MAX;
  454. cfinfo.CurrentStatementBytecodeMax = UINT32_MAX;
  455. this->m_callStack.Add(cfinfo);
  456. ////
  457. //If we are running for debugger then check if we need to set a breakpoint at entry to the first function we execute
  458. if(this->m_breakOnFirstUserCode)
  459. {
  460. this->m_breakOnFirstUserCode = false;
  461. this->m_activeTTDBP.SetLocationFromFunctionEntryAnyTime(this->m_topLevelCallbackEventTime, cfinfo.Function);
  462. this->SetActiveBP_Helper(function->GetFunctionBody()->GetScriptContext()->GetThreadContext()->TTDContext);
  463. }
  464. ////
  465. #if ENABLE_BASIC_TRACE || ENABLE_FULL_BC_TRACE
  466. this->m_diagnosticLogger.WriteCall(function, false, argc, argv, function->GetFunctionBody()->GetScriptContext()->GetThreadContext()->TTDLog->GetLastEventTime());
  467. #endif
  468. }
  469. void ExecutionInfoManager::PopCallEvent(Js::JavascriptFunction* function, Js::Var result)
  470. {
  471. this->m_lastReturnLocation.SetReturnLocation(this->m_callStack.Last());
  472. this->m_runningFunctionTimeCtr++;
  473. this->m_callStack.RemoveAtEnd();
  474. #if ENABLE_BASIC_TRACE || ENABLE_FULL_BC_TRACE
  475. this->m_diagnosticLogger.WriteReturn(function, result, function->GetFunctionBody()->GetScriptContext()->GetThreadContext()->TTDLog->GetLastEventTime());
  476. #endif
  477. }
  478. void ExecutionInfoManager::PopCallEventException(Js::JavascriptFunction* function)
  479. {
  480. //If we already have the last return as an exception then just leave it.
  481. //That is where the exception was first rasied, this return is just propagating it in this return.
  482. if(!this->m_lastReturnLocation.IsExceptionLocation())
  483. {
  484. this->m_lastReturnLocation.SetExceptionLocation(this->m_callStack.Last());
  485. }
  486. if(!this->m_lastExceptionPropagating)
  487. {
  488. this->m_lastExceptionLocation.SetLocationFromFrame(this->m_topLevelCallbackEventTime, this->m_callStack.Last());
  489. this->m_lastExceptionPropagating = true;
  490. }
  491. this->m_runningFunctionTimeCtr++;
  492. this->m_callStack.RemoveAtEnd();
  493. #if ENABLE_BASIC_TRACE || ENABLE_FULL_BC_TRACE
  494. this->m_diagnosticLogger.WriteReturnException(function, function->GetFunctionBody()->GetScriptContext()->GetThreadContext()->TTDLog->GetLastEventTime());
  495. #endif
  496. }
  497. void ExecutionInfoManager::ProcessCatchInfoForLastExecutedStatements()
  498. {
  499. this->m_lastReturnLocation.Clear();
  500. this->m_lastExceptionPropagating = false;
  501. }
  502. void ExecutionInfoManager::SetBreakOnFirstUserCode()
  503. {
  504. this->m_breakOnFirstUserCode = true;
  505. }
  506. void ExecutionInfoManager::SetPendingTTDResetToCurrentPosition()
  507. {
  508. this->GetTimeAndPositionForDebugger(this->m_pendingTTDBP);
  509. this->m_pendingTTDMoveMode = 0;
  510. }
  511. void ExecutionInfoManager::SetPendingTTDToTarget(const TTDebuggerSourceLocation& dsl)
  512. {
  513. this->m_pendingTTDBP.SetLocationCopy(dsl);
  514. this->m_pendingTTDMoveMode = 0;
  515. }
  516. void ExecutionInfoManager::SetPendingTTDStepBackMove()
  517. {
  518. this->GetPreviousTimeAndPositionForDebugger(this->m_pendingTTDBP);
  519. this->m_pendingTTDMoveMode = 0;
  520. }
  521. void ExecutionInfoManager::SetPendingTTDStepBackIntoMove()
  522. {
  523. this->GetLastExecutedTimeAndPositionForDebugger(this->m_pendingTTDBP);
  524. this->m_pendingTTDMoveMode = 0;
  525. }
  526. void ExecutionInfoManager::SetPendingTTDReverseContinueMove(uint64 moveflag)
  527. {
  528. this->m_continueBreakPoint.Clear();
  529. this->GetTimeAndPositionForDebugger(this->m_pendingTTDBP);
  530. this->m_pendingTTDMoveMode = moveflag;
  531. }
  532. void ExecutionInfoManager::SetPendingTTDUnhandledException()
  533. {
  534. this->GetLastExceptionTimeAndPositionForDebugger(this->m_pendingTTDBP);
  535. this->m_lastExceptionPropagating = false;
  536. this->m_pendingTTDMoveMode = 0;
  537. }
  538. bool ExecutionInfoManager::ProcessBPInfoPreBreak(Js::FunctionBody* fb, const EventLog* elog)
  539. {
  540. //if we aren't in debug mode then we always trigger BP's
  541. if(!fb->GetScriptContext()->ShouldPerformReplayDebuggerAction())
  542. {
  543. return true;
  544. }
  545. //If we are in debugger mode but are suppressing BP's for movement then suppress them
  546. if(ExecutionInfoManager::ShouldSuppressBreakpointsForTimeTravelMove(elog->GetCurrentTTDMode()))
  547. {
  548. //Check if we need to record the visit to this bp
  549. if(ExecutionInfoManager::ShouldRecordBreakpointsDuringTimeTravelScan(elog->GetCurrentTTDMode()))
  550. {
  551. this->AddCurrentLocationDuringScan(elog->GetCurrentTopLevelEventTime());
  552. }
  553. return false;
  554. }
  555. //If we are in debug mode and don't have an active BP target then we treat BP's as usual
  556. if(!this->m_activeTTDBP.HasValue())
  557. {
  558. return true;
  559. }
  560. //Finally we are in debug mode and we have an active BP target so only break if the BP is satisfied
  561. const SingleCallCounter& cfinfo = this->GetTopCallCounter();
  562. //Make sure we are in the right source code (via top level body ids)
  563. if(this->m_activeTTDBP.GetTopLevelBodyId() != cfinfo.Function->GetScriptContext()->TTDContextInfo->FindTopLevelCtrForBody(cfinfo.Function))
  564. {
  565. return false;
  566. }
  567. ULONG srcLine = 0;
  568. LONG srcColumn = -1;
  569. uint32 startOffset = cfinfo.Function->GetStatementStartOffset(cfinfo.CurrentStatementIndex);
  570. cfinfo.Function->GetSourceLineFromStartOffset_TTD(startOffset, &srcLine, &srcColumn);
  571. bool locationOk = ((uint32)srcLine == this->m_activeTTDBP.GetSourceLine()) & ((uint32)srcColumn == this->m_activeTTDBP.GetSourceColumn());
  572. bool ftimeOk = (this->m_activeTTDBP.GetFunctionTime() == -1) | ((uint64)this->m_activeTTDBP.GetFunctionTime() == cfinfo.FunctionTime);
  573. bool ltimeOk = (this->m_activeTTDBP.GetLoopTime() == -1) | ((uint64)this->m_activeTTDBP.GetLoopTime() == cfinfo.CurrentStatementLoopTime);
  574. return locationOk & ftimeOk & ltimeOk;
  575. }
  576. void ExecutionInfoManager::ProcessBPInfoPostBreak(Js::FunctionBody* fb)
  577. {
  578. if(!fb->GetScriptContext()->ShouldPerformReplayDebuggerAction())
  579. {
  580. return;
  581. }
  582. if(this->m_activeTTDBP.HasValue())
  583. {
  584. this->ClearActiveBPInfo(fb->GetScriptContext()->GetThreadContext()->TTDContext);
  585. }
  586. if(this->m_pendingTTDBP.HasValue())
  587. {
  588. //Reset any step controller logic
  589. fb->GetScriptContext()->GetThreadContext()->GetDebugManager()->stepController.Deactivate();
  590. throw TTD::TTDebuggerAbortException::CreateTopLevelAbortRequest(this->m_pendingTTDBP.GetRootEventTime(), this->m_pendingTTDMoveMode, _u("Reverse operation requested."));
  591. }
  592. }
  593. bool ExecutionInfoManager::IsLocationActiveBPAndNotExplicitBP(const TTDebuggerSourceLocation& current) const
  594. {
  595. //If we shound't remove the active BP when done then it is a user visible one so we just return false
  596. if(!this->m_shouldRemoveWhenDone)
  597. {
  598. return false;
  599. }
  600. //Check to see if the locations are the same
  601. return TTDebuggerSourceLocation::AreSameLocations_PlaceOnly(this->m_activeTTDBP, current);
  602. }
  603. void ExecutionInfoManager::AddCurrentLocationDuringScan(int64 topLevelEventTime)
  604. {
  605. TTDebuggerSourceLocation current;
  606. current.SetLocationFromFrame(topLevelEventTime, this->m_callStack.Last());
  607. if(this->m_activeTTDBP.HasValue() && TTDebuggerSourceLocation::AreSameLocations(this->m_activeTTDBP, current))
  608. {
  609. this->m_hitContinueSearchBP = true;
  610. }
  611. if(!this->m_hitContinueSearchBP && !this->IsLocationActiveBPAndNotExplicitBP(current))
  612. {
  613. this->m_continueBreakPoint.SetLocationCopy(current);
  614. }
  615. }
  616. bool ExecutionInfoManager::TryFindAndSetPreviousBP()
  617. {
  618. if(!this->m_continueBreakPoint.HasValue())
  619. {
  620. return false;
  621. }
  622. else
  623. {
  624. this->m_pendingTTDBP.SetLocationCopy(this->m_continueBreakPoint);
  625. this->m_continueBreakPoint.Clear();
  626. return true;
  627. }
  628. }
  629. //Get the target event time for the pending TTD breakpoint
  630. int64 ExecutionInfoManager::GetPendingTTDBPTargetEventTime() const
  631. {
  632. TTDAssert(this->m_pendingTTDBP.HasValue(), "We did not set the pending TTD breakpoint value?");
  633. return this->m_pendingTTDBP.GetRootEventTime();
  634. }
  635. void ExecutionInfoManager::LoadPreservedBPInfo(ThreadContext* threadContext)
  636. {
  637. while(this->m_unRestoredBreakpoints.Contains(nullptr))
  638. {
  639. this->m_unRestoredBreakpoints.Remove(nullptr);
  640. }
  641. const JsUtil::List<Js::ScriptContext*, HeapAllocator>& ctxs = threadContext->TTDContext->GetTTDContexts();
  642. for(int32 i = 0; i < ctxs.Count(); ++i)
  643. {
  644. Js::ScriptContext* ctx = ctxs.Item(i);
  645. JsUtil::List<uint32, HeapAllocator> bpIdsToDelete(&HeapAllocator::Instance);
  646. Js::ProbeContainer* probeContainer = ctx->GetDebugContext()->GetProbeContainer();
  647. probeContainer->MapProbes([&](int j, Js::Probe* pProbe)
  648. {
  649. Js::BreakpointProbe* bp = (Js::BreakpointProbe*)pProbe;
  650. if((int64)bp->GetId() != this->m_activeBPId)
  651. {
  652. Js::FunctionBody* body = bp->GetFunctionBody();
  653. int32 bpIndex = body->GetEnclosingStatementIndexFromByteCode(bp->GetBytecodeOffset());
  654. ULONG srcLine = 0;
  655. LONG srcColumn = -1;
  656. uint32 startOffset = body->GetStatementStartOffset(bpIndex);
  657. body->GetSourceLineFromStartOffset_TTD(startOffset, &srcLine, &srcColumn);
  658. TTDebuggerSourceLocation* bpLocation = TT_HEAP_NEW(TTDebuggerSourceLocation);
  659. bpLocation->SetLocationWithBP(bp->GetId(), body, srcLine, srcColumn);
  660. this->m_unRestoredBreakpoints.Add(bpLocation);
  661. bpIdsToDelete.Add(bp->GetId());
  662. }
  663. });
  664. for(int32 j = 0; j < bpIdsToDelete.Count(); ++j)
  665. {
  666. ctx->TTDHostCallbackFunctor.pfOnBPDeleteCallback(ctx->TTDHostCallbackFunctor.HostRuntime, bpIdsToDelete.Item(j));
  667. }
  668. //done with last context so release the debug document dictionary info
  669. if(i == ctxs.Count() - 1)
  670. {
  671. ctx->TTDHostCallbackFunctor.pfOnBPClearDocumentCallback(ctx->TTDHostCallbackFunctor.HostRuntime);
  672. }
  673. }
  674. }
  675. void ExecutionInfoManager::AddPreservedBPsForTopLevelLoad(uint32 topLevelBodyId, Js::FunctionBody* body)
  676. {
  677. Js::ScriptContext* ctx = body->GetScriptContext();
  678. Js::Utf8SourceInfo* utf8SourceInfo = body->GetUtf8SourceInfo();
  679. for(int32 i = 0; i < this->m_unRestoredBreakpoints.Count(); ++i)
  680. {
  681. if(this->m_unRestoredBreakpoints.Item(i) == nullptr)
  682. {
  683. continue;
  684. }
  685. const TTDebuggerSourceLocation* bpLocation = this->m_unRestoredBreakpoints.Item(i);
  686. if(bpLocation->GetTopLevelBodyId() == topLevelBodyId)
  687. {
  688. BOOL isNewBP = FALSE;
  689. ctx->TTDHostCallbackFunctor.pfOnBPRegisterCallback(ctx->TTDHostCallbackFunctor.HostRuntime, bpLocation->GetBPId(), ctx, utf8SourceInfo, bpLocation->GetSourceLine(), bpLocation->GetSourceColumn(), &isNewBP);
  690. TTDAssert(isNewBP, "We should be restoring a breapoint we removed previously!");
  691. //Now that it is set we can clear it from our list
  692. this->m_unRestoredBreakpoints.SetItem(i, nullptr);
  693. }
  694. }
  695. if(this->m_activeTTDBP.HasValue() && (this->m_activeBPId == -1) && (this->m_activeTTDBP.GetTopLevelBodyId() == topLevelBodyId))
  696. {
  697. this->SetActiveBP_Helper(body->GetScriptContext()->GetThreadContext()->TTDContext);
  698. }
  699. }
  700. void ExecutionInfoManager::UpdateLoopCountInfo()
  701. {
  702. SingleCallCounter& cfinfo = this->m_callStack.Last();
  703. cfinfo.LoopTime++;
  704. }
  705. void ExecutionInfoManager::UpdateCurrentStatementInfo(uint bytecodeOffset)
  706. {
  707. SingleCallCounter& cfinfo = this->GetTopCallCounter();
  708. if((cfinfo.CurrentStatementBytecodeMin <= bytecodeOffset) & (bytecodeOffset <= cfinfo.CurrentStatementBytecodeMax))
  709. {
  710. return;
  711. }
  712. else
  713. {
  714. Js::FunctionBody* fb = cfinfo.Function;
  715. TTDAssert(fb->GetUtf8SourceInfo() != nullptr, "Should always have a source info.");
  716. if (!fb->GetUtf8SourceInfo()->GetIsLibraryCode())
  717. {
  718. int32 cIndex = fb->GetEnclosingStatementIndexFromByteCode(bytecodeOffset, true);
  719. //We moved to a new statement
  720. Js::FunctionBody::StatementMap* pstmt = fb->GetStatementMaps()->Item(cIndex);
  721. bool newstmt = (cIndex != cfinfo.CurrentStatementIndex && pstmt->byteCodeSpan.begin <= (int)bytecodeOffset && (int)bytecodeOffset <= pstmt->byteCodeSpan.end);
  722. //Make sure async step back is ok -- We always step back to the first location in a statement and in most cases a function body must start at the first location in a statement.
  723. //However an await can be in the middle of a statment/expression and is implicitly the start of a function body. So, we must check for that case.
  724. bool functionBodyStartUnalignedWithStatementCase = (cfinfo.CurrentStatementIndex == -1) && (pstmt->byteCodeSpan.begin != (int)bytecodeOffset);
  725. if (newstmt && !functionBodyStartUnalignedWithStatementCase)
  726. {
  727. cfinfo.LastStatementIndex = cfinfo.CurrentStatementIndex;
  728. cfinfo.LastStatementLoopTime = cfinfo.CurrentStatementLoopTime;
  729. cfinfo.CurrentStatementIndex = cIndex;
  730. cfinfo.CurrentStatementLoopTime = cfinfo.LoopTime;
  731. cfinfo.CurrentStatementBytecodeMin = (uint32)pstmt->byteCodeSpan.begin;
  732. cfinfo.CurrentStatementBytecodeMax = (uint32)pstmt->byteCodeSpan.end;
  733. #if ENABLE_FULL_BC_TRACE
  734. ULONG srcLine = 0;
  735. LONG srcColumn = -1;
  736. uint32 startOffset = cfinfo.Function->GetFunctionBody()->GetStatementStartOffset(cfinfo.CurrentStatementIndex);
  737. cfinfo.Function->GetFunctionBody()->GetSourceLineFromStartOffset_TTD(startOffset, &srcLine, &srcColumn);
  738. this->m_diagnosticLogger.WriteStmtIndex((uint32)srcLine, (uint32)srcColumn);
  739. #endif
  740. }
  741. }
  742. }
  743. }
  744. void ExecutionInfoManager::ManageLastSourceInfoChecks(Js::FunctionBody* fb, bool bpDisable)
  745. {
  746. if(this->IsLastSourceLineEnabled() && this->IsFinalSourceLine())
  747. {
  748. this->SetPendingTTDResetToCurrentPosition();
  749. if(bpDisable)
  750. {
  751. //Reset any step controller logic
  752. fb->GetScriptContext()->GetThreadContext()->GetDebugManager()->stepController.Deactivate();
  753. }
  754. throw TTD::TTDebuggerAbortException::CreateTopLevelAbortRequest(this->m_pendingTTDBP.GetRootEventTime(), this->m_pendingTTDMoveMode, _u("Last source info hit -- reset to requested."));
  755. }
  756. }
  757. bool ExecutionInfoManager::IsLastSourceLineEnabled() const
  758. {
  759. return this->m_innerloopLastLocation.IsEnabled();
  760. }
  761. bool ExecutionInfoManager::IsFinalSourceLine() const
  762. {
  763. const SingleCallCounter& cfinfo = this->GetTopCallCounter();
  764. if(!this->m_innerloopLastLocation.CheckLastTimeMatch(this->m_topLevelCallbackEventTime, cfinfo.FunctionTime, cfinfo.LoopTime))
  765. {
  766. return false;
  767. }
  768. ULONG srcLine = 0;
  769. LONG srcColumn = -1;
  770. uint32 startOffset = cfinfo.Function->GetStatementStartOffset(cfinfo.CurrentStatementIndex);
  771. cfinfo.Function->GetSourceLineFromStartOffset_TTD(startOffset, &srcLine, &srcColumn);
  772. return this->m_innerloopLastLocation.CheckLineColumnMatch((uint32) srcLine, (uint32)srcColumn);
  773. }
  774. void ExecutionInfoManager::GetTimeAndPositionForDebugger(TTDebuggerSourceLocation& sourceLocation) const
  775. {
  776. const SingleCallCounter& cfinfo = this->GetTopCallCounter();
  777. ULONG srcLine = 0;
  778. LONG srcColumn = -1;
  779. uint32 startOffset = cfinfo.Function->GetStatementStartOffset(cfinfo.CurrentStatementIndex);
  780. cfinfo.Function->GetSourceLineFromStartOffset_TTD(startOffset, &srcLine, &srcColumn);
  781. sourceLocation.SetLocationFull(this->m_topLevelCallbackEventTime, cfinfo.FunctionTime, cfinfo.LoopTime, cfinfo.Function, srcLine, srcColumn);
  782. }
  783. #if ENABLE_OBJECT_SOURCE_TRACKING
  784. void ExecutionInfoManager::GetTimeAndPositionForDiagnosticObjectTracking(DiagnosticOrigin& originInfo) const
  785. {
  786. const SingleCallCounter& cfinfo = this->GetTopCallCounter();
  787. ULONG srcLine = 0;
  788. LONG srcColumn = -1;
  789. uint32 startOffset = cfinfo.Function->GetStatementStartOffset(cfinfo.CurrentStatementIndex);
  790. cfinfo.Function->GetSourceLineFromStartOffset_TTD(startOffset, &srcLine, &srcColumn);
  791. SetDiagnosticOriginInformation(originInfo, srcLine, cfinfo.Function->GetFunctionBody()->GetScriptContext()->GetThreadContext()->TTDLog->GetLastEventTime(), cfinfo.FunctionTime, cfinfo.LoopTime);
  792. }
  793. #endif
  794. bool ExecutionInfoManager::GetPreviousTimeAndPositionForDebugger(TTDebuggerSourceLocation& sourceLocation) const
  795. {
  796. bool noPrevious = false;
  797. const SingleCallCounter& cfinfo = this->GetTopCallCounter();
  798. //if we are at the first statement in the function then we want the parents current
  799. Js::FunctionBody* fbody = nullptr;
  800. int32 statementIndex = -1;
  801. uint64 ftime = 0;
  802. uint64 ltime = 0;
  803. if(cfinfo.LastStatementIndex == -1)
  804. {
  805. SingleCallCounter cfinfoCaller = { 0 };
  806. bool hasCaller = this->TryGetTopCallCallerCounter(cfinfoCaller);
  807. if (hasCaller)
  808. {
  809. ftime = cfinfoCaller.FunctionTime;
  810. ltime = cfinfoCaller.CurrentStatementLoopTime;
  811. fbody = cfinfoCaller.Function;
  812. statementIndex = cfinfoCaller.CurrentStatementIndex;
  813. }
  814. else
  815. {
  816. //Set the position info to the current statement and return true
  817. noPrevious = true;
  818. ftime = cfinfo.FunctionTime;
  819. ltime = cfinfo.CurrentStatementLoopTime;
  820. fbody = cfinfo.Function;
  821. statementIndex = cfinfo.CurrentStatementIndex;
  822. }
  823. }
  824. else
  825. {
  826. ftime = cfinfo.FunctionTime;
  827. ltime = cfinfo.LastStatementLoopTime;
  828. fbody = cfinfo.Function;
  829. statementIndex = cfinfo.LastStatementIndex;
  830. }
  831. ULONG srcLine = 0;
  832. LONG srcColumn = -1;
  833. uint32 startOffset = fbody->GetStatementStartOffset(statementIndex);
  834. fbody->GetSourceLineFromStartOffset_TTD(startOffset, &srcLine, &srcColumn);
  835. sourceLocation.SetLocationFull(this->m_topLevelCallbackEventTime, ftime, ltime, fbody, srcLine, srcColumn);
  836. return noPrevious;
  837. }
  838. void ExecutionInfoManager::GetLastExecutedTimeAndPositionForDebugger(TTDebuggerSourceLocation& sourceLocation) const
  839. {
  840. const TTLastReturnLocationInfo& cframe = this->m_lastReturnLocation;
  841. if(!cframe.IsDefined())
  842. {
  843. sourceLocation.Clear();
  844. return;
  845. }
  846. else
  847. {
  848. ULONG srcLine = 0;
  849. LONG srcColumn = -1;
  850. uint32 startOffset = cframe.GetLocation().Function->GetStatementStartOffset(cframe.GetLocation().CurrentStatementIndex);
  851. cframe.GetLocation().Function->GetSourceLineFromStartOffset_TTD(startOffset, &srcLine, &srcColumn);
  852. sourceLocation.SetLocationFull(this->m_topLevelCallbackEventTime, cframe.GetLocation().FunctionTime, cframe.GetLocation().CurrentStatementLoopTime, cframe.GetLocation().Function, srcLine, srcColumn);
  853. }
  854. }
  855. void ExecutionInfoManager::GetLastExceptionTimeAndPositionForDebugger(TTDebuggerSourceLocation& sourceLocation) const
  856. {
  857. //If no exception then this will also clear sourceLocation
  858. sourceLocation.SetLocationCopy(this->m_lastExceptionLocation);
  859. }
  860. void ExecutionInfoManager::ResetCallStackForTopLevelCall(int64 topLevelCallbackEventTime)
  861. {
  862. TTDAssert(this->m_callStack.Count() == 0, "We should be at the top-level entry!!!");
  863. this->m_topLevelCallbackEventTime = topLevelCallbackEventTime;
  864. this->m_runningFunctionTimeCtr = 0;
  865. this->m_lastReturnLocation.Clear();
  866. this->m_lastExceptionLocation.Clear();
  867. }
  868. void ExecutionInfoManager::SetBPInfoForActiveSegmentContinueScan(ThreadContextTTD* ttdThreadContext)
  869. {
  870. TTDAssert(this->m_pendingTTDBP.HasValue(), "We should always set this when launching a reverse continue!");
  871. this->m_activeTTDBP.SetLocationCopy(this->m_pendingTTDBP);
  872. this->SetActiveBPInfoAsNeeded(ttdThreadContext);
  873. }
  874. void ExecutionInfoManager::ClearBPInfoForActiveSegmentContinueScan(ThreadContextTTD* ttdThreadContext)
  875. {
  876. TTDAssert(this->m_activeTTDBP.HasValue(), "We should always have this set when we complete the active segment scan.");
  877. this->m_hitContinueSearchBP = false;
  878. this->ClearActiveBPInfo(ttdThreadContext);
  879. }
  880. void ExecutionInfoManager::SetActiveBP_Helper(ThreadContextTTD* ttdThreadContext)
  881. {
  882. Js::ScriptContext* ctx = ttdThreadContext->LookupContextForScriptId(this->m_activeTTDBP.GetScriptLogTagId());
  883. Js::FunctionBody* body = this->m_activeTTDBP.LoadFunctionBodyIfPossible(ctx);
  884. if(body == nullptr)
  885. {
  886. return;
  887. }
  888. Js::Utf8SourceInfo* utf8SourceInfo = body->GetUtf8SourceInfo();
  889. Js::DebugDocument* debugDocument = utf8SourceInfo->GetDebugDocument();
  890. TTDAssert(debugDocument != nullptr, "Something went wrong with our TTD debug breakpoints.");
  891. utf8SourceInfo->EnsureLineOffsetCacheNoThrow();
  892. charcount_t charPosition = 0;
  893. charcount_t byteOffset = 0;
  894. utf8SourceInfo->GetCharPositionForLineInfo(this->m_activeTTDBP.GetSourceLine(), &charPosition, &byteOffset);
  895. long ibos = charPosition + this->m_activeTTDBP.GetSourceColumn() + 1;
  896. Js::StatementLocation statement;
  897. debugDocument->GetStatementLocation(ibos, &statement);
  898. // Don't see a use case for supporting multiple breakpoints at same location.
  899. // If a breakpoint already exists, just return that
  900. Js::BreakpointProbe* probe = debugDocument->FindBreakpoint(statement);
  901. if(probe == nullptr)
  902. {
  903. this->m_shouldRemoveWhenDone = true;
  904. probe = debugDocument->SetBreakPoint(statement, BREAKPOINT_ENABLED);
  905. }
  906. this->m_activeBPId = probe->GetId();
  907. }
  908. void ExecutionInfoManager::SetActiveBPInfoAsNeeded(ThreadContextTTD* ttdThreadContext)
  909. {
  910. if(this->m_pendingTTDBP.HasValue())
  911. {
  912. this->m_activeTTDBP.SetLocationCopy(this->m_pendingTTDBP);
  913. this->SetActiveBP_Helper(ttdThreadContext);
  914. //Finally clear the pending BP info so we don't get confused later
  915. this->m_pendingTTDMoveMode = 0;
  916. this->m_pendingTTDBP.Clear();
  917. }
  918. }
  919. void ExecutionInfoManager::ClearActiveBPInfo(ThreadContextTTD* ttdThreadContext)
  920. {
  921. TTDAssert(this->m_activeTTDBP.HasValue(), "Need to check that we actually have info to clear first.");
  922. Js::ScriptContext* ctx = ttdThreadContext->LookupContextForScriptId(this->m_activeTTDBP.GetScriptLogTagId());
  923. Js::FunctionBody* body = this->m_activeTTDBP.LoadFunctionBodyIfPossible(ctx);
  924. Js::DebugDocument* debugDocument = body->GetUtf8SourceInfo()->GetDebugDocument();
  925. Js::StatementLocation statement;
  926. if(this->m_shouldRemoveWhenDone && debugDocument->FindBPStatementLocation((UINT)this->m_activeBPId, &statement))
  927. {
  928. debugDocument->SetBreakPoint(statement, BREAKPOINT_DELETED);
  929. }
  930. this->m_activeBPId = -1;
  931. this->m_shouldRemoveWhenDone = false;
  932. this->m_activeTTDBP.Clear();
  933. }
  934. void ExecutionInfoManager::ProcessScriptLoad(Js::ScriptContext* ctx, uint32 topLevelBodyId, Js::FunctionBody* body, Js::Utf8SourceInfo* utf8SourceInfo, CompileScriptException* se)
  935. {
  936. bool newScript = !this->m_debuggerNotifiedTopLevelBodies.Contains(topLevelBodyId);
  937. //Only notify of loaded script -- eval and new script is only notified later if we need to hit a bp in it?
  938. if(se != nullptr)
  939. {
  940. ctx->TTDHostCallbackFunctor.pfOnScriptLoadCallback(ctx->TTDHostCallbackFunctor.HostContext, body, utf8SourceInfo, se, newScript);
  941. }
  942. if(newScript)
  943. {
  944. this->m_debuggerNotifiedTopLevelBodies.AddNew(topLevelBodyId);
  945. }
  946. this->AddPreservedBPsForTopLevelLoad(topLevelBodyId, body);
  947. }
  948. void ExecutionInfoManager::ProcessScriptLoad_InflateReuseBody(uint32 topLevelBodyId, Js::FunctionBody* body)
  949. {
  950. this->AddPreservedBPsForTopLevelLoad(topLevelBodyId, body);
  951. }
  952. }
  953. #endif