//------------------------------------------------------------------------------------------------------- // 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 { namespace NSSnapObjects { ////////////////// //We basically build a fake vtable here and use it to fake class behavior without needing a virtual type features we don't need typedef Js::RecyclableObject*(*fPtr_DoObjectInflation)(const SnapObject* snpObject, InflateMap* inflator); typedef void(*fPtr_DoAddtlValueInstantiation)(const SnapObject* snpObject, Js::RecyclableObject* obj, InflateMap* inflator); typedef void(*fPtr_EmitAddtlInfo)(const SnapObject* snpObject, FileWriter* writer); typedef void(*fPtr_ParseAddtlInfo)(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); //Since may types don't need to do anything more in some cases we have a nop functions we set the fptr to null struct SnapObjectVTable { fPtr_DoObjectInflation InflationFunc; fPtr_DoAddtlValueInstantiation AddtlInstationationFunc; fPtr_EmitAddtlInfo EmitAddtlInfoFunc; fPtr_ParseAddtlInfo ParseAddtlInfoFunc; }; struct DependsOnInfo { uint32 DepOnCount; TTD_PTR_ID* DepOnPtrArray; }; ////////////////// //Base struct for each kind of object we have in the system also used to represent user defined objects directly //Although enumerators are not technically subtypes of Dynamic Object we include them here since they have ptrs and such struct SnapObject { //The id (address of the object) TTD_PTR_ID ObjectPtrId; //The tag we use to distinguish between kinds of snap objects SnapObjectType SnapObjectTag; //The type for the object NSSnapType::SnapType* SnapType; //The optional well known token for this object (or INVALID) TTD_WELLKNOWN_TOKEN OptWellKnownToken; //Return true if the object has the cross site vtable BOOL IsCrossSite; #if ENABLE_OBJECT_SOURCE_TRACKING DiagnosticOrigin DiagOriginInfo; #endif //The basic slots of the object the sizes are reproduced in a single array (VarArrayCount should be the same as MaxUsedSlotIndex from the type) uint32 VarArrayCount; TTDVar* VarArray; //The numeric indexed properties associated with the object (or invalid if no associated array) TTD_PTR_ID OptIndexedObjectArray; //Objects this depends on when creating (or nullptr if no dependencies) DependsOnInfo* OptDependsOnInfo; //A ptr for the remaining info which must be cast when needed by handler methods void* AddtlSnapObjectInfo; }; //Access the AddtlSnapObjectInfo for the snap object as the specified kind (asserts on the tag and casts the data) template T SnapObjectGetAddtlInfoAs(const SnapObject* snpObject) { TTDAssert(snpObject->SnapObjectTag == tag, "Tag does not match."); return reinterpret_cast(snpObject->AddtlSnapObjectInfo); } template void SnapObjectSetAddtlInfoAs(SnapObject* snpObject, T addtlInfo) { TTDAssert(sizeof(T) <= sizeof(void*), "Make sure your info fits into the space we have for it."); TTDAssert(snpObject->SnapObjectTag == tag, "Tag does not match."); snpObject->AddtlSnapObjectInfo = (void*)addtlInfo; } //The main method that should be called to extract the information from a snap object void ExtractCompoundObject(NSSnapObjects::SnapObject* sobj, Js::RecyclableObject* obj, bool isWellKnown, const TTDIdentifierDictionary& idToTypeMap, SlabAllocator& alloc); //Extract the basic information for a snap object (helpers) void StdPropertyExtract_StaticType(SnapObject* snpObject, Js::RecyclableObject* obj); void StdPropertyExtract_DynamicType(SnapObject* snpObject, Js::DynamicObject* dynObj, SlabAllocator& alloc); //a simple helper that we can call during the extract to make sure all needed fields are initialized (in cases where the are *no* depends on pointers) template void StdExtractSetKindSpecificInfo(SnapObject* snpObject, T addtlInfo) { SnapObjectSetAddtlInfoAs(snpObject, addtlInfo); } //a simple helper that we can call during the extract to make sure all needed fields are initialized (in cases where the *are* depends on pointers) template void StdExtractSetKindSpecificInfo(SnapObject* snpObject, T addtlInfo, SlabAllocator& alloc, uint32 dependsOnArrayCount, TTD_PTR_ID* dependsOnArray) { SnapObjectSetAddtlInfoAs(snpObject, addtlInfo); TTDAssert(dependsOnArrayCount != 0 && dependsOnArray != nullptr, "Why are you calling this then?"); snpObject->OptDependsOnInfo = alloc.SlabAllocateStruct(); snpObject->OptDependsOnInfo->DepOnCount = dependsOnArrayCount; snpObject->OptDependsOnInfo->DepOnPtrArray = dependsOnArray; } //Check to see if we have an old version of this object around and, if so, clean up its type/handler/standard properties and return it Js::DynamicObject* ReuseObjectCheckAndReset(const SnapObject* snpObject, InflateMap* inflator); //TODO: this is a workaround check until we can reliably reset objects -- allows us to early check for non-resetability and fall back to fully recreating script contexts bool DoesObjectBlockScriptContextReuse(const SnapObject* snpObject, Js::DynamicObject* dynObj, InflateMap* inflator); Js::DynamicObject* ObjectPropertyReset_WellKnown(const SnapObject* snpObject, Js::DynamicObject* dynObj, InflateMap* inflator); Js::DynamicObject* ObjectPropertyReset_General(const SnapObject* snpObject, Js::DynamicObject* dynObj, InflateMap* inflator); //Set all the general properties for the object void StdPropertyRestore(const SnapObject* snpObject, Js::DynamicObject* obj, InflateMap* inflator); //serialize the object data void EmitObject(const SnapObject* snpObject, FileWriter* writer, NSTokens::Separator separator, const SnapObjectVTable* vtable, ThreadContext* threadContext); //de-serialize a SnapObject void ParseObject(SnapObject* snpObject, bool readSeparator, FileReader* reader, SlabAllocator& alloc, const SnapObjectVTable* vtable, const TTDIdentifierDictionary& ptrIdToTypeMap); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif //// //Functions for the VTable for DynamicObject tags Js::RecyclableObject* DoObjectInflation_SnapDynamicObject(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop //EmitAddtlInfo is a nop //ParseAddtlInfo is a nop //AssertSnapEquiv is a nop Js::RecyclableObject* DoObjectInflation_SnapExternalObject(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop //EmitAddtlInfo is a nop //ParseAddtlInfo is a nop //AssertSnapEquiv is a nop ////////////////// //A struct that represents a script function object struct SnapScriptFunctionInfo { //The display name of the function TTString DebugFunctionName; //The function body reference id (if not library) TTD_PTR_ID BodyRefId; //The scope info for this function TTD_PTR_ID ScopeId; //The cached scope object for the function (if it has one) TTD_PTR_ID CachedScopeObjId; //The home object for the function (if it has one) TTD_PTR_ID HomeObjId; //If the function has computed name information and what it is (check if this is an invalid ptr) TTDVar ComputedNameInfo; }; //// //Functions for the VTable for SnapScriptFunction tags Js::RecyclableObject* DoObjectInflation_SnapScriptFunctionInfo(const SnapObject* snpObject, InflateMap* inflator); void DoAddtlValueInstantiation_SnapScriptFunctionInfo(const SnapObject* snpObject, Js::RecyclableObject* obj, InflateMap* inflator); void DoAddtlValueInstantiation_SnapScriptFunctionInfoEx(const SnapScriptFunctionInfo* snapFuncInfo, Js::ScriptFunction* fobj, InflateMap* inflator); void EmitAddtlInfo_SnapScriptFunctionInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapScriptFunctionInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); void EmitAddtlInfo_SnapScriptFunctionInfoEx(const SnapScriptFunctionInfo* snapFuncInfo, FileWriter* writer); void ParseAddtlInfo_SnapScriptFunctionInfoEx(SnapScriptFunctionInfo* snapFuncInfo, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapScriptFunctionInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif //// //RuntimeFunction is resolved via a wellknowntag so we don't worry about it //DoObjectInflation is a nop (should either be wellknown or handled as a sub-type) //DoAddtlValueInstantiation is a nop //EmitAddtlInfo is a nop //ParseAddtlInfo is a nop //AssertSnapEquiv is a nop //// //ExternalFunction always traps to log so we don't need any special information Js::RecyclableObject* DoObjectInflation_SnapExternalFunctionInfo(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop void EmitAddtlInfo_SnapExternalFunctionInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapExternalFunctionInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapExternalFunctionInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif //// //RevokerFunction needs TTD_PTR_ID* for the proxy value Js::RecyclableObject* DoObjectInflation_SnapRevokerFunctionInfo(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop void EmitAddtlInfo_SnapRevokerFunctionInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapRevokerFunctionInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapRevokerFunctionInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif //// //Functions for the VTable for SnapBoundFunctionObject tags //A class that represents a script function object struct SnapBoundFunctionInfo { //The function that is bound TTD_PTR_ID TargetFunction; //The "this" parameter to use TTD_PTR_ID BoundThis; //The count of bound arguments uint32 ArgCount; //The arguments TTDVar* ArgArray; }; Js::RecyclableObject* DoObjectInflation_SnapBoundFunctionInfo(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop void EmitAddtlInfo_SnapBoundFunctionInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapBoundFunctionInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapBoundFunctionInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif ////////////////// //// //Functions for the VTable for ActivationObject tags Js::RecyclableObject* DoObjectInflation_SnapActivationInfo(const SnapObject* snpObject, InflateMap* inflator); Js::RecyclableObject* DoObjectInflation_SnapBlockActivationObject(const SnapObject* snpObject, InflateMap* inflator); Js::RecyclableObject* DoObjectInflation_SnapPseudoActivationObject(const SnapObject* snpObject, InflateMap* inflator); Js::RecyclableObject* DoObjectInflation_SnapConsoleScopeActivationObject(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop //EmitAddtlInfo is a nop //ParseAddtlInfo is a nop //AssertSnapEquiv is a nop ////////////////// //A class that represents an arguments object info struct SnapHeapArgumentsInfo { //number of arguments uint32 NumOfArguments; //The frame object bool IsFrameNullPtr; TTD_PTR_ID FrameObject; uint32 FormalCount; byte* DeletedArgFlags; }; //// //Functions for the VTable for ArgumentsObject tags Js::RecyclableObject* DoObjectInflation_SnapHeapArgumentsInfo(const SnapObject* snpObject, InflateMap* inflator); Js::RecyclableObject* DoObjectInflation_SnapES5HeapArgumentsInfo(const SnapObject* snpObject, InflateMap* inflator); template void EmitAddtlInfo_SnapHeapArgumentsInfo(const SnapObject* snpObject, FileWriter* writer) { SnapHeapArgumentsInfo* argsInfo = SnapObjectGetAddtlInfoAs(snpObject); writer->WriteUInt32(NSTokens::Key::numberOfArgs, argsInfo->NumOfArguments, NSTokens::Separator::CommaAndBigSpaceSeparator); writer->WriteBool(NSTokens::Key::boolVal, argsInfo->IsFrameNullPtr, NSTokens::Separator::CommaSeparator); writer->WriteAddr(NSTokens::Key::objectId, argsInfo->FrameObject, NSTokens::Separator::CommaSeparator); writer->WriteLengthValue(argsInfo->FormalCount, NSTokens::Separator::CommaSeparator); writer->WriteKey(NSTokens::Key::deletedArgs, NSTokens::Separator::CommaSeparator); writer->WriteSequenceStart(); for(uint32 i = 0; i < argsInfo->FormalCount; ++i) { writer->WriteNakedByte(argsInfo->DeletedArgFlags[i], i != 0 ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator); } writer->WriteSequenceEnd(); } template void ParseAddtlInfo_SnapHeapArgumentsInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc) { SnapHeapArgumentsInfo* argsInfo = alloc.SlabAllocateStruct(); argsInfo->NumOfArguments = reader->ReadUInt32(NSTokens::Key::numberOfArgs, true); argsInfo->IsFrameNullPtr = reader->ReadBool(NSTokens::Key::boolVal, true); argsInfo->FrameObject = reader->ReadAddr(NSTokens::Key::objectId, true); argsInfo->FormalCount = reader->ReadLengthValue(true); if(argsInfo->FormalCount == 0) { argsInfo->DeletedArgFlags = nullptr; } else { argsInfo->DeletedArgFlags = alloc.SlabAllocateArray(argsInfo->FormalCount); } reader->ReadKey(NSTokens::Key::deletedArgs, true); reader->ReadSequenceStart(); for(uint32 i = 0; i < argsInfo->FormalCount; ++i) { argsInfo->DeletedArgFlags[i] = reader->ReadNakedByte(i != 0); } reader->ReadSequenceEnd(); SnapObjectSetAddtlInfoAs(snpObject, argsInfo); } #if ENABLE_SNAPSHOT_COMPARE template void AssertSnapEquiv_SnapHeapArgumentsInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap) { SnapHeapArgumentsInfo* argsInfo1 = SnapObjectGetAddtlInfoAs(sobj1); SnapHeapArgumentsInfo* argsInfo2 = SnapObjectGetAddtlInfoAs(sobj2); compareMap.DiagnosticAssert(argsInfo1->NumOfArguments == argsInfo2->NumOfArguments); compareMap.DiagnosticAssert(argsInfo1->IsFrameNullPtr == argsInfo2->IsFrameNullPtr); compareMap.CheckConsistentAndAddPtrIdMapping_Special(argsInfo1->FrameObject, argsInfo2->FrameObject, _u("frameObject")); compareMap.DiagnosticAssert(argsInfo1->FormalCount == argsInfo2->FormalCount); for(uint32 i = 0; i < argsInfo1->FormalCount; ++i) { compareMap.DiagnosticAssert(argsInfo1->DeletedArgFlags[i] == argsInfo2->DeletedArgFlags[i]); } } #endif ////////////////// //// //Promise Info struct SnapPromiseInfo { uint32 Status; bool isHandled; TTDVar Result; // //We have the reaction info's inline even theought we want to preserve their pointer identity when inflating. //So we duplicate data here but avoid needed to add more kinds to the mark/extract logic and will check on inflation. // uint32 ResolveReactionCount; NSSnapValues::SnapPromiseReactionInfo* ResolveReactions; uint32 RejectReactionCount; NSSnapValues::SnapPromiseReactionInfo* RejectReactions; }; Js::RecyclableObject* DoObjectInflation_SnapPromiseInfo(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop void EmitAddtlInfo_SnapPromiseInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapPromiseInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapPromiseInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif //// //PromiseResolveOrRejectFunction Info struct SnapPromiseResolveOrRejectFunctionInfo { TTD_PTR_ID PromiseId; bool IsReject; //This has a pointer identity but we duplicate here and check on inflate TTD_PTR_ID AlreadyResolvedWrapperId; bool AlreadyResolvedValue; }; Js::RecyclableObject* DoObjectInflation_SnapPromiseResolveOrRejectFunctionInfo(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop void EmitAddtlInfo_SnapPromiseResolveOrRejectFunctionInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapPromiseResolveOrRejectFunctionInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapPromiseResolveOrRejectFunctionInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif //// //ReactionTaskFunction Info struct SnapPromiseReactionTaskFunctionInfo { TTDVar Argument; TTD::NSSnapValues::SnapPromiseReactionInfo Reaction; }; Js::RecyclableObject* DoObjectInflation_SnapPromiseReactionTaskFunctionInfo(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop void EmitAddtlInfo_SnapPromiseReactionTaskFunctionInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapPromiseReactionTaskFunctionInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapPromiseReactionTaskFunctionInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif //// //AllResolveElementFunctionObject Info struct SnapPromiseAllResolveElementFunctionInfo { NSSnapValues::SnapPromiseCapabilityInfo Capabilities; uint32 Index; TTD_PTR_ID RemainingElementsWrapperId; uint32 RemainingElementsValue; TTD_PTR_ID Values; bool AlreadyCalled; }; Js::RecyclableObject* DoObjectInflation_SnapPromiseAllResolveElementFunctionInfo(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop void EmitAddtlInfo_SnapPromiseAllResolveElementFunctionInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapPromiseAllResolveElementFunctionInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapPromiseAllResolveElementFunctionInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif ////////////////// //// //SnapBoxedValueObject is resolved via a TTDVar to the underlying value or ptrId Js::RecyclableObject* DoObjectInflation_SnapBoxedValue(const SnapObject* snpObject, InflateMap* inflator); void DoAddtlValueInstantiation_SnapBoxedValue(const SnapObject* snpObject, Js::RecyclableObject* obj, InflateMap* inflator); void EmitAddtlInfo_SnapBoxedValue(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapBoxedValue(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapBoxedValue(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif //// //SnapDateObject is resolved via a double* value Js::RecyclableObject* DoObjectInflation_SnapDate(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop void EmitAddtlInfo_SnapDate(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapDate(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapDate(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif //A struct that represents a regular expression object struct SnapRegexInfo { //The underlying regex string value TTString RegexStr; //Regex flags value UnifiedRegex::RegexFlags Flags; //The char count or flag value from the regex object CharCount LastIndexOrFlag; //The last index var from the regex object TTDVar LastIndexVar; }; //// //Functions for the VTable for SnapRegexObject Js::RecyclableObject* DoObjectInflation_SnapRegexInfo(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop void EmitAddtlInfo_SnapRegexInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapRegexInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapRegexInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif //// //SnapErrorObject has no data currently so we nop on most things Js::RecyclableObject* DoObjectInflation_SnapError(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop //EmitAddtlInfo is a nop //ParseAddtlInfo is a nop //AssertSnapEquiv is a nop ////////////////// //A struct that represents Javascript arrays and Native arrays (T can be Var, int32, or double) template struct SnapArrayInfoBlock { //The index ranges that this info holds uint32 FirstIndex; uint32 LastIndex; //The contents of this array range [FirstIndex, LastIndex) T* ArrayRangeContents; byte* ArrayValidTags; //0 is invalid 1 is valid //The next slice of array elements SnapArrayInfoBlock* Next; }; //A struct that represents Javascript arrays and Native arrays (T can be Var, int32, or double) template struct SnapArrayInfo { //The index ranges that this info holds uint32 Length; //The array elements or null if this is empty SnapArrayInfoBlock* Data; }; template SnapArrayInfoBlock* AllocateArrayInfoBlock(SlabAllocator& alloc, uint32 firstIndex, uint32 lastIndex) { SnapArrayInfoBlock* sai = alloc.SlabAllocateStruct< SnapArrayInfoBlock >(); sai->FirstIndex = firstIndex; sai->LastIndex = lastIndex; sai->ArrayRangeContents = alloc.SlabAllocateArray(lastIndex - firstIndex); sai->ArrayValidTags = alloc.SlabAllocateArray(lastIndex - firstIndex); //only zero valid flags (which guard the contents values) if(zeroFillValid) { memset(sai->ArrayValidTags, 0, lastIndex - firstIndex); } sai->Next = nullptr; return sai; } template SnapArrayInfo* ExtractArrayValues(Js::JavascriptArray* arrayObject, SlabAllocator& alloc) { SnapArrayInfoBlock* sai = nullptr; uint32 length = arrayObject->GetLength(); if(length == 0) { ; //just leave it as a null ptr } else if(length <= TTD_ARRAY_SMALL_ARRAY) { sai = AllocateArrayInfoBlock(alloc, 0, length); for(uint32 i = 0; i < length; ++i) { sai->ArrayValidTags[i] = (byte)arrayObject->DirectGetItemAt(i, sai->ArrayRangeContents + i); } } else { SnapArrayInfoBlock* curr = nullptr; for(uint32 idx = arrayObject->GetNextIndex(Js::JavascriptArray::InvalidIndex); idx != Js::JavascriptArray::InvalidIndex; idx = arrayObject->GetNextIndex(idx)) { if(sai == nullptr) { uint32 endIdx = (idx <= (Js::JavascriptArray::MaxArrayLength - TTD_ARRAY_BLOCK_SIZE)) ? (idx + TTD_ARRAY_BLOCK_SIZE) : Js::JavascriptArray::MaxArrayLength; sai = AllocateArrayInfoBlock(alloc, idx, endIdx); curr = sai; } TTDAssert(curr != nullptr, "Should get set with variable sai above when needed!"); if(idx >= curr->LastIndex) { uint32 endIdx = (idx <= (Js::JavascriptArray::MaxArrayLength - TTD_ARRAY_BLOCK_SIZE)) ? (idx + TTD_ARRAY_BLOCK_SIZE) : Js::JavascriptArray::MaxArrayLength; curr->Next = AllocateArrayInfoBlock(alloc, idx, endIdx); curr = curr->Next; } curr->ArrayValidTags[idx - curr->FirstIndex] = TRUE; arrayObject->DirectGetItemAt(idx, curr->ArrayRangeContents + (idx - curr->FirstIndex)); } } SnapArrayInfo* res = alloc.SlabAllocateStruct< SnapArrayInfo >(); res->Length = arrayObject->GetLength(); res->Data = sai; return res; } int32 SnapArrayInfo_InflateValue(int32 value, InflateMap* inflator); void SnapArrayInfo_EmitValue(int32 value, FileWriter* writer); void SnapArrayInfo_ParseValue(int32* into, FileReader* reader, SlabAllocator& alloc); double SnapArrayInfo_InflateValue(double value, InflateMap* inflator); void SnapArrayInfo_EmitValue(double value, FileWriter* writer); void SnapArrayInfo_ParseValue(double* into, FileReader* reader, SlabAllocator& alloc); Js::Var SnapArrayInfo_InflateValue(TTDVar value, InflateMap* inflator); void SnapArrayInfo_EmitValue(TTDVar value, FileWriter* writer); void SnapArrayInfo_ParseValue(TTDVar* into, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void SnapArrayInfo_EquivValue(int32 val1, int32 val2, TTDCompareMap& compareMap, int32 i); void SnapArrayInfo_EquivValue(double val1, double val2, TTDCompareMap& compareMap, int32 i); void SnapArrayInfo_EquivValue(TTDVar val1, TTDVar val2, TTDCompareMap& compareMap, int32 i); #endif //// //Functions for the VTable for SnapArrayObject tags template Js::RecyclableObject* DoObjectInflation_SnapArrayInfo(const SnapObject* snpObject, InflateMap* inflator) { //Arrays can change type on us so seems easiest to always re-create them. //We can re-evaluate this choice later if needed and add checks for same type-ness. const SnapArrayInfo* arrayInfo = SnapObjectGetAddtlInfoAs*, snapArrayKind>(snpObject); const SnapArrayInfoBlock* dataBlock = arrayInfo->Data; Js::ScriptContext* ctx = inflator->LookupScriptContext(snpObject->SnapType->ScriptContextLogId); Js::JavascriptLibrary* jslib = ctx->GetLibrary(); uint32 preAllocSpace = 0; if(dataBlock != nullptr && dataBlock->Next == nullptr && dataBlock->FirstIndex == 0 && dataBlock->LastIndex <= TTD_ARRAY_SMALL_ARRAY) { preAllocSpace = dataBlock->LastIndex; //first index is 0 } if(snpObject->SnapType->JsTypeId == Js::TypeIds_Array) { if(preAllocSpace == 0) { return jslib->CreateArray(); } else { Js::DynamicObject* rcObj = ReuseObjectCheckAndReset(snpObject, inflator); if(rcObj != nullptr) { Js::JavascriptArray::FromVar(rcObj)->SetLength(preAllocSpace); return rcObj; } else { return jslib->CreateArray(preAllocSpace); } } } else if(snpObject->SnapType->JsTypeId == Js::TypeIds_NativeIntArray) { return (preAllocSpace > 0) ? ctx->GetLibrary()->CreateNativeIntArray(preAllocSpace) : ctx->GetLibrary()->CreateNativeIntArray(); } else if(snpObject->SnapType->JsTypeId == Js::TypeIds_NativeFloatArray) { return (preAllocSpace > 0) ? ctx->GetLibrary()->CreateNativeFloatArray(preAllocSpace) : ctx->GetLibrary()->CreateNativeFloatArray(); } else { TTDAssert(false, "Unknown array type!"); return nullptr; } } template void DoAddtlValueInstantiation_SnapArrayInfoCore(SnapArrayInfo* arrayInfo, Js::JavascriptArray* arrayObj, InflateMap* inflator) { const SnapArrayInfoBlock* dataBlock = arrayInfo->Data; while(dataBlock != nullptr) { for(uint32 i = 0; i < (dataBlock->LastIndex - dataBlock->FirstIndex); ++i) { if(dataBlock->ArrayValidTags[i]) { T ttdVal = dataBlock->ArrayRangeContents[i]; U jsVal = SnapArrayInfo_InflateValue(ttdVal, inflator); arrayObj->DirectSetItemAt(i + dataBlock->FirstIndex, jsVal); } } dataBlock = dataBlock->Next; } //Ensure this value is set correctly in case of sparse arrays arrayObj->SetLength(arrayInfo->Length); } template void DoAddtlValueInstantiation_SnapArrayInfo(const SnapObject* snpObject, Js::RecyclableObject* obj, InflateMap* inflator) { SnapArrayInfo* arrayInfo = SnapObjectGetAddtlInfoAs*, snapArrayKind>(snpObject); Js::JavascriptArray* arrayObj = static_cast(obj); DoAddtlValueInstantiation_SnapArrayInfoCore(arrayInfo, arrayObj, inflator); } template void EmitAddtlInfo_SnapArrayInfoCore(SnapArrayInfo* arrayInfo, FileWriter* writer) { writer->WriteLengthValue(arrayInfo->Length, NSTokens::Separator::CommaSeparator); uint32 blockCount = 0; for(SnapArrayInfoBlock* currInfo = arrayInfo->Data; currInfo != nullptr; currInfo = currInfo->Next) { blockCount++; } writer->WriteLengthValue(blockCount, NSTokens::Separator::CommaAndBigSpaceSeparator); writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator); writer->AdjustIndent(1); for(SnapArrayInfoBlock* currInfo = arrayInfo->Data; currInfo != nullptr; currInfo = currInfo->Next) { writer->WriteRecordStart(currInfo == arrayInfo->Data ? NSTokens::Separator::BigSpaceSeparator : NSTokens::Separator::CommaAndBigSpaceSeparator); writer->WriteUInt32(NSTokens::Key::index, currInfo->FirstIndex); writer->WriteUInt32(NSTokens::Key::offset, currInfo->LastIndex, NSTokens::Separator::CommaSeparator); writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator); for(uint32 i = currInfo->FirstIndex; i < currInfo->LastIndex; ++i) { uint32 j = (i - currInfo->FirstIndex); writer->WriteRecordStart(j == 0 ? NSTokens::Separator::NoSeparator : NSTokens::Separator::CommaSeparator); writer->WriteInt32(NSTokens::Key::isValid, currInfo->ArrayValidTags[j]); if(currInfo->ArrayValidTags[j]) { SnapArrayInfo_EmitValue(currInfo->ArrayRangeContents[j], writer); } writer->WriteRecordEnd(); } writer->WriteSequenceEnd(); writer->WriteRecordEnd(); } writer->AdjustIndent(-1); writer->WriteSequenceEnd(NSTokens::Separator::BigSpaceSeparator); } template void EmitAddtlInfo_SnapArrayInfo(const SnapObject* snpObject, FileWriter* writer) { SnapArrayInfo* arrayInfo = SnapObjectGetAddtlInfoAs*, snapArrayKind>(snpObject); EmitAddtlInfo_SnapArrayInfoCore(arrayInfo, writer); } template SnapArrayInfo* ParseAddtlInfo_SnapArrayInfoCore(FileReader* reader, SlabAllocator& alloc) { uint32 alength = reader->ReadLengthValue(true); SnapArrayInfoBlock* arrayInfo = nullptr; SnapArrayInfoBlock* curr = nullptr; uint32 blockCount = reader->ReadLengthValue(true); reader->ReadSequenceStart_WDefaultKey(true); for(uint32 k = 0; k < blockCount; ++k) { reader->ReadRecordStart(k != 0); SnapArrayInfoBlock* tmp = alloc.SlabAllocateStruct< SnapArrayInfoBlock >(); tmp->FirstIndex = reader->ReadUInt32(NSTokens::Key::index); tmp->LastIndex = reader->ReadUInt32(NSTokens::Key::offset, true); tmp->ArrayValidTags = alloc.SlabAllocateArray(tmp->LastIndex - tmp->FirstIndex); tmp->ArrayRangeContents = alloc.SlabAllocateArray(tmp->LastIndex - tmp->FirstIndex); tmp->Next = nullptr; if(curr != nullptr) { curr->Next = tmp; } curr = tmp; TTDAssert(curr != nullptr, "Sanity assert failed."); if(arrayInfo == nullptr) { arrayInfo = curr; } reader->ReadSequenceStart_WDefaultKey(true); for(uint32 i = curr->FirstIndex; i < curr->LastIndex; ++i) { uint32 j = (i - curr->FirstIndex); reader->ReadRecordStart(j != 0); curr->ArrayValidTags[j] = (byte)reader->ReadInt32(NSTokens::Key::isValid); if(curr->ArrayValidTags[j]) { SnapArrayInfo_ParseValue(curr->ArrayRangeContents + j, reader, alloc); } reader->ReadRecordEnd(); } reader->ReadSequenceEnd(); reader->ReadRecordEnd(); } reader->ReadSequenceEnd(); SnapArrayInfo* res = alloc.SlabAllocateStruct< SnapArrayInfo >(); res->Length = alength; res->Data = arrayInfo; return res; } template void ParseAddtlInfo_SnapArrayInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc) { SnapArrayInfo* arrayInfo = ParseAddtlInfo_SnapArrayInfoCore(reader, alloc); SnapObjectSetAddtlInfoAs*, snapArrayKind>(snpObject, arrayInfo); } #if ENABLE_SNAPSHOT_COMPARE template void AdvanceArrayIndex_SnapArrayInfoCompare(uint32* index, uint32* pos, const SnapArrayInfoBlock** segment) { *index = *index + 1; if(*index >= (*segment)->LastIndex) { *segment = (*segment)->Next; *pos = 0; if(*segment != nullptr) { *index = (*segment)->FirstIndex; } } else { TTDAssert(*index >= (*segment)->FirstIndex, "Something went wrong."); *pos = *index - (*segment)->FirstIndex; } } template void AssertSnapEquiv_SnapArrayInfoCore(const SnapArrayInfoBlock* arrayInfo1, const SnapArrayInfoBlock* arrayInfo2, TTDCompareMap& compareMap) { uint32 index1 = (arrayInfo1 != nullptr) ? arrayInfo1->FirstIndex : 0; uint32 pos1 = 0; uint32 index2 = (arrayInfo2 != nullptr) ? arrayInfo2->FirstIndex : 0; uint32 pos2 = 0; while(arrayInfo1 != nullptr && arrayInfo2 != nullptr) { if(index1 < index2) { compareMap.DiagnosticAssert(!arrayInfo1->ArrayValidTags[pos1]); AdvanceArrayIndex_SnapArrayInfoCompare(&index1, &pos1, &arrayInfo1); } else if(index1 > index2) { compareMap.DiagnosticAssert(!arrayInfo2->ArrayValidTags[pos2]); AdvanceArrayIndex_SnapArrayInfoCompare(&index2, &pos2, &arrayInfo2); } else { compareMap.DiagnosticAssert(arrayInfo1->ArrayValidTags[pos1] == arrayInfo2->ArrayValidTags[pos2]); if(arrayInfo1->ArrayValidTags[pos1]) { SnapArrayInfo_EquivValue(arrayInfo1->ArrayRangeContents[pos1], arrayInfo2->ArrayRangeContents[pos2], compareMap, index1); } AdvanceArrayIndex_SnapArrayInfoCompare(&index1, &pos1, &arrayInfo1); AdvanceArrayIndex_SnapArrayInfoCompare(&index2, &pos2, &arrayInfo2); } } //make sure any remaining entries an empty while(arrayInfo1 != nullptr) { compareMap.DiagnosticAssert(!arrayInfo1->ArrayValidTags[pos1]); AdvanceArrayIndex_SnapArrayInfoCompare(&index1, &pos1, &arrayInfo1); } while(arrayInfo1 != nullptr) { compareMap.DiagnosticAssert(!arrayInfo2->ArrayValidTags[pos2]); AdvanceArrayIndex_SnapArrayInfoCompare(&index2, &pos2, &arrayInfo2); } } template void AssertSnapEquiv_SnapArrayInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap) { const SnapArrayInfo* arrayInfo1 = SnapObjectGetAddtlInfoAs*, snapArrayKind>(sobj1); const SnapArrayInfo* arrayInfo2 = SnapObjectGetAddtlInfoAs*, snapArrayKind>(sobj2); compareMap.DiagnosticAssert(arrayInfo1->Length == arrayInfo2->Length); AssertSnapEquiv_SnapArrayInfoCore(arrayInfo1->Data, arrayInfo2->Data, compareMap); } #endif ////////////////// //A struct that represents a single getter/setter value in an ES5 array struct SnapES5ArrayGetterSetterEntry { uint32 Index; Js::PropertyAttributes Attributes; TTDVar Getter; TTDVar Setter; }; //A struct that represents Javascript ES5 arrays struct SnapES5ArrayInfo { //Values copied from the ES5ArrayTypeHandler indexed data map uint32 GetterSetterCount; SnapES5ArrayGetterSetterEntry* GetterSetterEntries; //Values that are copied from the underlying data array SnapArrayInfo* BasicArrayData; //True if the length is writable bool IsLengthWritable; }; Js::RecyclableObject* DoObjectInflation_SnapES5ArrayInfo(const SnapObject* snpObject, InflateMap* inflator); void DoAddtlValueInstantiation_SnapES5ArrayInfo(const SnapObject* snpObject, Js::RecyclableObject* obj, InflateMap* inflator); void EmitAddtlInfo_SnapES5ArrayInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapES5ArrayInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapES5ArrayInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif ////////////////// //A struct that represents an array buffer struct SnapArrayBufferInfo { //The length of the array in bytes uint32 Length; //The byte array with the data byte* Buff; }; //// //Functions for the VTable for SnapArrayBufferObject Js::RecyclableObject* DoObjectInflation_SnapArrayBufferInfo(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop void EmitAddtlInfo_SnapArrayBufferInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapArrayBufferInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapArrayBufferInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif //A struct that represents a typed array struct SnapTypedArrayInfo { //The byte offset that the data starts in in the buffer uint32 ByteOffset; //The length of the array (in terms of the underlying typed values) uint32 Length; //The array buffer that this typed array is a projection of -- need to fix this in cpp file too TTD_PTR_ID ArrayBufferAddr; }; //// //Functions for the VTable for SnapTypedArrayObject Js::RecyclableObject* DoObjectInflation_SnapTypedArrayInfo(const SnapObject* snpObject, InflateMap* inflator); //DoAddtlValueInstantiation is a nop void EmitAddtlInfo_SnapTypedArrayInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapTypedArrayInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapTypedArrayInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif ////////////////// //A struct that represents a set (or weakset) object struct SnapSetInfo { //The number of elements in the set uint32 SetSize; //The set values we want to store TTDVar* SetValueArray; }; //// //Functions for the VTable for SnapSetObject Js::RecyclableObject* DoObjectInflation_SnapSetInfo(const SnapObject* snpObject, InflateMap* inflator); void DoAddtlValueInstantiation_SnapSetInfo(const SnapObject* snpObject, Js::RecyclableObject* obj, InflateMap* inflator); void EmitAddtlInfo_SnapSetInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapSetInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapSetInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif ////////////////// //A struct that represents a map (or weakmap) object struct SnapMapInfo { //The number of elements in the set uint32 MapSize; //The keys/values we want to store (keys are at i, values at i + 1) TTDVar* MapKeyValueArray; }; //// //Functions for the VTable for SnapMapObject Js::RecyclableObject* DoObjectInflation_SnapMapInfo(const SnapObject* snpObject, InflateMap* inflator); void DoAddtlValueInstantiation_SnapMapInfo(const SnapObject* snpObject, Js::RecyclableObject* obj, InflateMap* inflator); void EmitAddtlInfo_SnapMapInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapMapInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapMapInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif ////////////////// //A struct that represents a map (or weakmap) object struct SnapProxyInfo { //The handler ptrid (or invalid if revoked) TTD_PTR_ID HandlerId; //The target ptrid (or invalid if revoked) TTD_PTR_ID TargetId; }; //// //Functions for the VTable for SnapProxyObject Js::RecyclableObject* DoObjectInflation_SnapProxyInfo(const SnapObject* snpObject, InflateMap* inflator); void EmitAddtlInfo_SnapProxyInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapProxyInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapProxyInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif ////////////////// struct SnapGeneratorFunctionInfo { TTD_PTR_ID scriptFunction; // pointer to GeneratorVirtualScriptFunction bool isAnonymousFunction; }; struct SnapGeneratorVirtualScriptFunctionInfo : SnapScriptFunctionInfo { TTD_PTR_ID realFunction; //pointer to JavascriptGeneratorFunction }; struct SnapAsyncFunctionInfo { }; struct SnapGeneratorInfo { int generatorPrototype; // 0 == unknown, 1 == nullType, 2 == generatorPrototype Js::RegSlot frame_slotCount; TTDVar* frame_slotArray; uint32 state; // enum value of JavascriptGenerator.GeneratorState TTD_PTR_ID scriptFunction; uint32 arguments_callInfo_count; uint8 arguments_callInfo_flags; uint arguments_count; TTDVar* arguments_values; uint byteCodeReader_offset; }; Js::RecyclableObject* DoObjectInflation_SnapGeneratorInfo(const SnapObject* snpObject, InflateMap* inflator); void DoAddtlValueInstantiation_SnapGeneratorInfo(const SnapObject* snpObject, Js::RecyclableObject* obj, InflateMap* inflator); void EmitAddtlInfo_SnapGeneratorInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapGeneratorInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapGeneratorInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif Js::RecyclableObject *DoObjectInflation_SnapGeneratorFunctionInfo(const SnapObject *snpObject, InflateMap *inflator); void DoAddtlValueInstantiation_SnapGeneratorFunctionInfo(const SnapObject *snpObject, Js::RecyclableObject *obj, InflateMap *inflator); void EmitAddtlInfo_SnapGeneratorFunctionInfo(const SnapObject *snpObject, FileWriter *writer); void ParseAddtlInfo_SnapGeneratorFunctionInfo(SnapObject *snpObject, FileReader *reader, SlabAllocator &alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapGeneratorFunctionInfo(const SnapObject *sobj1, const SnapObject *sobj2, TTDCompareMap &compareMap); #endif Js::RecyclableObject* DoObjectInflation_SnapGeneratorVirtualScriptFunctionInfo(const SnapObject *snpObject, InflateMap *inflator); void DoAddtlValueInstantiation_SnapGeneratorVirtualScriptFunctionInfo(const SnapObject *snpObject, Js::RecyclableObject *obj, InflateMap *inflator); void EmitAddtlInfo_SnapGeneratorVirtualScriptFunctionInfo(const SnapObject *snpObject, FileWriter *writer); void ParseAddtlInfo_SnapGeneratorVirtualScriptFunctionInfo(SnapObject *snpObject, FileReader *reader, SlabAllocator &alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapGeneratorVirtualScriptFunctionInfo(const SnapObject *sobj1, const SnapObject *sobj2, TTDCompareMap &compareMap); #endif Js::RecyclableObject *DoObjectInflation_SnapAsyncFunction(const SnapObject *snpObject, InflateMap *inflator); void DoAddtlValueInstantiation_SnapAsyncFunction(const SnapObject* snpObject, Js::RecyclableObject* obj, InflateMap* inflator); void EmitAddtlInfo_SnapAsyncFunction(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapAsyncFunction(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapAsyncFunction(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif ////////// struct SnapJavascriptPromiseAsyncSpawnExecutorFunctionInfo { TTD_PTR_ID generator; TTDVar target; }; Js::RecyclableObject *DoObjectInflation_SnapJavascriptPromiseAsyncSpawnExecutorFunction(const SnapObject *snpObject, InflateMap *inflator); void DoAddtlValueInstantiation_SnapJavascriptPromiseAsyncSpawnExecutorFunction(const SnapObject* snpObject, Js::RecyclableObject* obj, InflateMap* inflator); void EmitAddtlInfo_SnapJavascriptPromiseAsyncSpawnExecutorFunction(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapJavascriptPromiseAsyncSpawnExecutorFunction(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapJavascriptPromiseAsyncSpawnExecutorFunction(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif ////////// struct SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo { TTD_PTR_ID generator; TTDVar reject; TTDVar resolve; bool isReject; TTDVar argument; uint32 entryPoint; }; Js::RecyclableObject *DoObjectInflation_SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo(const SnapObject *snpObject, InflateMap *inflator); void DoAddtlValueInstantiation_SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo(const SnapObject* snpObject, Js::RecyclableObject* obj, InflateMap* inflator); void EmitAddtlInfo_SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo(const SnapObject* snpObject, FileWriter* writer); void ParseAddtlInfo_SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo(SnapObject* snpObject, FileReader* reader, SlabAllocator& alloc); #if ENABLE_SNAPSHOT_COMPARE void AssertSnapEquiv_SnapJavascriptPromiseAsyncSpawnStepArgumentExecutorFunctionInfo(const SnapObject* sobj1, const SnapObject* sobj2, TTDCompareMap& compareMap); #endif ////////// } } #endif