TTSnapshot.cpp 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  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. void SnapShot::EmitSnapshotToFile(FileWriter* writer, ThreadContext* threadContext) const
  10. {
  11. TTDTimer timer;
  12. double startWrite = timer.Now();
  13. writer->WriteRecordStart();
  14. writer->AdjustIndent(1);
  15. uint64 usedSpace = 0;
  16. uint64 reservedSpace = 0;
  17. this->ComputeSnapshotMemory(&usedSpace, &reservedSpace);
  18. writer->WriteDouble(NSTokens::Key::timeTotal, this->GCTime + this->MarkTime + this->ExtractTime);
  19. writer->WriteUInt64(NSTokens::Key::usedMemory, usedSpace, NSTokens::Separator::CommaSeparator);
  20. writer->WriteUInt64(NSTokens::Key::reservedMemory, reservedSpace, NSTokens::Separator::CommaSeparator);
  21. writer->WriteDouble(NSTokens::Key::timeGC, this->GCTime, NSTokens::Separator::CommaSeparator);
  22. writer->WriteDouble(NSTokens::Key::timeMark, this->MarkTime, NSTokens::Separator::CommaSeparator);
  23. writer->WriteDouble(NSTokens::Key::timeExtract, this->ExtractTime, NSTokens::Separator::CommaSeparator);
  24. writer->WriteLengthValue(this->m_ctxList.Count(), NSTokens::Separator::CommaAndBigSpaceSeparator);
  25. writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaAndBigSpaceSeparator);
  26. writer->AdjustIndent(1);
  27. bool firstCtx = true;
  28. for(auto iter = this->m_ctxList.GetIterator(); iter.IsValid(); iter.MoveNext())
  29. {
  30. NSSnapValues::EmitSnapContext(iter.Current(), writer, firstCtx ? NSTokens::Separator::BigSpaceSeparator : NSTokens::Separator::CommaAndBigSpaceSeparator);
  31. firstCtx = false;
  32. }
  33. writer->AdjustIndent(-1);
  34. writer->WriteSequenceEnd(NSTokens::Separator::BigSpaceSeparator);
  35. writer->WriteLengthValue(this->m_tcSymbolRegistrationMapContents.Count(), NSTokens::Separator::CommaAndBigSpaceSeparator);
  36. writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
  37. bool firstTCSymbol = true;
  38. for(auto iter = this->m_tcSymbolRegistrationMapContents.GetIterator(); iter.IsValid(); iter.MoveNext())
  39. {
  40. writer->WriteNakedUInt32((uint32)*iter.Current(), firstTCSymbol ? NSTokens::Separator::NoSeparator : NSTokens::Separator::CommaSeparator);
  41. firstTCSymbol = false;
  42. }
  43. writer->WriteSequenceEnd();
  44. writer->WriteLogTag(NSTokens::Key::ctxTag, this->m_activeScriptContext, NSTokens::Separator::CommaAndBigSpaceSeparator);
  45. SnapShot::EmitListHelper(&SnapShot::SnapRootPinEntryEmit, this->m_rootList, writer);
  46. ////
  47. SnapShot::EmitListHelper(&NSSnapType::EmitSnapHandler, this->m_handlerList, writer);
  48. SnapShot::EmitListHelper(&NSSnapType::EmitSnapType, this->m_typeList, writer);
  49. ////
  50. writer->WriteLengthValue(this->m_functionBodyList.Count(), NSTokens::Separator::CommaAndBigSpaceSeparator);
  51. writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaAndBigSpaceSeparator);
  52. writer->AdjustIndent(1);
  53. bool firstBody = true;
  54. for(auto iter = this->m_functionBodyList.GetIterator(); iter.IsValid(); iter.MoveNext())
  55. {
  56. NSSnapValues::EmitFunctionBodyInfo(iter.Current(), writer, firstBody ? NSTokens::Separator::BigSpaceSeparator : NSTokens::Separator::CommaAndBigSpaceSeparator);
  57. firstBody = false;
  58. }
  59. writer->AdjustIndent(-1);
  60. writer->WriteSequenceEnd(NSTokens::Separator::BigSpaceSeparator);
  61. SnapShot::EmitListHelper(&NSSnapValues::EmitSnapPrimitiveValue, this->m_primitiveObjectList, writer);
  62. writer->WriteLengthValue(this->m_compoundObjectList.Count(), NSTokens::Separator::CommaAndBigSpaceSeparator);
  63. writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaAndBigSpaceSeparator);
  64. writer->AdjustIndent(1);
  65. bool firstObj = true;
  66. for(auto iter = this->m_compoundObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  67. {
  68. NSSnapObjects::EmitObject(iter.Current(), writer, firstObj ? NSTokens::Separator::BigSpaceSeparator : NSTokens::Separator::CommaAndBigSpaceSeparator, this->m_snapObjectVTableArray, threadContext);
  69. firstObj = false;
  70. }
  71. writer->AdjustIndent(-1);
  72. writer->WriteSequenceEnd(NSTokens::Separator::BigSpaceSeparator);
  73. ////
  74. SnapShot::EmitListHelper(&NSSnapValues::EmitScriptFunctionScopeInfo, this->m_scopeEntries, writer);
  75. SnapShot::EmitListHelper(&NSSnapValues::EmitSlotArrayInfo, this->m_slotArrayEntries, writer);
  76. ////
  77. double almostEndWrite = timer.Now();
  78. writer->WriteDouble(NSTokens::Key::timeWrite, (almostEndWrite - startWrite) / 1000.0, NSTokens::Separator::CommaAndBigSpaceSeparator);
  79. writer->AdjustIndent(-1);
  80. writer->WriteRecordEnd(NSTokens::Separator::BigSpaceSeparator);
  81. }
  82. SnapShot* SnapShot::ParseSnapshotFromFile(FileReader* reader)
  83. {
  84. reader->ReadRecordStart();
  85. reader->ReadDouble(NSTokens::Key::timeTotal);
  86. reader->ReadUInt64(NSTokens::Key::usedMemory, true);
  87. reader->ReadUInt64(NSTokens::Key::reservedMemory, true);
  88. reader->ReadDouble(NSTokens::Key::timeGC, true);
  89. reader->ReadDouble(NSTokens::Key::timeMark, true);
  90. reader->ReadDouble(NSTokens::Key::timeExtract, true);
  91. SnapShot* snap = TT_HEAP_NEW(SnapShot, 0.0);
  92. uint32 ctxCount = reader->ReadLengthValue(true);
  93. reader->ReadSequenceStart_WDefaultKey(true);
  94. for(uint32 i = 0; i < ctxCount; ++i)
  95. {
  96. NSSnapValues::SnapContext* snpCtx = snap->m_ctxList.NextOpenEntry();
  97. NSSnapValues::ParseSnapContext(snpCtx, i != 0, reader, snap->GetSnapshotSlabAllocator());
  98. }
  99. reader->ReadSequenceEnd();
  100. uint32 tcSymbolCount = reader->ReadLengthValue(true);
  101. reader->ReadSequenceStart_WDefaultKey(true);
  102. for(uint32 i = 0; i < tcSymbolCount; ++i)
  103. {
  104. Js::PropertyId* symid = snap->m_tcSymbolRegistrationMapContents.NextOpenEntry();
  105. *symid = reader->ReadNakedUInt32(i != 0);
  106. }
  107. reader->ReadSequenceEnd();
  108. snap->m_activeScriptContext = reader->ReadLogTag(NSTokens::Key::ctxTag, true);
  109. SnapShot::ParseListHelper(&SnapShot::SnapRootPinEntryParse, snap->m_rootList, reader, snap->GetSnapshotSlabAllocator());
  110. ////
  111. SnapShot::ParseListHelper(&NSSnapType::ParseSnapHandler, snap->m_handlerList, reader, snap->GetSnapshotSlabAllocator());
  112. TTDIdentifierDictionary<TTD_PTR_ID, NSSnapType::SnapHandler*> handlerMap;
  113. handlerMap.Initialize(snap->m_handlerList.Count());
  114. for(auto iter = snap->m_handlerList.GetIterator(); iter.IsValid(); iter.MoveNext())
  115. {
  116. handlerMap.AddItem(iter.Current()->HandlerId, iter.Current());
  117. }
  118. SnapShot::ParseListHelper_WMap(&NSSnapType::ParseSnapType, snap->m_typeList, reader, snap->GetSnapshotSlabAllocator(), handlerMap);
  119. TTDIdentifierDictionary<TTD_PTR_ID, NSSnapType::SnapType*> typeMap;
  120. typeMap.Initialize(snap->m_typeList.Count());
  121. for(auto iter = snap->m_typeList.GetIterator(); iter.IsValid(); iter.MoveNext())
  122. {
  123. typeMap.AddItem(iter.Current()->TypePtrId, iter.Current());
  124. }
  125. ////
  126. uint32 bodyCount = reader->ReadLengthValue(true);
  127. reader->ReadSequenceStart_WDefaultKey(true);
  128. for(uint32 i = 0; i < bodyCount; ++i)
  129. {
  130. NSSnapValues::FunctionBodyResolveInfo* into = snap->m_functionBodyList.NextOpenEntry();
  131. NSSnapValues::ParseFunctionBodyInfo(into, i != 0, reader, snap->GetSnapshotSlabAllocator());
  132. }
  133. reader->ReadSequenceEnd();
  134. SnapShot::ParseListHelper_WMap(&NSSnapValues::ParseSnapPrimitiveValue, snap->m_primitiveObjectList, reader, snap->GetSnapshotSlabAllocator(), typeMap);
  135. uint32 objCount = reader->ReadLengthValue(true);
  136. reader->ReadSequenceStart_WDefaultKey(true);
  137. for(uint32 i = 0; i < objCount; ++i)
  138. {
  139. NSSnapObjects::SnapObject* into = snap->m_compoundObjectList.NextOpenEntry();
  140. NSSnapObjects::ParseObject(into, i != 0, reader, snap->GetSnapshotSlabAllocator(), snap->m_snapObjectVTableArray, typeMap);
  141. }
  142. reader->ReadSequenceEnd();
  143. ////
  144. SnapShot::ParseListHelper(&NSSnapValues::ParseScriptFunctionScopeInfo, snap->m_scopeEntries, reader, snap->GetSnapshotSlabAllocator());
  145. SnapShot::ParseListHelper(&NSSnapValues::ParseSlotArrayInfo, snap->m_slotArrayEntries, reader, snap->GetSnapshotSlabAllocator());
  146. reader->ReadDouble(NSTokens::Key::timeWrite, true);
  147. reader->ReadRecordEnd();
  148. return snap;
  149. }
  150. void SnapShot::InflateSingleObject(const NSSnapObjects::SnapObject* snpObject, InflateMap* inflator, const TTDIdentifierDictionary<TTD_PTR_ID, NSSnapObjects::SnapObject*>& idToSnpObjectMap) const
  151. {
  152. if(inflator->IsObjectAlreadyInflated(snpObject->ObjectPtrId))
  153. {
  154. return;
  155. }
  156. if(snpObject->OptDependsOnInfo != nullptr)
  157. {
  158. for(uint32 i = 0; i < snpObject->OptDependsOnInfo->DepOnCount; ++i)
  159. {
  160. const NSSnapObjects::SnapObject* depOnObj = idToSnpObjectMap.LookupKnownItem(snpObject->OptDependsOnInfo->DepOnPtrArray[i]);
  161. //This is recursive but should be shallow
  162. this->InflateSingleObject(depOnObj, inflator, idToSnpObjectMap);
  163. }
  164. }
  165. Js::RecyclableObject* res = nullptr;
  166. if(snpObject->OptWellKnownToken != TTD_INVALID_WELLKNOWN_TOKEN)
  167. {
  168. Js::ScriptContext* ctx = inflator->LookupScriptContext(snpObject->SnapType->ScriptContextLogId);
  169. res = ctx->TTDWellKnownInfo->LookupKnownObjectFromPath(snpObject->OptWellKnownToken);
  170. //Well known objects may always be dirty (e.g. we are re-using a context) so we always want to clean them
  171. res = NSSnapObjects::ObjectPropertyReset_WellKnown(snpObject, Js::DynamicObject::FromVar(res), inflator);
  172. TTDAssert(res != nullptr, "Should always produce a result!!!");
  173. }
  174. else
  175. {
  176. //lookup the inflator function for this object and call it
  177. NSSnapObjects::fPtr_DoObjectInflation inflateFPtr = this->m_snapObjectVTableArray[(uint32)snpObject->SnapObjectTag].InflationFunc;
  178. if(inflateFPtr == nullptr)
  179. {
  180. char buff[1024];
  181. sprintf_s(buff, "We probably forgot to update the vtable with a tag we added. Tag is [%i]. SnapRuntimeFunctionObject is [%i]", (uint32)snpObject->SnapObjectTag, TTD::NSSnapObjects::SnapObjectType::SnapRuntimeFunctionObject);
  182. TTDAssert(inflateFPtr != nullptr, buff);
  183. }
  184. res = inflateFPtr(snpObject, inflator);
  185. }
  186. if(Js::DynamicType::Is(snpObject->SnapType->JsTypeId))
  187. {
  188. //Always ok to be x-site but if snap was x-site then we must be too
  189. Js::DynamicObject* dynObj = Js::DynamicObject::FromVar(res);
  190. if(snpObject->IsCrossSite && !dynObj->IsCrossSiteObject())
  191. {
  192. Js::CrossSite::MarshalCrossSite_TTDInflate(dynObj);
  193. }
  194. }
  195. inflator->AddObject(snpObject->ObjectPtrId, res);
  196. }
  197. void SnapShot::ReLinkThreadContextInfo(InflateMap* inflator, ThreadContextTTD* intoCtx) const
  198. {
  199. for(auto iter = this->m_rootList.GetIterator(); iter.IsValid(); iter.MoveNext())
  200. {
  201. const NSSnapValues::SnapRootInfoEntry* rootEntry = iter.Current();
  202. Js::RecyclableObject* rootObj = inflator->LookupObject(rootEntry->LogObject);
  203. intoCtx->ForceSetRootInfoInRestore(rootEntry->LogId, rootObj, rootEntry->MaybeLongLivedRoot);
  204. }
  205. if(this->m_activeScriptContext == TTD_INVALID_LOG_PTR_ID)
  206. {
  207. intoCtx->TTDExternalObjectFunctions.pfSetActiveJsRTContext(intoCtx->GetRuntimeHandle(), nullptr);
  208. }
  209. else
  210. {
  211. Js::ScriptContext* ctx = inflator->LookupScriptContext(this->m_activeScriptContext);
  212. intoCtx->TTDExternalObjectFunctions.pfSetActiveJsRTContext(intoCtx->GetRuntimeHandle(), ctx);
  213. }
  214. }
  215. void SnapShot::SnapRootPinEntryEmit(const NSSnapValues::SnapRootInfoEntry* spe, FileWriter* snapwriter, NSTokens::Separator separator)
  216. {
  217. snapwriter->WriteRecordStart(separator);
  218. snapwriter->WriteLogTag(NSTokens::Key::logTag, spe->LogId);
  219. snapwriter->WriteAddr(NSTokens::Key::objectId, spe->LogObject, NSTokens::Separator::CommaSeparator);
  220. snapwriter->WriteBool(NSTokens::Key::boolVal, spe->MaybeLongLivedRoot, NSTokens::Separator::CommaSeparator);
  221. snapwriter->WriteRecordEnd();
  222. }
  223. void SnapShot::SnapRootPinEntryParse(NSSnapValues::SnapRootInfoEntry* spe, bool readSeparator, FileReader* reader, SlabAllocator& alloc)
  224. {
  225. reader->ReadRecordStart(readSeparator);
  226. spe->LogId = reader->ReadLogTag(NSTokens::Key::logTag);
  227. spe->LogObject = reader->ReadAddr(NSTokens::Key::objectId, true);
  228. spe->MaybeLongLivedRoot = reader->ReadBool(NSTokens::Key::boolVal, true);
  229. reader->ReadRecordEnd();
  230. }
  231. void SnapShot::ComputeSnapshotMemory(uint64* usedSpace, uint64* reservedSpace) const
  232. {
  233. return this->m_slabAllocator.ComputeMemoryUsed(usedSpace, reservedSpace);
  234. }
  235. SnapShot::SnapShot(double gcTime)
  236. : m_slabAllocator(TTD_SLAB_BLOCK_ALLOCATION_SIZE_LARGE),
  237. m_ctxList(&this->m_slabAllocator), m_tcSymbolRegistrationMapContents(&this->m_slabAllocator), m_activeScriptContext(TTD_INVALID_LOG_PTR_ID),
  238. m_rootList(&this->m_slabAllocator),
  239. m_handlerList(&this->m_slabAllocator), m_typeList(&this->m_slabAllocator),
  240. m_functionBodyList(&this->m_slabAllocator), m_primitiveObjectList(&this->m_slabAllocator), m_compoundObjectList(&this->m_slabAllocator),
  241. m_scopeEntries(&this->m_slabAllocator), m_slotArrayEntries(&this->m_slabAllocator),
  242. m_snapObjectVTableArray(nullptr),
  243. GCTime(gcTime), MarkTime(0.0), ExtractTime(0.0)
  244. {
  245. this->m_snapObjectVTableArray = this->m_slabAllocator.SlabAllocateArray<NSSnapObjects::SnapObjectVTable>((uint32)NSSnapObjects::SnapObjectType::Limit);
  246. memset(this->m_snapObjectVTableArray, 0, sizeof(NSSnapObjects::SnapObjectVTable) * (uint32)NSSnapObjects::SnapObjectType::Limit);
  247. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::Invalid] = { nullptr, nullptr, nullptr, nullptr };
  248. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapUnhandledObject] = { nullptr, nullptr, nullptr, nullptr };
  249. ////
  250. //For the objects that have inflators
  251. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapDynamicObject] = { &NSSnapObjects::DoObjectInflation_SnapDynamicObject, nullptr, nullptr, nullptr };
  252. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapExternalObject] = { &NSSnapObjects::DoObjectInflation_SnapExternalObject, nullptr, nullptr, nullptr };
  253. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapScriptFunctionObject] = { &NSSnapObjects::DoObjectInflation_SnapScriptFunctionInfo, &NSSnapObjects::DoAddtlValueInstantiation_SnapScriptFunctionInfo, &NSSnapObjects::EmitAddtlInfo_SnapScriptFunctionInfo, &NSSnapObjects::ParseAddtlInfo_SnapScriptFunctionInfo };
  254. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapRuntimeFunctionObject] = { nullptr, nullptr, nullptr, nullptr }; //should always be wellknown objects and the extra state is in the functionbody defs
  255. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapExternalFunctionObject] = { &NSSnapObjects::DoObjectInflation_SnapExternalFunctionInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapExternalFunctionInfo, &NSSnapObjects::ParseAddtlInfo_SnapExternalFunctionInfo };
  256. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapRuntimeRevokerFunctionObject] = { &NSSnapObjects::DoObjectInflation_SnapRevokerFunctionInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapRevokerFunctionInfo, &NSSnapObjects::ParseAddtlInfo_SnapRevokerFunctionInfo };
  257. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapBoundFunctionObject] = { &NSSnapObjects::DoObjectInflation_SnapBoundFunctionInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapBoundFunctionInfo, &NSSnapObjects::ParseAddtlInfo_SnapBoundFunctionInfo };
  258. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapActivationObject] = { &NSSnapObjects::DoObjectInflation_SnapActivationInfo, nullptr, nullptr, nullptr };
  259. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapBlockActivationObject] = { &NSSnapObjects::DoObjectInflation_SnapBlockActivationObject, nullptr, nullptr, nullptr };
  260. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapPseudoActivationObject] = { &NSSnapObjects::DoObjectInflation_SnapPseudoActivationObject, nullptr, nullptr, nullptr };
  261. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapConsoleScopeActivationObject] = { &NSSnapObjects::DoObjectInflation_SnapConsoleScopeActivationObject, nullptr, nullptr, nullptr };
  262. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapHeapArgumentsObject] = { &NSSnapObjects::DoObjectInflation_SnapHeapArgumentsInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapHeapArgumentsInfo<NSSnapObjects::SnapObjectType::SnapHeapArgumentsObject>, &NSSnapObjects::ParseAddtlInfo_SnapHeapArgumentsInfo<NSSnapObjects::SnapObjectType::SnapHeapArgumentsObject> };
  263. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapES5HeapArgumentsObject] = { &NSSnapObjects::DoObjectInflation_SnapES5HeapArgumentsInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapHeapArgumentsInfo<NSSnapObjects::SnapObjectType::SnapES5HeapArgumentsObject>, &NSSnapObjects::ParseAddtlInfo_SnapHeapArgumentsInfo<NSSnapObjects::SnapObjectType::SnapES5HeapArgumentsObject> };
  264. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapBoxedValueObject] = { &NSSnapObjects::DoObjectInflation_SnapBoxedValue, &NSSnapObjects::DoAddtlValueInstantiation_SnapBoxedValue, &NSSnapObjects::EmitAddtlInfo_SnapBoxedValue, &NSSnapObjects::ParseAddtlInfo_SnapBoxedValue };
  265. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapDateObject] = { &NSSnapObjects::DoObjectInflation_SnapDate, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapDate, &NSSnapObjects::ParseAddtlInfo_SnapDate };
  266. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapRegexObject] = { &NSSnapObjects::DoObjectInflation_SnapRegexInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapRegexInfo, &NSSnapObjects::ParseAddtlInfo_SnapRegexInfo };
  267. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapErrorObject] = { &NSSnapObjects::DoObjectInflation_SnapError, nullptr, nullptr, nullptr };
  268. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapArrayObject] = { &NSSnapObjects::DoObjectInflation_SnapArrayInfo<Js::Var, NSSnapObjects::SnapObjectType::SnapArrayObject>, &NSSnapObjects::DoAddtlValueInstantiation_SnapArrayInfo<TTDVar, Js::Var, NSSnapObjects::SnapObjectType::SnapArrayObject>, &NSSnapObjects::EmitAddtlInfo_SnapArrayInfo<TTDVar, NSSnapObjects::SnapObjectType::SnapArrayObject>, &NSSnapObjects::ParseAddtlInfo_SnapArrayInfo<TTDVar, NSSnapObjects::SnapObjectType::SnapArrayObject> };
  269. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapNativeIntArrayObject] = { &NSSnapObjects::DoObjectInflation_SnapArrayInfo<int32, NSSnapObjects::SnapObjectType::SnapNativeIntArrayObject>, &NSSnapObjects::DoAddtlValueInstantiation_SnapArrayInfo<int32, int32, NSSnapObjects::SnapObjectType::SnapNativeIntArrayObject>, &NSSnapObjects::EmitAddtlInfo_SnapArrayInfo<int32, NSSnapObjects::SnapObjectType::SnapNativeIntArrayObject>, &NSSnapObjects::ParseAddtlInfo_SnapArrayInfo<int32, NSSnapObjects::SnapObjectType::SnapNativeIntArrayObject> };
  270. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapNativeFloatArrayObject] = { &NSSnapObjects::DoObjectInflation_SnapArrayInfo<double, NSSnapObjects::SnapObjectType::SnapNativeFloatArrayObject>, &NSSnapObjects::DoAddtlValueInstantiation_SnapArrayInfo<double, double, NSSnapObjects::SnapObjectType::SnapNativeFloatArrayObject>, &NSSnapObjects::EmitAddtlInfo_SnapArrayInfo<double, NSSnapObjects::SnapObjectType::SnapNativeFloatArrayObject>, &NSSnapObjects::ParseAddtlInfo_SnapArrayInfo<double, NSSnapObjects::SnapObjectType::SnapNativeFloatArrayObject> };
  271. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapES5ArrayObject] = { &NSSnapObjects::DoObjectInflation_SnapES5ArrayInfo, &NSSnapObjects::DoAddtlValueInstantiation_SnapES5ArrayInfo, &NSSnapObjects::EmitAddtlInfo_SnapES5ArrayInfo, &NSSnapObjects::ParseAddtlInfo_SnapES5ArrayInfo };
  272. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapArrayBufferObject] = { &NSSnapObjects::DoObjectInflation_SnapArrayBufferInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapArrayBufferInfo, &NSSnapObjects::ParseAddtlInfo_SnapArrayBufferInfo };
  273. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapTypedArrayObject] = { &NSSnapObjects::DoObjectInflation_SnapTypedArrayInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapTypedArrayInfo, &NSSnapObjects::ParseAddtlInfo_SnapTypedArrayInfo };
  274. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapSetObject] = { &NSSnapObjects::DoObjectInflation_SnapSetInfo, &NSSnapObjects::DoAddtlValueInstantiation_SnapSetInfo, &NSSnapObjects::EmitAddtlInfo_SnapSetInfo, &NSSnapObjects::ParseAddtlInfo_SnapSetInfo };
  275. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapMapObject] = { &NSSnapObjects::DoObjectInflation_SnapMapInfo, &NSSnapObjects::DoAddtlValueInstantiation_SnapMapInfo, &NSSnapObjects::EmitAddtlInfo_SnapMapInfo, &NSSnapObjects::ParseAddtlInfo_SnapMapInfo };
  276. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapProxyObject] = { &NSSnapObjects::DoObjectInflation_SnapProxyInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapProxyInfo, &NSSnapObjects::ParseAddtlInfo_SnapProxyInfo };
  277. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapPromiseObject] = { &NSSnapObjects::DoObjectInflation_SnapPromiseInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapPromiseInfo, &NSSnapObjects::ParseAddtlInfo_SnapPromiseInfo };
  278. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapPromiseResolveOrRejectFunctionObject] = { &NSSnapObjects::DoObjectInflation_SnapPromiseResolveOrRejectFunctionInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapPromiseResolveOrRejectFunctionInfo, &NSSnapObjects::ParseAddtlInfo_SnapPromiseResolveOrRejectFunctionInfo };
  279. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapPromiseReactionTaskFunctionObject] = { &NSSnapObjects::DoObjectInflation_SnapPromiseReactionTaskFunctionInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapPromiseReactionTaskFunctionInfo, &NSSnapObjects::ParseAddtlInfo_SnapPromiseReactionTaskFunctionInfo };
  280. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapPromiseAllResolveElementFunctionObject] = { &NSSnapObjects::DoObjectInflation_SnapPromiseAllResolveElementFunctionInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapPromiseAllResolveElementFunctionInfo, &NSSnapObjects::ParseAddtlInfo_SnapPromiseAllResolveElementFunctionInfo };
  281. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapGeneratorFunction] = {
  282. &NSSnapObjects::DoObjectInflation_SnapGeneratorFunctionInfo,
  283. &NSSnapObjects::DoAddtlValueInstantiation_SnapGeneratorFunctionInfo,
  284. &NSSnapObjects::EmitAddtlInfo_SnapGeneratorFunctionInfo,
  285. &NSSnapObjects::ParseAddtlInfo_SnapGeneratorFunctionInfo };
  286. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapGeneratorVirtualScriptFunction] = {
  287. &NSSnapObjects::DoObjectInflation_SnapGeneratorVirtualScriptFunctionInfo,
  288. &NSSnapObjects::DoAddtlValueInstantiation_SnapGeneratorVirtualScriptFunctionInfo,
  289. &NSSnapObjects::EmitAddtlInfo_SnapGeneratorVirtualScriptFunctionInfo,
  290. &NSSnapObjects::ParseAddtlInfo_SnapGeneratorVirtualScriptFunctionInfo };
  291. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapAsyncFunction] = {
  292. &NSSnapObjects::DoObjectInflation_SnapAsyncFunction,
  293. &NSSnapObjects::DoAddtlValueInstantiation_SnapAsyncFunction,
  294. &NSSnapObjects::EmitAddtlInfo_SnapAsyncFunction,
  295. &NSSnapObjects::ParseAddtlInfo_SnapAsyncFunction
  296. };
  297. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapGenerator] = {
  298. &NSSnapObjects::DoObjectInflation_SnapGeneratorInfo,
  299. &NSSnapObjects::DoAddtlValueInstantiation_SnapGeneratorInfo,
  300. &NSSnapObjects::EmitAddtlInfo_SnapGeneratorInfo,
  301. &NSSnapObjects::ParseAddtlInfo_SnapGeneratorInfo };
  302. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::JavascriptPromiseAsyncSpawnExecutorFunction] = {
  303. &NSSnapObjects::DoObjectInflation_SnapJavascriptPromiseAsyncSpawnExecutorFunction,
  304. &NSSnapObjects::DoAddtlValueInstantiation_SnapJavascriptPromiseAsyncSpawnExecutorFunction,
  305. &NSSnapObjects::EmitAddtlInfo_SnapJavascriptPromiseAsyncSpawnExecutorFunction,
  306. &NSSnapObjects::ParseAddtlInfo_SnapJavascriptPromiseAsyncSpawnExecutorFunction
  307. };
  308. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::JavascriptPromiseAsyncSpawnStepArgumentExecutorFunction] = {
  309. &NSSnapObjects::DoObjectInflation_SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo,
  310. &NSSnapObjects::DoAddtlValueInstantiation_SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo,
  311. &NSSnapObjects::EmitAddtlInfo_SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo,
  312. &NSSnapObjects::ParseAddtlInfo_SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo
  313. };
  314. ////
  315. //For the objects that are always well known
  316. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapWellKnownObject] = { nullptr, nullptr, nullptr, nullptr };
  317. }
  318. SnapShot::~SnapShot()
  319. {
  320. ;
  321. }
  322. uint32 SnapShot::ContextCount() const
  323. {
  324. return this->m_ctxList.Count();
  325. }
  326. uint32 SnapShot::HandlerCount() const
  327. {
  328. return this->m_handlerList.Count();
  329. }
  330. uint32 SnapShot::TypeCount() const
  331. {
  332. return this->m_typeList.Count();
  333. }
  334. uint32 SnapShot::BodyCount() const
  335. {
  336. return this->m_functionBodyList.Count();
  337. }
  338. uint32 SnapShot::PrimitiveCount() const
  339. {
  340. return this->m_primitiveObjectList.Count();
  341. }
  342. uint32 SnapShot::ObjectCount() const
  343. {
  344. return this->m_compoundObjectList.Count();
  345. }
  346. uint32 SnapShot::EnvCount() const
  347. {
  348. return this->m_scopeEntries.Count();
  349. }
  350. uint32 SnapShot::SlotArrayCount() const
  351. {
  352. return this->m_slotArrayEntries.Count();
  353. }
  354. uint32 SnapShot::GetDbgScopeCountNonTopLevel() const
  355. {
  356. uint32 dbgScopeCount = 0;
  357. for(auto iter = this->m_functionBodyList.GetIterator(); iter.IsValid(); iter.MoveNext())
  358. {
  359. dbgScopeCount += iter.Current()->ScopeChainInfo.ScopeCount;
  360. }
  361. return dbgScopeCount;
  362. }
  363. UnorderedArrayList<NSSnapValues::SnapContext, TTD_ARRAY_LIST_SIZE_XSMALL>& SnapShot::GetContextList()
  364. {
  365. return this->m_ctxList;
  366. }
  367. const UnorderedArrayList<NSSnapValues::SnapContext, TTD_ARRAY_LIST_SIZE_XSMALL>& SnapShot::GetContextList() const
  368. {
  369. return this->m_ctxList;
  370. }
  371. UnorderedArrayList<Js::PropertyId, TTD_ARRAY_LIST_SIZE_XSMALL>& SnapShot::GetTCSymbolMapInfoList()
  372. {
  373. return this->m_tcSymbolRegistrationMapContents;
  374. }
  375. TTD_LOG_PTR_ID SnapShot::GetActiveScriptContext() const
  376. {
  377. return this->m_activeScriptContext;
  378. }
  379. void SnapShot::SetActiveScriptContext(TTD_LOG_PTR_ID activeCtx)
  380. {
  381. this->m_activeScriptContext = activeCtx;
  382. }
  383. UnorderedArrayList<NSSnapValues::SnapRootInfoEntry, TTD_ARRAY_LIST_SIZE_MID>& SnapShot::GetRootList()
  384. {
  385. return this->m_rootList;
  386. }
  387. NSSnapType::SnapHandler* SnapShot::GetNextAvailableHandlerEntry()
  388. {
  389. return this->m_handlerList.NextOpenEntry();
  390. }
  391. NSSnapType::SnapType* SnapShot::GetNextAvailableTypeEntry()
  392. {
  393. return this->m_typeList.NextOpenEntry();
  394. }
  395. NSSnapValues::FunctionBodyResolveInfo* SnapShot::GetNextAvailableFunctionBodyResolveInfoEntry()
  396. {
  397. return this->m_functionBodyList.NextOpenEntry();
  398. }
  399. NSSnapValues::SnapPrimitiveValue* SnapShot::GetNextAvailablePrimitiveObjectEntry()
  400. {
  401. return this->m_primitiveObjectList.NextOpenEntry();
  402. }
  403. NSSnapObjects::SnapObject* SnapShot::GetNextAvailableCompoundObjectEntry()
  404. {
  405. return this->m_compoundObjectList.NextOpenEntry();
  406. }
  407. NSSnapValues::ScriptFunctionScopeInfo* SnapShot::GetNextAvailableFunctionScopeEntry()
  408. {
  409. return this->m_scopeEntries.NextOpenEntry();
  410. }
  411. NSSnapValues::SlotArrayInfo* SnapShot::GetNextAvailableSlotArrayEntry()
  412. {
  413. return this->m_slotArrayEntries.NextOpenEntry();
  414. }
  415. SlabAllocator& SnapShot::GetSnapshotSlabAllocator()
  416. {
  417. return this->m_slabAllocator;
  418. }
  419. bool SnapShot::AllWellKnownObjectsReusable(InflateMap* inflator) const
  420. {
  421. for(auto iter = this->m_compoundObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  422. {
  423. const NSSnapObjects::SnapObject* snpObj = iter.Current();
  424. if(snpObj->OptWellKnownToken != TTD_INVALID_WELLKNOWN_TOKEN)
  425. {
  426. Js::RecyclableObject* rObj = inflator->FindReusableObject_WellKnowReuseCheck(snpObj->ObjectPtrId);
  427. bool blocking = NSSnapObjects::DoesObjectBlockScriptContextReuse(snpObj, Js::DynamicObject::FromVar(rObj), inflator);
  428. if(blocking)
  429. {
  430. return false;
  431. }
  432. }
  433. }
  434. return true;
  435. }
  436. void SnapShot::Inflate(InflateMap* inflator, ThreadContextTTD* tCtx) const
  437. {
  438. //We assume the caller has inflated all of the ScriptContexts for us and we are just filling in the objects
  439. ////
  440. //set the map from all function body ids to their snap representations
  441. TTDIdentifierDictionary<TTD_PTR_ID, NSSnapValues::FunctionBodyResolveInfo*> idToSnpBodyMap;
  442. idToSnpBodyMap.Initialize(this->m_functionBodyList.Count());
  443. for(auto iter = this->m_functionBodyList.GetIterator(); iter.IsValid(); iter.MoveNext())
  444. {
  445. idToSnpBodyMap.AddItem(iter.Current()->FunctionBodyId, iter.Current());
  446. }
  447. //set the map from all compound object ids to their snap representations
  448. TTDIdentifierDictionary<TTD_PTR_ID, NSSnapObjects::SnapObject*> idToSnpObjectMap;
  449. idToSnpObjectMap.Initialize(this->m_compoundObjectList.Count());
  450. for(auto iter = this->m_compoundObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  451. {
  452. idToSnpObjectMap.AddItem(iter.Current()->ObjectPtrId, iter.Current());
  453. }
  454. ////
  455. //inflate all the function bodies
  456. for(auto iter = this->m_functionBodyList.GetIterator(); iter.IsValid(); iter.MoveNext())
  457. {
  458. const NSSnapValues::FunctionBodyResolveInfo* fbInfo = iter.Current();
  459. NSSnapValues::InflateFunctionBody(fbInfo, inflator, idToSnpBodyMap);
  460. }
  461. //inflate all the primitive objects
  462. for(auto iter = this->m_primitiveObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  463. {
  464. const NSSnapValues::SnapPrimitiveValue* pSnap = iter.Current();
  465. NSSnapValues::InflateSnapPrimitiveValue(pSnap, inflator);
  466. }
  467. //inflate all the regular objects
  468. for(auto iter = this->m_compoundObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  469. {
  470. const NSSnapObjects::SnapObject* sObj = iter.Current();
  471. this->InflateSingleObject(sObj, inflator, idToSnpObjectMap);
  472. }
  473. //take care of all the slot arrays
  474. for(auto iter = this->m_slotArrayEntries.GetIterator(); iter.IsValid(); iter.MoveNext())
  475. {
  476. const NSSnapValues::SlotArrayInfo* sai = iter.Current();
  477. Field(Js::Var)* slots = NSSnapValues::InflateSlotArrayInfo(sai, inflator);
  478. inflator->AddSlotArray(sai->SlotId, slots);
  479. }
  480. //and the scope entries
  481. for(auto iter = this->m_scopeEntries.GetIterator(); iter.IsValid(); iter.MoveNext())
  482. {
  483. const NSSnapValues::ScriptFunctionScopeInfo* sfsi = iter.Current();
  484. Js::FrameDisplay* frame = NSSnapValues::InflateScriptFunctionScopeInfo(sfsi, inflator);
  485. inflator->AddEnvironment(sfsi->ScopeId, frame);
  486. }
  487. //Link up the object pointers
  488. for(auto iter = this->m_compoundObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  489. {
  490. const NSSnapObjects::SnapObject* sobj = iter.Current();
  491. Js::RecyclableObject* iobj = inflator->LookupObject(sobj->ObjectPtrId);
  492. NSSnapObjects::fPtr_DoAddtlValueInstantiation addtlInstFPtr = this->m_snapObjectVTableArray[(uint32)sobj->SnapObjectTag].AddtlInstationationFunc;
  493. if(addtlInstFPtr != nullptr)
  494. {
  495. addtlInstFPtr(sobj, iobj, inflator);
  496. }
  497. if(Js::DynamicType::Is(sobj->SnapType->JsTypeId))
  498. {
  499. NSSnapObjects::StdPropertyRestore(sobj, Js::DynamicObject::FromVar(iobj), inflator);
  500. }
  501. }
  502. this->ReLinkThreadContextInfo(inflator, tCtx);
  503. for(auto iter = this->m_ctxList.GetIterator(); iter.IsValid(); iter.MoveNext())
  504. {
  505. const NSSnapValues::SnapContext* snpCtx = iter.Current();
  506. Js::ScriptContext* sctx = inflator->LookupScriptContext(snpCtx->ScriptContextLogId);
  507. NSSnapValues::ResetPendingAsyncBufferModInfo(snpCtx, sctx, inflator);
  508. }
  509. //reset the threadContext symbol map
  510. JsUtil::BaseDictionary<Js::HashedCharacterBuffer<char16>*, const Js::PropertyRecord*, Recycler, PowerOf2SizePolicy, Js::PropertyRecordStringHashComparer>* tcSymbolRegistrationMap = tCtx->GetThreadContext()->GetSymbolRegistrationMap_TTD();
  511. tcSymbolRegistrationMap->Clear();
  512. for(auto iter = this->m_tcSymbolRegistrationMapContents.GetIterator(); iter.IsValid(); iter.MoveNext())
  513. {
  514. Js::PropertyId pid = *iter.Current();
  515. const Js::PropertyRecord* pRecord = tCtx->GetThreadContext()->GetPropertyName(pid);
  516. Js::HashedCharacterBuffer<char16> * propertyName = RecyclerNew(tCtx->GetThreadContext()->GetRecycler(), Js::HashedCharacterBuffer<char16>, pRecord->GetBuffer(), pRecord->GetLength());
  517. tcSymbolRegistrationMap->Add(propertyName, pRecord);
  518. }
  519. }
  520. void SnapShot::EmitSnapshot(int64 snapId, ThreadContext* threadContext) const
  521. {
  522. char asciiResourceName[64];
  523. sprintf_s(asciiResourceName, 64, "snap_%I64i.snp", snapId);
  524. TTDataIOInfo& iofp = threadContext->TTDContext->TTDataIOInfo;
  525. JsTTDStreamHandle snapHandle = iofp.pfOpenResourceStream(iofp.ActiveTTUriLength, iofp.ActiveTTUri, strlen(asciiResourceName), asciiResourceName, false, true);
  526. TTDAssert(snapHandle != nullptr, "Failed to open snapshot resource stream for writing.");
  527. TTD_SNAP_WRITER snapwriter(snapHandle, iofp.pfWriteBytesToStream, iofp.pfFlushAndCloseStream);
  528. this->EmitSnapshotToFile(&snapwriter, threadContext);
  529. snapwriter.FlushAndClose();
  530. }
  531. SnapShot* SnapShot::Parse(int64 snapId, ThreadContext* threadContext)
  532. {
  533. char asciiResourceName[64];
  534. sprintf_s(asciiResourceName, 64, "snap_%I64i.snp", snapId);
  535. TTDataIOInfo& iofp = threadContext->TTDContext->TTDataIOInfo;
  536. JsTTDStreamHandle snapHandle = iofp.pfOpenResourceStream(iofp.ActiveTTUriLength, iofp.ActiveTTUri, strlen(asciiResourceName), asciiResourceName, true, false);
  537. TTDAssert(snapHandle != nullptr, "Failed to open snapshot resource stream for reading.");
  538. TTD_SNAP_READER snapreader(snapHandle, iofp.pfReadBytesFromStream, iofp.pfFlushAndCloseStream);
  539. SnapShot* snap = SnapShot::ParseSnapshotFromFile(&snapreader);
  540. return snap;
  541. }
  542. #if ENABLE_SNAPSHOT_COMPARE
  543. void SnapShot::InitializeForSnapshotCompare(const SnapShot* snap1, const SnapShot* snap2, TTDCompareMap& compareMap)
  544. {
  545. ////
  546. //Initialize all of the maps
  547. //top-level functions
  548. for(auto iter = snap1->m_ctxList.GetIterator(); iter.IsValid(); iter.MoveNext())
  549. {
  550. const NSSnapValues::SnapContext* ctx = iter.Current();
  551. for(uint32 i = 0; i < ctx->LoadedTopLevelScriptCount; ++i)
  552. {
  553. compareMap.H1FunctionTopLevelLoadMap.AddNew(ctx->LoadedTopLevelScriptArray[i].ContextSpecificBodyPtrId, ctx->LoadedTopLevelScriptArray[i].TopLevelBodyCtr);
  554. }
  555. for(uint32 i = 0; i < ctx->NewFunctionTopLevelScriptCount; ++i)
  556. {
  557. compareMap.H1FunctionTopLevelNewMap.AddNew(ctx->NewFunctionTopLevelScriptArray[i].ContextSpecificBodyPtrId, ctx->NewFunctionTopLevelScriptArray[i].TopLevelBodyCtr);
  558. }
  559. for(uint32 i = 0; i < ctx->EvalTopLevelScriptCount; ++i)
  560. {
  561. compareMap.H1FunctionTopLevelEvalMap.AddNew(ctx->EvalTopLevelScriptArray[i].ContextSpecificBodyPtrId, ctx->EvalTopLevelScriptArray[i].TopLevelBodyCtr);
  562. }
  563. }
  564. for(auto iter = snap2->m_ctxList.GetIterator(); iter.IsValid(); iter.MoveNext())
  565. {
  566. const NSSnapValues::SnapContext* ctx = iter.Current();
  567. for(uint32 i = 0; i < ctx->LoadedTopLevelScriptCount; ++i)
  568. {
  569. compareMap.H2FunctionTopLevelLoadMap.AddNew(ctx->LoadedTopLevelScriptArray[i].ContextSpecificBodyPtrId, ctx->LoadedTopLevelScriptArray[i].TopLevelBodyCtr);
  570. }
  571. for(uint32 i = 0; i < ctx->NewFunctionTopLevelScriptCount; ++i)
  572. {
  573. compareMap.H2FunctionTopLevelNewMap.AddNew(ctx->NewFunctionTopLevelScriptArray[i].ContextSpecificBodyPtrId, ctx->NewFunctionTopLevelScriptArray[i].TopLevelBodyCtr);
  574. }
  575. for(uint32 i = 0; i < ctx->EvalTopLevelScriptCount; ++i)
  576. {
  577. compareMap.H2FunctionTopLevelEvalMap.AddNew(ctx->EvalTopLevelScriptArray[i].ContextSpecificBodyPtrId, ctx->EvalTopLevelScriptArray[i].TopLevelBodyCtr);
  578. }
  579. }
  580. //Values and things
  581. for(auto iter = snap1->m_primitiveObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  582. {
  583. compareMap.H1ValueMap.AddNew(iter.Current()->PrimitiveValueId, iter.Current());
  584. }
  585. for(auto iter = snap2->m_primitiveObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  586. {
  587. compareMap.H2ValueMap.AddNew(iter.Current()->PrimitiveValueId, iter.Current());
  588. }
  589. for(auto iter = snap1->m_slotArrayEntries.GetIterator(); iter.IsValid(); iter.MoveNext())
  590. {
  591. compareMap.H1SlotArrayMap.AddNew(iter.Current()->SlotId, iter.Current());
  592. }
  593. for(auto iter = snap2->m_slotArrayEntries.GetIterator(); iter.IsValid(); iter.MoveNext())
  594. {
  595. compareMap.H2SlotArrayMap.AddNew(iter.Current()->SlotId, iter.Current());
  596. }
  597. for(auto iter = snap1->m_scopeEntries.GetIterator(); iter.IsValid(); iter.MoveNext())
  598. {
  599. compareMap.H1FunctionScopeInfoMap.AddNew(iter.Current()->ScopeId, iter.Current());
  600. }
  601. for(auto iter = snap2->m_scopeEntries.GetIterator(); iter.IsValid(); iter.MoveNext())
  602. {
  603. compareMap.H2FunctionScopeInfoMap.AddNew(iter.Current()->ScopeId, iter.Current());
  604. }
  605. //Bodies and objects
  606. for(auto iter = snap1->m_functionBodyList.GetIterator(); iter.IsValid(); iter.MoveNext())
  607. {
  608. compareMap.H1FunctionBodyMap.AddNew(iter.Current()->FunctionBodyId, iter.Current());
  609. }
  610. for(auto iter = snap2->m_functionBodyList.GetIterator(); iter.IsValid(); iter.MoveNext())
  611. {
  612. compareMap.H2FunctionBodyMap.AddNew(iter.Current()->FunctionBodyId, iter.Current());
  613. }
  614. for(auto iter = snap1->m_compoundObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  615. {
  616. compareMap.H1ObjectMap.AddNew(iter.Current()->ObjectPtrId, iter.Current());
  617. }
  618. for(auto iter = snap2->m_compoundObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  619. {
  620. compareMap.H2ObjectMap.AddNew(iter.Current()->ObjectPtrId, iter.Current());
  621. }
  622. }
  623. void SnapShot::DoSnapshotCompare(const SnapShot* snap1, const SnapShot* snap2, TTDCompareMap& compareMap)
  624. {
  625. //compare the roots to kick things off
  626. compareMap.DiagnosticAssert(snap1->m_rootList.Count() == snap2->m_rootList.Count());
  627. JsUtil::BaseDictionary<TTD_LOG_PTR_ID, NSSnapValues::SnapRootInfoEntry*, HeapAllocator> allRootMap1(&HeapAllocator::Instance);
  628. JsUtil::BaseDictionary<TTD_LOG_PTR_ID, NSSnapValues::SnapRootInfoEntry*, HeapAllocator> allRootMap2(&HeapAllocator::Instance);
  629. for(auto iter1 = snap1->m_rootList.GetIterator(); iter1.IsValid(); iter1.MoveNext())
  630. {
  631. NSSnapValues::SnapRootInfoEntry* rootEntry1 = iter1.Current();
  632. allRootMap1.AddNew(rootEntry1->LogId, rootEntry1);
  633. }
  634. for(auto iter2 = snap2->m_rootList.GetIterator(); iter2.IsValid(); iter2.MoveNext())
  635. {
  636. NSSnapValues::SnapRootInfoEntry* rootEntry2 = iter2.Current();
  637. allRootMap2.AddNew(rootEntry2->LogId, rootEntry2);
  638. bool ll1 = allRootMap1.Item(rootEntry2->LogId)->MaybeLongLivedRoot;
  639. compareMap.DiagnosticAssert(ll1 == rootEntry2->MaybeLongLivedRoot);
  640. TTD_PTR_ID id1 = allRootMap1.Item(rootEntry2->LogId)->LogObject;
  641. compareMap.CheckConsistentAndAddPtrIdMapping_Root(id1, rootEntry2->LogObject, rootEntry2->LogId);
  642. }
  643. //Get the script contexts into the mix
  644. compareMap.DiagnosticAssert(snap1->m_activeScriptContext == snap2->m_activeScriptContext);
  645. compareMap.DiagnosticAssert(snap1->m_ctxList.Count() == snap2->m_ctxList.Count());
  646. for(auto iter1 = snap1->m_ctxList.GetIterator(); iter1.IsValid(); iter1.MoveNext())
  647. {
  648. const NSSnapValues::SnapContext* ctx1 = iter1.Current();
  649. const NSSnapValues::SnapContext* ctx2 = nullptr;
  650. for(auto iter2 = snap2->m_ctxList.GetIterator(); iter2.IsValid(); iter2.MoveNext())
  651. {
  652. if(ctx1->ScriptContextLogId == iter2.Current()->ScriptContextLogId)
  653. {
  654. ctx2 = iter2.Current();
  655. break;
  656. }
  657. }
  658. compareMap.DiagnosticAssert(ctx2 != nullptr);
  659. NSSnapValues::AssertSnapEquiv(ctx1, ctx2, allRootMap1, allRootMap2, compareMap);
  660. }
  661. //compare the contents of the two thread context symbol maps
  662. compareMap.DiagnosticAssert(snap1->m_tcSymbolRegistrationMapContents.Count() == snap2->m_tcSymbolRegistrationMapContents.Count());
  663. for(auto iter1 = snap1->m_tcSymbolRegistrationMapContents.GetIterator(); iter1.IsValid(); iter1.MoveNext())
  664. {
  665. const Js::PropertyId pid1 = *iter1.Current();
  666. bool match = false;
  667. for(auto iter2 = snap2->m_tcSymbolRegistrationMapContents.GetIterator(); iter2.IsValid(); iter2.MoveNext())
  668. {
  669. if(*iter2.Current() == pid1)
  670. {
  671. match = true;
  672. break;
  673. }
  674. }
  675. compareMap.DiagnosticAssert(match);
  676. }
  677. //Iterate on the worklist until we are done
  678. TTDCompareTag ctag = TTDCompareTag::Done;
  679. TTD_PTR_ID ptrId1 = TTD_INVALID_PTR_ID;
  680. TTD_PTR_ID ptrId2 = TTD_INVALID_PTR_ID;
  681. uint32 comparedSlotArrays = 0;
  682. uint32 comparedScopes = 0;
  683. uint32 comparedObjects = 0;
  684. compareMap.GetNextCompareInfo(&ctag, &ptrId1, &ptrId2);
  685. while(ctag != TTDCompareTag::Done)
  686. {
  687. if(ctag == TTDCompareTag::SlotArray)
  688. {
  689. const NSSnapValues::SlotArrayInfo* sai1 = nullptr;
  690. const NSSnapValues::SlotArrayInfo* sai2 = nullptr;
  691. compareMap.GetCompareValues(ctag, ptrId1, &sai1, ptrId2, &sai2);
  692. NSSnapValues::AssertSnapEquiv(sai1, sai2, compareMap);
  693. comparedSlotArrays++;
  694. }
  695. else if(ctag == TTDCompareTag::FunctionScopeInfo)
  696. {
  697. const NSSnapValues::ScriptFunctionScopeInfo* scope1 = nullptr;
  698. const NSSnapValues::ScriptFunctionScopeInfo* scope2 = nullptr;
  699. compareMap.GetCompareValues(ctag, ptrId1, &scope1, ptrId2, &scope2);
  700. NSSnapValues::AssertSnapEquiv(scope1, scope2, compareMap);
  701. comparedScopes++;
  702. }
  703. else if(ctag == TTDCompareTag::TopLevelLoadFunction)
  704. {
  705. uint64 fload1 = 0;
  706. uint64 fload2 = 0;
  707. compareMap.GetCompareValues(ctag, ptrId1, &fload1, ptrId2, &fload2);
  708. compareMap.DiagnosticAssert(fload1 == fload2);
  709. }
  710. else if(ctag == TTDCompareTag::TopLevelNewFunction)
  711. {
  712. uint64 fnew1 = 0;
  713. uint64 fnew2 = 0;
  714. compareMap.GetCompareValues(ctag, ptrId1, &fnew1, ptrId2, &fnew2);
  715. compareMap.DiagnosticAssert(fnew1 == fnew2);
  716. }
  717. else if(ctag == TTDCompareTag::TopLevelEvalFunction)
  718. {
  719. uint64 feval1 = 0;
  720. uint64 feval2 = 0;
  721. compareMap.GetCompareValues(ctag, ptrId1, &feval1, ptrId2, &feval2);
  722. compareMap.DiagnosticAssert(feval1 == feval2);
  723. }
  724. else if(ctag == TTDCompareTag::FunctionBody)
  725. {
  726. const NSSnapValues::FunctionBodyResolveInfo* fb1 = nullptr;
  727. const NSSnapValues::FunctionBodyResolveInfo* fb2 = nullptr;
  728. compareMap.GetCompareValues(ctag, ptrId1, &fb1, ptrId2, &fb2);
  729. NSSnapValues::AssertSnapEquiv(fb1, fb2, compareMap);
  730. }
  731. else if(ctag == TTDCompareTag::SnapObject)
  732. {
  733. const NSSnapObjects::SnapObject* obj1 = nullptr;
  734. const NSSnapObjects::SnapObject* obj2 = nullptr;
  735. compareMap.GetCompareValues(ctag, ptrId1, &obj1, ptrId2, &obj2);
  736. NSSnapObjects::AssertSnapEquiv(obj1, obj2, compareMap);
  737. comparedObjects++;
  738. }
  739. else
  740. {
  741. TTDAssert(false, "Missing tag in case list!!!");
  742. }
  743. compareMap.GetNextCompareInfo(&ctag, &ptrId1, &ptrId2);
  744. }
  745. //Make sure all objects/values have been matched -- well not quite since we don't align and treaverse WeakSet values we might not compare everything -- maybe improve later?
  746. compareMap.DiagnosticAssert(comparedSlotArrays <= snap1->m_slotArrayEntries.Count() && comparedSlotArrays <= snap2->m_slotArrayEntries.Count());
  747. compareMap.DiagnosticAssert(comparedScopes <= snap1->m_scopeEntries.Count() && comparedScopes <= snap2->m_scopeEntries.Count());
  748. compareMap.DiagnosticAssert(comparedObjects <= snap1->m_compoundObjectList.Count() && comparedObjects <= snap2->m_compoundObjectList.Count());
  749. compareMap.DiagnosticAssert(snap1->m_slotArrayEntries.Count() == snap2->m_slotArrayEntries.Count());
  750. compareMap.DiagnosticAssert(snap1->m_scopeEntries.Count() == snap2->m_scopeEntries.Count());
  751. compareMap.DiagnosticAssert(snap1->m_compoundObjectList.Count() == snap2->m_compoundObjectList.Count());
  752. //
  753. //TODO: if we missed something we may want to put code here to identify it
  754. //
  755. }
  756. #endif
  757. }
  758. #endif