TTSnapshot.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  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->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::timeMark, this->MarkTime, NSTokens::Separator::CommaSeparator);
  22. writer->WriteDouble(NSTokens::Key::timeExtract, this->ExtractTime, NSTokens::Separator::CommaSeparator);
  23. writer->WriteLengthValue(this->m_ctxList.Count(), NSTokens::Separator::CommaAndBigSpaceSeparator);
  24. writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaAndBigSpaceSeparator);
  25. writer->AdjustIndent(1);
  26. bool firstCtx = true;
  27. for(auto iter = this->m_ctxList.GetIterator(); iter.IsValid(); iter.MoveNext())
  28. {
  29. NSSnapValues::EmitSnapContext(iter.Current(), writer, firstCtx ? NSTokens::Separator::BigSpaceSeparator : NSTokens::Separator::CommaAndBigSpaceSeparator);
  30. firstCtx = false;
  31. }
  32. writer->AdjustIndent(-1);
  33. writer->WriteSequenceEnd(NSTokens::Separator::BigSpaceSeparator);
  34. ////
  35. SnapShot::EmitListHelper(&NSSnapType::EmitSnapHandler, this->m_handlerList, writer);
  36. SnapShot::EmitListHelper(&NSSnapType::EmitSnapType, this->m_typeList, writer);
  37. ////
  38. writer->WriteLengthValue(this->m_functionBodyList.Count(), NSTokens::Separator::CommaAndBigSpaceSeparator);
  39. writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaAndBigSpaceSeparator);
  40. writer->AdjustIndent(1);
  41. bool firstBody = true;
  42. for(auto iter = this->m_functionBodyList.GetIterator(); iter.IsValid(); iter.MoveNext())
  43. {
  44. NSSnapValues::EmitFunctionBodyInfo(iter.Current(), writer, firstBody ? NSTokens::Separator::BigSpaceSeparator : NSTokens::Separator::CommaAndBigSpaceSeparator);
  45. firstBody = false;
  46. }
  47. writer->AdjustIndent(-1);
  48. writer->WriteSequenceEnd(NSTokens::Separator::BigSpaceSeparator);
  49. SnapShot::EmitListHelper(&NSSnapValues::EmitSnapPrimitiveValue, this->m_primitiveObjectList, writer);
  50. writer->WriteLengthValue(this->m_compoundObjectList.Count(), NSTokens::Separator::CommaAndBigSpaceSeparator);
  51. writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaAndBigSpaceSeparator);
  52. writer->AdjustIndent(1);
  53. bool firstObj = true;
  54. for(auto iter = this->m_compoundObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  55. {
  56. NSSnapObjects::EmitObject(iter.Current(), writer, firstObj ? NSTokens::Separator::BigSpaceSeparator : NSTokens::Separator::CommaAndBigSpaceSeparator, this->m_snapObjectVTableArray, threadContext);
  57. firstObj = false;
  58. }
  59. writer->AdjustIndent(-1);
  60. writer->WriteSequenceEnd(NSTokens::Separator::BigSpaceSeparator);
  61. ////
  62. SnapShot::EmitListHelper(&NSSnapValues::EmitScriptFunctionScopeInfo, this->m_scopeEntries, writer);
  63. SnapShot::EmitListHelper(&NSSnapValues::EmitSlotArrayInfo, this->m_slotArrayEntries, writer);
  64. ////
  65. double almostEndWrite = timer.Now();
  66. writer->WriteDouble(NSTokens::Key::timeWrite, (almostEndWrite - startWrite) / 1000.0, NSTokens::Separator::CommaAndBigSpaceSeparator);
  67. writer->AdjustIndent(-1);
  68. writer->WriteRecordEnd(NSTokens::Separator::BigSpaceSeparator);
  69. }
  70. SnapShot* SnapShot::ParseSnapshotFromFile(FileReader* reader)
  71. {
  72. reader->ReadRecordStart();
  73. reader->ReadDouble(NSTokens::Key::timeTotal);
  74. reader->ReadUInt64(NSTokens::Key::usedMemory, true);
  75. reader->ReadUInt64(NSTokens::Key::reservedMemory, true);
  76. reader->ReadDouble(NSTokens::Key::timeMark, true);
  77. reader->ReadDouble(NSTokens::Key::timeExtract, true);
  78. SnapShot* snap = TT_HEAP_NEW(SnapShot);
  79. uint32 ctxCount = reader->ReadLengthValue(true);
  80. reader->ReadSequenceStart_WDefaultKey(true);
  81. for(uint32 i = 0; i < ctxCount; ++i)
  82. {
  83. NSSnapValues::SnapContext* snpCtx = snap->m_ctxList.NextOpenEntry();
  84. NSSnapValues::ParseSnapContext(snpCtx, i != 0, reader, snap->GetSnapshotSlabAllocator());
  85. }
  86. reader->ReadSequenceEnd();
  87. ////
  88. SnapShot::ParseListHelper(&NSSnapType::ParseSnapHandler, snap->m_handlerList, reader, snap->GetSnapshotSlabAllocator());
  89. TTDIdentifierDictionary<TTD_PTR_ID, NSSnapType::SnapHandler*> handlerMap;
  90. handlerMap.Initialize(snap->m_handlerList.Count());
  91. for(auto iter = snap->m_handlerList.GetIterator(); iter.IsValid(); iter.MoveNext())
  92. {
  93. handlerMap.AddItem(iter.Current()->HandlerId, iter.Current());
  94. }
  95. SnapShot::ParseListHelper_WMap(&NSSnapType::ParseSnapType, snap->m_typeList, reader, snap->GetSnapshotSlabAllocator(), handlerMap);
  96. TTDIdentifierDictionary<TTD_PTR_ID, NSSnapType::SnapType*> typeMap;
  97. typeMap.Initialize(snap->m_typeList.Count());
  98. for(auto iter = snap->m_typeList.GetIterator(); iter.IsValid(); iter.MoveNext())
  99. {
  100. typeMap.AddItem(iter.Current()->TypePtrId, iter.Current());
  101. }
  102. ////
  103. uint32 bodyCount = reader->ReadLengthValue(true);
  104. reader->ReadSequenceStart_WDefaultKey(true);
  105. for(uint32 i = 0; i < bodyCount; ++i)
  106. {
  107. NSSnapValues::FunctionBodyResolveInfo* into = snap->m_functionBodyList.NextOpenEntry();
  108. NSSnapValues::ParseFunctionBodyInfo(into, i != 0, reader, snap->GetSnapshotSlabAllocator());
  109. }
  110. reader->ReadSequenceEnd();
  111. SnapShot::ParseListHelper_WMap(&NSSnapValues::ParseSnapPrimitiveValue, snap->m_primitiveObjectList, reader, snap->GetSnapshotSlabAllocator(), typeMap);
  112. uint32 objCount = reader->ReadLengthValue(true);
  113. reader->ReadSequenceStart_WDefaultKey(true);
  114. for(uint32 i = 0; i < objCount; ++i)
  115. {
  116. NSSnapObjects::SnapObject* into = snap->m_compoundObjectList.NextOpenEntry();
  117. NSSnapObjects::ParseObject(into, i != 0, reader, snap->GetSnapshotSlabAllocator(), snap->m_snapObjectVTableArray, typeMap);
  118. }
  119. reader->ReadSequenceEnd();
  120. ////
  121. SnapShot::ParseListHelper(&NSSnapValues::ParseScriptFunctionScopeInfo, snap->m_scopeEntries, reader, snap->GetSnapshotSlabAllocator());
  122. SnapShot::ParseListHelper(&NSSnapValues::ParseSlotArrayInfo, snap->m_slotArrayEntries, reader, snap->GetSnapshotSlabAllocator());
  123. reader->ReadDouble(NSTokens::Key::timeWrite, true);
  124. reader->ReadRecordEnd();
  125. return snap;
  126. }
  127. void SnapShot::InflateSingleObject(const NSSnapObjects::SnapObject* snpObject, InflateMap* inflator, const TTDIdentifierDictionary<TTD_PTR_ID, NSSnapObjects::SnapObject*>& idToSnpObjectMap) const
  128. {
  129. if(inflator->IsObjectAlreadyInflated(snpObject->ObjectPtrId))
  130. {
  131. return;
  132. }
  133. if(snpObject->OptDependsOnInfo != nullptr)
  134. {
  135. for(uint32 i = 0; i < snpObject->OptDependsOnInfo->DepOnCount; ++i)
  136. {
  137. const NSSnapObjects::SnapObject* depOnObj = idToSnpObjectMap.LookupKnownItem(snpObject->OptDependsOnInfo->DepOnPtrArray[i]);
  138. //This is recursive but should be shallow
  139. this->InflateSingleObject(depOnObj, inflator, idToSnpObjectMap);
  140. }
  141. }
  142. Js::RecyclableObject* res = nullptr;
  143. if(snpObject->OptWellKnownToken != TTD_INVALID_WELLKNOWN_TOKEN)
  144. {
  145. Js::ScriptContext* ctx = inflator->LookupScriptContext(snpObject->SnapType->ScriptContextLogId);
  146. res = ctx->TTDWellKnownInfo->LookupKnownObjectFromPath(snpObject->OptWellKnownToken);
  147. //Well known objects may always be dirty (e.g. we are re-using a context) so we always want to clean them
  148. res = NSSnapObjects::ObjectPropertyReset(snpObject, Js::DynamicObject::FromVar(res), inflator, true);
  149. AssertMsg(res != nullptr, "Should always produce a result!!!");
  150. }
  151. else
  152. {
  153. //lookup the inflator function for this object and call it
  154. NSSnapObjects::fPtr_DoObjectInflation inflateFPtr = this->m_snapObjectVTableArray[(uint32)snpObject->SnapObjectTag].InflationFunc;
  155. AssertMsg(inflateFPtr != nullptr, "We probably forgot to update the vtable with a tag we added.");
  156. res = inflateFPtr(snpObject, inflator);
  157. }
  158. inflator->AddObject(snpObject->ObjectPtrId, res);
  159. }
  160. void SnapShot::ComputeSnapshotMemory(uint64* usedSpace, uint64* reservedSpace) const
  161. {
  162. return this->m_slabAllocator.ComputeMemoryUsed(usedSpace, reservedSpace);
  163. }
  164. SnapShot::SnapShot()
  165. : m_slabAllocator(TTD_SLAB_BLOCK_ALLOCATION_SIZE_LARGE),
  166. m_ctxList(&this->m_slabAllocator), m_handlerList(&this->m_slabAllocator), m_typeList(&this->m_slabAllocator),
  167. m_functionBodyList(&this->m_slabAllocator), m_primitiveObjectList(&this->m_slabAllocator), m_compoundObjectList(&this->m_slabAllocator),
  168. m_scopeEntries(&this->m_slabAllocator), m_slotArrayEntries(&this->m_slabAllocator),
  169. m_snapObjectVTableArray(nullptr),
  170. MarkTime(0.0), ExtractTime(0.0)
  171. {
  172. this->m_snapObjectVTableArray = this->m_slabAllocator.SlabAllocateArray<NSSnapObjects::SnapObjectVTable>((uint32)NSSnapObjects::SnapObjectType::Limit);
  173. memset(this->m_snapObjectVTableArray, 0, sizeof(NSSnapObjects::SnapObjectVTable) * (uint32)NSSnapObjects::SnapObjectType::Limit);
  174. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::Invalid] = { nullptr, nullptr, nullptr, nullptr };
  175. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapUnhandledObject] = { nullptr, nullptr, nullptr, nullptr };
  176. ////
  177. //For the objects that have inflators
  178. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapDynamicObject] = { &NSSnapObjects::DoObjectInflation_SnapDynamicObject, nullptr, nullptr, nullptr };
  179. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapScriptFunctionObject] = { &NSSnapObjects::DoObjectInflation_SnapScriptFunctionInfo, &NSSnapObjects::DoAddtlValueInstantiation_SnapScriptFunctionInfo, &NSSnapObjects::EmitAddtlInfo_SnapScriptFunctionInfo, &NSSnapObjects::ParseAddtlInfo_SnapScriptFunctionInfo };
  180. 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
  181. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapExternalFunctionObject] = { &NSSnapObjects::DoObjectInflation_SnapExternalFunctionInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapExternalFunctionInfo, &NSSnapObjects::ParseAddtlInfo_SnapExternalFunctionInfo };
  182. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapRuntimeRevokerFunctionObject] = { &NSSnapObjects::DoObjectInflation_SnapRevokerFunctionInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapRevokerFunctionInfo, &NSSnapObjects::ParseAddtlInfo_SnapRevokerFunctionInfo };
  183. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapBoundFunctionObject] = { &NSSnapObjects::DoObjectInflation_SnapBoundFunctionInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapBoundFunctionInfo, &NSSnapObjects::ParseAddtlInfo_SnapBoundFunctionInfo };
  184. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapActivationObject] = { &NSSnapObjects::DoObjectInflation_SnapActivationInfo, nullptr, nullptr, nullptr };
  185. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapBlockActivationObject] = { &NSSnapObjects::DoObjectInflation_SnapBlockActivationObject, nullptr, nullptr, nullptr };
  186. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapPseudoActivationObject] = { &NSSnapObjects::DoObjectInflation_SnapPseudoActivationObject, nullptr, nullptr, nullptr };
  187. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapConsoleScopeActivationObject] = { &NSSnapObjects::DoObjectInflation_SnapConsoleScopeActivationObject, nullptr, nullptr, nullptr };
  188. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapActivationObjectEx] = { &NSSnapObjects::DoObjectInflation_SnapActivationExInfo, nullptr, nullptr, nullptr };
  189. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapHeapArgumentsObject] = { &NSSnapObjects::DoObjectInflation_SnapHeapArgumentsInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapHeapArgumentsInfo<NSSnapObjects::SnapObjectType::SnapHeapArgumentsObject>, &NSSnapObjects::ParseAddtlInfo_SnapHeapArgumentsInfo<NSSnapObjects::SnapObjectType::SnapHeapArgumentsObject> };
  190. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapES5HeapArgumentsObject] = { &NSSnapObjects::DoObjectInflation_SnapES5HeapArgumentsInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapHeapArgumentsInfo<NSSnapObjects::SnapObjectType::SnapES5HeapArgumentsObject>, &NSSnapObjects::ParseAddtlInfo_SnapHeapArgumentsInfo<NSSnapObjects::SnapObjectType::SnapES5HeapArgumentsObject> };
  191. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapBoxedValueObject] = { &NSSnapObjects::DoObjectInflation_SnapBoxedValue, &NSSnapObjects::DoAddtlValueInstantiation_SnapBoxedValue, &NSSnapObjects::EmitAddtlInfo_SnapBoxedValue, &NSSnapObjects::ParseAddtlInfo_SnapBoxedValue };
  192. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapDateObject] = { &NSSnapObjects::DoObjectInflation_SnapDate, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapDate, &NSSnapObjects::ParseAddtlInfo_SnapDate };
  193. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapRegexObject] = { &NSSnapObjects::DoObjectInflation_SnapRegexInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapRegexInfo, &NSSnapObjects::ParseAddtlInfo_SnapRegexInfo };
  194. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapErrorObject] = { &NSSnapObjects::DoObjectInflation_SnapError, nullptr, nullptr, nullptr };
  195. 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> };
  196. 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> };
  197. 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> };
  198. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapES5ArrayObject] = { &NSSnapObjects::DoObjectInflation_SnapES5ArrayInfo, &NSSnapObjects::DoAddtlValueInstantiation_SnapES5ArrayInfo, &NSSnapObjects::EmitAddtlInfo_SnapES5ArrayInfo, &NSSnapObjects::ParseAddtlInfo_SnapES5ArrayInfo };
  199. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapArrayBufferObject] = { &NSSnapObjects::DoObjectInflation_SnapArrayBufferInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapArrayBufferInfo, &NSSnapObjects::ParseAddtlInfo_SnapArrayBufferInfo };
  200. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapTypedArrayObject] = { &NSSnapObjects::DoObjectInflation_SnapTypedArrayInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapTypedArrayInfo, &NSSnapObjects::ParseAddtlInfo_SnapTypedArrayInfo };
  201. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapSetObject] = { &NSSnapObjects::DoObjectInflation_SnapSetInfo, &NSSnapObjects::DoAddtlValueInstantiation_SnapSetInfo, &NSSnapObjects::EmitAddtlInfo_SnapSetInfo, &NSSnapObjects::ParseAddtlInfo_SnapSetInfo };
  202. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapMapObject] = { &NSSnapObjects::DoObjectInflation_SnapMapInfo, &NSSnapObjects::DoAddtlValueInstantiation_SnapMapInfo, &NSSnapObjects::EmitAddtlInfo_SnapMapInfo, &NSSnapObjects::ParseAddtlInfo_SnapMapInfo };
  203. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapProxyObject] = { &NSSnapObjects::DoObjectInflation_SnapProxyInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapProxyInfo, &NSSnapObjects::ParseAddtlInfo_SnapProxyInfo };
  204. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapPromiseObject] = { &NSSnapObjects::DoObjectInflation_SnapPromiseInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapPromiseInfo, &NSSnapObjects::ParseAddtlInfo_SnapPromiseInfo };
  205. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapPromiseResolveOrRejectFunctionObject] = { &NSSnapObjects::DoObjectInflation_SnapPromiseResolveOrRejectFunctionInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapPromiseResolveOrRejectFunctionInfo, &NSSnapObjects::ParseAddtlInfo_SnapPromiseResolveOrRejectFunctionInfo };
  206. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapPromiseReactionTaskFunctionObject] = { &NSSnapObjects::DoObjectInflation_SnapPromiseReactionTaskFunctionInfo, nullptr, &NSSnapObjects::EmitAddtlInfo_SnapPromiseReactionTaskFunctionInfo, &NSSnapObjects::ParseAddtlInfo_SnapPromiseReactionTaskFunctionInfo };
  207. ////
  208. //For the objects that are always well known
  209. this->m_snapObjectVTableArray[(uint32)NSSnapObjects::SnapObjectType::SnapWellKnownObject] = { nullptr, nullptr, nullptr, nullptr };
  210. }
  211. SnapShot::~SnapShot()
  212. {
  213. ;
  214. }
  215. uint32 SnapShot::ContextCount() const
  216. {
  217. return this->m_ctxList.Count();
  218. }
  219. uint32 SnapShot::HandlerCount() const
  220. {
  221. return this->m_handlerList.Count();
  222. }
  223. uint32 SnapShot::TypeCount() const
  224. {
  225. return this->m_typeList.Count();
  226. }
  227. uint32 SnapShot::BodyCount() const
  228. {
  229. return this->m_functionBodyList.Count();
  230. }
  231. uint32 SnapShot::PrimitiveCount() const
  232. {
  233. return this->m_primitiveObjectList.Count();
  234. }
  235. uint32 SnapShot::ObjectCount() const
  236. {
  237. return this->m_compoundObjectList.Count();
  238. }
  239. uint32 SnapShot::EnvCount() const
  240. {
  241. return this->m_scopeEntries.Count();
  242. }
  243. uint32 SnapShot::SlotArrayCount() const
  244. {
  245. return this->m_slotArrayEntries.Count();
  246. }
  247. uint32 SnapShot::GetDbgScopeCountNonTopLevel() const
  248. {
  249. uint32 dbgScopeCount = 0;
  250. for(auto iter = this->m_functionBodyList.GetIterator(); iter.IsValid(); iter.MoveNext())
  251. {
  252. dbgScopeCount += iter.Current()->ScopeChainInfo.ScopeCount;
  253. }
  254. return dbgScopeCount;
  255. }
  256. UnorderedArrayList<NSSnapValues::SnapContext, TTD_ARRAY_LIST_SIZE_XSMALL>& SnapShot::GetContextList()
  257. {
  258. return this->m_ctxList;
  259. }
  260. const UnorderedArrayList<NSSnapValues::SnapContext, TTD_ARRAY_LIST_SIZE_XSMALL>& SnapShot::GetContextList() const
  261. {
  262. return this->m_ctxList;
  263. }
  264. NSSnapType::SnapHandler* SnapShot::GetNextAvailableHandlerEntry()
  265. {
  266. return this->m_handlerList.NextOpenEntry();
  267. }
  268. NSSnapType::SnapType* SnapShot::GetNextAvailableTypeEntry()
  269. {
  270. return this->m_typeList.NextOpenEntry();
  271. }
  272. NSSnapValues::FunctionBodyResolveInfo* SnapShot::GetNextAvailableFunctionBodyResolveInfoEntry()
  273. {
  274. return this->m_functionBodyList.NextOpenEntry();
  275. }
  276. NSSnapValues::SnapPrimitiveValue* SnapShot::GetNextAvailablePrimitiveObjectEntry()
  277. {
  278. return this->m_primitiveObjectList.NextOpenEntry();
  279. }
  280. NSSnapObjects::SnapObject* SnapShot::GetNextAvailableCompoundObjectEntry()
  281. {
  282. return this->m_compoundObjectList.NextOpenEntry();
  283. }
  284. NSSnapValues::ScriptFunctionScopeInfo* SnapShot::GetNextAvailableFunctionScopeEntry()
  285. {
  286. return this->m_scopeEntries.NextOpenEntry();
  287. }
  288. NSSnapValues::SlotArrayInfo* SnapShot::GetNextAvailableSlotArrayEntry()
  289. {
  290. return this->m_slotArrayEntries.NextOpenEntry();
  291. }
  292. SlabAllocator& SnapShot::GetSnapshotSlabAllocator()
  293. {
  294. return this->m_slabAllocator;
  295. }
  296. void SnapShot::Inflate(InflateMap* inflator, const NSSnapValues::SnapContext* sCtx) const
  297. {
  298. //We assume the caller has inflated all of the ScriptContexts for us and we are just filling in the objects
  299. ////
  300. //set the map from all function body ids to their snap representations
  301. TTDIdentifierDictionary<TTD_PTR_ID, NSSnapValues::FunctionBodyResolveInfo*> idToSnpBodyMap;
  302. idToSnpBodyMap.Initialize(this->m_functionBodyList.Count());
  303. for(auto iter = this->m_functionBodyList.GetIterator(); iter.IsValid(); iter.MoveNext())
  304. {
  305. idToSnpBodyMap.AddItem(iter.Current()->FunctionBodyId, iter.Current());
  306. }
  307. //set the map from all compound object ids to their snap representations
  308. TTDIdentifierDictionary<TTD_PTR_ID, NSSnapObjects::SnapObject*> idToSnpObjectMap;
  309. idToSnpObjectMap.Initialize(this->m_compoundObjectList.Count());
  310. for(auto iter = this->m_compoundObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  311. {
  312. idToSnpObjectMap.AddItem(iter.Current()->ObjectPtrId, iter.Current());
  313. }
  314. ////
  315. //inflate all the function bodies
  316. for(auto iter = this->m_functionBodyList.GetIterator(); iter.IsValid(); iter.MoveNext())
  317. {
  318. const NSSnapValues::FunctionBodyResolveInfo* fbInfo = iter.Current();
  319. NSSnapValues::InflateFunctionBody(fbInfo, inflator, idToSnpBodyMap);
  320. }
  321. //inflate all the primitive objects
  322. for(auto iter = this->m_primitiveObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  323. {
  324. const NSSnapValues::SnapPrimitiveValue* pSnap = iter.Current();
  325. NSSnapValues::InflateSnapPrimitiveValue(pSnap, inflator);
  326. }
  327. //inflate all the regular objects
  328. for(auto iter = this->m_compoundObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  329. {
  330. const NSSnapObjects::SnapObject* sObj = iter.Current();
  331. this->InflateSingleObject(sObj, inflator, idToSnpObjectMap);
  332. }
  333. //take care of all the slot arrays
  334. for(auto iter = this->m_slotArrayEntries.GetIterator(); iter.IsValid(); iter.MoveNext())
  335. {
  336. const NSSnapValues::SlotArrayInfo* sai = iter.Current();
  337. Js::Var* slots = NSSnapValues::InflateSlotArrayInfo(sai, inflator);
  338. inflator->AddSlotArray(sai->SlotId, slots);
  339. }
  340. //and the scope entries
  341. for(auto iter = this->m_scopeEntries.GetIterator(); iter.IsValid(); iter.MoveNext())
  342. {
  343. const NSSnapValues::ScriptFunctionScopeInfo* sfsi = iter.Current();
  344. Js::FrameDisplay* frame = NSSnapValues::InflateScriptFunctionScopeInfo(sfsi, inflator);
  345. inflator->AddEnvironment(sfsi->ScopeId, frame);
  346. }
  347. //Link up the object pointers
  348. for(auto iter = this->m_compoundObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  349. {
  350. const NSSnapObjects::SnapObject* sobj = iter.Current();
  351. Js::RecyclableObject* iobj = inflator->LookupObject(sobj->ObjectPtrId);
  352. NSSnapObjects::fPtr_DoAddtlValueInstantiation addtlInstFPtr = this->m_snapObjectVTableArray[(uint32)sobj->SnapObjectTag].AddtlInstationationFunc;
  353. if(addtlInstFPtr != nullptr)
  354. {
  355. addtlInstFPtr(sobj, iobj, inflator);
  356. }
  357. if(Js::DynamicType::Is(sobj->SnapType->JsTypeId))
  358. {
  359. NSSnapObjects::StdPropertyRestore(sobj, Js::DynamicObject::FromVar(iobj), inflator);
  360. }
  361. }
  362. Js::ScriptContext* tCtx = inflator->LookupScriptContext(sCtx->m_scriptContextLogId);
  363. NSSnapValues::ReLinkRoots(sCtx, tCtx, inflator);
  364. NSSnapValues::ResetPendingAsyncBufferModInfo(sCtx, tCtx, inflator);
  365. }
  366. void SnapShot::EmitSnapshot(int64 snapId, ThreadContext* threadContext) const
  367. {
  368. char asciiResourceName[64];
  369. sprintf_s(asciiResourceName, 64, "snap_%I64i.snp", snapId);
  370. JsTTDStreamHandle snapHandle = threadContext->TTDStreamFunctions.pfGetResourceStream(threadContext->TTDUri.UriByteLength, threadContext->TTDUri.UriBytes, asciiResourceName, false, true);
  371. TTD_SNAP_WRITER snapwriter(snapHandle, TTD_COMPRESSED_OUTPUT, threadContext->TTDStreamFunctions.pfWriteBytesToStream, threadContext->TTDStreamFunctions.pfFlushAndCloseStream);
  372. this->EmitSnapshotToFile(&snapwriter, threadContext);
  373. snapwriter.FlushAndClose();
  374. }
  375. SnapShot* SnapShot::Parse(int64 snapId, ThreadContext* threadContext)
  376. {
  377. char asciiResourceName[64];
  378. sprintf_s(asciiResourceName, 64, "snap_%I64i.snp", snapId);
  379. JsTTDStreamHandle snapHandle = threadContext->TTDStreamFunctions.pfGetResourceStream(threadContext->TTDUri.UriByteLength, threadContext->TTDUri.UriBytes, asciiResourceName, true, false);
  380. TTD_SNAP_READER snapreader(snapHandle, TTD_COMPRESSED_OUTPUT, threadContext->TTDStreamFunctions.pfReadBytesFromStream, threadContext->TTDStreamFunctions.pfFlushAndCloseStream);
  381. SnapShot* snap = SnapShot::ParseSnapshotFromFile(&snapreader);
  382. return snap;
  383. }
  384. #if ENABLE_SNAPSHOT_COMPARE
  385. void SnapShot::InitializeForSnapshotCompare(const SnapShot* snap1, const SnapShot* snap2, TTDCompareMap& compareMap)
  386. {
  387. ////
  388. //Initialize all of the maps
  389. //top-level functions
  390. for(auto iter = snap1->m_ctxList.GetIterator(); iter.IsValid(); iter.MoveNext())
  391. {
  392. const NSSnapValues::SnapContext* ctx = iter.Current();
  393. for(uint32 i = 0; i < ctx->m_loadedTopLevelScriptCount; ++i)
  394. {
  395. compareMap.H1FunctionTopLevelLoadMap.AddNew(ctx->m_loadedTopLevelScriptArray[i].ContextSpecificBodyPtrId, ctx->m_loadedTopLevelScriptArray[i].TopLevelBodyCtr);
  396. }
  397. for(uint32 i = 0; i < ctx->m_newFunctionTopLevelScriptCount; ++i)
  398. {
  399. compareMap.H1FunctionTopLevelNewMap.AddNew(ctx->m_newFunctionTopLevelScriptArray[i].ContextSpecificBodyPtrId, ctx->m_newFunctionTopLevelScriptArray[i].TopLevelBodyCtr);
  400. }
  401. for(uint32 i = 0; i < ctx->m_evalTopLevelScriptCount; ++i)
  402. {
  403. compareMap.H1FunctionTopLevelEvalMap.AddNew(ctx->m_evalTopLevelScriptArray[i].ContextSpecificBodyPtrId, ctx->m_evalTopLevelScriptArray[i].TopLevelBodyCtr);
  404. }
  405. }
  406. for(auto iter = snap2->m_ctxList.GetIterator(); iter.IsValid(); iter.MoveNext())
  407. {
  408. const NSSnapValues::SnapContext* ctx = iter.Current();
  409. for(uint32 i = 0; i < ctx->m_loadedTopLevelScriptCount; ++i)
  410. {
  411. compareMap.H2FunctionTopLevelLoadMap.AddNew(ctx->m_loadedTopLevelScriptArray[i].ContextSpecificBodyPtrId, ctx->m_loadedTopLevelScriptArray[i].TopLevelBodyCtr);
  412. }
  413. for(uint32 i = 0; i < ctx->m_newFunctionTopLevelScriptCount; ++i)
  414. {
  415. compareMap.H2FunctionTopLevelNewMap.AddNew(ctx->m_newFunctionTopLevelScriptArray[i].ContextSpecificBodyPtrId, ctx->m_newFunctionTopLevelScriptArray[i].TopLevelBodyCtr);
  416. }
  417. for(uint32 i = 0; i < ctx->m_evalTopLevelScriptCount; ++i)
  418. {
  419. compareMap.H2FunctionTopLevelEvalMap.AddNew(ctx->m_evalTopLevelScriptArray[i].ContextSpecificBodyPtrId, ctx->m_evalTopLevelScriptArray[i].TopLevelBodyCtr);
  420. }
  421. }
  422. //Values and things
  423. for(auto iter = snap1->m_primitiveObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  424. {
  425. compareMap.H1ValueMap.AddNew(iter.Current()->PrimitiveValueId, iter.Current());
  426. }
  427. for(auto iter = snap2->m_primitiveObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  428. {
  429. compareMap.H2ValueMap.AddNew(iter.Current()->PrimitiveValueId, iter.Current());
  430. }
  431. for(auto iter = snap1->m_slotArrayEntries.GetIterator(); iter.IsValid(); iter.MoveNext())
  432. {
  433. compareMap.H1SlotArrayMap.AddNew(iter.Current()->SlotId, iter.Current());
  434. }
  435. for(auto iter = snap2->m_slotArrayEntries.GetIterator(); iter.IsValid(); iter.MoveNext())
  436. {
  437. compareMap.H2SlotArrayMap.AddNew(iter.Current()->SlotId, iter.Current());
  438. }
  439. for(auto iter = snap1->m_scopeEntries.GetIterator(); iter.IsValid(); iter.MoveNext())
  440. {
  441. compareMap.H1FunctionScopeInfoMap.AddNew(iter.Current()->ScopeId, iter.Current());
  442. }
  443. for(auto iter = snap2->m_scopeEntries.GetIterator(); iter.IsValid(); iter.MoveNext())
  444. {
  445. compareMap.H2FunctionScopeInfoMap.AddNew(iter.Current()->ScopeId, iter.Current());
  446. }
  447. //Bodies and objects
  448. for(auto iter = snap1->m_functionBodyList.GetIterator(); iter.IsValid(); iter.MoveNext())
  449. {
  450. compareMap.H1FunctionBodyMap.AddNew(iter.Current()->FunctionBodyId, iter.Current());
  451. }
  452. for(auto iter = snap2->m_functionBodyList.GetIterator(); iter.IsValid(); iter.MoveNext())
  453. {
  454. compareMap.H2FunctionBodyMap.AddNew(iter.Current()->FunctionBodyId, iter.Current());
  455. }
  456. for(auto iter = snap1->m_compoundObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  457. {
  458. compareMap.H1ObjectMap.AddNew(iter.Current()->ObjectPtrId, iter.Current());
  459. }
  460. for(auto iter = snap2->m_compoundObjectList.GetIterator(); iter.IsValid(); iter.MoveNext())
  461. {
  462. compareMap.H2ObjectMap.AddNew(iter.Current()->ObjectPtrId, iter.Current());
  463. }
  464. }
  465. void SnapShot::DoSnapshotCompare(const SnapShot* snap1, const SnapShot* snap2, TTDCompareMap& compareMap)
  466. {
  467. //compare the script contexts to kick things off -- assume single context
  468. const NSSnapValues::SnapContext* ctx1 = snap1->m_ctxList.GetIterator().Current();
  469. const NSSnapValues::SnapContext* ctx2 = snap2->m_ctxList.GetIterator().Current();
  470. NSSnapValues::AssertSnapEquiv(ctx1, ctx2, compareMap);
  471. //Iterate on the worklist until we are done
  472. TTDCompareTag ctag = TTDCompareTag::Done;
  473. TTD_PTR_ID ptrId1 = TTD_INVALID_PTR_ID;
  474. TTD_PTR_ID ptrId2 = TTD_INVALID_PTR_ID;
  475. uint32 comparedSlotArrays = 0;
  476. uint32 comparedScopes = 0;
  477. uint32 comparedObjects = 0;
  478. compareMap.GetNextCompareInfo(&ctag, &ptrId1, &ptrId2);
  479. while(ctag != TTDCompareTag::Done)
  480. {
  481. if(ctag == TTDCompareTag::SlotArray)
  482. {
  483. const NSSnapValues::SlotArrayInfo* sai1 = nullptr;
  484. const NSSnapValues::SlotArrayInfo* sai2 = nullptr;
  485. compareMap.GetCompareValues(ctag, ptrId1, &sai1, ptrId2, &sai2);
  486. NSSnapValues::AssertSnapEquiv(sai1, sai2, compareMap);
  487. comparedSlotArrays++;
  488. }
  489. else if(ctag == TTDCompareTag::FunctionScopeInfo)
  490. {
  491. const NSSnapValues::ScriptFunctionScopeInfo* scope1 = nullptr;
  492. const NSSnapValues::ScriptFunctionScopeInfo* scope2 = nullptr;
  493. compareMap.GetCompareValues(ctag, ptrId1, &scope1, ptrId2, &scope2);
  494. NSSnapValues::AssertSnapEquiv(scope1, scope2, compareMap);
  495. comparedScopes++;
  496. }
  497. else if(ctag == TTDCompareTag::TopLevelLoadFunction)
  498. {
  499. uint64 fload1 = 0;
  500. uint64 fload2 = 0;
  501. compareMap.GetCompareValues(ctag, ptrId1, &fload1, ptrId2, &fload2);
  502. compareMap.DiagnosticAssert(fload1 == fload2);
  503. }
  504. else if(ctag == TTDCompareTag::TopLevelNewFunction)
  505. {
  506. uint64 fnew1 = 0;
  507. uint64 fnew2 = 0;
  508. compareMap.GetCompareValues(ctag, ptrId1, &fnew1, ptrId2, &fnew2);
  509. compareMap.DiagnosticAssert(fnew1 == fnew2);
  510. }
  511. else if(ctag == TTDCompareTag::TopLevelEvalFunction)
  512. {
  513. uint64 feval1 = 0;
  514. uint64 feval2 = 0;
  515. compareMap.GetCompareValues(ctag, ptrId1, &feval1, ptrId2, &feval2);
  516. compareMap.DiagnosticAssert(feval1 == feval2);
  517. }
  518. else if(ctag == TTDCompareTag::FunctionBody)
  519. {
  520. const NSSnapValues::FunctionBodyResolveInfo* fb1 = nullptr;
  521. const NSSnapValues::FunctionBodyResolveInfo* fb2 = nullptr;
  522. compareMap.GetCompareValues(ctag, ptrId1, &fb1, ptrId2, &fb2);
  523. NSSnapValues::AssertSnapEquiv(fb1, fb2, compareMap);
  524. }
  525. else if(ctag == TTDCompareTag::SnapObject)
  526. {
  527. const NSSnapObjects::SnapObject* obj1 = nullptr;
  528. const NSSnapObjects::SnapObject* obj2 = nullptr;
  529. compareMap.GetCompareValues(ctag, ptrId1, &obj1, ptrId2, &obj2);
  530. NSSnapObjects::AssertSnapEquiv(obj1, obj2, compareMap);
  531. comparedObjects++;
  532. }
  533. else
  534. {
  535. AssertMsg(false, "Missing tag in case list!!!");
  536. }
  537. compareMap.GetNextCompareInfo(&ctag, &ptrId1, &ptrId2);
  538. }
  539. //Make sure all objects/values have been matched
  540. //
  541. //TODO: this is weird we do a < since weak sets/maps can't be checked without backtracking or some topo ordering on the keys
  542. //
  543. compareMap.DiagnosticAssert(comparedSlotArrays <= snap1->m_slotArrayEntries.Count() && comparedSlotArrays <= snap2->m_slotArrayEntries.Count());
  544. compareMap.DiagnosticAssert(comparedScopes <= snap1->m_scopeEntries.Count() && comparedScopes <= snap2->m_scopeEntries.Count());
  545. compareMap.DiagnosticAssert(comparedObjects <= snap1->m_compoundObjectList.Count() && comparedObjects <= snap2->m_compoundObjectList.Count());
  546. compareMap.DiagnosticAssert(snap1->m_slotArrayEntries.Count() == snap2->m_slotArrayEntries.Count());
  547. compareMap.DiagnosticAssert(snap1->m_scopeEntries.Count() == snap2->m_scopeEntries.Count());
  548. compareMap.DiagnosticAssert(snap1->m_compoundObjectList.Count() == snap2->m_compoundObjectList.Count());
  549. //
  550. //TODO: if we missed something we may want to put code here to identify it
  551. //
  552. }
  553. #endif
  554. }
  555. #endif