| //------------------------------------------------------------------------------------------------------- |
| // Copyright (C) Microsoft. All rights reserved. |
| // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. |
| //------------------------------------------------------------------------------------------------------- |
| #pragma once |
| |
| #if ENABLE_TTD |
| |
| namespace TTD |
| { |
| //A class that represents a heap snapshot the page context |
| class SnapShot |
| { |
| private: |
| //// |
| //The slab allocator we use for storing the data extracted |
| SlabAllocator m_slabAllocator; |
| |
| //// |
| //List containing the "context" information for the objects in this snapshot |
| UnorderedArrayList<NSSnapValues::SnapContext, TTD_ARRAY_LIST_SIZE_XSMALL> m_ctxList; |
| |
| //List containing all the propertyids for the symbols that are in the thread context symbolRegistrationMap |
| UnorderedArrayList<Js::PropertyId, TTD_ARRAY_LIST_SIZE_XSMALL> m_tcSymbolRegistrationMapContents; |
| |
| //The active script context |
| TTD_LOG_PTR_ID m_activeScriptContext; |
| |
| //A list of all the global root objects and local root objects |
| UnorderedArrayList<NSSnapValues::SnapRootInfoEntry, TTD_ARRAY_LIST_SIZE_MID> m_rootList; |
| |
| //// |
| //Lists containing the "type" information for the objects in this snapshot |
| |
| //The list of all the dynamichandler definitions that the snapshot uses |
| UnorderedArrayList<NSSnapType::SnapHandler, TTD_ARRAY_LIST_SIZE_DEFAULT> m_handlerList; |
| |
| //The list of all the type definitions that the snapshot uses |
| UnorderedArrayList<NSSnapType::SnapType, TTD_ARRAY_LIST_SIZE_DEFAULT> m_typeList; |
| |
| //// |
| //Lists containing the objects in this snapshot |
| |
| //The list of all the type definitions that the snapshot uses |
| UnorderedArrayList<NSSnapValues::FunctionBodyResolveInfo, TTD_ARRAY_LIST_SIZE_DEFAULT> m_functionBodyList; |
| |
| //The list of all the primitive objects (empty until we convert all the primitive pinned objects during extractor unlink) |
| UnorderedArrayList<NSSnapValues::SnapPrimitiveValue, TTD_ARRAY_LIST_SIZE_LARGE> m_primitiveObjectList; |
| |
| //The list of all the non-primitive javascript objects in the snapshot |
| UnorderedArrayList<NSSnapObjects::SnapObject, TTD_ARRAY_LIST_SIZE_LARGE> m_compoundObjectList; |
| |
| //pseudo vtable for working with snap objects |
| NSSnapObjects::SnapObjectVTable* m_snapObjectVTableArray; |
| |
| //// |
| //Function scope info |
| |
| //All the scopes in the snapshot |
| UnorderedArrayList<NSSnapValues::ScriptFunctionScopeInfo, TTD_ARRAY_LIST_SIZE_DEFAULT> m_scopeEntries; |
| |
| //All the slot arrays in the snapshot |
| UnorderedArrayList<NSSnapValues::SlotArrayInfo, TTD_ARRAY_LIST_SIZE_DEFAULT> m_slotArrayEntries; |
| |
| //Emit the json file for the snapshot into the given directory |
| void EmitSnapshotToFile(FileWriter* writer, ThreadContext* threadContext) const; |
| static SnapShot* ParseSnapshotFromFile(FileReader* reader); |
| |
| template<typename Fn, typename T, size_t allocSize> |
| static void EmitListHelper(Fn emitFunc, const UnorderedArrayList<T, allocSize>& list, FileWriter* snapwriter) |
| { |
| snapwriter->WriteLengthValue(list.Count(), NSTokens::Separator::CommaAndBigSpaceSeparator); |
| snapwriter->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaAndBigSpaceSeparator); |
| snapwriter->AdjustIndent(1); |
| bool firstElement = true; |
| for(auto iter = list.GetIterator(); iter.IsValid(); iter.MoveNext()) |
| { |
| (*emitFunc)(iter.Current(), snapwriter, firstElement ? NSTokens::Separator::BigSpaceSeparator : NSTokens::Separator::CommaAndBigSpaceSeparator); |
| firstElement = false; |
| } |
| snapwriter->AdjustIndent(-1); |
| snapwriter->WriteSequenceEnd(NSTokens::Separator::BigSpaceSeparator); |
| } |
| |
| template<typename Fn, typename T, size_t allocSize> |
| static void ParseListHelper(Fn parseFunc, UnorderedArrayList<T, allocSize>& list, FileReader* snapreader, SlabAllocator& alloc) |
| { |
| uint32 count = snapreader->ReadLengthValue(true); |
| snapreader->ReadSequenceStart_WDefaultKey(true); |
| for(uint32 i = 0; i < count; ++i) |
| { |
| T* into = list.NextOpenEntry(); |
| (*parseFunc)(into, i != 0, snapreader, alloc); |
| } |
| snapreader->ReadSequenceEnd(); |
| } |
| |
| template<typename Fn, typename T, typename U, size_t allocSize> |
| static void ParseListHelper_WMap(Fn parseFunc, UnorderedArrayList<T, allocSize>& list, FileReader* snapreader, SlabAllocator& alloc, const TTDIdentifierDictionary<TTD_PTR_ID, U>& infoMap) |
| { |
| uint32 count = snapreader->ReadLengthValue(true); |
| snapreader->ReadSequenceStart_WDefaultKey(true); |
| for(uint32 i = 0; i < count; ++i) |
| { |
| T* into = list.NextOpenEntry(); |
| (*parseFunc)(into, i != 0, snapreader, alloc, infoMap); |
| } |
| snapreader->ReadSequenceEnd(); |
| } |
| |
| //Inflate a single JS object |
| void InflateSingleObject(const NSSnapObjects::SnapObject* snpObject, InflateMap* inflator, const TTDIdentifierDictionary<TTD_PTR_ID, NSSnapObjects::SnapObject*>& idToSnpObjectMap) const; |
| |
| void ReLinkThreadContextInfo(InflateMap* inflator, ThreadContextTTD* intoCtx) const; |
| |
| static void SnapRootPinEntryEmit(const NSSnapValues::SnapRootInfoEntry* spe, FileWriter* snapwriter, NSTokens::Separator separator); |
| static void SnapRootPinEntryParse(NSSnapValues::SnapRootInfoEntry* spe, bool readSeperator, FileReader* reader, SlabAllocator& alloc); |
| |
| public: |
| //Performance counter values |
| double GCTime; |
| double MarkTime; |
| double ExtractTime; |
| |
| //Compute the memory used by this snapshot |
| void ComputeSnapshotMemory(uint64* usedSpace, uint64* reservedSpace) const; |
| |
| SnapShot(double gcTime); |
| ~SnapShot(); |
| |
| //Get the counts for the various list sizes (not constant time -- so use carefully!!!!) |
| uint32 ContextCount() const; |
| uint32 HandlerCount() const; |
| uint32 TypeCount() const; |
| uint32 BodyCount() const; |
| uint32 PrimitiveCount() const; |
| uint32 ObjectCount() const; |
| uint32 EnvCount() const; |
| uint32 SlotArrayCount() const; |
| uint32 GetDbgScopeCountNonTopLevel() const; |
| |
| //Get the context list for this snapshot |
| UnorderedArrayList<NSSnapValues::SnapContext, TTD_ARRAY_LIST_SIZE_XSMALL>& GetContextList(); |
| const UnorderedArrayList<NSSnapValues::SnapContext, TTD_ARRAY_LIST_SIZE_XSMALL>& GetContextList() const; |
| |
| //Get the thread context symbol map info list for this snapshot |
| UnorderedArrayList<Js::PropertyId, TTD_ARRAY_LIST_SIZE_XSMALL>& GetTCSymbolMapInfoList(); |
| |
| TTD_LOG_PTR_ID GetActiveScriptContext() const; |
| void SetActiveScriptContext(TTD_LOG_PTR_ID activeCtx); |
| |
| //Get the root lists |
| UnorderedArrayList<NSSnapValues::SnapRootInfoEntry, TTD_ARRAY_LIST_SIZE_MID>& GetRootList(); |
| |
| //Get a pointer to the next open handler slot that we can fill |
| NSSnapType::SnapHandler* GetNextAvailableHandlerEntry(); |
| |
| //Get a pointer to the next open handler slot that we can fill |
| NSSnapType::SnapType* GetNextAvailableTypeEntry(); |
| |
| //Get a pointer to the next open FunctionBodyResolveInfo slot that we can fill |
| NSSnapValues::FunctionBodyResolveInfo* GetNextAvailableFunctionBodyResolveInfoEntry(); |
| |
| //Get a pointer to the next open primitive object slot that we can fill |
| NSSnapValues::SnapPrimitiveValue* GetNextAvailablePrimitiveObjectEntry(); |
| |
| //Get a pointer to the next open compound object slot that we can fill |
| NSSnapObjects::SnapObject* GetNextAvailableCompoundObjectEntry(); |
| |
| //Get a pointer to the next open scope entry slot that we can fill |
| NSSnapValues::ScriptFunctionScopeInfo* GetNextAvailableFunctionScopeEntry(); |
| |
| //Get a pointer to the next open slot array entry that we can fill |
| NSSnapValues::SlotArrayInfo* GetNextAvailableSlotArrayEntry(); |
| |
| //Get the slab allocator for this snapshot context |
| SlabAllocator& GetSnapshotSlabAllocator(); |
| |
| //Make sure that all well known objects can be re-used -- if not we will need to recreate all script contexts from scratch |
| bool AllWellKnownObjectsReusable(InflateMap* inflator) const; |
| |
| //Inflate the snapshot |
| void Inflate(InflateMap* inflator, ThreadContextTTD* tCtx) const; |
| |
| //serialize the snapshot data |
| void EmitSnapshot(int64 snapId, ThreadContext* threadContext) const; |
| |
| //de-serialize the snapshot data |
| static SnapShot* Parse(int64 snapId, ThreadContext* threadContext); |
| |
| #if ENABLE_SNAPSHOT_COMPARE |
| static void InitializeForSnapshotCompare(const SnapShot* snap1, const SnapShot* snap2, TTDCompareMap& compareMap); |
| |
| static void DoSnapshotCompare(const SnapShot* snap1, const SnapShot* snap2, TTDCompareMap& compareMap); |
| #endif |
| }; |
| } |
| |
| #endif |
| |