TTInflateMap.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeDebugPch.h"
  6. #if ENABLE_TTD
  7. #define PATH_BUFFER_COUNT 256
  8. namespace TTD
  9. {
  10. InflateMap::InflateMap()
  11. : m_typeMap(), m_handlerMap(),
  12. m_tagToGlobalObjectMap(), m_objectMap(),
  13. m_functionBodyMap(), m_environmentMap(), m_slotArrayMap(), m_promiseDataMap(&HeapAllocator::Instance),
  14. m_debuggerScopeHomeBodyMap(), m_debuggerScopeChainIndexMap(),
  15. m_inflatePinSet(), m_environmentPinSet(), m_oldInflatePinSet(),
  16. m_oldObjectMap(), m_oldFunctionBodyMap(), m_propertyReset(&HeapAllocator::Instance)
  17. {
  18. ;
  19. }
  20. InflateMap::~InflateMap()
  21. {
  22. if(this->m_inflatePinSet != nullptr)
  23. {
  24. this->m_inflatePinSet.Unroot(this->m_inflatePinSet->GetAllocator());
  25. }
  26. if(this->m_environmentPinSet != nullptr)
  27. {
  28. this->m_environmentPinSet.Unroot(this->m_environmentPinSet->GetAllocator());
  29. }
  30. if(this->m_slotArrayPinSet != nullptr)
  31. {
  32. this->m_slotArrayPinSet.Unroot(this->m_slotArrayPinSet->GetAllocator());
  33. }
  34. if(this->m_oldInflatePinSet != nullptr)
  35. {
  36. this->m_oldInflatePinSet.Unroot(this->m_oldInflatePinSet->GetAllocator());
  37. }
  38. }
  39. void InflateMap::PrepForInitialInflate(ThreadContext* threadContext, uint32 ctxCount, uint32 handlerCount, uint32 typeCount, uint32 objectCount, uint32 bodyCount, uint32 dbgScopeCount, uint32 envCount, uint32 slotCount)
  40. {
  41. this->m_typeMap.Initialize(typeCount);
  42. this->m_handlerMap.Initialize(handlerCount);
  43. this->m_tagToGlobalObjectMap.Initialize(ctxCount);
  44. this->m_objectMap.Initialize(objectCount);
  45. this->m_functionBodyMap.Initialize(bodyCount);
  46. this->m_debuggerScopeHomeBodyMap.Initialize(dbgScopeCount);
  47. this->m_debuggerScopeChainIndexMap.Initialize(dbgScopeCount);
  48. this->m_environmentMap.Initialize(envCount);
  49. this->m_slotArrayMap.Initialize(slotCount);
  50. this->m_promiseDataMap.Clear();
  51. Recycler * recycler = threadContext->GetRecycler();
  52. this->m_inflatePinSet.Root(RecyclerNew(recycler, ObjectPinSet, recycler, objectCount), recycler);
  53. this->m_environmentPinSet.Root(RecyclerNew(recycler, EnvironmentPinSet, recycler, objectCount), recycler);
  54. this->m_slotArrayPinSet.Root(RecyclerNew(recycler, SlotArrayPinSet, recycler, objectCount), recycler);
  55. }
  56. void InflateMap::PrepForReInflate(uint32 ctxCount, uint32 handlerCount, uint32 typeCount, uint32 objectCount, uint32 bodyCount, uint32 dbgScopeCount, uint32 envCount, uint32 slotCount)
  57. {
  58. this->m_typeMap.Initialize(typeCount);
  59. this->m_handlerMap.Initialize(handlerCount);
  60. this->m_tagToGlobalObjectMap.Initialize(ctxCount);
  61. this->m_debuggerScopeHomeBodyMap.Initialize(dbgScopeCount);
  62. this->m_debuggerScopeChainIndexMap.Initialize(dbgScopeCount);
  63. this->m_environmentMap.Initialize(envCount);
  64. this->m_slotArrayMap.Initialize(slotCount);
  65. this->m_promiseDataMap.Clear();
  66. //We re-use these values (and reset things below) so we don't neet to initialize them here
  67. //m_objectMap
  68. //m_functionBodyMap
  69. //copy info we want to reuse into the old maps
  70. this->m_oldObjectMap.MoveDataInto(this->m_objectMap);
  71. this->m_oldFunctionBodyMap.MoveDataInto(this->m_functionBodyMap);
  72. //allocate the old pin set and fill it
  73. TTDAssert(this->m_oldInflatePinSet == nullptr, "Old pin set is not null.");
  74. Recycler* pinRecycler = this->m_inflatePinSet->GetAllocator();
  75. this->m_oldInflatePinSet.Root(RecyclerNew(pinRecycler, ObjectPinSet, pinRecycler, this->m_inflatePinSet->Count()), pinRecycler);
  76. for(auto iter = this->m_inflatePinSet->GetIterator(); iter.IsValid(); iter.MoveNext())
  77. {
  78. this->m_oldInflatePinSet->AddNew(iter.CurrentKey());
  79. }
  80. this->m_inflatePinSet->Clear();
  81. this->m_environmentPinSet->Clear();
  82. this->m_slotArrayPinSet->Clear();
  83. }
  84. void InflateMap::CleanupAfterInflate()
  85. {
  86. this->m_handlerMap.Unload();
  87. this->m_typeMap.Unload();
  88. this->m_tagToGlobalObjectMap.Unload();
  89. this->m_debuggerScopeHomeBodyMap.Unload();
  90. this->m_debuggerScopeChainIndexMap.Unload();
  91. this->m_environmentMap.Unload();
  92. this->m_slotArrayMap.Unload();
  93. this->m_promiseDataMap.Clear();
  94. //We re-use these values (and reset things later) so we don't want to unload them here
  95. //m_objectMap
  96. //m_functionBodyMap
  97. this->m_oldObjectMap.Unload();
  98. this->m_oldFunctionBodyMap.Unload();
  99. this->m_propertyReset.Clear();
  100. if(this->m_oldInflatePinSet != nullptr)
  101. {
  102. this->m_oldInflatePinSet.Unroot(this->m_oldInflatePinSet->GetAllocator());
  103. }
  104. }
  105. bool InflateMap::IsObjectAlreadyInflated(TTD_PTR_ID objid) const
  106. {
  107. return this->m_objectMap.Contains(objid);
  108. }
  109. bool InflateMap::IsFunctionBodyAlreadyInflated(TTD_PTR_ID fbodyid) const
  110. {
  111. return this->m_functionBodyMap.Contains(fbodyid);
  112. }
  113. Js::RecyclableObject* InflateMap::FindReusableObjectIfExists(TTD_PTR_ID objid) const
  114. {
  115. if(!this->m_oldObjectMap.IsValid())
  116. {
  117. return nullptr;
  118. }
  119. else
  120. {
  121. return this->m_oldObjectMap.LookupKnownItem(objid);
  122. }
  123. }
  124. Js::FunctionBody* InflateMap::FindReusableFunctionBodyIfExists(TTD_PTR_ID fbodyid) const
  125. {
  126. if(!this->m_oldFunctionBodyMap.IsValid())
  127. {
  128. return nullptr;
  129. }
  130. else
  131. {
  132. return this->m_oldFunctionBodyMap.LookupKnownItem(fbodyid);
  133. }
  134. }
  135. Js::RecyclableObject* InflateMap::FindReusableObject_WellKnowReuseCheck(TTD_PTR_ID objid) const
  136. {
  137. return this->m_objectMap.LookupKnownItem(objid);
  138. }
  139. Js::DynamicTypeHandler* InflateMap::LookupHandler(TTD_PTR_ID handlerId) const
  140. {
  141. return this->m_handlerMap.LookupKnownItem(handlerId);
  142. }
  143. Js::Type* InflateMap::LookupType(TTD_PTR_ID typeId) const
  144. {
  145. return this->m_typeMap.LookupKnownItem(typeId);
  146. }
  147. Js::ScriptContext* InflateMap::LookupScriptContext(TTD_LOG_PTR_ID sctag) const
  148. {
  149. return this->m_tagToGlobalObjectMap.LookupKnownItem(sctag)->GetScriptContext();
  150. }
  151. Js::RecyclableObject* InflateMap::LookupObject(TTD_PTR_ID objid) const
  152. {
  153. return this->m_objectMap.LookupKnownItem(objid);
  154. }
  155. Js::FunctionBody* InflateMap::LookupFunctionBody(TTD_PTR_ID functionId) const
  156. {
  157. return this->m_functionBodyMap.LookupKnownItem(functionId);
  158. }
  159. Js::FrameDisplay* InflateMap::LookupEnvironment(TTD_PTR_ID envid) const
  160. {
  161. return this->m_environmentMap.LookupKnownItem(envid);
  162. }
  163. Field(Js::Var)* InflateMap::LookupSlotArray(TTD_PTR_ID slotid) const
  164. {
  165. return this->m_slotArrayMap.LookupKnownItem(slotid);
  166. }
  167. void InflateMap::LookupInfoForDebugScope(TTD_PTR_ID dbgScopeId, Js::FunctionBody** homeBody, int32* chainIndex) const
  168. {
  169. *homeBody = this->m_debuggerScopeHomeBodyMap.LookupKnownItem(dbgScopeId);
  170. *chainIndex = this->m_debuggerScopeChainIndexMap.LookupKnownItem(dbgScopeId);
  171. }
  172. void InflateMap::AddDynamicHandler(TTD_PTR_ID handlerId, Js::DynamicTypeHandler* value)
  173. {
  174. this->m_handlerMap.AddItem(handlerId, value);
  175. }
  176. void InflateMap::AddType(TTD_PTR_ID typeId, Js::Type* value)
  177. {
  178. this->m_typeMap.AddItem(typeId, value);
  179. }
  180. void InflateMap::AddScriptContext(TTD_LOG_PTR_ID sctag, Js::ScriptContext* value)
  181. {
  182. Js::GlobalObject* globalObj = value->GetGlobalObject();
  183. this->m_tagToGlobalObjectMap.AddItem(sctag, globalObj);
  184. value->ScriptContextLogTag = sctag;
  185. }
  186. void InflateMap::AddObject(TTD_PTR_ID objid, Js::RecyclableObject* value)
  187. {
  188. this->m_objectMap.AddItem(objid, value);
  189. this->m_inflatePinSet->AddNew(value);
  190. }
  191. void InflateMap::AddInflationFunctionBody(TTD_PTR_ID functionId, Js::FunctionBody* value)
  192. {
  193. this->m_functionBodyMap.AddItem(functionId, value);
  194. //Function bodies are either root (and kept live by our root pin set in the script context/info) or are reachable from it
  195. }
  196. void InflateMap::AddEnvironment(TTD_PTR_ID envId, Js::FrameDisplay* value)
  197. {
  198. this->m_environmentMap.AddItem(envId, value);
  199. this->m_environmentPinSet->AddNew(value);
  200. }
  201. void InflateMap::AddSlotArray(TTD_PTR_ID slotId, Field(Js::Var)* value)
  202. {
  203. this->m_slotArrayMap.AddItem(slotId, value);
  204. this->m_slotArrayPinSet->AddNew(value);
  205. }
  206. void InflateMap::UpdateFBScopes(const NSSnapValues::SnapFunctionBodyScopeChain& scopeChainInfo, Js::FunctionBody* fb)
  207. {
  208. TTDAssert((int32)scopeChainInfo.ScopeCount == (fb->GetScopeObjectChain() != nullptr ? fb->GetScopeObjectChain()->pScopeChain->Count() : 0), "Mismatch in scope counts!!!");
  209. if(fb->GetScopeObjectChain() != nullptr)
  210. {
  211. Js::ScopeObjectChain* scChain = fb->GetScopeObjectChain();
  212. for(int32 i = 0; i < scChain->pScopeChain->Count(); ++i)
  213. {
  214. TTD_PTR_ID dbgScopeId = scopeChainInfo.ScopeArray[i];
  215. if(!this->m_debuggerScopeHomeBodyMap.Contains(dbgScopeId))
  216. {
  217. this->m_debuggerScopeHomeBodyMap.AddItem(dbgScopeId, fb);
  218. this->m_debuggerScopeChainIndexMap.AddItem(dbgScopeId, i);
  219. }
  220. }
  221. }
  222. }
  223. JsUtil::BaseHashSet<Js::PropertyId, HeapAllocator>& InflateMap::GetPropertyResetSet()
  224. {
  225. return this->m_propertyReset;
  226. }
  227. Js::Var InflateMap::InflateTTDVar(TTDVar var) const
  228. {
  229. if(Js::TaggedNumber::Is(var))
  230. {
  231. return static_cast<Js::Var>(var);
  232. }
  233. else
  234. {
  235. return this->LookupObject(TTD_CONVERT_VAR_TO_PTR_ID(var));
  236. }
  237. }
  238. //////////////////
  239. #if ENABLE_SNAPSHOT_COMPARE
  240. TTDComparePath::TTDComparePath()
  241. : m_prefix(nullptr), m_stepKind(StepKind::Empty), m_step()
  242. {
  243. ;
  244. }
  245. TTDComparePath::TTDComparePath(const TTDComparePath* prefix, StepKind stepKind, const PathEntry& nextStep)
  246. : m_prefix(prefix), m_stepKind(stepKind), m_step(nextStep)
  247. {
  248. ;
  249. }
  250. TTDComparePath::~TTDComparePath()
  251. {
  252. ;
  253. }
  254. void TTDComparePath::WritePathToConsole(ThreadContext* threadContext, bool printNewline, _Out_writes_z_(namebuffLength) char16* namebuff, charcount_t namebuffLength) const
  255. {
  256. if(this->m_prefix != nullptr)
  257. {
  258. this->m_prefix->WritePathToConsole(threadContext, false, namebuff, namebuffLength);
  259. }
  260. if(this->m_stepKind == StepKind::PropertyData || this->m_stepKind == StepKind::PropertyGetter || this->m_stepKind == StepKind::PropertySetter)
  261. {
  262. const Js::PropertyRecord* pRecord = threadContext->GetPropertyName((Js::PropertyId)this->m_step.IndexOrPID);
  263. js_memcpy_s(namebuff, namebuffLength * sizeof(char16), pRecord->GetBuffer(), pRecord->GetLength() * sizeof(char16));
  264. // Don't allow the null to be written past the end of the buffer.
  265. namebuff[min(namebuffLength - 1, pRecord->GetLength())] = _u('\0');
  266. }
  267. bool isFirst = (this->m_prefix == nullptr);
  268. switch(this->m_stepKind)
  269. {
  270. case StepKind::Empty:
  271. break;
  272. case StepKind::Root:
  273. Output::Print(_u("root#%I64i"), this->m_step.IndexOrPID);
  274. break;
  275. case StepKind::PropertyData:
  276. Output::Print(_u("%ls%ls"), (isFirst ? _u("") : _u(".")), namebuff);
  277. break;
  278. case StepKind::PropertyGetter:
  279. Output::Print(_u("%ls<%ls"), (isFirst ? _u("") : _u(".")), namebuff);
  280. break;
  281. case StepKind::PropertySetter:
  282. Output::Print(_u("%ls>%ls"), (isFirst ? _u("") : _u(".")), namebuff);
  283. break;
  284. case StepKind::Array:
  285. Output::Print(_u("[%I64i]"), this->m_step.IndexOrPID);
  286. break;
  287. case StepKind::Scope:
  288. Output::Print(_u("%ls_scope[%I64i]"), (isFirst ? _u("") : _u(".")), this->m_step.IndexOrPID);
  289. break;
  290. case StepKind::SlotArray:
  291. Output::Print(_u("%ls_slots[%I64i]"), (isFirst ? _u("") : _u(".")), this->m_step.IndexOrPID);
  292. break;
  293. case StepKind::FunctionBody:
  294. Output::Print(_u("%ls%ls"), (isFirst ? _u("") : _u(".")), this->m_step.OptName);
  295. break;
  296. case StepKind::Special:
  297. Output::Print(_u("%ls_%ls"), (isFirst ? _u("") : _u(".")), this->m_step.OptName);
  298. break;
  299. case StepKind::SpecialArray:
  300. Output::Print(_u("%ls_%ls[%I64i]"), (isFirst ? _u("") : _u(".")), this->m_step.OptName, this->m_step.IndexOrPID);
  301. break;
  302. default:
  303. TTDAssert(false, "Unknown tag in switch statement!!!");
  304. break;
  305. }
  306. if(printNewline)
  307. {
  308. Output::Print(_u("\n"));
  309. }
  310. }
  311. TTDCompareMap::TTDCompareMap(ThreadContext* threadContext)
  312. : StrictCrossSite(false), H1PtrIdWorklist(&HeapAllocator::Instance), H1PtrToH2PtrMap(&HeapAllocator::Instance), SnapObjCmpVTable(nullptr), H1PtrToPathMap(&HeapAllocator::Instance),
  313. CurrentPath(nullptr), CurrentH1Ptr(TTD_INVALID_PTR_ID), CurrentH2Ptr(TTD_INVALID_PTR_ID), Context(threadContext),
  314. //
  315. H1ValueMap(&HeapAllocator::Instance), H1SlotArrayMap(&HeapAllocator::Instance), H1FunctionScopeInfoMap(&HeapAllocator::Instance),
  316. H1FunctionTopLevelLoadMap(&HeapAllocator::Instance), H1FunctionTopLevelNewMap(&HeapAllocator::Instance), H1FunctionTopLevelEvalMap(&HeapAllocator::Instance),
  317. H1FunctionBodyMap(&HeapAllocator::Instance), H1ObjectMap(&HeapAllocator::Instance), H1PendingAsyncModBufferSet(&HeapAllocator::Instance),
  318. //
  319. H2ValueMap(&HeapAllocator::Instance), H2SlotArrayMap(&HeapAllocator::Instance), H2FunctionScopeInfoMap(&HeapAllocator::Instance),
  320. H2FunctionTopLevelLoadMap(&HeapAllocator::Instance), H2FunctionTopLevelNewMap(&HeapAllocator::Instance), H2FunctionTopLevelEvalMap(&HeapAllocator::Instance),
  321. H2FunctionBodyMap(&HeapAllocator::Instance), H2ObjectMap(&HeapAllocator::Instance), H2PendingAsyncModBufferSet(&HeapAllocator::Instance)
  322. {
  323. this->StrictCrossSite = !threadContext->TTDLog->IsDebugModeFlagSet();
  324. this->PathBuffer = TT_HEAP_ALLOC_ARRAY_ZERO(char16, PATH_BUFFER_COUNT);
  325. this->SnapObjCmpVTable = TT_HEAP_ALLOC_ARRAY_ZERO(fPtr_AssertSnapEquivAddtlInfo, (int32)NSSnapObjects::SnapObjectType::Limit);
  326. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapScriptFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapScriptFunctionInfo;
  327. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapExternalFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapExternalFunctionInfo;
  328. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapRuntimeRevokerFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapRevokerFunctionInfo;
  329. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapBoundFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapBoundFunctionInfo;
  330. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapHeapArgumentsObject] = &NSSnapObjects::AssertSnapEquiv_SnapHeapArgumentsInfo<NSSnapObjects::SnapObjectType::SnapHeapArgumentsObject>;
  331. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapES5HeapArgumentsObject] = &NSSnapObjects::AssertSnapEquiv_SnapHeapArgumentsInfo<NSSnapObjects::SnapObjectType::SnapES5HeapArgumentsObject>;
  332. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapBoxedValueObject] = &NSSnapObjects::AssertSnapEquiv_SnapBoxedValue;
  333. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapDateObject] = &NSSnapObjects::AssertSnapEquiv_SnapDate;
  334. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapRegexObject] = &NSSnapObjects::AssertSnapEquiv_SnapRegexInfo;
  335. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapArrayObject] = &NSSnapObjects::AssertSnapEquiv_SnapArrayInfo<TTDVar, NSSnapObjects::SnapObjectType::SnapArrayObject>;
  336. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapNativeIntArrayObject] = &NSSnapObjects::AssertSnapEquiv_SnapArrayInfo<int, NSSnapObjects::SnapObjectType::SnapNativeIntArrayObject>;
  337. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapNativeFloatArrayObject] = &NSSnapObjects::AssertSnapEquiv_SnapArrayInfo<double, NSSnapObjects::SnapObjectType::SnapNativeFloatArrayObject>;
  338. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapES5ArrayObject] = &NSSnapObjects::AssertSnapEquiv_SnapES5ArrayInfo;
  339. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapArrayBufferObject] = &NSSnapObjects::AssertSnapEquiv_SnapArrayBufferInfo;
  340. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapTypedArrayObject] = &NSSnapObjects::AssertSnapEquiv_SnapTypedArrayInfo;
  341. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapSetObject] = &NSSnapObjects::AssertSnapEquiv_SnapSetInfo;
  342. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapMapObject] = &NSSnapObjects::AssertSnapEquiv_SnapMapInfo;
  343. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapProxyObject] = &NSSnapObjects::AssertSnapEquiv_SnapProxyInfo;
  344. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapPromiseObject] = &NSSnapObjects::AssertSnapEquiv_SnapPromiseInfo;
  345. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapPromiseResolveOrRejectFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapPromiseResolveOrRejectFunctionInfo;
  346. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapPromiseReactionTaskFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapPromiseReactionTaskFunctionInfo;
  347. this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapPromiseAllResolveElementFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapPromiseAllResolveElementFunctionInfo;
  348. }
  349. TTDCompareMap::~TTDCompareMap()
  350. {
  351. TT_HEAP_FREE_ARRAY(char16, this->PathBuffer, PATH_BUFFER_COUNT);
  352. TT_HEAP_FREE_ARRAY(TTD::fPtr_AssertSnapEquivAddtlInfo, this->SnapObjCmpVTable, (int32)NSSnapObjects::SnapObjectType::Limit);
  353. //delete all the compare paths
  354. for(auto iter = this->H1PtrToPathMap.GetIterator(); iter.IsValid(); iter.MoveNext())
  355. {
  356. TT_HEAP_DELETE(TTDComparePath, iter.CurrentValue());
  357. }
  358. }
  359. void TTDCompareMap::DiagnosticAssert(bool condition)
  360. {
  361. if(!condition)
  362. {
  363. if(this->CurrentPath != nullptr)
  364. {
  365. Output::Print(_u("Snap1 ptrid: *0x%I64x\n"), this->CurrentH1Ptr);
  366. Output::Print(_u("Snap2 ptrid: *0x%I64x\n"), this->CurrentH2Ptr);
  367. this->CurrentPath->WritePathToConsole(this->Context, true, this->PathBuffer, PATH_BUFFER_COUNT);
  368. }
  369. }
  370. TTDAssert(condition, "Diagnostic compare assertion failed!!!");
  371. }
  372. void TTDCompareMap::CheckConsistentAndAddPtrIdMapping_Helper(TTD_PTR_ID h1PtrId, TTD_PTR_ID h2PtrId, TTDComparePath::StepKind stepKind, const TTDComparePath::PathEntry& next)
  373. {
  374. if(h1PtrId == TTD_INVALID_PTR_ID || h2PtrId == TTD_INVALID_PTR_ID)
  375. {
  376. this->DiagnosticAssert(h1PtrId == TTD_INVALID_PTR_ID && h2PtrId == TTD_INVALID_PTR_ID);
  377. }
  378. else if(this->H1PtrToH2PtrMap.ContainsKey(h1PtrId))
  379. {
  380. this->DiagnosticAssert(this->H1PtrToH2PtrMap.Item(h1PtrId) == h2PtrId);
  381. }
  382. else if(this->H1ValueMap.ContainsKey(h1PtrId))
  383. {
  384. this->DiagnosticAssert(this->H2ValueMap.ContainsKey(h2PtrId));
  385. const NSSnapValues::SnapPrimitiveValue* v1 = this->H1ValueMap.Item(h1PtrId);
  386. const NSSnapValues::SnapPrimitiveValue* v2 = this->H2ValueMap.Item(h2PtrId);
  387. NSSnapValues::AssertSnapEquiv(v1, v2, *this);
  388. }
  389. else
  390. {
  391. this->H1PtrIdWorklist.Enqueue(h1PtrId);
  392. TTDComparePath* objPath = TT_HEAP_NEW(TTDComparePath, this->CurrentPath, stepKind, next);
  393. this->H1PtrToPathMap.AddNew(h1PtrId, objPath);
  394. this->H1PtrToH2PtrMap.AddNew(h1PtrId, h2PtrId);
  395. }
  396. }
  397. void TTDCompareMap::CheckConsistentAndAddPtrIdMapping_Scope(TTD_PTR_ID h1PtrId, TTD_PTR_ID h2PtrId, uint32 index)
  398. {
  399. TTDComparePath::PathEntry next{ index, nullptr };
  400. this->CheckConsistentAndAddPtrIdMapping_Helper(h1PtrId, h2PtrId, TTDComparePath::StepKind::Scope, next);
  401. }
  402. void TTDCompareMap::CheckConsistentAndAddPtrIdMapping_FunctionBody(TTD_PTR_ID h1PtrId, TTD_PTR_ID h2PtrId)
  403. {
  404. TTDComparePath::PathEntry next{ -1, _u("!body") };
  405. this->CheckConsistentAndAddPtrIdMapping_Helper(h1PtrId, h2PtrId, TTDComparePath::StepKind::FunctionBody, next);
  406. }
  407. void TTDCompareMap::CheckConsistentAndAddPtrIdMapping_Special(TTD_PTR_ID h1PtrId, TTD_PTR_ID h2PtrId, const char16* specialField)
  408. {
  409. TTDComparePath::PathEntry next{ -1, specialField };
  410. this->CheckConsistentAndAddPtrIdMapping_Helper(h1PtrId, h2PtrId, TTDComparePath::StepKind::Special, next);
  411. }
  412. void TTDCompareMap::CheckConsistentAndAddPtrIdMapping_Root(TTD_PTR_ID h1PtrId, TTD_PTR_ID h2PtrId, TTD_LOG_PTR_ID tag)
  413. {
  414. TTDComparePath::PathEntry next{ (uint32)tag, nullptr };
  415. this->CheckConsistentAndAddPtrIdMapping_Helper(h1PtrId, h2PtrId, TTDComparePath::StepKind::Root, next);
  416. }
  417. void TTDCompareMap::CheckConsistentAndAddPtrIdMapping_NoEnqueue(TTD_PTR_ID h1PtrId, TTD_PTR_ID h2PtrId)
  418. {
  419. if(h1PtrId == TTD_INVALID_PTR_ID || h2PtrId == TTD_INVALID_PTR_ID)
  420. {
  421. this->DiagnosticAssert(h1PtrId == TTD_INVALID_PTR_ID && h2PtrId == TTD_INVALID_PTR_ID);
  422. }
  423. else if(this->H1PtrToH2PtrMap.ContainsKey(h1PtrId))
  424. {
  425. this->DiagnosticAssert(this->H1PtrToH2PtrMap.Item(h1PtrId) == h2PtrId);
  426. }
  427. else
  428. {
  429. this->H1PtrToH2PtrMap.AddNew(h1PtrId, h2PtrId);
  430. }
  431. }
  432. void TTDCompareMap::GetNextCompareInfo(TTDCompareTag* tag, TTD_PTR_ID* h1PtrId, TTD_PTR_ID* h2PtrId)
  433. {
  434. if(this->H1PtrIdWorklist.Empty())
  435. {
  436. *tag = TTDCompareTag::Done;
  437. *h1PtrId = TTD_INVALID_PTR_ID;
  438. *h2PtrId = TTD_INVALID_PTR_ID;
  439. }
  440. else
  441. {
  442. *h1PtrId = this->H1PtrIdWorklist.Dequeue();
  443. *h2PtrId = this->H1PtrToH2PtrMap.Item(*h1PtrId);
  444. this->CurrentPath = this->H1PtrToPathMap.Item(*h1PtrId);
  445. this->CurrentH1Ptr = *h1PtrId;
  446. this->CurrentH2Ptr = *h2PtrId;
  447. if(this->H1SlotArrayMap.ContainsKey(*h1PtrId))
  448. {
  449. this->DiagnosticAssert(this->H2SlotArrayMap.ContainsKey(*h2PtrId));
  450. *tag = TTDCompareTag::SlotArray;
  451. }
  452. else if(this->H1FunctionScopeInfoMap.ContainsKey(*h1PtrId))
  453. {
  454. this->DiagnosticAssert(this->H2FunctionScopeInfoMap.ContainsKey(*h2PtrId));
  455. *tag = TTDCompareTag::FunctionScopeInfo;
  456. }
  457. else if(this->H1FunctionTopLevelLoadMap.ContainsKey(*h1PtrId))
  458. {
  459. this->DiagnosticAssert(this->H2FunctionTopLevelLoadMap.ContainsKey(*h2PtrId));
  460. *tag = TTDCompareTag::TopLevelLoadFunction;
  461. }
  462. else if(this->H1FunctionTopLevelNewMap.ContainsKey(*h1PtrId))
  463. {
  464. this->DiagnosticAssert(this->H2FunctionTopLevelNewMap.ContainsKey(*h2PtrId));
  465. *tag = TTDCompareTag::TopLevelNewFunction;
  466. }
  467. else if(this->H1FunctionTopLevelEvalMap.ContainsKey(*h1PtrId))
  468. {
  469. this->DiagnosticAssert(this->H2FunctionTopLevelEvalMap.ContainsKey(*h2PtrId));
  470. *tag = TTDCompareTag::TopLevelEvalFunction;
  471. }
  472. else if(this->H1FunctionBodyMap.ContainsKey(*h1PtrId))
  473. {
  474. this->DiagnosticAssert(this->H2FunctionBodyMap.ContainsKey(*h2PtrId));
  475. *tag = TTDCompareTag::FunctionBody;
  476. }
  477. else if(this->H1ObjectMap.ContainsKey(*h1PtrId))
  478. {
  479. this->DiagnosticAssert(this->H2ObjectMap.ContainsKey(*h2PtrId));
  480. *tag = TTDCompareTag::SnapObject;
  481. }
  482. else
  483. {
  484. TTDAssert(!this->H1ValueMap.ContainsKey(*h1PtrId), "Should be comparing by value!!!");
  485. TTDAssert(false, "Id not found in any of the maps!!!");
  486. *tag = TTDCompareTag::Done;
  487. }
  488. }
  489. }
  490. void TTDCompareMap::GetCompareValues(TTDCompareTag compareTag, TTD_PTR_ID h1PtrId, const NSSnapValues::SlotArrayInfo** val1, TTD_PTR_ID h2PtrId, const NSSnapValues::SlotArrayInfo** val2)
  491. {
  492. TTDAssert(compareTag == TTDCompareTag::SlotArray, "Should be a type");
  493. *val1 = this->H1SlotArrayMap.Item(h1PtrId);
  494. *val2 = this->H2SlotArrayMap.Item(h2PtrId);
  495. }
  496. void TTDCompareMap::GetCompareValues(TTDCompareTag compareTag, TTD_PTR_ID h1PtrId, const NSSnapValues::ScriptFunctionScopeInfo** val1, TTD_PTR_ID h2PtrId, const NSSnapValues::ScriptFunctionScopeInfo** val2)
  497. {
  498. TTDAssert(compareTag == TTDCompareTag::FunctionScopeInfo, "Should be a type");
  499. *val1 = this->H1FunctionScopeInfoMap.Item(h1PtrId);
  500. *val2 = this->H2FunctionScopeInfoMap.Item(h2PtrId);
  501. }
  502. void TTDCompareMap::GetCompareValues(TTDCompareTag compareTag, TTD_PTR_ID h1PtrId, uint64* val1, TTD_PTR_ID h2PtrId, uint64* val2)
  503. {
  504. if(compareTag == TTDCompareTag::TopLevelLoadFunction)
  505. {
  506. *val1 = this->H1FunctionTopLevelLoadMap.Item(h1PtrId);
  507. *val2 = this->H2FunctionTopLevelLoadMap.Item(h2PtrId);
  508. }
  509. else if(compareTag == TTDCompareTag::TopLevelNewFunction)
  510. {
  511. *val1 = this->H1FunctionTopLevelNewMap.Item(h1PtrId);
  512. *val2 = this->H2FunctionTopLevelNewMap.Item(h2PtrId);
  513. }
  514. else
  515. {
  516. TTDAssert(compareTag == TTDCompareTag::TopLevelEvalFunction, "Should be a type");
  517. *val1 = this->H1FunctionTopLevelEvalMap.Item(h1PtrId);
  518. *val2 = this->H2FunctionTopLevelEvalMap.Item(h2PtrId);
  519. }
  520. }
  521. void TTDCompareMap::GetCompareValues(TTDCompareTag compareTag, TTD_PTR_ID h1PtrId, const NSSnapValues::FunctionBodyResolveInfo** val1, TTD_PTR_ID h2PtrId, const NSSnapValues::FunctionBodyResolveInfo** val2)
  522. {
  523. TTDAssert(compareTag == TTDCompareTag::FunctionBody, "Should be a type");
  524. *val1 = this->H1FunctionBodyMap.Item(h1PtrId);
  525. *val2 = this->H2FunctionBodyMap.Item(h2PtrId);
  526. }
  527. void TTDCompareMap::GetCompareValues(TTDCompareTag compareTag, TTD_PTR_ID h1PtrId, const NSSnapObjects::SnapObject** val1, TTD_PTR_ID h2PtrId, const NSSnapObjects::SnapObject** val2)
  528. {
  529. TTDAssert(compareTag == TTDCompareTag::SnapObject, "Should be a type");
  530. *val1 = this->H1ObjectMap.Item(h1PtrId);
  531. *val2 = this->H2ObjectMap.Item(h2PtrId);
  532. }
  533. #endif
  534. }
  535. #endif