2
0

TTEvents.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  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_EVENT_BASE_SIZE sizeof(TTD::NSLogEvents::EventLogEntry)
  8. #define TTD_EVENT_PLUS_DATA_SIZE_DIRECT(S) TTD_WORD_ALIGN_ALLOC_SIZE(TTD_EVENT_BASE_SIZE + S)
  9. #define TTD_EVENT_PLUS_DATA_SIZE(T) TTD_WORD_ALIGN_ALLOC_SIZE(TTD_EVENT_BASE_SIZE + sizeof(T))
  10. //The limit on event times used as the default value
  11. #define TTD_EVENT_MAXTIME INT64_MAX
  12. //Values copied from ChakraCommon.h
  13. #define TTD_REPLAY_JS_INVALID_REFERENCE nullptr
  14. #define TTD_REPLAY_JsErrorInvalidArgument 65537
  15. #define TTD_REPLAY_JsErrorArgumentNotObject 65548
  16. #define TTD_REPLAY_JsErrorCategoryScript 196609
  17. #define TTD_REPLAY_JsErrorScriptTerminated 196611
  18. #define TTD_REPLAY_VALIDATE_JSREF(p) \
  19. if (p == TTD_REPLAY_JS_INVALID_REFERENCE) \
  20. { \
  21. return; \
  22. }
  23. #define TTD_REPLAY_MARSHAL_OBJECT(p, scriptContext) \
  24. Js::RecyclableObject* __obj = Js::RecyclableObject::FromVar(p); \
  25. if (__obj->GetScriptContext() != scriptContext) \
  26. { \
  27. p = Js::CrossSite::MarshalVar(scriptContext, __obj); \
  28. }
  29. #define TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(p, scriptContext) \
  30. TTD_REPLAY_VALIDATE_JSREF(p); \
  31. if (Js::RecyclableObject::Is(p)) \
  32. { \
  33. TTD_REPLAY_MARSHAL_OBJECT(p, scriptContext) \
  34. }
  35. #define TTD_REPLAY_VALIDATE_INCOMING_OBJECT(p, scriptContext) \
  36. { \
  37. TTD_REPLAY_VALIDATE_JSREF(p); \
  38. if(!Js::JavascriptOperators::IsObject(p)) \
  39. { \
  40. return; \
  41. } \
  42. TTD_REPLAY_MARSHAL_OBJECT(p, scriptContext) \
  43. }
  44. #define TTD_REPLAY_VALIDATE_INCOMING_OBJECT_OR_NULL(p, scriptContext) \
  45. { \
  46. TTD_REPLAY_VALIDATE_JSREF(p); \
  47. if(!Js::JavascriptOperators::IsObjectOrNull(p)) \
  48. { \
  49. return; \
  50. } \
  51. TTD_REPLAY_MARSHAL_OBJECT(p, scriptContext) \
  52. }
  53. #define TTD_REPLAY_VALIDATE_INCOMING_FUNCTION(p, scriptContext) \
  54. { \
  55. TTD_REPLAY_VALIDATE_JSREF(p); \
  56. if(!Js::JavascriptFunction::Is(p)) \
  57. { \
  58. return; \
  59. } \
  60. TTD_REPLAY_MARSHAL_OBJECT(p, scriptContext) \
  61. }
  62. #define TTD_REPLAY_ACTIVE_CONTEXT(executeContext) \
  63. Js::ScriptContext* ctx = executeContext->GetActiveScriptContext(); \
  64. TTDAssert(ctx != nullptr, "This should be non-null!!!");
  65. namespace TTD
  66. {
  67. namespace NSLogEvents
  68. {
  69. //An enumeration of the event kinds in the system
  70. enum class EventKind : uint32
  71. {
  72. Invalid = 0x0,
  73. //Tags for internal engine events
  74. SnapshotTag,
  75. EventLoopYieldPointTag,
  76. TopLevelCodeTag,
  77. TelemetryLogTag,
  78. DoubleTag,
  79. StringTag,
  80. RandomSeedTag,
  81. PropertyEnumTag,
  82. SymbolCreationTag,
  83. WeakCollectionContainsTag,
  84. ExternalCbRegisterCall,
  85. ExternalCallTag,
  86. ExplicitLogWriteTag,
  87. TTDInnerLoopLogWriteTag,
  88. TTDFetchAutoTraceStatusTag,
  89. //JsRTActionTag is a marker for where the JsRT actions begin
  90. JsRTActionTag,
  91. CreateScriptContextActionTag,
  92. SetActiveScriptContextActionTag,
  93. #if !INT32VAR
  94. CreateIntegerActionTag,
  95. #endif
  96. CreateNumberActionTag,
  97. CreateBooleanActionTag,
  98. CreateStringActionTag,
  99. CreateSymbolActionTag,
  100. CreateErrorActionTag,
  101. CreateRangeErrorActionTag,
  102. CreateReferenceErrorActionTag,
  103. CreateSyntaxErrorActionTag,
  104. CreateTypeErrorActionTag,
  105. CreateURIErrorActionTag,
  106. VarConvertToNumberActionTag,
  107. VarConvertToBooleanActionTag,
  108. VarConvertToStringActionTag,
  109. VarConvertToObjectActionTag,
  110. AddRootRefActionTag,
  111. AddWeakRootRefActionTag,
  112. //No remove weak root ref, this is handled when syncing at snapshot points
  113. AllocateObjectActionTag,
  114. AllocateExternalObjectActionTag,
  115. AllocateArrayActionTag,
  116. AllocateArrayBufferActionTag,
  117. AllocateExternalArrayBufferActionTag,
  118. AllocateFunctionActionTag,
  119. HostExitProcessTag,
  120. GetAndClearExceptionWithMetadataActionTag,
  121. GetAndClearExceptionActionTag,
  122. SetExceptionActionTag,
  123. HasPropertyActionTag,
  124. InstanceOfActionTag,
  125. EqualsActionTag,
  126. LessThanActionTag,
  127. GetPropertyIdFromSymbolTag,
  128. GetPrototypeActionTag,
  129. GetPropertyActionTag,
  130. GetIndexActionTag,
  131. GetOwnPropertyInfoActionTag,
  132. GetOwnPropertyNamesInfoActionTag,
  133. GetOwnPropertySymbolsInfoActionTag,
  134. DefinePropertyActionTag,
  135. DeletePropertyActionTag,
  136. SetPrototypeActionTag,
  137. SetPropertyActionTag,
  138. SetIndexActionTag,
  139. GetTypedArrayInfoActionTag,
  140. RawBufferCopySync,
  141. RawBufferModifySync,
  142. RawBufferAsyncModificationRegister,
  143. RawBufferAsyncModifyComplete,
  144. ConstructCallActionTag,
  145. CodeParseActionTag,
  146. CallExistingFunctionActionTag,
  147. HasOwnPropertyActionTag,
  148. GetDataViewInfoActionTag,
  149. Count
  150. };
  151. //Inflate an argument variable for an action during replay and record passing an value to the host
  152. void PassVarToHostInReplay(ThreadContextTTD* executeContext, TTDVar origVar, Js::Var replayVar);
  153. Js::Var InflateVarInReplay(ThreadContextTTD* executeContext, TTDVar var);
  154. //The kind of context that the replay code should execute in
  155. enum class ContextExecuteKind
  156. {
  157. None,
  158. GlobalAPIWrapper,
  159. ContextAPIWrapper,
  160. ContextAPINoScriptWrapper
  161. };
  162. typedef void(*fPtr_EventLogActionEntryInfoExecute)(const EventLogEntry* evt, ThreadContextTTD* execCtx);
  163. typedef void(*fPtr_EventLogEntryInfoUnload)(EventLogEntry* evt, UnlinkableSlabAllocator& alloc);
  164. typedef void(*fPtr_EventLogEntryInfoEmit)(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  165. typedef void(*fPtr_EventLogEntryInfoParse)(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  166. //A struct that we use for our pseudo v-table on the EventLogEntry data
  167. struct EventLogEntryVTableEntry
  168. {
  169. ContextExecuteKind ContextKind;
  170. fPtr_EventLogActionEntryInfoExecute ExecuteFP;
  171. fPtr_EventLogEntryInfoUnload UnloadFP;
  172. fPtr_EventLogEntryInfoEmit EmitFP;
  173. fPtr_EventLogEntryInfoParse ParseFP;
  174. size_t DataSize;
  175. };
  176. //A base struct for our event log entries -- we will use the kind tags as v-table values
  177. //Data is stored in buffer memory immediately following this struct
  178. struct EventLogEntry
  179. {
  180. //The kind of the event
  181. EventKind EventKind;
  182. //The result status code
  183. int32 ResultStatus;
  184. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  185. //The event time for this event
  186. int64 EventTimeStamp;
  187. #endif
  188. };
  189. template <typename T, EventKind tag>
  190. const T* GetInlineEventDataAs(const EventLogEntry* evt)
  191. {
  192. TTDAssert(evt->EventKind == tag, "Bad tag match!");
  193. return reinterpret_cast<const T*>(((byte*)evt) + TTD_EVENT_BASE_SIZE);
  194. }
  195. template <typename T, EventKind tag>
  196. T* GetInlineEventDataAs(EventLogEntry* evt)
  197. {
  198. TTDAssert(evt->EventKind == tag, "Bad tag match!");
  199. return reinterpret_cast<T*>(((byte*)evt) + TTD_EVENT_BASE_SIZE);
  200. }
  201. template<EventKind tag>
  202. void EventLogEntry_Initialize(EventLogEntry* evt, int64 etime)
  203. {
  204. evt->EventKind = tag;
  205. evt->ResultStatus = -1;
  206. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  207. static_assert(TTD_EVENT_BASE_SIZE % 4 == 0, "This should always be word aligned.");
  208. AssertMsg(((uint64)evt) % 4 == 0, "We want this word aligned for performance so who messed it up.");
  209. evt->EventTimeStamp = etime;
  210. #endif
  211. }
  212. //Helpers for initializing, emitting and parsing the basic event data
  213. void EventLogEntry_Emit(const EventLogEntry* evt, EventLogEntryVTableEntry* evtFPVTable, FileWriter* writer, ThreadContext* threadContext, NSTokens::Separator separator);
  214. EventKind EventLogEntry_ParseHeader(bool readSeparator, FileReader* reader);
  215. void EventLogEntry_ParseRest(EventLogEntry* evt, EventLogEntryVTableEntry* evtFPVTable, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  216. bool EventFailsWithRuntimeError(const EventLogEntry* evt);
  217. bool EventDoesNotReturn(const EventLogEntry* evt);
  218. bool EventCompletesNormally(const EventLogEntry* evt);
  219. bool EventCompletesWithException(const EventLogEntry* evt);
  220. //////////////////
  221. //A struct that represents snapshot events
  222. struct SnapshotEventLogEntry
  223. {
  224. //The timestamp we should restore to
  225. int64 RestoreTimestamp;
  226. //The snapshot (we many persist this to disk and inflate back in later)
  227. SnapShot* Snap;
  228. //The logids of live contexts
  229. uint32 LiveContextCount;
  230. TTD_LOG_PTR_ID* LiveContextIdArray;
  231. //The logids of live roots (with non-zero weak references)
  232. uint32 LongLivedRefRootsCount;
  233. TTD_LOG_PTR_ID* LongLivedRefRootsIdArray;
  234. };
  235. void SnapshotEventLogEntry_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc);
  236. void SnapshotEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  237. void SnapshotEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  238. void SnapshotEventLogEntry_EnsureSnapshotDeserialized(EventLogEntry* evt, ThreadContext* threadContext);
  239. void SnapshotEventLogEntry_UnloadSnapshot(EventLogEntry* evt);
  240. //A struct that represents snapshot events
  241. struct EventLoopYieldPointEntry
  242. {
  243. //The timestamp of this yieldpoint
  244. int64 EventTimeStamp;
  245. //The wall clock time when this point is reached
  246. double EventWallTime;
  247. };
  248. void EventLoopYieldPointEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  249. void EventLoopYieldPointEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  250. //////////////////
  251. //A struct that represents a top level code load event
  252. struct CodeLoadEventLogEntry
  253. {
  254. //The code counter id for the TopLevelFunctionBodyInfo
  255. uint32 BodyCounterId;
  256. };
  257. void CodeLoadEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  258. void CodeLoadEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  259. //A struct that represents telemetry events from the user code
  260. struct TelemetryEventLogEntry
  261. {
  262. //A string that contains all of the info that is logged
  263. TTString InfoString;
  264. //Do we want to print the msg or just record it internally
  265. bool DoPrint;
  266. };
  267. void TelemetryEventLogEntry_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc);
  268. void TelemetryEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  269. void TelemetryEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  270. //////////////////
  271. //A struct that represents the generation of random seeds
  272. struct RandomSeedEventLogEntry
  273. {
  274. //The values associated with the event
  275. uint64 Seed0;
  276. uint64 Seed1;
  277. };
  278. void RandomSeedEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  279. void RandomSeedEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  280. //A struct that represents a simple event that needs a double value (e.g. date values)
  281. struct DoubleEventLogEntry
  282. {
  283. //The value associated with the event
  284. double DoubleValue;
  285. };
  286. void DoubleEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  287. void DoubleEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  288. //A struct that represents a simple event that needs a string value (e.g. date values)
  289. struct StringValueEventLogEntry
  290. {
  291. //The value associated with the event
  292. TTString StringValue;
  293. };
  294. void StringValueEventLogEntry_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc);
  295. void StringValueEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  296. void StringValueEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  297. //////////////////
  298. //A struct that represents a single enumeration step for properties on a dynamic object
  299. struct PropertyEnumStepEventLogEntry
  300. {
  301. //The return code, property id, and attributes returned
  302. BOOL ReturnCode;
  303. Js::PropertyId Pid;
  304. Js::PropertyAttributes Attributes;
  305. //Optional property name string (may need to actually use later if pid can be Constants::NoProperty)
  306. //Always set if if doing extra diagnostics otherwise only as needed
  307. TTString PropertyString;
  308. };
  309. void PropertyEnumStepEventLogEntry_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc);
  310. void PropertyEnumStepEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  311. void PropertyEnumStepEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  312. //////////////////
  313. //A struct that represents the creation of a symbol (which we need to make sure gets the correct property id)
  314. struct SymbolCreationEventLogEntry
  315. {
  316. //The property id of the created symbol
  317. Js::PropertyId Pid;
  318. };
  319. void SymbolCreationEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  320. void SymbolCreationEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  321. //////////////////
  322. //A struct that tracks if a weak key value is in a weak collection
  323. struct WeakCollectionContainsEventLogEntry
  324. {
  325. bool ContainsValue;
  326. };
  327. void WeakCollectionContainsEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  328. void WeakCollectionContainsEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  329. //////////////////
  330. //A struct for logging the invocation of the host callback registration function
  331. struct ExternalCbRegisterCallEventLogEntry
  332. {
  333. //the number of arguments and the argument array -- function is always argument[0]
  334. TTDVar CallbackFunction;
  335. //The last event time that is nested in this external call
  336. int64 LastNestedEventTime;
  337. };
  338. int64 ExternalCbRegisterCallEventLogEntry_GetLastNestedEventTime(const EventLogEntry* evt);
  339. void ExternalCbRegisterCallEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  340. void ExternalCbRegisterCallEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  341. //////////////////
  342. //A struct for logging calls from Chakra to an external function (e.g., record start of external execution and later any argument information)
  343. struct ExternalCallEventLogEntry
  344. {
  345. //The root nesting depth
  346. int32 RootNestingDepth;
  347. //the number of arguments and the argument array -- function is always argument[0]
  348. uint32 ArgCount;
  349. TTDVar* ArgArray;
  350. //the value of new.target if present
  351. TTDVar NewTarget;
  352. //The return value of the external call
  353. TTDVar ReturnValue;
  354. //The last event time that is nested in this external call
  355. int64 LastNestedEventTime;
  356. //if we need to check exception information
  357. bool CheckExceptionStatus;
  358. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  359. //the function name for the function that is invoked
  360. TTString FunctionName;
  361. #endif
  362. };
  363. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  364. void ExternalCallEventLogEntry_ProcessDiagInfoPre(EventLogEntry* evt, Js::JavascriptFunction* function, UnlinkableSlabAllocator& alloc);
  365. #endif
  366. int64 ExternalCallEventLogEntry_GetLastNestedEventTime(const EventLogEntry* evt);
  367. void ExternalCallEventLogEntry_ProcessArgs(EventLogEntry* evt, int32 rootDepth, Js::JavascriptFunction* function, const Js::Arguments& args, bool checkExceptions, UnlinkableSlabAllocator& alloc);
  368. void ExternalCallEventLogEntry_ProcessReturn(EventLogEntry* evt, Js::Var res, int64 lastNestedEvent);
  369. void ExternalCallEventLogEntry_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc);
  370. void ExternalCallEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  371. void ExternalCallEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  372. //////////////////
  373. //A struct for when we explicitly write a log entry -- currently empty placeholder
  374. struct ExplicitLogWriteEventLogEntry
  375. {
  376. ;
  377. };
  378. void ExplicitLogWriteEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  379. void ExplicitLogWriteEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  380. //A struct for when we explicitly write a log entry with innerloop ttd end-breakpoint
  381. struct TTDInnerLoopLogWriteEventLogEntry
  382. {
  383. //copies the data for a TTDebuggerSourceLocation that we can set when we start the replay session (and track the end of the execution)
  384. TTD_LOG_PTR_ID SourceScriptLogId;
  385. int64 EventTime; //-1 indicates an INVALID location
  386. int64 FunctionTime; //-1 indicates any ftime is OK
  387. int64 LoopTime; //-1 indicates any ltime is OK
  388. uint32 TopLevelBodyId;
  389. uint32 FunctionLine; //line containing function starts at
  390. uint32 FunctionColumn; //column containing function starts at
  391. uint32 Line; //line in source
  392. uint32 Column; //column in source
  393. };
  394. void TTDInnerLoopLogWriteEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  395. void TTDInnerLoopLogWriteEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  396. //A struct for recording the result of a read of the AutoTraceStatus
  397. struct TTDFetchAutoTraceStatusEventLogEntry
  398. {
  399. bool IsEnabled;
  400. };
  401. void TTDFetchAutoTraceStatusEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext);
  402. void TTDFetchAutoTraceStatusEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc);
  403. }
  404. }
  405. #endif