TTActionEvents.cpp 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304
  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. #include "Library/JavascriptExceptionMetadata.h"
  7. #if ENABLE_TTD
  8. namespace TTD
  9. {
  10. namespace NSLogEvents
  11. {
  12. bool IsJsRTActionRootCall(const EventLogEntry* evt)
  13. {
  14. if(evt->EventKind != NSLogEvents::EventKind::CallExistingFunctionActionTag)
  15. {
  16. return false;
  17. }
  18. const JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  19. return cfAction->CallbackDepth == 0;
  20. }
  21. int64 AccessTimeInRootCallOrSnapshot(const EventLogEntry* evt, bool& isSnap, bool& isRoot, bool& hasRtrSnap)
  22. {
  23. isSnap = false;
  24. isRoot = false;
  25. hasRtrSnap = false;
  26. if(evt->EventKind == NSLogEvents::EventKind::SnapshotTag)
  27. {
  28. const NSLogEvents::SnapshotEventLogEntry* snapEvent = NSLogEvents::GetInlineEventDataAs<NSLogEvents::SnapshotEventLogEntry, NSLogEvents::EventKind::SnapshotTag>(evt);
  29. isSnap = true;
  30. return snapEvent->RestoreTimestamp;
  31. }
  32. else if(NSLogEvents::IsJsRTActionRootCall(evt))
  33. {
  34. const NSLogEvents::JsRTCallFunctionAction* rootEntry = NSLogEvents::GetInlineEventDataAs<NSLogEvents::JsRTCallFunctionAction, NSLogEvents::EventKind::CallExistingFunctionActionTag>(evt);
  35. isRoot = true;
  36. hasRtrSnap = (rootEntry->AdditionalReplayInfo != nullptr && rootEntry->AdditionalReplayInfo->RtRSnap != nullptr);
  37. return rootEntry->CallEventTime;
  38. }
  39. else
  40. {
  41. return -1;
  42. }
  43. }
  44. bool TryGetTimeFromRootCallOrSnapshot(const EventLogEntry* evt, int64& res)
  45. {
  46. bool isSnap = false;
  47. bool isRoot = false;
  48. bool hasRtrSnap = false;
  49. res = AccessTimeInRootCallOrSnapshot(evt, isSnap, isRoot, hasRtrSnap);
  50. return (isSnap | isRoot);
  51. }
  52. int64 GetTimeFromRootCallOrSnapshot(const EventLogEntry* evt)
  53. {
  54. int64 res = -1;
  55. bool success = TryGetTimeFromRootCallOrSnapshot(evt, res);
  56. TTDAssert(success, "Not a root or snapshot!!!");
  57. return res;
  58. }
  59. void CreateScriptContext_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  60. {
  61. const JsRTCreateScriptContextAction* cAction = GetInlineEventDataAs<JsRTCreateScriptContextAction, EventKind::CreateScriptContextActionTag>(evt);
  62. Js::ScriptContext* resCtx = nullptr;
  63. executeContext->TTDExternalObjectFunctions.pfCreateJsRTContextCallback(executeContext->GetRuntimeHandle(), &resCtx);
  64. TTDAssert(resCtx != nullptr, "Create failed");
  65. executeContext->AddRootRef_Replay(cAction->GlobalObject, resCtx->GetGlobalObject());
  66. resCtx->ScriptContextLogTag = cAction->GlobalObject;
  67. executeContext->AddRootRef_Replay(cAction->KnownObjects->UndefinedObject, resCtx->GetLibrary()->GetUndefined());
  68. executeContext->AddRootRef_Replay(cAction->KnownObjects->NullObject, resCtx->GetLibrary()->GetNull());
  69. executeContext->AddRootRef_Replay(cAction->KnownObjects->TrueObject, resCtx->GetLibrary()->GetTrue());
  70. executeContext->AddRootRef_Replay(cAction->KnownObjects->FalseObject, resCtx->GetLibrary()->GetFalse());
  71. }
  72. void CreateScriptContext_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc)
  73. {
  74. JsRTCreateScriptContextAction* cAction = GetInlineEventDataAs<JsRTCreateScriptContextAction, EventKind::CreateScriptContextActionTag>(evt);
  75. alloc.UnlinkAllocation(cAction->KnownObjects);
  76. }
  77. void CreateScriptContext_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
  78. {
  79. const JsRTCreateScriptContextAction* cAction = GetInlineEventDataAs<JsRTCreateScriptContextAction, EventKind::CreateScriptContextActionTag>(evt);
  80. writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
  81. writer->WriteLogTag(NSTokens::Key::logTag, cAction->GlobalObject, NSTokens::Separator::NoSeparator);
  82. writer->WriteLogTag(NSTokens::Key::logTag, cAction->KnownObjects->UndefinedObject, NSTokens::Separator::CommaSeparator);
  83. writer->WriteLogTag(NSTokens::Key::logTag, cAction->KnownObjects->NullObject, NSTokens::Separator::CommaSeparator);
  84. writer->WriteLogTag(NSTokens::Key::logTag, cAction->KnownObjects->TrueObject, NSTokens::Separator::CommaSeparator);
  85. writer->WriteLogTag(NSTokens::Key::logTag, cAction->KnownObjects->FalseObject, NSTokens::Separator::CommaSeparator);
  86. writer->WriteSequenceEnd();
  87. }
  88. void CreateScriptContext_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
  89. {
  90. JsRTCreateScriptContextAction* cAction = GetInlineEventDataAs<JsRTCreateScriptContextAction, EventKind::CreateScriptContextActionTag>(evt);
  91. cAction->KnownObjects = alloc.SlabAllocateStruct<JsRTCreateScriptContextAction_KnownObjects>();
  92. reader->ReadSequenceStart_WDefaultKey(true);
  93. cAction->GlobalObject = reader->ReadLogTag(NSTokens::Key::logTag, false);
  94. cAction->KnownObjects->UndefinedObject = reader->ReadLogTag(NSTokens::Key::logTag, true);
  95. cAction->KnownObjects->NullObject = reader->ReadLogTag(NSTokens::Key::logTag, true);
  96. cAction->KnownObjects->TrueObject = reader->ReadLogTag(NSTokens::Key::logTag, true);
  97. cAction->KnownObjects->FalseObject = reader->ReadLogTag(NSTokens::Key::logTag, true);
  98. reader->ReadSequenceEnd();
  99. }
  100. void SetActiveScriptContext_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  101. {
  102. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::SetActiveScriptContextActionTag>(evt);
  103. Js::Var gvar = InflateVarInReplay(executeContext, GetVarItem_0(action));
  104. TTDAssert(gvar == nullptr || Js::GlobalObject::Is(gvar), "Something is not right here!");
  105. Js::GlobalObject* gobj = static_cast<Js::GlobalObject*>(gvar);
  106. Js::ScriptContext* newCtx = (gobj != nullptr) ? gobj->GetScriptContext() : nullptr;
  107. executeContext->TTDExternalObjectFunctions.pfSetActiveJsRTContext(executeContext->GetRuntimeHandle(), newCtx);
  108. }
  109. #if !INT32VAR
  110. void CreateInt_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  111. {
  112. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  113. const JsRTIntegralArgumentAction* action = GetInlineEventDataAs<JsRTIntegralArgumentAction, EventKind::CreateIntegerActionTag>(evt);
  114. Js::Var res = Js::JavascriptNumber::ToVar((int32)action->Scalar, ctx);
  115. JsRTActionHandleResultForReplay<JsRTIntegralArgumentAction, EventKind::CreateIntegerActionTag>(executeContext, evt, res);
  116. }
  117. #endif
  118. void CreateNumber_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  119. {
  120. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  121. const JsRTDoubleArgumentAction* action = GetInlineEventDataAs<JsRTDoubleArgumentAction, EventKind::CreateNumberActionTag>(evt);
  122. Js::Var res = Js::JavascriptNumber::ToVarNoCheck(action->DoubleValue, ctx);
  123. JsRTActionHandleResultForReplay<JsRTDoubleArgumentAction, EventKind::CreateNumberActionTag>(executeContext, evt, res);
  124. }
  125. void CreateBoolean_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  126. {
  127. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  128. const JsRTIntegralArgumentAction* action = GetInlineEventDataAs<JsRTIntegralArgumentAction, EventKind::CreateBooleanActionTag>(evt);
  129. Js::Var res = action->Scalar ? ctx->GetLibrary()->GetTrue() : ctx->GetLibrary()->GetFalse();
  130. JsRTActionHandleResultForReplay<JsRTIntegralArgumentAction, EventKind::CreateBooleanActionTag>(executeContext, evt, res);
  131. }
  132. void CreateString_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  133. {
  134. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  135. const JsRTStringArgumentAction* action = GetInlineEventDataAs<JsRTStringArgumentAction, EventKind::CreateStringActionTag>(evt);
  136. Js::Var res = Js::JavascriptString::NewCopyBuffer(action->StringValue.Contents, action->StringValue.Length, ctx);
  137. JsRTActionHandleResultForReplay<JsRTStringArgumentAction, EventKind::CreateStringActionTag>(executeContext, evt, res);
  138. }
  139. void CreateSymbol_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  140. {
  141. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  142. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::CreateSymbolActionTag>(evt);
  143. Js::Var description = InflateVarInReplay(executeContext, GetVarItem_0(action));
  144. Js::JavascriptString* descriptionString;
  145. if(description != nullptr)
  146. {
  147. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(description, ctx);
  148. descriptionString = Js::JavascriptConversion::ToString(description, ctx);
  149. }
  150. else
  151. {
  152. descriptionString = ctx->GetLibrary()->GetEmptyString();
  153. }
  154. Js::Var res = ctx->GetLibrary()->CreateSymbol(descriptionString);
  155. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::CreateSymbolActionTag>(executeContext, evt, res);
  156. }
  157. void Execute_CreateErrorHelper(const JsRTSingleVarArgumentAction* errorData, ThreadContextTTD* executeContext, Js::ScriptContext* ctx, EventKind eventKind, Js::Var* res)
  158. {
  159. Js::Var message = InflateVarInReplay(executeContext, GetVarItem_0(errorData));
  160. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(message, ctx);
  161. *res = nullptr;
  162. switch(eventKind)
  163. {
  164. case EventKind::CreateErrorActionTag:
  165. *res = ctx->GetLibrary()->CreateError();
  166. break;
  167. case EventKind::CreateRangeErrorActionTag:
  168. *res = ctx->GetLibrary()->CreateRangeError();
  169. break;
  170. case EventKind::CreateReferenceErrorActionTag:
  171. *res = ctx->GetLibrary()->CreateReferenceError();
  172. break;
  173. case EventKind::CreateSyntaxErrorActionTag:
  174. *res = ctx->GetLibrary()->CreateSyntaxError();
  175. break;
  176. case EventKind::CreateTypeErrorActionTag:
  177. *res = ctx->GetLibrary()->CreateTypeError();
  178. break;
  179. case EventKind::CreateURIErrorActionTag:
  180. *res = ctx->GetLibrary()->CreateURIError();
  181. break;
  182. default:
  183. TTDAssert(false, "Missing error kind!!!");
  184. }
  185. Js::JavascriptOperators::OP_SetProperty(*res, Js::PropertyIds::message, message, ctx);
  186. }
  187. void VarConvertToNumber_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  188. {
  189. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  190. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::VarConvertToNumberActionTag>(evt);
  191. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  192. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(var, ctx);
  193. Js::Var res = Js::JavascriptOperators::ToNumber(var, ctx);
  194. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::VarConvertToNumberActionTag>(executeContext, evt, res);
  195. }
  196. void VarConvertToBoolean_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  197. {
  198. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  199. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::VarConvertToBooleanActionTag>(evt);
  200. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  201. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(var, ctx);
  202. Js::JavascriptConversion::ToBool(var, ctx) ? ctx->GetLibrary()->GetTrue() : ctx->GetLibrary()->GetFalse();
  203. //It is either true or false which we always track so no need to do result mapping
  204. }
  205. void VarConvertToString_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  206. {
  207. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  208. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::VarConvertToStringActionTag>(evt);
  209. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  210. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(var, ctx);
  211. Js::Var res = Js::JavascriptConversion::ToString(var, ctx);
  212. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::VarConvertToStringActionTag>(executeContext, evt, res);
  213. }
  214. void VarConvertToObject_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  215. {
  216. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  217. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::VarConvertToObjectActionTag>(evt);
  218. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  219. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(var, ctx);
  220. Js::Var res = Js::JavascriptOperators::ToObject(var, ctx);
  221. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  222. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::VarConvertToObjectActionTag>(executeContext, evt, res);
  223. }
  224. void AddRootRef_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  225. {
  226. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::AddRootRefActionTag>(evt);
  227. TTD_LOG_PTR_ID origId = reinterpret_cast<TTD_LOG_PTR_ID>(GetVarItem_0(action));
  228. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  229. Js::RecyclableObject* newObj = Js::RecyclableObject::FromVar(var);
  230. executeContext->AddRootRef_Replay(origId, newObj);
  231. }
  232. void AddWeakRootRef_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  233. {
  234. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::AddWeakRootRefActionTag>(evt);
  235. TTD_LOG_PTR_ID origId = reinterpret_cast<TTD_LOG_PTR_ID>(GetVarItem_0(action));
  236. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  237. Js::RecyclableObject* newObj = Js::RecyclableObject::FromVar(var);
  238. executeContext->AddRootRef_Replay(origId, newObj);
  239. }
  240. void AllocateObject_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  241. {
  242. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  243. Js::RecyclableObject* res = ctx->GetLibrary()->CreateObject();
  244. JsRTActionHandleResultForReplay<JsRTResultOnlyAction, EventKind::AllocateObjectActionTag>(executeContext, evt, res);
  245. }
  246. void AllocateExternalObject_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  247. {
  248. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  249. Js::Var res = nullptr;
  250. executeContext->TTDExternalObjectFunctions.pfCreateExternalObject(ctx, &res);
  251. JsRTActionHandleResultForReplay<JsRTResultOnlyAction, EventKind::AllocateExternalObjectActionTag>(executeContext, evt, res);
  252. }
  253. void AllocateArrayAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  254. {
  255. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  256. const JsRTIntegralArgumentAction* action = GetInlineEventDataAs<JsRTIntegralArgumentAction, EventKind::AllocateArrayActionTag>(evt);
  257. Js::Var res = ctx->GetLibrary()->CreateArray((uint32)action->Scalar);
  258. JsRTActionHandleResultForReplay<JsRTIntegralArgumentAction, EventKind::AllocateArrayActionTag>(executeContext, evt, res);
  259. }
  260. void AllocateArrayBufferAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  261. {
  262. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  263. const JsRTIntegralArgumentAction* action = GetInlineEventDataAs<JsRTIntegralArgumentAction, EventKind::AllocateArrayBufferActionTag>(evt);
  264. Js::ArrayBuffer* abuff = ctx->GetLibrary()->CreateArrayBuffer((uint32)action->Scalar);
  265. TTDAssert(abuff->GetByteLength() == (uint32)action->Scalar, "Something is wrong with our sizes.");
  266. JsRTActionHandleResultForReplay<JsRTIntegralArgumentAction, EventKind::AllocateArrayBufferActionTag>(executeContext, evt, (Js::Var)abuff);
  267. }
  268. void AllocateExternalArrayBufferAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  269. {
  270. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  271. const JsRTByteBufferAction* action = GetInlineEventDataAs<JsRTByteBufferAction, EventKind::AllocateExternalArrayBufferActionTag>(evt);
  272. Js::ArrayBuffer* abuff = ctx->GetLibrary()->CreateArrayBuffer(action->Length);
  273. TTDAssert(abuff->GetByteLength() == action->Length, "Something is wrong with our sizes.");
  274. if(action->Length != 0)
  275. {
  276. js_memcpy_s(abuff->GetBuffer(), abuff->GetByteLength(), action->Buffer, action->Length);
  277. }
  278. JsRTActionHandleResultForReplay<JsRTByteBufferAction, EventKind::AllocateExternalArrayBufferActionTag>(executeContext, evt, (Js::Var)abuff);
  279. }
  280. void AllocateFunctionAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  281. {
  282. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  283. const JsRTSingleVarScalarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarScalarArgumentAction, EventKind::AllocateFunctionActionTag>(evt);
  284. Js::Var res = nullptr;
  285. if(!GetScalarItem_0(action))
  286. {
  287. res = ctx->GetLibrary()->CreateStdCallExternalFunction(&Js::JavascriptExternalFunction::TTDReplayDummyExternalMethod, 0, nullptr);
  288. }
  289. else
  290. {
  291. Js::Var nameVar = InflateVarInReplay(executeContext, GetVarItem_0(action));
  292. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(nameVar, ctx);
  293. Js::JavascriptString* name = nullptr;
  294. if(nameVar != nullptr)
  295. {
  296. name = Js::JavascriptConversion::ToString(nameVar, ctx);
  297. }
  298. else
  299. {
  300. name = ctx->GetLibrary()->GetEmptyString();
  301. }
  302. res = ctx->GetLibrary()->CreateStdCallExternalFunction(&Js::JavascriptExternalFunction::TTDReplayDummyExternalMethod, name, nullptr);
  303. }
  304. JsRTActionHandleResultForReplay<JsRTSingleVarScalarArgumentAction, EventKind::AllocateFunctionActionTag>(executeContext, evt, res);
  305. }
  306. void HostProcessExitAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  307. {
  308. throw TTDebuggerAbortException::CreateAbortEndOfLog(_u("End of log reached with Host Process Exit -- returning to top-level."));
  309. }
  310. void GetAndClearExceptionWithMetadataAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  311. {
  312. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  313. HRESULT hr = S_OK;
  314. Js::JavascriptExceptionObject *recordedException = nullptr;
  315. BEGIN_TRANSLATE_OOM_TO_HRESULT
  316. if (ctx->HasRecordedException())
  317. {
  318. recordedException = ctx->GetAndClearRecordedException();
  319. }
  320. END_TRANSLATE_OOM_TO_HRESULT(hr)
  321. Js::Var exception = nullptr;
  322. if (recordedException != nullptr)
  323. {
  324. exception = recordedException->GetThrownObject(nullptr);
  325. }
  326. if (exception != nullptr)
  327. {
  328. Js::ScriptContext * scriptContext = executeContext->GetActiveScriptContext();
  329. Js::Var exceptionMetadata = Js::JavascriptExceptionMetadata::CreateMetadataVar(scriptContext);
  330. Js::FunctionBody *functionBody = recordedException->GetFunctionBody();
  331. Js::JavascriptOperators::OP_SetProperty(exceptionMetadata, Js::PropertyIds::exception, exception, scriptContext);
  332. if (functionBody == nullptr)
  333. {
  334. // This is probably a parse error. We can get the error location metadata from the thrown object.
  335. Js::JavascriptExceptionMetadata::PopulateMetadataFromCompileException(exceptionMetadata, exception, scriptContext);
  336. }
  337. else
  338. {
  339. if (!Js::JavascriptExceptionMetadata::PopulateMetadataFromException(exceptionMetadata, recordedException, scriptContext))
  340. {
  341. return;
  342. }
  343. }
  344. JsRTActionHandleResultForReplay<JsRTResultOnlyAction, EventKind::GetAndClearExceptionWithMetadataActionTag>(executeContext, evt, exceptionMetadata);
  345. }
  346. }
  347. void GetAndClearExceptionAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  348. {
  349. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  350. HRESULT hr = S_OK;
  351. Js::JavascriptExceptionObject *recordedException = nullptr;
  352. BEGIN_TRANSLATE_OOM_TO_HRESULT
  353. if (ctx->HasRecordedException())
  354. {
  355. recordedException = ctx->GetAndClearRecordedException();
  356. }
  357. END_TRANSLATE_OOM_TO_HRESULT(hr)
  358. Js::Var exception = nullptr;
  359. if(recordedException != nullptr)
  360. {
  361. exception = recordedException->GetThrownObject(nullptr);
  362. }
  363. if(exception != nullptr)
  364. {
  365. JsRTActionHandleResultForReplay<JsRTResultOnlyAction, EventKind::GetAndClearExceptionActionTag>(executeContext, evt, exception);
  366. }
  367. }
  368. void SetExceptionAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  369. {
  370. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  371. const JsRTSingleVarScalarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarScalarArgumentAction, EventKind::SetExceptionActionTag>(evt);
  372. Js::Var exception = InflateVarInReplay(executeContext, GetVarItem_0(action));
  373. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(exception, ctx);
  374. bool propagateToDebugger = GetScalarItem_0(action) ? true : false;
  375. Js::JavascriptExceptionObject *exceptionObject;
  376. exceptionObject = RecyclerNew(ctx->GetRecycler(), Js::JavascriptExceptionObject, exception, ctx, nullptr);
  377. ctx->RecordException(exceptionObject, propagateToDebugger);
  378. }
  379. void HasPropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  380. {
  381. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  382. const JsRTSingleVarScalarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarScalarArgumentAction, EventKind::HasPropertyActionTag>(evt);
  383. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  384. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  385. //Result is not needed but trigger computation for any effects
  386. Js::JavascriptOperators::OP_HasProperty(var, GetPropertyIdItem(action), ctx);
  387. }
  388. void InstanceOfAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  389. {
  390. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  391. const JsRTDoubleVarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarArgumentAction, EventKind::InstanceOfActionTag>(evt);
  392. Js::Var object = InflateVarInReplay(executeContext, GetVarItem_0(action));
  393. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(object, ctx);
  394. Js::Var constructor = InflateVarInReplay(executeContext, GetVarItem_1(action));
  395. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(constructor, ctx);
  396. //Result is not needed but trigger computation for any effects
  397. Js::RecyclableObject::FromVar(constructor)->HasInstance(object, ctx);
  398. }
  399. void EqualsAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  400. {
  401. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  402. const JsRTDoubleVarSingleScalarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarSingleScalarArgumentAction, EventKind::EqualsActionTag>(evt);
  403. Js::Var object1 = InflateVarInReplay(executeContext, GetVarItem_0(action));
  404. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(object1, ctx);
  405. Js::Var object2 = InflateVarInReplay(executeContext, GetVarItem_1(action));
  406. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(object2, ctx);
  407. //Result is not needed but trigger computation for any effects
  408. if(GetScalarItem_0(action))
  409. {
  410. Js::JavascriptOperators::StrictEqual(object1, object2, ctx);
  411. }
  412. else
  413. {
  414. Js::JavascriptOperators::Equal(object1, object2, ctx);
  415. }
  416. }
  417. void GetPropertyIdFromSymbolAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  418. {
  419. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  420. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::GetPropertyIdFromSymbolTag>(evt);
  421. Js::Var sym = InflateVarInReplay(executeContext, GetVarItem_0(action));
  422. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(sym, ctx);
  423. //These really don't have any effect, we need the marshal in validate, so just skip since Js::JavascriptSymbol has strange declaration order
  424. //
  425. //if(!Js::JavascriptSymbol::Is(sym))
  426. //{
  427. // return JsErrorPropertyNotSymbol;
  428. //}
  429. //
  430. //Js::JavascriptSymbol::FromVar(symbol)->GetValue();
  431. }
  432. void GetPrototypeAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  433. {
  434. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  435. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::GetPrototypeActionTag>(evt);
  436. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  437. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  438. Js::Var res = Js::JavascriptOperators::OP_GetPrototype(var,ctx);
  439. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  440. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::GetPrototypeActionTag>(executeContext, evt, res);
  441. }
  442. void GetPropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  443. {
  444. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  445. const JsRTSingleVarScalarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarScalarArgumentAction, EventKind::GetPropertyActionTag>(evt);
  446. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  447. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  448. Js::Var res = Js::JavascriptOperators::OP_GetProperty(var, GetPropertyIdItem(action), ctx);
  449. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  450. JsRTActionHandleResultForReplay<JsRTSingleVarScalarArgumentAction, EventKind::GetPropertyActionTag>(executeContext, evt, res);
  451. }
  452. void GetIndexAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  453. {
  454. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  455. const JsRTDoubleVarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarArgumentAction, EventKind::GetIndexActionTag>(evt);
  456. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  457. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  458. Js::Var index = InflateVarInReplay(executeContext, GetVarItem_1(action));
  459. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(index, ctx);
  460. Js::Var res = Js::JavascriptOperators::OP_GetElementI(var, index, ctx);
  461. JsRTActionHandleResultForReplay<JsRTDoubleVarArgumentAction, EventKind::GetIndexActionTag>(executeContext, evt, res);
  462. }
  463. void GetOwnPropertyInfoAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  464. {
  465. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  466. const JsRTSingleVarScalarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarScalarArgumentAction, EventKind::GetOwnPropertyInfoActionTag>(evt);
  467. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  468. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  469. Js::Var res = nullptr;
  470. Js::PropertyDescriptor propertyDescriptorValue;
  471. if(Js::JavascriptOperators::GetOwnPropertyDescriptor(Js::RecyclableObject::FromVar(var), GetPropertyIdItem(action), ctx, &propertyDescriptorValue))
  472. {
  473. res = Js::JavascriptOperators::FromPropertyDescriptor(propertyDescriptorValue, ctx);
  474. }
  475. else
  476. {
  477. res = ctx->GetLibrary()->GetUndefined();
  478. }
  479. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  480. JsRTActionHandleResultForReplay<JsRTSingleVarScalarArgumentAction, EventKind::GetOwnPropertyInfoActionTag>(executeContext, evt, res);
  481. }
  482. void GetOwnPropertyNamesInfoAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  483. {
  484. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  485. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::GetOwnPropertyNamesInfoActionTag>(evt);
  486. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  487. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  488. Js::JavascriptArray* res = Js::JavascriptOperators::GetOwnPropertyNames(var, ctx);
  489. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  490. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::GetOwnPropertyNamesInfoActionTag>(executeContext, evt, res);
  491. }
  492. void GetOwnPropertySymbolsInfoAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  493. {
  494. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  495. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::GetOwnPropertySymbolsInfoActionTag>(evt);
  496. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  497. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  498. Js::JavascriptArray* res = Js::JavascriptOperators::GetOwnPropertySymbols(var, ctx);
  499. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  500. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::GetOwnPropertySymbolsInfoActionTag>(executeContext, evt, res);
  501. }
  502. void DefinePropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  503. {
  504. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  505. const JsRTDoubleVarSingleScalarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarSingleScalarArgumentAction, EventKind::DefinePropertyActionTag>(evt);
  506. Js::Var object = InflateVarInReplay(executeContext, GetVarItem_0(action));
  507. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(object, ctx);
  508. Js::Var propertyDescriptor = InflateVarInReplay(executeContext, GetVarItem_1(action));
  509. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(propertyDescriptor, ctx);
  510. Js::PropertyDescriptor propertyDescriptorValue;
  511. Js::JavascriptOperators::ToPropertyDescriptor(propertyDescriptor, &propertyDescriptorValue, ctx);
  512. Js::JavascriptOperators::DefineOwnPropertyDescriptor(Js::RecyclableObject::FromVar(object), GetPropertyIdItem(action), propertyDescriptorValue, true, ctx);
  513. }
  514. void DeletePropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  515. {
  516. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  517. const JsRTSingleVarDoubleScalarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarDoubleScalarArgumentAction, EventKind::DeletePropertyActionTag>(evt);
  518. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  519. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  520. Js::Var res = Js::JavascriptOperators::OP_DeleteProperty(var, GetPropertyIdItem(action), ctx, GetScalarItem_1(action) ? Js::PropertyOperation_StrictMode : Js::PropertyOperation_None);
  521. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  522. JsRTActionHandleResultForReplay<JsRTSingleVarDoubleScalarArgumentAction, EventKind::DeletePropertyActionTag>(executeContext, evt, res);
  523. }
  524. void SetPrototypeAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  525. {
  526. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  527. const JsRTDoubleVarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarArgumentAction, EventKind::SetPrototypeActionTag>(evt);
  528. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  529. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  530. Js::Var proto = InflateVarInReplay(executeContext, GetVarItem_1(action));
  531. TTD_REPLAY_VALIDATE_INCOMING_OBJECT_OR_NULL(proto, ctx);
  532. Js::JavascriptObject::ChangePrototype(Js::RecyclableObject::FromVar(var), Js::RecyclableObject::FromVar(proto), true, ctx);
  533. }
  534. void SetPropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  535. {
  536. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  537. const JsRTDoubleVarDoubleScalarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarDoubleScalarArgumentAction, EventKind::SetPropertyActionTag>(evt);
  538. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  539. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  540. Js::Var value = InflateVarInReplay(executeContext, GetVarItem_1(action));
  541. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(value, ctx);
  542. Js::JavascriptOperators::OP_SetProperty(var, GetPropertyIdItem(action), value, ctx, nullptr, GetScalarItem_1(action) ? Js::PropertyOperation_StrictMode : Js::PropertyOperation_None);
  543. }
  544. void SetIndexAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  545. {
  546. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  547. const JsRTTrippleVarArgumentAction* action = GetInlineEventDataAs<JsRTTrippleVarArgumentAction, EventKind::SetIndexActionTag>(evt);
  548. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  549. TTD_REPLAY_VALIDATE_INCOMING_OBJECT(var, ctx);
  550. Js::Var index = InflateVarInReplay(executeContext, GetVarItem_1(action));
  551. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(index, ctx);
  552. Js::Var value = InflateVarInReplay(executeContext, GetVarItem_2(action));
  553. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(value, ctx);
  554. Js::JavascriptOperators::OP_SetElementI(var, index, value, ctx);
  555. }
  556. void GetTypedArrayInfoAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  557. {
  558. const JsRTSingleVarArgumentAction* action = GetInlineEventDataAs<JsRTSingleVarArgumentAction, EventKind::GetTypedArrayInfoActionTag>(evt);
  559. Js::Var var = InflateVarInReplay(executeContext, GetVarItem_0(action));
  560. Js::TypedArrayBase* typedArrayBase = Js::TypedArrayBase::FromVar(var);
  561. Js::Var res = typedArrayBase->GetArrayBuffer();
  562. //Need additional notify since JsRTActionHandleResultForReplay may allocate but GetTypedArrayInfo does not enter runtime
  563. //Failure will kick all the way out to replay loop -- which is what we want
  564. AUTO_NESTED_HANDLED_EXCEPTION_TYPE(ExceptionType_OutOfMemory);
  565. JsRTActionHandleResultForReplay<JsRTSingleVarArgumentAction, EventKind::GetTypedArrayInfoActionTag>(executeContext, evt, res);
  566. }
  567. //////////////////
  568. void JsRTRawBufferCopyAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
  569. {
  570. const JsRTRawBufferCopyAction* rbcAction = GetInlineEventDataAs<JsRTRawBufferCopyAction, EventKind::RawBufferCopySync>(evt);
  571. writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
  572. NSSnapValues::EmitTTDVar(rbcAction->Dst, writer, NSTokens::Separator::NoSeparator);
  573. writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
  574. NSSnapValues::EmitTTDVar(rbcAction->Src, writer, NSTokens::Separator::NoSeparator);
  575. writer->WriteUInt32(NSTokens::Key::u32Val, rbcAction->DstIndx, NSTokens::Separator::CommaSeparator);
  576. writer->WriteUInt32(NSTokens::Key::u32Val, rbcAction->SrcIndx, NSTokens::Separator::CommaSeparator);
  577. writer->WriteUInt32(NSTokens::Key::u32Val, rbcAction->Count, NSTokens::Separator::CommaSeparator);
  578. }
  579. void JsRTRawBufferCopyAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
  580. {
  581. JsRTRawBufferCopyAction* rbcAction = GetInlineEventDataAs<JsRTRawBufferCopyAction, EventKind::RawBufferCopySync>(evt);
  582. reader->ReadKey(NSTokens::Key::argRetVal, true);
  583. rbcAction->Dst = NSSnapValues::ParseTTDVar(false, reader);
  584. reader->ReadKey(NSTokens::Key::argRetVal, true);
  585. rbcAction->Src = NSSnapValues::ParseTTDVar(false, reader);
  586. rbcAction->DstIndx = reader->ReadUInt32(NSTokens::Key::u32Val, true);
  587. rbcAction->SrcIndx = reader->ReadUInt32(NSTokens::Key::u32Val, true);
  588. rbcAction->Count = reader->ReadUInt32(NSTokens::Key::u32Val, true);
  589. }
  590. void RawBufferCopySync_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  591. {
  592. const JsRTRawBufferCopyAction* action = GetInlineEventDataAs<JsRTRawBufferCopyAction, EventKind::RawBufferCopySync>(evt);
  593. Js::Var dst = InflateVarInReplay(executeContext, action->Dst); //never cross context
  594. Js::Var src = InflateVarInReplay(executeContext, action->Src); //never cross context
  595. TTDAssert(Js::ArrayBuffer::Is(dst) && Js::ArrayBuffer::Is(src), "Not array buffer objects!!!");
  596. TTDAssert(action->DstIndx + action->Count <= Js::ArrayBuffer::FromVar(dst)->GetByteLength(), "Copy off end of buffer!!!");
  597. TTDAssert(action->SrcIndx + action->Count <= Js::ArrayBuffer::FromVar(src)->GetByteLength(), "Copy off end of buffer!!!");
  598. byte* dstBuff = Js::ArrayBuffer::FromVar(dst)->GetBuffer() + action->DstIndx;
  599. byte* srcBuff = Js::ArrayBuffer::FromVar(src)->GetBuffer() + action->SrcIndx;
  600. //node uses mmove so we do too
  601. memmove(dstBuff, srcBuff, action->Count);
  602. }
  603. void RawBufferModifySync_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  604. {
  605. const JsRTRawBufferModifyAction* action = GetInlineEventDataAs<JsRTRawBufferModifyAction, EventKind::RawBufferModifySync>(evt);
  606. Js::Var trgt = InflateVarInReplay(executeContext, action->Trgt); //never cross context
  607. TTDAssert(Js::ArrayBuffer::Is(trgt), "Not array buffer object!!!");
  608. TTDAssert(action->Index + action->Length <= Js::ArrayBuffer::FromVar(trgt)->GetByteLength(), "Copy off end of buffer!!!");
  609. byte* trgtBuff = Js::ArrayBuffer::FromVar(trgt)->GetBuffer() + action->Index;
  610. js_memcpy_s(trgtBuff, action->Length, action->Data, action->Length);
  611. }
  612. void RawBufferAsyncModificationRegister_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  613. {
  614. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  615. const JsRTRawBufferModifyAction* action = GetInlineEventDataAs<JsRTRawBufferModifyAction, EventKind::RawBufferAsyncModificationRegister>(evt);
  616. Js::Var trgt = InflateVarInReplay(executeContext, action->Trgt); //never cross context
  617. ctx->TTDContextInfo->AddToAsyncPendingList(Js::ArrayBuffer::FromVar(trgt), action->Index);
  618. }
  619. void RawBufferAsyncModifyComplete_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  620. {
  621. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  622. const JsRTRawBufferModifyAction* action = GetInlineEventDataAs<JsRTRawBufferModifyAction, EventKind::RawBufferAsyncModifyComplete>(evt);
  623. Js::Var trgt = InflateVarInReplay(executeContext, action->Trgt); //never cross context
  624. const Js::ArrayBuffer* dstBuff = Js::ArrayBuffer::FromVar(trgt);
  625. byte* copyBuff = dstBuff->GetBuffer() + action->Index;
  626. byte* finalModPos = dstBuff->GetBuffer() + action->Index + action->Length;
  627. TTDPendingAsyncBufferModification pendingAsyncInfo = { 0 };
  628. ctx->TTDContextInfo->GetFromAsyncPendingList(&pendingAsyncInfo, finalModPos);
  629. TTDAssert(dstBuff == pendingAsyncInfo.ArrayBufferVar && action->Index == pendingAsyncInfo.Index, "Something is not right.");
  630. js_memcpy_s(copyBuff, action->Length, action->Data, action->Length);
  631. }
  632. //////////////////
  633. void JsRTConstructCallAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  634. {
  635. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  636. const JsRTConstructCallAction* ccAction = GetInlineEventDataAs<JsRTConstructCallAction, EventKind::ConstructCallActionTag>(evt);
  637. Js::Var jsFunctionVar = InflateVarInReplay(executeContext, ccAction->ArgArray[0]);
  638. TTD_REPLAY_VALIDATE_INCOMING_FUNCTION(jsFunctionVar, ctx);
  639. //remove implicit constructor function as first arg in callInfo and argument loop below
  640. for(uint32 i = 1; i < ccAction->ArgCount; ++i)
  641. {
  642. Js::Var argi = InflateVarInReplay(executeContext, ccAction->ArgArray[i]);
  643. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(argi, ctx);
  644. ccAction->ExecArgs[i - 1] = argi;
  645. }
  646. Js::JavascriptFunction* jsFunction = Js::JavascriptFunction::FromVar(jsFunctionVar);
  647. Js::CallInfo callInfo(Js::CallFlags::CallFlags_New, (ushort)(ccAction->ArgCount - 1));
  648. Js::Arguments jsArgs(callInfo, ccAction->ExecArgs);
  649. //
  650. //TODO: we will want to look at this at some point -- either treat as "top-level" call or maybe constructors are fast so we can just jump back to previous "real" code
  651. //TTDAssert(!Js::ScriptFunction::Is(jsFunction) || execContext->GetThreadContext()->TTDRootNestingCount != 0, "This will cause user code to execute and we need to add support for that as a top-level call source!!!!");
  652. //
  653. Js::Var res = Js::JavascriptFunction::CallAsConstructor(jsFunction, /* overridingNewTarget = */nullptr, jsArgs, ctx);
  654. Assert(res == nullptr || !Js::CrossSite::NeedMarshalVar(res, ctx));
  655. JsRTActionHandleResultForReplay<JsRTConstructCallAction, EventKind::ConstructCallActionTag>(executeContext, evt, res);
  656. }
  657. void JsRTConstructCallAction_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc)
  658. {
  659. JsRTConstructCallAction* ccAction = GetInlineEventDataAs<JsRTConstructCallAction, EventKind::ConstructCallActionTag>(evt);
  660. if(ccAction->ArgArray != nullptr)
  661. {
  662. alloc.UnlinkAllocation(ccAction->ArgArray);
  663. }
  664. if(ccAction->ExecArgs != nullptr)
  665. {
  666. alloc.UnlinkAllocation(ccAction->ExecArgs);
  667. }
  668. }
  669. void JsRTConstructCallAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
  670. {
  671. const JsRTConstructCallAction* ccAction = GetInlineEventDataAs<JsRTConstructCallAction, EventKind::ConstructCallActionTag>(evt);
  672. writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
  673. NSSnapValues::EmitTTDVar(ccAction->Result, writer, NSTokens::Separator::NoSeparator);
  674. writer->WriteLengthValue(ccAction->ArgCount, NSTokens::Separator::CommaSeparator);
  675. writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
  676. for(uint32 i = 0; i < ccAction->ArgCount; ++i)
  677. {
  678. NSTokens::Separator sep = (i != 0) ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator;
  679. NSSnapValues::EmitTTDVar(ccAction->ArgArray[i], writer, sep);
  680. }
  681. writer->WriteSequenceEnd();
  682. }
  683. void JsRTConstructCallAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
  684. {
  685. JsRTConstructCallAction* ccAction = GetInlineEventDataAs<JsRTConstructCallAction, EventKind::ConstructCallActionTag>(evt);
  686. reader->ReadKey(NSTokens::Key::argRetVal, true);
  687. ccAction->Result = NSSnapValues::ParseTTDVar(false, reader);
  688. ccAction->ArgCount = reader->ReadLengthValue(true);
  689. ccAction->ArgArray = alloc.SlabAllocateArray<TTDVar>(ccAction->ArgCount);
  690. reader->ReadSequenceStart_WDefaultKey(true);
  691. for(uint32 i = 0; i < ccAction->ArgCount; ++i)
  692. {
  693. ccAction->ArgArray[i] = NSSnapValues::ParseTTDVar(i != 0, reader);
  694. }
  695. reader->ReadSequenceEnd();
  696. ccAction->ExecArgs = (ccAction->ArgCount > 1) ? alloc.SlabAllocateArray<Js::Var>(ccAction->ArgCount - 1) : nullptr; //ArgCount includes slot for function which we don't use in exec
  697. }
  698. void JsRTCodeParseAction_SetBodyCtrId(EventLogEntry* parseEvent, uint32 bodyCtrId)
  699. {
  700. JsRTCodeParseAction* cpAction = GetInlineEventDataAs<JsRTCodeParseAction, EventKind::CodeParseActionTag>(parseEvent);
  701. cpAction->BodyCtrId = bodyCtrId;
  702. }
  703. void JsRTCodeParseAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  704. {
  705. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  706. const JsRTCodeParseAction* cpAction = GetInlineEventDataAs<JsRTCodeParseAction, EventKind::CodeParseActionTag>(evt);
  707. Js::JavascriptFunction* function = nullptr;
  708. byte* script = cpAction->SourceCode;
  709. uint32 scriptByteLength = cpAction->SourceByteLength;
  710. TTDAssert(cpAction->IsUtf8 == ((cpAction->LoadFlag & LoadScriptFlag_Utf8Source) == LoadScriptFlag_Utf8Source), "Utf8 status is inconsistent!!!");
  711. SourceContextInfo * sourceContextInfo = ctx->GetSourceContextInfo((DWORD_PTR)cpAction->SourceContextId, nullptr);
  712. if(sourceContextInfo == nullptr)
  713. {
  714. const char16* srcUri = cpAction->SourceUri.Contents;
  715. uint32 srcUriLength = cpAction->SourceUri.Length;
  716. sourceContextInfo = ctx->CreateSourceContextInfo((DWORD_PTR)cpAction->SourceContextId, srcUri, srcUriLength, nullptr);
  717. }
  718. TTDAssert(cpAction->IsUtf8 || sizeof(wchar) == sizeof(char16), "Non-utf8 code only allowed on windows!!!");
  719. const int chsize = (cpAction->LoadFlag & LoadScriptFlag_Utf8Source) ? sizeof(char) : sizeof(char16);
  720. SRCINFO si = {
  721. /* sourceContextInfo */ sourceContextInfo,
  722. /* dlnHost */ 0,
  723. /* ulColumnHost */ 0,
  724. /* lnMinHost */ 0,
  725. /* ichMinHost */ 0,
  726. /* ichLimHost */ static_cast<ULONG>(scriptByteLength / chsize), // OK to truncate since this is used to limit sourceText in debugDocument/compilation errors.
  727. /* ulCharOffset */ 0,
  728. /* mod */ kmodGlobal,
  729. /* grfsi */ 0
  730. };
  731. Js::Utf8SourceInfo* utf8SourceInfo = nullptr;
  732. CompileScriptException se;
  733. function = ctx->LoadScript(script, scriptByteLength, &si, &se,
  734. &utf8SourceInfo, Js::Constants::GlobalCode, cpAction->LoadFlag, nullptr);
  735. TTDAssert(function != nullptr, "Something went wrong");
  736. Js::FunctionBody* fb = TTD::JsSupport::ForceAndGetFunctionBody(function->GetParseableFunctionInfo());
  737. ////
  738. //We don't do this automatically in the eval helper so do it here
  739. BEGIN_JS_RUNTIME_CALL(ctx);
  740. {
  741. ctx->TTDContextInfo->ProcessFunctionBodyOnLoad(fb, nullptr);
  742. ctx->TTDContextInfo->RegisterLoadedScript(fb, cpAction->BodyCtrId);
  743. fb->GetUtf8SourceInfo()->SetSourceInfoForDebugReplay_TTD(cpAction->BodyCtrId);
  744. }
  745. END_JS_RUNTIME_CALL(ctx);
  746. if(ctx->ShouldPerformDebuggerAction())
  747. {
  748. ctx->GetThreadContext()->TTDExecutionInfo->ProcessScriptLoad(ctx, cpAction->BodyCtrId, fb, utf8SourceInfo, &se);
  749. }
  750. ////
  751. JsRTActionHandleResultForReplay<JsRTCodeParseAction, EventKind::CodeParseActionTag>(executeContext, evt, (Js::Var)function);
  752. }
  753. void JsRTCodeParseAction_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc)
  754. {
  755. JsRTCodeParseAction* cpAction = GetInlineEventDataAs<JsRTCodeParseAction, EventKind::CodeParseActionTag>(evt);
  756. alloc.UnlinkAllocation(cpAction->SourceCode);
  757. if(!IsNullPtrTTString(cpAction->SourceUri))
  758. {
  759. alloc.UnlinkString(cpAction->SourceUri);
  760. }
  761. }
  762. void JsRTCodeParseAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
  763. {
  764. const JsRTCodeParseAction* cpAction = GetInlineEventDataAs<JsRTCodeParseAction, EventKind::CodeParseActionTag>(evt);
  765. writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
  766. NSSnapValues::EmitTTDVar(cpAction->Result, writer, NSTokens::Separator::NoSeparator);
  767. writer->WriteUInt64(NSTokens::Key::sourceContextId, cpAction->SourceContextId, NSTokens::Separator::CommaSeparator);
  768. writer->WriteTag<LoadScriptFlag>(NSTokens::Key::loadFlag, cpAction->LoadFlag, NSTokens::Separator::CommaSeparator);
  769. writer->WriteUInt32(NSTokens::Key::bodyCounterId, cpAction->BodyCtrId, NSTokens::Separator::CommaSeparator);
  770. writer->WriteString(NSTokens::Key::uri, cpAction->SourceUri, NSTokens::Separator::CommaSeparator);
  771. writer->WriteBool(NSTokens::Key::boolVal, cpAction->IsUtf8, NSTokens::Separator::CommaSeparator);
  772. writer->WriteLengthValue(cpAction->SourceByteLength, NSTokens::Separator::CommaSeparator);
  773. JsSupport::WriteCodeToFile(threadContext, true, cpAction->BodyCtrId, cpAction->IsUtf8, cpAction->SourceCode, cpAction->SourceByteLength);
  774. }
  775. void JsRTCodeParseAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
  776. {
  777. JsRTCodeParseAction* cpAction = GetInlineEventDataAs<JsRTCodeParseAction, EventKind::CodeParseActionTag>(evt);
  778. reader->ReadKey(NSTokens::Key::argRetVal, true);
  779. cpAction->Result = NSSnapValues::ParseTTDVar(false, reader);
  780. cpAction->SourceContextId = reader->ReadUInt64(NSTokens::Key::sourceContextId, true);
  781. cpAction->LoadFlag = reader->ReadTag<LoadScriptFlag>(NSTokens::Key::loadFlag, true);
  782. cpAction->BodyCtrId = reader->ReadUInt32(NSTokens::Key::bodyCounterId, true);
  783. reader->ReadString(NSTokens::Key::uri, alloc, cpAction->SourceUri, true);
  784. cpAction->IsUtf8 = reader->ReadBool(NSTokens::Key::boolVal, true);
  785. cpAction->SourceByteLength = reader->ReadLengthValue(true);
  786. cpAction->SourceCode = alloc.SlabAllocateArray<byte>(cpAction->SourceByteLength);
  787. JsSupport::ReadCodeFromFile(threadContext, true, cpAction->BodyCtrId, cpAction->IsUtf8, cpAction->SourceCode, cpAction->SourceByteLength);
  788. }
  789. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  790. int64 JsRTCallFunctionAction_GetLastNestedEventTime(const EventLogEntry* evt)
  791. {
  792. const JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  793. return cfAction->LastNestedEvent;
  794. }
  795. void JsRTCallFunctionAction_ProcessDiagInfoPre(EventLogEntry* evt, Js::Var funcVar, UnlinkableSlabAllocator& alloc)
  796. {
  797. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  798. if(Js::JavascriptFunction::Is(funcVar))
  799. {
  800. Js::JavascriptString* displayName = Js::JavascriptFunction::FromVar(funcVar)->GetDisplayName();
  801. alloc.CopyStringIntoWLength(displayName->GetSz(), displayName->GetLength(), cfAction->FunctionName);
  802. }
  803. else
  804. {
  805. alloc.CopyNullTermStringInto(_u("#not a function#"), cfAction->FunctionName);
  806. }
  807. //In case we don't terminate add these nicely
  808. cfAction->LastNestedEvent = TTD_EVENT_MAXTIME;
  809. }
  810. void JsRTCallFunctionAction_ProcessDiagInfoPost(EventLogEntry* evt, int64 lastNestedEvent)
  811. {
  812. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  813. cfAction->LastNestedEvent = lastNestedEvent;
  814. }
  815. #endif
  816. void JsRTCallFunctionAction_ProcessArgs(EventLogEntry* evt, int32 rootDepth, int64 callEventTime, Js::Var funcVar, uint32 argc, Js::Var* argv, int64 topLevelCallbackEventTime, UnlinkableSlabAllocator& alloc)
  817. {
  818. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  819. cfAction->CallbackDepth = rootDepth;
  820. cfAction->ArgCount = argc + 1;
  821. static_assert(sizeof(TTDVar) == sizeof(Js::Var), "These need to be the same size (and have same bit layout) for this to work!");
  822. cfAction->ArgArray = alloc.SlabAllocateArray<TTDVar>(cfAction->ArgCount);
  823. cfAction->ArgArray[0] = TTD_CONVERT_JSVAR_TO_TTDVAR(funcVar);
  824. js_memcpy_s(cfAction->ArgArray + 1, (cfAction->ArgCount -1) * sizeof(TTDVar), argv, argc * sizeof(Js::Var));
  825. cfAction->CallEventTime = callEventTime;
  826. cfAction->TopLevelCallbackEventTime = topLevelCallbackEventTime;
  827. cfAction->AdditionalReplayInfo = nullptr;
  828. //Result is initialized when we register this with the popper
  829. }
  830. void JsRTCallFunctionAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
  831. {
  832. TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
  833. const JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  834. ThreadContext* threadContext = ctx->GetThreadContext();
  835. Js::Var jsFunctionVar = InflateVarInReplay(executeContext, cfAction->ArgArray[0]);
  836. TTD_REPLAY_VALIDATE_INCOMING_FUNCTION(jsFunctionVar, ctx);
  837. Js::JavascriptFunction *jsFunction = Js::JavascriptFunction::FromVar(jsFunctionVar);
  838. //remove implicit constructor function as first arg in callInfo and argument loop below
  839. Js::CallInfo callInfo((ushort)(cfAction->ArgCount - 1));
  840. for(uint32 i = 1; i < cfAction->ArgCount; ++i)
  841. {
  842. Js::Var argi = InflateVarInReplay(executeContext, cfAction->ArgArray[i]);
  843. TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(argi, ctx);
  844. cfAction->AdditionalReplayInfo->ExecArgs[i - 1] = argi;
  845. }
  846. Js::Arguments jsArgs(callInfo, cfAction->AdditionalReplayInfo->ExecArgs);
  847. //If this isn't a root function then just call it -- don't need to reset anything and exceptions can just continue
  848. if(cfAction->CallbackDepth != 0)
  849. {
  850. Js::Var result = jsFunction->CallRootFunction(jsArgs, ctx, true);
  851. if(result != nullptr)
  852. {
  853. Assert(result == nullptr || !Js::CrossSite::NeedMarshalVar(result, ctx));
  854. }
  855. //since we tag in JsRT we need to tag here too
  856. JsRTActionHandleResultForReplay<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(executeContext, evt, result);
  857. TTDAssert(NSLogEvents::EventCompletesNormally(evt), "Why did we get a different completion");
  858. }
  859. else
  860. {
  861. threadContext->TTDLog->ResetCallStackForTopLevelCall(cfAction->TopLevelCallbackEventTime);
  862. if(threadContext->TTDExecutionInfo != nullptr)
  863. {
  864. threadContext->TTDExecutionInfo->ResetCallStackForTopLevelCall(cfAction->TopLevelCallbackEventTime);
  865. }
  866. try
  867. {
  868. Js::Var result = jsFunction->CallRootFunction(jsArgs, ctx, true);
  869. //since we tag in JsRT we need to tag here too
  870. JsRTActionHandleResultForReplay<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(executeContext, evt, result);
  871. TTDAssert(NSLogEvents::EventCompletesNormally(evt), "Why did we get a different completion");
  872. }
  873. catch(const Js::JavascriptException& err)
  874. {
  875. TTDAssert(NSLogEvents::EventCompletesWithException(evt), "Why did we get a different exception");
  876. if(executeContext->GetActiveScriptContext()->ShouldPerformDebuggerAction())
  877. {
  878. //convert to uncaught debugger exception for host
  879. TTDebuggerSourceLocation lastLocation;
  880. threadContext->TTDExecutionInfo->GetLastExecutedTimeAndPositionForDebugger(lastLocation);
  881. JsRTCallFunctionAction_SetLastExecutedStatementAndFrameInfo(const_cast<EventLogEntry*>(evt), lastLocation);
  882. err.GetAndClear(); // discard exception object
  883. //Reset any step controller logic
  884. if(ctx->GetThreadContext()->GetDebugManager() != nullptr)
  885. {
  886. ctx->GetThreadContext()->GetDebugManager()->stepController.Deactivate();
  887. }
  888. throw TTDebuggerAbortException::CreateUncaughtExceptionAbortRequest(lastLocation.GetRootEventTime(), _u("Uncaught JavaScript exception -- Propagate to top-level."));
  889. }
  890. throw;
  891. }
  892. catch(Js::ScriptAbortException)
  893. {
  894. TTDAssert(NSLogEvents::EventCompletesWithException(evt), "Why did we get a different exception");
  895. if(executeContext->GetActiveScriptContext()->ShouldPerformDebuggerAction())
  896. {
  897. //convert to uncaught debugger exception for host
  898. TTDebuggerSourceLocation lastLocation;
  899. threadContext->TTDExecutionInfo->GetLastExecutedTimeAndPositionForDebugger(lastLocation);
  900. JsRTCallFunctionAction_SetLastExecutedStatementAndFrameInfo(const_cast<EventLogEntry*>(evt), lastLocation);
  901. throw TTDebuggerAbortException::CreateUncaughtExceptionAbortRequest(lastLocation.GetRootEventTime(), _u("Uncaught Script exception -- Propagate to top-level."));
  902. }
  903. else
  904. {
  905. throw;
  906. }
  907. }
  908. catch(...)
  909. {
  910. if(executeContext->GetActiveScriptContext()->ShouldPerformDebuggerAction())
  911. {
  912. TTDebuggerSourceLocation lastLocation;
  913. threadContext->TTDExecutionInfo->GetLastExecutedTimeAndPositionForDebugger(lastLocation);
  914. JsRTCallFunctionAction_SetLastExecutedStatementAndFrameInfo(const_cast<EventLogEntry*>(evt), lastLocation);
  915. }
  916. throw;
  917. }
  918. }
  919. }
  920. void JsRTCallFunctionAction_UnloadEventMemory(EventLogEntry* evt, UnlinkableSlabAllocator& alloc)
  921. {
  922. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  923. alloc.UnlinkAllocation(cfAction->ArgArray);
  924. if(cfAction->AdditionalReplayInfo != nullptr)
  925. {
  926. if(cfAction->AdditionalReplayInfo->ExecArgs != nullptr)
  927. {
  928. alloc.UnlinkAllocation(cfAction->AdditionalReplayInfo->ExecArgs);
  929. }
  930. JsRTCallFunctionAction_UnloadSnapshot(evt);
  931. if(cfAction->AdditionalReplayInfo->LastExecutedLocation.HasValue())
  932. {
  933. cfAction->AdditionalReplayInfo->LastExecutedLocation.Clear();
  934. }
  935. alloc.UnlinkAllocation(cfAction->AdditionalReplayInfo);
  936. }
  937. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  938. alloc.UnlinkString(cfAction->FunctionName);
  939. #endif
  940. }
  941. void JsRTCallFunctionAction_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext)
  942. {
  943. const JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  944. writer->WriteKey(NSTokens::Key::argRetVal, NSTokens::Separator::CommaSeparator);
  945. NSSnapValues::EmitTTDVar(cfAction->Result, writer, NSTokens::Separator::NoSeparator);
  946. writer->WriteInt32(NSTokens::Key::rootNestingDepth, cfAction->CallbackDepth, NSTokens::Separator::CommaSeparator);
  947. writer->WriteLengthValue(cfAction->ArgCount, NSTokens::Separator::CommaSeparator);
  948. writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
  949. for(uint32 i = 0; i < cfAction->ArgCount; ++i)
  950. {
  951. NSTokens::Separator sep = (i != 0) ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator;
  952. NSSnapValues::EmitTTDVar(cfAction->ArgArray[i], writer, sep);
  953. }
  954. writer->WriteSequenceEnd();
  955. writer->WriteInt64(NSTokens::Key::eventTime, cfAction->CallEventTime, NSTokens::Separator::CommaSeparator);
  956. writer->WriteInt64(NSTokens::Key::eventTime, cfAction->TopLevelCallbackEventTime, NSTokens::Separator::CommaSeparator);
  957. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  958. writer->WriteInt64(NSTokens::Key::i64Val, cfAction->LastNestedEvent, NSTokens::Separator::CommaSeparator);
  959. writer->WriteString(NSTokens::Key::name, cfAction->FunctionName, NSTokens::Separator::CommaSeparator);
  960. #endif
  961. }
  962. void JsRTCallFunctionAction_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc)
  963. {
  964. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  965. reader->ReadKey(NSTokens::Key::argRetVal, true);
  966. cfAction->Result = NSSnapValues::ParseTTDVar(false, reader);
  967. cfAction->CallbackDepth = reader->ReadInt32(NSTokens::Key::rootNestingDepth, true);
  968. cfAction->ArgCount = reader->ReadLengthValue(true);
  969. cfAction->ArgArray = alloc.SlabAllocateArray<TTDVar>(cfAction->ArgCount);
  970. reader->ReadSequenceStart_WDefaultKey(true);
  971. for(uint32 i = 0; i < cfAction->ArgCount; ++i)
  972. {
  973. cfAction->ArgArray[i] = NSSnapValues::ParseTTDVar(i != 0, reader);
  974. }
  975. reader->ReadSequenceEnd();
  976. cfAction->CallEventTime = reader->ReadInt64(NSTokens::Key::eventTime, true);
  977. cfAction->TopLevelCallbackEventTime = reader->ReadInt64(NSTokens::Key::eventTime, true);
  978. cfAction->AdditionalReplayInfo = alloc.SlabAllocateStruct<JsRTCallFunctionAction_ReplayAdditionalInfo>();
  979. cfAction->AdditionalReplayInfo->RtRSnap = nullptr;
  980. cfAction->AdditionalReplayInfo->ExecArgs = (cfAction->ArgCount > 1) ? alloc.SlabAllocateArray<Js::Var>(cfAction->ArgCount - 1) : nullptr; //ArgCount includes slot for function which we don't use in exec
  981. cfAction->AdditionalReplayInfo->LastExecutedLocation.Initialize();
  982. #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
  983. cfAction->LastNestedEvent = reader->ReadInt64(NSTokens::Key::i64Val, true);
  984. reader->ReadString(NSTokens::Key::name, alloc, cfAction->FunctionName, true);
  985. #endif
  986. }
  987. void JsRTCallFunctionAction_UnloadSnapshot(EventLogEntry* evt)
  988. {
  989. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  990. if(cfAction->AdditionalReplayInfo != nullptr && cfAction->AdditionalReplayInfo->RtRSnap != nullptr)
  991. {
  992. TT_HEAP_DELETE(SnapShot, cfAction->AdditionalReplayInfo->RtRSnap);
  993. cfAction->AdditionalReplayInfo->RtRSnap = nullptr;
  994. }
  995. }
  996. void JsRTCallFunctionAction_SetLastExecutedStatementAndFrameInfo(EventLogEntry* evt, const TTDebuggerSourceLocation& lastSourceLocation)
  997. {
  998. JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  999. cfAction->AdditionalReplayInfo->LastExecutedLocation.SetLocationCopy(lastSourceLocation);
  1000. }
  1001. bool JsRTCallFunctionAction_GetLastExecutedStatementAndFrameInfoForDebugger(const EventLogEntry* evt, TTDebuggerSourceLocation& lastSourceInfo)
  1002. {
  1003. const JsRTCallFunctionAction* cfAction = GetInlineEventDataAs<JsRTCallFunctionAction, EventKind::CallExistingFunctionActionTag>(evt);
  1004. if(cfAction->AdditionalReplayInfo->LastExecutedLocation.HasValue())
  1005. {
  1006. lastSourceInfo.SetLocationCopy(cfAction->AdditionalReplayInfo->LastExecutedLocation);
  1007. return true;
  1008. }
  1009. else
  1010. {
  1011. lastSourceInfo.Clear();
  1012. return false;
  1013. }
  1014. }
  1015. }
  1016. }
  1017. #endif