TTInflateMap.cpp 27 KB

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