| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474 |
- //-------------------------------------------------------------------------------------------------------
- // 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
- {
- class TTDTimer
- {
- private:
- PlatformAgnostic::DateTime::HiResTimer m_timer;
- public:
- TTDTimer()
- : m_timer()
- {
- ;
- }
- ~TTDTimer()
- {
- ;
- }
- double Now()
- {
- return this->m_timer.Now();
- }
- };
- namespace JsSupport
- {
- //return true if the Var is a tagged number (inline)
- bool IsVarTaggedInline(Js::Var v);
- //return true if the Var is a ptr var value
- bool IsVarPtrValued(Js::Var v);
- //return true if the Var is a primitive value (string, number, symbol, etc.)
- bool IsVarPrimitiveKind(Js::Var v);
- //return true if the Var is a richer value (enumerator, dynamicObject, array, etc.)
- bool IsVarComplexKind(Js::Var v);
- #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
- //Check if 2 inline values are equivalent -- JIT can use number vs. Int in interp mode but as long as values mean the same thing we are cool
- bool AreInlineVarsEquiv(Js::Var v1, Js::Var v2);
- #endif
- //Ensure a function is fully parsed/deserialized
- Js::FunctionBody* ForceAndGetFunctionBody(Js::ParseableFunctionInfo* pfi);
- void WriteCodeToFile(ThreadContext* threadContext, bool fromEvent, uint32 bodyId, bool isUtf8Source, byte* sourceBuffer, uint32 length);
- void ReadCodeFromFile(ThreadContext* threadContext, bool fromEvent, uint32 bodyId, bool isUtf8Source, byte* sourceBuffer, uint32 length);
- }
- namespace NSSnapValues
- {
- //////////////////
- //Helpers for TTDVars
- enum class TTDVarEmitTag
- {
- TTDVarInvalid = 0x0,
- TTDVarNull,
- TTDVarInt,
- TTDVarDouble,
- TTDVarAddr
- };
- //serialize the TTDVar
- void EmitTTDVar(TTDVar var, FileWriter* writer, NSTokens::Separator separator);
- //de-serialize the TTDVar
- TTDVar ParseTTDVar(bool readSeparator, FileReader* reader);
- #if ENABLE_SNAPSHOT_COMPARE
- bool CheckSnapEquivTTDDouble(double d1, double d2);
- void AssertSnapEquivTTDVar_Helper(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, TTDComparePath::StepKind stepKind, const TTDComparePath::PathEntry& next);
- void AssertSnapEquivTTDVar_Property(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, Js::PropertyId pid);
- void AssertSnapEquivTTDVar_PropertyGetter(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, Js::PropertyId pid);
- void AssertSnapEquivTTDVar_PropertySetter(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, Js::PropertyId pid);
- void AssertSnapEquivTTDVar_Array(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, uint32 index);
- void AssertSnapEquivTTDVar_SlotArray(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, uint32 index);
- void AssertSnapEquivTTDVar_Special(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, const char16* specialField);
- void AssertSnapEquivTTDVar_SpecialArray(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, const char16* specialField, uint32 index);
- #endif
- //////////////////
- //A structure for the primitive javascript types
- struct SnapPrimitiveValue
- {
- //The id (address of the object)
- TTD_PTR_ID PrimitiveValueId;
- //The type of the primitive value
- NSSnapType::SnapType* SnapType;
- //The optional well known token for this object (or INVALID)
- TTD_WELLKNOWN_TOKEN OptWellKnownToken;
- union
- {
- BOOL u_boolValue;
- int64 u_int64Value;
- uint64 u_uint64Value;
- double u_doubleValue;
- TTString* u_stringValue;
- Js::PropertyId u_propertyIdValue;
- };
- };
- void ExtractSnapPrimitiveValue(SnapPrimitiveValue* snapValue, Js::RecyclableObject* jsValue, bool isWellKnown, const TTDIdentifierDictionary<TTD_PTR_ID, NSSnapType::SnapType*>& idToTypeMap, SlabAllocator& alloc);
- void InflateSnapPrimitiveValue(const SnapPrimitiveValue* snapValue, InflateMap* inflator);
- void EmitSnapPrimitiveValue(const SnapPrimitiveValue* snapValue, FileWriter* writer, NSTokens::Separator separator);
- void ParseSnapPrimitiveValue(SnapPrimitiveValue* snapValue, bool readSeparator, FileReader* reader, SlabAllocator& alloc, const TTDIdentifierDictionary<TTD_PTR_ID, NSSnapType::SnapType*>& ptrIdToTypeMap);
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const SnapPrimitiveValue* v1, const SnapPrimitiveValue* v2, TTDCompareMap& compareMap);
- #endif
- //////////////////
- //If a scope is a slot array this class encodes the slot information and original address of the slot array
- struct SlotArrayInfo
- {
- //The unique id for the slot array scope entry
- TTD_PTR_ID SlotId;
- //The tag of the script context that this slot array is associated with
- TTD_LOG_PTR_ID ScriptContextLogId;
- //The number of slots in the scope array
- uint32 SlotCount;
- //The data values for the slots in the scope entry
- TTDVar* Slots;
- //The property ids associated with each index
- Js::PropertyId* PIDArray;
- //The meta-data for the slot array
- bool isFunctionBodyMetaData;
- TTD_PTR_ID OptFunctionBodyId;
- TTD_PTR_ID OptDebugScopeId;
- TTD_WELLKNOWN_TOKEN OptWellKnownDbgScope;
- };
- Field(Js::Var)* InflateSlotArrayInfo(const SlotArrayInfo* slotInfo, InflateMap* inflator);
- void EmitSlotArrayInfo(const SlotArrayInfo* slotInfo, FileWriter* writer, NSTokens::Separator separator);
- void ParseSlotArrayInfo(SlotArrayInfo* slotInfo, bool readSeparator, FileReader* reader, SlabAllocator& alloc);
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const SlotArrayInfo* sai1, const SlotArrayInfo* sai2, TTDCompareMap& compareMap);
- #endif
- //A struct to represent a single scope entry for a function
- struct ScopeInfoEntry
- {
- //The tag indicating what type of scope entry this is
- Js::ScopeType Tag;
- //The id for looking up the entry data
- //Either ptr object for Activation and With Scopes or the slotid for SlotArray Scopes
- TTD_PTR_ID IDValue;
- };
- //A class to represent a scope list for a script function
- struct ScriptFunctionScopeInfo
- {
- //The unique id for the scope array associated with this function
- TTD_PTR_ID ScopeId;
- //The id of the script context that this slot array is associated with
- TTD_LOG_PTR_ID ScriptContextLogId;
- //The number of scope entries
- uint16 ScopeCount;
- //The array of scope entries this function has
- ScopeInfoEntry* ScopeArray;
- };
- Js::FrameDisplay* InflateScriptFunctionScopeInfo(const ScriptFunctionScopeInfo* funcScopeInfo, InflateMap* inflator);
- void EmitScriptFunctionScopeInfo(const ScriptFunctionScopeInfo* funcScopeInfo, FileWriter* writer, NSTokens::Separator separator);
- void ParseScriptFunctionScopeInfo(ScriptFunctionScopeInfo* funcScopeInfo, bool readSeparator, FileReader* reader, SlabAllocator& alloc);
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const ScriptFunctionScopeInfo* funcScopeInfo1, const ScriptFunctionScopeInfo* funcScopeInfo2, TTDCompareMap& compareMap);
- #endif
- //////////////////
- //Capability info for a promise
- struct SnapPromiseCapabilityInfo
- {
- //The unique id for the capability entry
- TTD_PTR_ID CapabilityId;
- TTDVar PromiseVar;
- TTDVar ResolveVar;
- TTDVar RejectVar;
- };
- Js::JavascriptPromiseCapability* InflatePromiseCapabilityInfo(const SnapPromiseCapabilityInfo* capabilityInfo, Js::ScriptContext* ctx, InflateMap* inflator);
- void EmitPromiseCapabilityInfo(const SnapPromiseCapabilityInfo* capabilityInfo, FileWriter* writer, NSTokens::Separator separator);
- void ParsePromiseCapabilityInfo(SnapPromiseCapabilityInfo* capabilityInfo, bool readSeparator, FileReader* reader, SlabAllocator& alloc);
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const SnapPromiseCapabilityInfo* capabilityInfo1, const SnapPromiseCapabilityInfo* capabilityInfo2, TTDCompareMap& compareMap);
- #endif
- //A struct to represent a PromiseReaction
- struct SnapPromiseReactionInfo
- {
- //The unique id for PromiseReaction
- TTD_PTR_ID PromiseReactionId;
- TTD_PTR_ID HandlerObjId;
- SnapPromiseCapabilityInfo Capabilities;
- };
- Js::JavascriptPromiseReaction* InflatePromiseReactionInfo(const SnapPromiseReactionInfo* reactionInfo, Js::ScriptContext* ctx, InflateMap* inflator);
- void EmitPromiseReactionInfo(const SnapPromiseReactionInfo* reactionInfo, FileWriter* writer, NSTokens::Separator separator);
- void ParsePromiseReactionInfo(SnapPromiseReactionInfo* reactionInfo, bool readSeparator, FileReader* reader, SlabAllocator& alloc);
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const SnapPromiseReactionInfo* reactionInfo1, const SnapPromiseReactionInfo* reactionInfo2, TTDCompareMap& compareMap);
- #endif
- //////////////////
- //Information on the scopechain for a function body
- struct SnapFunctionBodyScopeChain
- {
- //The number of scopes associated with this function body
- uint32 ScopeCount;
- //The Ids of the scopes
- TTD_PTR_ID* ScopeArray;
- };
- void ExtractSnapFunctionBodyScopeChain(bool isWellKnownFunction, SnapFunctionBodyScopeChain& scopeChain, Js::FunctionBody* fb, SlabAllocator& alloc);
- void EmitSnapFunctionBodyScopeChain(const SnapFunctionBodyScopeChain& scopeChain, FileWriter* writer);
- void ParseSnapFunctionBodyScopeChain(SnapFunctionBodyScopeChain& scopeChain, FileReader* reader, SlabAllocator& alloc);
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const SnapFunctionBodyScopeChain& chain1, const SnapFunctionBodyScopeChain& chain2, TTDCompareMap& compareMap);
- #endif
- //////////////////
- //Information that is common to all top-level bodies
- struct TopLevelCommonBodyResolveInfo
- {
- //The context this body is associated with
- TTD_LOG_PTR_ID ScriptContextLogId;
- //A unique counter we produce for every top-level body as it is loaded
- uint32 TopLevelBodyCtr;
- //The string name of the function
- TTString FunctionName;
- //The module id and source context
- Js::ModuleID ModuleId;
- uint64 SourceContextId;
- //Src URI may be null
- TTString SourceUri;
- //The source length/buffer and if it is utf8 or char16 encoded
- bool IsUtf8;
- uint32 ByteLength;
- byte* SourceBuffer;
- //The (possibly empty) scope chain info
- SnapFunctionBodyScopeChain ScopeChainInfo;
- //The number of bytes (or -1 if not set) and the buffer for the serialized bytecode
- mutable DWORD DbgSerializedBytecodeSize;
- mutable byte* DbgSerializedBytecodeBuffer;
- };
- //Extract WITHOUT COPYING the info needed for this top level function -- use in script context when function is parsed to keep all the info together and then we do the copying later when doing snapshots
- void ExtractTopLevelCommonBodyResolveInfo(TopLevelCommonBodyResolveInfo* fbInfo, Js::FunctionBody* fb, uint32 topLevelCtr, Js::ModuleID moduleId, uint64 sourceContextId, bool isUtf8source, const byte* source, uint32 sourceLen, SlabAllocator& alloc);
- void EmitTopLevelCommonBodyResolveInfo(const TopLevelCommonBodyResolveInfo* fbInfo, bool emitInline, ThreadContext* threadContext, FileWriter* writer, NSTokens::Separator separator);
- void ParseTopLevelCommonBodyResolveInfo(TopLevelCommonBodyResolveInfo* fbInfo, bool readSeparator, bool parseInline, ThreadContext* threadContext, FileReader* reader, SlabAllocator& alloc);
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const TopLevelCommonBodyResolveInfo* fbInfo1, const TopLevelCommonBodyResolveInfo* fbInfo2, TTDCompareMap& compareMap);
- #endif
- //A struct that we can use to resolve a top-level script load function bodies and info
- struct TopLevelScriptLoadFunctionBodyResolveInfo
- {
- //The base information for the top-level resolve info
- TopLevelCommonBodyResolveInfo TopLevelBase;
- //The script flag this was loaded with
- LoadScriptFlag LoadFlag;
- };
- void ExtractTopLevelLoadedFunctionBodyInfo(TopLevelScriptLoadFunctionBodyResolveInfo* fbInfo, Js::FunctionBody* fb, uint32 topLevelCtr, Js::ModuleID moduleId, uint64 sourceContextId, bool isUtf8, const byte* source, uint32 sourceLen, LoadScriptFlag loadFlag, SlabAllocator& alloc);
- Js::FunctionBody* InflateTopLevelLoadedFunctionBodyInfo(const TopLevelScriptLoadFunctionBodyResolveInfo* fbInfo, Js::ScriptContext* ctx);
- void EmitTopLevelLoadedFunctionBodyInfo(const TopLevelScriptLoadFunctionBodyResolveInfo* fbInfo, ThreadContext* threadContext, FileWriter* writer, NSTokens::Separator separator);
- void ParseTopLevelLoadedFunctionBodyInfo(TopLevelScriptLoadFunctionBodyResolveInfo* fbInfo, bool readSeparator, ThreadContext* threadContext, FileReader* reader, SlabAllocator& alloc);
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const TopLevelScriptLoadFunctionBodyResolveInfo* fbInfo1, const TopLevelScriptLoadFunctionBodyResolveInfo* fbInfo2, TTDCompareMap& compareMap);
- #endif
- //A struct that we can use to resolve a top-level 'new Function' function bodies and info
- struct TopLevelNewFunctionBodyResolveInfo
- {
- //The base information for the top-level resolve info
- TopLevelCommonBodyResolveInfo TopLevelBase;
- };
- void ExtractTopLevelNewFunctionBodyInfo(TopLevelNewFunctionBodyResolveInfo* fbInfo, Js::FunctionBody* fb, uint32 topLevelCtr, Js::ModuleID moduleId, const char16* source, uint32 sourceLen, SlabAllocator& alloc);
- Js::FunctionBody* InflateTopLevelNewFunctionBodyInfo(const TopLevelNewFunctionBodyResolveInfo* fbInfo, Js::ScriptContext* ctx);
- void EmitTopLevelNewFunctionBodyInfo(const TopLevelNewFunctionBodyResolveInfo* fbInfo, ThreadContext* threadContext, FileWriter* writer, NSTokens::Separator separator);
- void ParseTopLevelNewFunctionBodyInfo(TopLevelNewFunctionBodyResolveInfo* fbInfo, bool readSeparator, ThreadContext* threadContext, FileReader* reader, SlabAllocator& alloc);
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const TopLevelNewFunctionBodyResolveInfo* fbInfo1, const TopLevelNewFunctionBodyResolveInfo* fbInfo2, TTDCompareMap& compareMap);
- #endif
- //A struct that we can use to resolve a top-level 'eval' function bodies and info
- struct TopLevelEvalFunctionBodyResolveInfo
- {
- //The base information for the top-level resolve info
- TopLevelCommonBodyResolveInfo TopLevelBase;
- //Additional data for handling the eval
- uint64 EvalFlags;
- bool RegisterDocument;
- bool IsIndirect;
- bool IsStrictMode;
- };
- void ExtractTopLevelEvalFunctionBodyInfo(TopLevelEvalFunctionBodyResolveInfo* fbInfo, Js::FunctionBody* fb, uint32 topLevelCtr, Js::ModuleID moduleId, const char16* source, uint32 sourceLen, uint32 grfscr, bool registerDocument, BOOL isIndirect, BOOL strictMode, SlabAllocator& alloc);
- Js::FunctionBody* InflateTopLevelEvalFunctionBodyInfo(const TopLevelEvalFunctionBodyResolveInfo* fbInfo, Js::ScriptContext* ctx);
- void EmitTopLevelEvalFunctionBodyInfo(const TopLevelEvalFunctionBodyResolveInfo* fbInfo, ThreadContext* threadContext, FileWriter* writer, NSTokens::Separator separator);
- void ParseTopLevelEvalFunctionBodyInfo(TopLevelEvalFunctionBodyResolveInfo* fbInfo, bool readSeparator, ThreadContext* threadContext, FileReader* reader, SlabAllocator& alloc);
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const TopLevelEvalFunctionBodyResolveInfo* fbInfo1, const TopLevelEvalFunctionBodyResolveInfo* fbInfo2, TTDCompareMap& compareMap);
- #endif
- //A struct that we can use to resolve a function body during inflation
- struct FunctionBodyResolveInfo
- {
- //The id this body is associated with
- TTD_PTR_ID FunctionBodyId;
- //The context this body is associated with
- TTD_LOG_PTR_ID ScriptContextLogId;
- //The string name of the function
- TTString FunctionName;
- //The known path to a function with the desired body
- TTD_WELLKNOWN_TOKEN OptKnownPath;
- //The ptr id of the parent function body
- TTD_PTR_ID OptParentBodyId;
- //The line number the function is def starts on
- int64 OptLine;
- //The column number the function is def starts on
- int64 OptColumn;
- //The (possibly empty) scope chain info
- SnapFunctionBodyScopeChain ScopeChainInfo;
- };
- void ExtractFunctionBodyInfo(FunctionBodyResolveInfo* fbInfo, Js::FunctionBody* fb, bool isWellKnown, SlabAllocator& alloc);
- void InflateFunctionBody(const FunctionBodyResolveInfo* fbInfo, InflateMap* inflator, const TTDIdentifierDictionary<TTD_PTR_ID, FunctionBodyResolveInfo*>& idToFbResolveMap);
- void EmitFunctionBodyInfo(const FunctionBodyResolveInfo* fbInfo, FileWriter* writer, NSTokens::Separator separator);
- void ParseFunctionBodyInfo(FunctionBodyResolveInfo* fbInfo, bool readSeparator, FileReader* reader, SlabAllocator& alloc);
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const FunctionBodyResolveInfo* fbInfo1, const FunctionBodyResolveInfo* fbInfo2, TTDCompareMap& compareMap);
- #endif
- //////////////////
- struct SnapRootInfoEntry
- {
- //The log id value
- TTD_LOG_PTR_ID LogId;
- //The object that this log id is mapped to
- TTD_PTR_ID LogObject;
- //True if the root maybe long lived/false otherwise
- bool MaybeLongLivedRoot;
- };
- struct SnapPendingAsyncBufferModification
- {
- //The log id value
- TTD_LOG_PTR_ID LogId;
- //The index value associated with this modification
- uint32 Index;
- };
- //A structure for serializing/tracking script contexts
- struct SnapContext
- {
- //The tag id of the script context (actually the global object associated with this context)
- TTD_LOG_PTR_ID ScriptContextLogId;
- //The random seed for the context
- bool IsPNRGSeeded;
- uint64 RandomSeed0;
- uint64 RandomSeed1;
- //The main URI of the context
- TTString ContextSRC;
- //A list of all *root* scripts that have been loaded into this context
- uint32 LoadedTopLevelScriptCount;
- TopLevelFunctionInContextRelation* LoadedTopLevelScriptArray;
- uint32 NewFunctionTopLevelScriptCount;
- TopLevelFunctionInContextRelation* NewFunctionTopLevelScriptArray;
- uint32 EvalTopLevelScriptCount;
- TopLevelFunctionInContextRelation* EvalTopLevelScriptArray;
- //A list of all the pending async buffer modifications
- uint32 PendingAsyncModCount;
- SnapPendingAsyncBufferModification* PendingAsyncModArray;
- };
- void ExtractScriptContext(SnapContext* snapCtx, Js::ScriptContext* ctx, const JsUtil::BaseDictionary<Js::RecyclableObject*, TTD_LOG_PTR_ID, HeapAllocator>& objToLogIdMap, const JsUtil::BaseHashSet<Js::FunctionBody*, HeapAllocator>& liveTopLevelBodies, SlabAllocator& alloc);
- void InflateScriptContext(const SnapContext* snpCtx, Js::ScriptContext* intoCtx, InflateMap* inflator,
- const TTDIdentifierDictionary<uint64, TopLevelScriptLoadFunctionBodyResolveInfo*>& topLevelLoadScriptMap,
- const TTDIdentifierDictionary<uint64, TopLevelNewFunctionBodyResolveInfo*>& topLevelNewScriptMap,
- const TTDIdentifierDictionary<uint64, TopLevelEvalFunctionBodyResolveInfo*>& topLevelEvalScriptMap);
- void ResetPendingAsyncBufferModInfo(const SnapContext* snpCtx, Js::ScriptContext* intoCtx, InflateMap* inflator);
- void EmitSnapContext(const SnapContext* snapCtx, FileWriter* writer, NSTokens::Separator separator);
- void ParseSnapContext(SnapContext* intoCtx, bool readSeparator, FileReader* reader, SlabAllocator& alloc);
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const SnapContext* snapCtx1, const SnapContext* snapCtx2, const JsUtil::BaseDictionary<TTD_LOG_PTR_ID, NSSnapValues::SnapRootInfoEntry*, HeapAllocator>& allRootMap1, const JsUtil::BaseDictionary<TTD_LOG_PTR_ID, NSSnapValues::SnapRootInfoEntry*, HeapAllocator>& allRootMap2, TTDCompareMap& compareMap);
- #endif
- }
- }
- #endif
|