TTEventLog.h 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  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. #pragma once
  6. #if ENABLE_TTD
  7. #define TTD_EVENTLOG_LIST_BLOCK_SIZE 65536
  8. namespace TTD
  9. {
  10. //A class to ensure that even when exceptions are thrown we increment/decrement the root nesting depth
  11. class TTDNestingDepthAutoAdjuster
  12. {
  13. private:
  14. ThreadContext* m_threadContext;
  15. public:
  16. TTDNestingDepthAutoAdjuster(ThreadContext* threadContext)
  17. : m_threadContext(threadContext)
  18. {
  19. this->m_threadContext->TTDRootNestingCount++;
  20. }
  21. ~TTDNestingDepthAutoAdjuster()
  22. {
  23. this->m_threadContext->TTDRootNestingCount--;
  24. }
  25. };
  26. //A class to manage the recording of JsRT action call state
  27. class TTDJsRTActionResultAutoRecorder
  28. {
  29. private:
  30. NSLogEvents::EventLogEntry* m_actionEvent;
  31. TTDVar* m_resultPtr;
  32. public:
  33. TTDJsRTActionResultAutoRecorder()
  34. : m_actionEvent(nullptr), m_resultPtr(nullptr)
  35. {
  36. ;
  37. }
  38. void InitializeWithEventAndEnter(NSLogEvents::EventLogEntry* actionEvent)
  39. {
  40. TTDAssert(this->m_actionEvent == nullptr, "Don't double initialize");
  41. this->m_actionEvent = actionEvent;
  42. }
  43. void InitializeWithEventAndEnterWResult(NSLogEvents::EventLogEntry* actionEvent, TTDVar* resultPtr)
  44. {
  45. TTDAssert(this->m_actionEvent == nullptr, "Don't double initialize");
  46. this->m_actionEvent = actionEvent;
  47. this->m_resultPtr = resultPtr;
  48. *(this->m_resultPtr) = (TTDVar)nullptr; //set the result field to a default value in case we fail during execution
  49. }
  50. void SetResult(Js::Var* result)
  51. {
  52. TTDAssert(this->m_resultPtr != nullptr, "Why are we calling this then???");
  53. if(result != nullptr)
  54. {
  55. *(this->m_resultPtr) = TTD_CONVERT_JSVAR_TO_TTDVAR(*(result));
  56. }
  57. }
  58. void CompleteWithStatusCode(int32 exitStatus)
  59. {
  60. if(this->m_actionEvent != nullptr)
  61. {
  62. TTDAssert(this->m_actionEvent->ResultStatus == -1, "Hmm this got changed somewhere???");
  63. this->m_actionEvent->ResultStatus = exitStatus;
  64. }
  65. }
  66. };
  67. //A class to ensure that even when exceptions are thrown we record the time difference info
  68. class TTDJsRTFunctionCallActionPopperRecorder
  69. {
  70. private:
  71. Js::ScriptContext* m_ctx;
  72. double m_beginTime;
  73. NSLogEvents::EventLogEntry* m_callAction;
  74. public:
  75. TTDJsRTFunctionCallActionPopperRecorder();
  76. ~TTDJsRTFunctionCallActionPopperRecorder();
  77. void InitializeForRecording(Js::ScriptContext* ctx, double beginWallTime, NSLogEvents::EventLogEntry* callAction);
  78. };
  79. //A list class for the events that we accumulate in the event log
  80. class TTEventList
  81. {
  82. public:
  83. struct TTEventListLink
  84. {
  85. //The current end of the allocated data in the block
  86. size_t CurrPos;
  87. //The First index that holds data
  88. size_t StartPos;
  89. //The actual block for the data
  90. byte* BlockData;
  91. //The next block in the list
  92. TTEventListLink* Next;
  93. TTEventListLink* Previous;
  94. };
  95. private:
  96. //The the data in this
  97. TTEventListLink* m_headBlock;
  98. //the allocators we use for this work
  99. UnlinkableSlabAllocator* m_alloc;
  100. //The vtable with callbacks for the event log entries in the list
  101. const NSLogEvents::EventLogEntryVTableEntry* m_vtable;
  102. //Map from event entries to previous event entries -- only valid in replay mode otherwise empty
  103. JsUtil::BaseDictionary<const NSLogEvents::EventLogEntry*, size_t, HeapAllocator> m_previousEventMap;
  104. void AddArrayLink();
  105. void RemoveArrayLink(TTEventListLink* block);
  106. public:
  107. TTEventList(UnlinkableSlabAllocator* alloc);
  108. void SetVTable(const NSLogEvents::EventLogEntryVTableEntry* vtable);
  109. void InitializePreviousEventMap();
  110. void UnloadEventList();
  111. //Add the entry to the list
  112. template <typename T>
  113. NSLogEvents::EventLogEntry* GetNextAvailableEntry()
  114. {
  115. const size_t esize = TTD_EVENT_PLUS_DATA_SIZE(T);
  116. if((this->m_headBlock == nullptr) || (this->m_headBlock->CurrPos + esize >= TTD_EVENTLOG_LIST_BLOCK_SIZE))
  117. {
  118. this->AddArrayLink();
  119. }
  120. NSLogEvents::EventLogEntry* entry = reinterpret_cast<NSLogEvents::EventLogEntry*>(this->m_headBlock->BlockData + this->m_headBlock->CurrPos);
  121. this->m_headBlock->CurrPos += esize;
  122. return entry;
  123. }
  124. //Add the entry to the list
  125. NSLogEvents::EventLogEntry* GetNextAvailableEntry(size_t requiredSize);
  126. //Delete the entry from the list (must always be the first link/entry in the list)
  127. //This also calls unload on the entry
  128. void DeleteFirstEntry(TTEventListLink* block, NSLogEvents::EventLogEntry* data);
  129. //Return true if this is empty
  130. bool IsEmpty() const;
  131. //NOT constant time
  132. uint32 Count() const;
  133. class Iterator
  134. {
  135. private:
  136. TTEventListLink* m_currLink;
  137. size_t m_currIdx;
  138. const NSLogEvents::EventLogEntryVTableEntry* m_vtable;
  139. const JsUtil::BaseDictionary<const NSLogEvents::EventLogEntry*, size_t, HeapAllocator>* m_previousEventMap;
  140. public:
  141. Iterator();
  142. Iterator(TTEventListLink* head, size_t pos, const NSLogEvents::EventLogEntryVTableEntry* vtable, const JsUtil::BaseDictionary<const NSLogEvents::EventLogEntry*, size_t, HeapAllocator>* previousEventMap);
  143. const NSLogEvents::EventLogEntry* Current() const;
  144. NSLogEvents::EventLogEntry* Current();
  145. //Get the underlying block for deletion support
  146. TTEventListLink* GetBlock();
  147. bool IsValid() const;
  148. void MoveNext();
  149. void MovePrevious_ReplayOnly();
  150. };
  151. Iterator GetIteratorAtFirst() const;
  152. Iterator GetIteratorAtLast_ReplayOnly() const;
  153. };
  154. //A class that represents the event log for the program execution
  155. class EventLog
  156. {
  157. private:
  158. ThreadContext* m_threadContext;
  159. //Allocator we use for all the events we see
  160. UnlinkableSlabAllocator m_eventSlabAllocator;
  161. //Allocator we use for all the property records
  162. SlabAllocator m_miscSlabAllocator;
  163. //The global event time variable and a high res timer we can use to extract some diagnostic timing info as we go
  164. int64 m_eventTimeCtr;
  165. //A high res timer we can use to extract some diagnostic timing info as we go
  166. TTDTimer m_timer;
  167. //Top-Level callback event time (or -1 if we are not in a callback)
  168. int64 m_topLevelCallbackEventTime;
  169. //The list of all the events and the iterator we use during replay
  170. NSLogEvents::EventLogEntryVTableEntry* m_eventListVTable;
  171. TTEventList m_eventList;
  172. TTEventList::Iterator m_currentReplayEventIterator;
  173. //The current mode the system is running in (and a stack of mode push/pops that we use to generate it)
  174. TTModeStack m_modeStack;
  175. TTDMode m_currentMode;
  176. bool m_autoTracesEnabled;
  177. //The snapshot extractor that this log uses
  178. SnapshotExtractor m_snapExtractor;
  179. //The execution time that has elapsed since the last snapshot
  180. double m_elapsedExecutionTimeSinceSnapshot;
  181. //If we are inflating a snapshot multiple times we want to re-use the inflated objects when possible so keep this recent info
  182. int64 m_lastInflateSnapshotTime;
  183. InflateMap* m_lastInflateMap;
  184. //Pin set of all property records created during this logging session
  185. RecyclerRootPtr<PropertyRecordPinSet> m_propertyRecordPinSet;
  186. UnorderedArrayList<NSSnapType::SnapPropertyRecord, TTD_ARRAY_LIST_SIZE_DEFAULT> m_propertyRecordList;
  187. //The value of the threadContext sourceInfoCounter in record -- in replay initialize to this value to avoid collisions
  188. uint32 m_sourceInfoCount;
  189. //A list of all *root* scripts that have been loaded during this session
  190. UnorderedArrayList<NSSnapValues::TopLevelScriptLoadFunctionBodyResolveInfo, TTD_ARRAY_LIST_SIZE_MID> m_loadedTopLevelScripts;
  191. UnorderedArrayList<NSSnapValues::TopLevelNewFunctionBodyResolveInfo, TTD_ARRAY_LIST_SIZE_SMALL> m_newFunctionTopLevelScripts;
  192. UnorderedArrayList<NSSnapValues::TopLevelEvalFunctionBodyResolveInfo, TTD_ARRAY_LIST_SIZE_SMALL> m_evalTopLevelScripts;
  193. ////
  194. //Helper methods
  195. //Get the current XTTDEventTime and advance the event time counter
  196. int64 GetCurrentEventTimeAndAdvance()
  197. {
  198. return this->m_eventTimeCtr++;
  199. }
  200. //Advance the time and event position for replay
  201. void AdvanceTimeAndPositionForReplay();
  202. //Look at the stack to get the new computed mode
  203. void UpdateComputedMode();
  204. //A helper for extracting snapshots
  205. SnapShot* DoSnapshotExtract_Helper(double gcTime, JsUtil::BaseHashSet<Js::FunctionBody*, HeapAllocator>& liveTopLevelBodies);
  206. //Replay a snapshot event -- either just advance the event position or, if running diagnostics, take new snapshot and compare
  207. void ReplaySnapshotEvent();
  208. //Replay an event loop yield point event
  209. void ReplayEventLoopYieldPointEvent();
  210. template <typename T, NSLogEvents::EventKind tag>
  211. NSLogEvents::EventLogEntry* RecordGetInitializedEvent(T** extraData)
  212. {
  213. AssertMsg(TTD_EVENT_PLUS_DATA_SIZE_DIRECT(sizeof(T)) == this->m_eventListVTable[(uint32)tag].DataSize, "Computed and extracted data sizes don't match!!!");
  214. NSLogEvents::EventLogEntry* res = this->m_eventList.GetNextAvailableEntry<T>();
  215. NSLogEvents::EventLogEntry_Initialize<tag>(res, this->GetCurrentEventTimeAndAdvance());
  216. *extraData = NSLogEvents::GetInlineEventDataAs<T, tag>(res);
  217. return res;
  218. }
  219. template <typename T, NSLogEvents::EventKind tag>
  220. T* RecordGetInitializedEvent_DataOnly()
  221. {
  222. AssertMsg(TTD_EVENT_PLUS_DATA_SIZE_DIRECT(sizeof(T)) == this->m_eventListVTable[(uint32)tag].DataSize, "Computed and extracted data sizes don't match!!!");
  223. NSLogEvents::EventLogEntry* res = this->m_eventList.GetNextAvailableEntry<T>();
  224. NSLogEvents::EventLogEntry_Initialize<tag>(res, this->GetCurrentEventTimeAndAdvance());
  225. //For these operations are not allowed to fail so success is always 0
  226. res->ResultStatus = 0;
  227. return NSLogEvents::GetInlineEventDataAs<T, tag>(res);
  228. }
  229. //Sometimes we need to abort replay and immediately return to the top-level host (debugger) so it can decide what to do next
  230. // (1) If we are trying to replay something and we are at the end of the log then we need to terminate
  231. // (2) If we are at a breakpoint and we want to step back (in some form) then we need to terminate
  232. void AbortReplayReturnToHost();
  233. //A helper for getting and doing some iterator manipulation during replay
  234. template <typename T, NSLogEvents::EventKind tag>
  235. const T* ReplayGetReplayEvent_Helper()
  236. {
  237. if(!this->m_currentReplayEventIterator.IsValid())
  238. {
  239. this->AbortReplayReturnToHost();
  240. }
  241. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  242. TTDAssert(this->m_currentReplayEventIterator.Current()->EventTimeStamp == this->m_eventTimeCtr, "Out of Sync!!!");
  243. #endif
  244. const NSLogEvents::EventLogEntry* evt = this->m_currentReplayEventIterator.Current();
  245. this->AdvanceTimeAndPositionForReplay();
  246. return NSLogEvents::GetInlineEventDataAs<T, tag>(evt);
  247. }
  248. //Initialize the vtable for the event list data
  249. void InitializeEventListVTable();
  250. public:
  251. EventLog(ThreadContext* threadContext);
  252. ~EventLog();
  253. //When we stop recording we want to unload all of the data in the log (otherwise we get strange transitions if we start again later)
  254. void UnloadAllLogData();
  255. //Initialize the log so that it is ready to perform TTD (record or replay) and set into the correct global mode
  256. void InitForTTDRecord(bool debug);
  257. void InitForTTDReplay(TTDataIOInfo& iofp, const char* parseUri, size_t parseUriLength, bool debug);
  258. //If the last statement of this log is an inner loop emit event put the data in lsi otherwise leave it as the default value
  259. void LoadLastSourceLineInfo(TTInnerLoopLastStatementInfo& lsi, TTD::TTDebuggerSourceLocation& dsl) const;
  260. //reset the bottom (global) mode with the specific value
  261. void SetGlobalMode(TTDMode m);
  262. //Mark that a snapshot is in (or or is now complete)
  263. void SetSnapshotOrInflateInProgress(bool flag);
  264. //push a new debugger mode
  265. void PushMode(TTDMode m);
  266. //pop the top debugger mode
  267. void PopMode(TTDMode m);
  268. //Get the current mode for TTD execution
  269. TTDMode GetCurrentTTDMode() const;
  270. //Set the mode flags on the script context based on the TTDMode in the Log
  271. void SetModeFlagsOnContext(Js::ScriptContext* ctx);
  272. //Get the global mode flags for creating a script context
  273. void GetModesForExplicitContextCreate(bool& inRecord, bool& activelyRecording, bool& inReplay);
  274. //Just check if the debug mode flag has been set (don't check any active or suppressed properties)
  275. bool IsDebugModeFlagSet() const;
  276. //Add a property record to our pin set
  277. void AddPropertyRecord(const Js::PropertyRecord* record);
  278. //Add top level function load info to our sets
  279. const NSSnapValues::TopLevelScriptLoadFunctionBodyResolveInfo* AddScriptLoad(Js::FunctionBody* fb, Js::ModuleID moduleId, uint64 sourceContextId, const byte* source, uint32 sourceLen, LoadScriptFlag loadFlag);
  280. const NSSnapValues::TopLevelNewFunctionBodyResolveInfo* AddNewFunction(Js::FunctionBody* fb, Js::ModuleID moduleId, const char16* source, uint32 sourceLen);
  281. const NSSnapValues::TopLevelEvalFunctionBodyResolveInfo* AddEvalFunction(Js::FunctionBody* fb, Js::ModuleID moduleId, const char16* source, uint32 sourceLen, uint32 grfscr, bool registerDocument, BOOL isIndirect, BOOL strictMode);
  282. uint32 GetSourceInfoCount() const;
  283. void RecordTopLevelCodeAction(uint32 bodyCtrId);
  284. uint32 ReplayTopLevelCodeAction();
  285. ////////////////////////////////
  286. //Logging support
  287. //Log an event generated by user telemetry
  288. void RecordTelemetryLogEvent(Js::JavascriptString* infoStringJs, bool doPrint);
  289. //Replay a user telemetry event
  290. void ReplayTelemetryLogEvent(Js::JavascriptString* infoStringJs);
  291. //Log an event generated to write the log to a given uri
  292. void RecordEmitLogEvent(Js::JavascriptString* uriString);
  293. //Replay a event that writes the log to a given uri
  294. void ReplayEmitLogEvent();
  295. //Record that we are accessing the TTDFetchAutoTraceStatus and what the value is
  296. void RecordTTDFetchAutoTraceStatusEvent(bool status);
  297. //Replay that we are accessing the TTDFetchAutoTraceStatus
  298. bool ReplayTTDFetchAutoTraceStatusLogEvent();
  299. //Log a time that is fetched during date operations
  300. void RecordDateTimeEvent(double time);
  301. //Log a time (as a string) that is fetched during date operations
  302. void RecordDateStringEvent(Js::JavascriptString* stringValue);
  303. //replay date event (which should be the current event)
  304. void ReplayDateTimeEvent(double* result);
  305. //replay date event with a string result (which should be the current event)
  306. void ReplayDateStringEvent(Js::ScriptContext* ctx, Js::JavascriptString** result);
  307. //Log a random seed value that is being generated using external entropy
  308. void RecordExternalEntropyRandomEvent(uint64 seed0, uint64 seed1);
  309. //Replay a random seed value that is being generated using external entropy
  310. void ReplayExternalEntropyRandomEvent(uint64* seed0, uint64* seed1);
  311. //Log property enumeration step
  312. void RecordPropertyEnumEvent(BOOL returnCode, Js::PropertyId pid, Js::PropertyAttributes attributes, Js::JavascriptString* propertyName);
  313. //Replay a property enumeration step
  314. void ReplayPropertyEnumEvent(Js::ScriptContext* requestContext, BOOL* returnCode, Js::BigPropertyIndex* newIndex, const Js::DynamicObject* obj, Js::PropertyId* pid, Js::PropertyAttributes* attributes, Js::JavascriptString** propertyName);
  315. //Log symbol creation
  316. void RecordSymbolCreationEvent(Js::PropertyId pid);
  317. //Replay symbol creation
  318. void ReplaySymbolCreationEvent(Js::PropertyId* pid);
  319. //Log if a weak collection contained a value when an operation occours
  320. void RecordWeakCollectionContainsEvent(bool contains);
  321. //Replay a weak collection contained a value when an operation occours (return the truth value)
  322. bool ReplayWeakCollectionContainsEvent();
  323. //Log a value event for return from an external call
  324. NSLogEvents::EventLogEntry* RecordExternalCallEvent(Js::JavascriptFunction* func, int32 rootDepth, const Js::Arguments& args, bool checkExceptions);
  325. void RecordExternalCallEvent_Complete(Js::JavascriptFunction* efunction, NSLogEvents::EventLogEntry* evt, Js::Var result);
  326. //replay an external return event (which should be the current event)
  327. void ReplayExternalCallEvent(Js::JavascriptFunction* function, const Js::Arguments& args, Js::Var* result);
  328. NSLogEvents::EventLogEntry* RecordEnqueueTaskEvent(Js::Var taskVar);
  329. void RecordEnqueueTaskEvent_Complete(NSLogEvents::EventLogEntry* evt);
  330. void ReplayEnqueueTaskEvent(Js::ScriptContext* ctx, Js::Var taskVar);
  331. //Get the current top-level event time
  332. int64 GetCurrentTopLevelEventTime() const;
  333. //Get the event time corresponding to the first/last/k-th top-level event in the log
  334. int64 GetFirstEventTimeInLog() const;
  335. int64 GetLastEventTimeInLog() const;
  336. int64 GetKthEventTimeInLog(uint32 k) const;
  337. //Ensure the call stack is clear and counters are zeroed appropriately
  338. void ResetCallStackForTopLevelCall(int64 topLevelCallbackEventTime);
  339. //Check if we want to take a snapshot
  340. bool IsTimeForSnapshot() const;
  341. //After a snapshot we may want to discard old events so do that in here as needed
  342. void PruneLogLength();
  343. //Get/Increment the elapsed time since the last snapshot
  344. void IncrementElapsedSnapshotTime(double addtlTime);
  345. ////////////////////////////////
  346. //Snapshot and replay support
  347. //Do the snapshot extraction
  348. void DoSnapshotExtract();
  349. //Take a ready-to-run snapshot for the event if needed
  350. void DoRtrSnapIfNeeded();
  351. //Find the event time that has the snapshot we want to inflate from in order to replay to the requested target time
  352. //Return -1 if no such snapshot is available
  353. int64 FindSnapTimeForEventTime(int64 targetTime, int64* optEndSnapTime);
  354. //Find the enclosing snapshot interval for the specified event time
  355. void GetSnapShotBoundInterval(int64 targetTime, int64* snapIntervalStart, int64* snapIntervalEnd) const;
  356. //Find the snapshot start time for the previous interval return -1 if no such time exists
  357. int64 GetPreviousSnapshotInterval(int64 currentSnapTime) const;
  358. //Do the inflation of the snapshot that is at the given event time
  359. void DoSnapshotInflate(int64 etime);
  360. //Run execute top level event calls until the given time is reached
  361. void ReplayRootEventsToTime(int64 eventTime);
  362. //For a single root level event -- snapshot, yield point, or ActionEvent
  363. void ReplaySingleRootEntry();
  364. //When we have an externalFunction (or promise register) we exit script context and need to play until the event time counts up to (and including) the given eventTime
  365. void ReplayActionEventSequenceThroughTime(int64 eventTime);
  366. //Replay the enter/exit and any iteration need to discharge all the effects of a single ActionEvent
  367. void ReplaySingleActionEventEntry();
  368. ////////////////////////////////
  369. //Host API record & replay support
  370. //Return true if this is a propertyRecord reference
  371. bool IsPropertyRecordRef(void* ref) const;
  372. //Get the current time from the hi res timer
  373. double GetCurrentWallTime();
  374. //Get the most recently assigned event time value
  375. int64 GetLastEventTime() const;
  376. NSLogEvents::EventLogEntry* RecordJsRTCreateScriptContext(TTDJsRTActionResultAutoRecorder& actionPopper);
  377. void RecordJsRTCreateScriptContextResult(NSLogEvents::EventLogEntry* evt, Js::ScriptContext* newCtx);
  378. void RecordJsRTSetCurrentContext(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var globalObject);
  379. #if !INT32VAR
  380. void RecordJsRTCreateInteger(TTDJsRTActionResultAutoRecorder& actionPopper, int value);
  381. #endif
  382. //Record creation operations
  383. void RecordJsRTCreateNumber(TTDJsRTActionResultAutoRecorder& actionPopper, double value);
  384. void RecordJsRTCreateBoolean(TTDJsRTActionResultAutoRecorder& actionPopper, bool value);
  385. void RecordJsRTCreateString(TTDJsRTActionResultAutoRecorder& actionPopper, const char16* stringValue, size_t stringLength);
  386. void RecordJsRTCreateSymbol(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var);
  387. //Record error creation
  388. void RecordJsRTCreateError(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var msg);
  389. void RecordJsRTCreateRangeError(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var vmsg);
  390. void RecordJsRTCreateReferenceError(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var msg);
  391. void RecordJsRTCreateSyntaxError(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var msg);
  392. void RecordJsRTCreateTypeError(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var msg);
  393. void RecordJsRTCreateURIError(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var msg);
  394. //Record conversions
  395. void RecordJsRTVarToNumberConversion(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var);
  396. void RecordJsRTVarToBooleanConversion(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var);
  397. void RecordJsRTVarToStringConversion(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var);
  398. void RecordJsRTVarToObjectConversion(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var);
  399. //Record lifetime management events
  400. void RecordJsRTAddRootRef(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var);
  401. void RecordJsRTAddWeakRootRef(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var);
  402. void RecordJsRTEventLoopYieldPoint();
  403. //Record object allocate operations
  404. void RecordJsRTAllocateBasicObject(TTDJsRTActionResultAutoRecorder& actionPopper);
  405. void RecordJsRTAllocateExternalObject(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var prototype);
  406. void RecordJsRTAllocateBasicArray(TTDJsRTActionResultAutoRecorder& actionPopper, uint32 length);
  407. void RecordJsRTAllocateArrayBuffer(TTDJsRTActionResultAutoRecorder& actionPopper, uint32 size);
  408. void RecordJsRTAllocateExternalArrayBuffer(TTDJsRTActionResultAutoRecorder& actionPopper, byte* buff, uint32 size);
  409. void RecordJsRTAllocateFunction(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var optMetadata);
  410. //Record GetAndClearException
  411. void RecordJsRTHostExitProcess(TTDJsRTActionResultAutoRecorder& actionPopper, int32 exitCode);
  412. void RecordJsRTGetAndClearExceptionWithMetadata(TTDJsRTActionResultAutoRecorder& actionPopper);
  413. void RecordJsRTGetAndClearException(TTDJsRTActionResultAutoRecorder& actionPopper);
  414. void RecordJsRTSetException(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var, bool propagateToDebugger);
  415. //Record query operations
  416. void RecordJsRTHasProperty(TTDJsRTActionResultAutoRecorder& actionPopper, const Js::PropertyRecord* pRecord, Js::Var var);
  417. void RecordJsRTHasOwnProperty(TTDJsRTActionResultAutoRecorder& actionPopper, const Js::PropertyRecord* pRecord, Js::Var var);
  418. void RecordJsRTInstanceOf(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var object, Js::Var constructor);
  419. void RecordJsRTEquals(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var1, Js::Var var2, bool doStrict);
  420. void RecordJsRTLessThan(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var1, Js::Var var2, bool allowsEqual);
  421. //Record getters with native results
  422. void RecordJsRTGetPropertyIdFromSymbol(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var sym);
  423. //Record Object Getters
  424. void RecordJsRTGetPrototype(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var);
  425. void RecordJsRTGetProperty(TTDJsRTActionResultAutoRecorder& actionPopper, const Js::PropertyRecord* pRecord, Js::Var var);
  426. void RecordJsRTGetIndex(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var index, Js::Var var);
  427. void RecordJsRTGetOwnPropertyInfo(TTDJsRTActionResultAutoRecorder& actionPopper, const Js::PropertyRecord* pRecord, Js::Var var);
  428. void RecordJsRTGetOwnPropertyNamesInfo(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var);
  429. void RecordJsRTGetOwnPropertySymbolsInfo(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var);
  430. //Record Object Setters
  431. void RecordJsRTDefineProperty(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var, const Js::PropertyRecord* pRecord, Js::Var propertyDescriptor);
  432. void RecordJsRTDeleteProperty(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var, const Js::PropertyRecord* pRecord, bool useStrictRules);
  433. void RecordJsRTSetPrototype(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var, Js::Var proto);
  434. void RecordJsRTSetProperty(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var, const Js::PropertyRecord* pRecord, Js::Var val, bool useStrictRules);
  435. void RecordJsRTSetIndex(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var, Js::Var index, Js::Var val);
  436. //Record a get info from a typed array
  437. void RecordJsRTGetTypedArrayInfo(Js::Var var, Js::Var result);
  438. void RecordJsRTGetDataViewInfo(Js::Var var, Js::Var result);
  439. //Record various raw byte* from ArrayBuffer manipulations
  440. void RecordJsRTRawBufferCopySync(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var dst, uint32 dstIndex, Js::Var src, uint32 srcIndex, uint32 length);
  441. void RecordJsRTRawBufferModifySync(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var dst, uint32 index, uint32 count);
  442. void RecordJsRTRawBufferAsyncModificationRegister(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var dst, uint32 index);
  443. void RecordJsRTRawBufferAsyncModifyComplete(TTDJsRTActionResultAutoRecorder& actionPopper, TTDPendingAsyncBufferModification& pendingAsyncInfo, byte* finalModPos);
  444. //Record a constructor call from JsRT
  445. void RecordJsRTConstructCall(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var funcVar, uint32 argCount, Js::Var* args);
  446. //Record code parse
  447. NSLogEvents::EventLogEntry* RecordJsRTCodeParse(TTDJsRTActionResultAutoRecorder& actionPopper, LoadScriptFlag loadFlag, bool isUft8, const byte* script, uint32 scriptByteLength, uint64 sourceContextId, const char16* sourceUri);
  448. //Record callback of an existing function
  449. NSLogEvents::EventLogEntry* RecordJsRTCallFunction(TTDJsRTActionResultAutoRecorder& actionPopper, int32 rootDepth, Js::Var funcVar, uint32 argCount, Js::Var* args);
  450. ////////////////////////////////
  451. //Emit code and support
  452. void InnerLoopEmitLog(const TTDebuggerSourceLocation& writeLocation, const char* emitUri, size_t emitUriLength);
  453. bool CanWriteInnerLoopTrace() const;
  454. void SetAutoTraceEnabled(bool enabled);
  455. bool GetAutoTraceEnabled() const;
  456. void EmitLog(const char* emitUri, size_t emitUriLength, NSLogEvents::EventLogEntry* optInnerLoopEvent = nullptr);
  457. void ParseLogInto(TTDataIOInfo& iofp, const char* parseUri, size_t parseUriLength);
  458. };
  459. //In cases where we may have many exits where we need to pop something we pushed earlier (i.e. exceptions)
  460. class TTModeStackAutoPopper
  461. {
  462. private:
  463. EventLog* m_log;
  464. TTDMode m_popMode; //the mode to pop or invalid if we don't need to pop anything
  465. public:
  466. TTModeStackAutoPopper(EventLog* log)
  467. : m_log(log), m_popMode(TTDMode::Invalid)
  468. {
  469. ;
  470. }
  471. void PushModeAndSetToAutoPop(TTDMode mode)
  472. {
  473. this->m_log->PushMode(mode);
  474. this->m_popMode = mode;
  475. }
  476. ~TTModeStackAutoPopper()
  477. {
  478. if(this->m_popMode != TTDMode::Invalid)
  479. {
  480. this->m_log->PopMode(this->m_popMode);
  481. }
  482. }
  483. };
  484. }
  485. #endif