| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "RuntimeDebugPch.h"
- #if ENABLE_TTD
- #include "ByteCode/ByteCodeSerializer.h"
- namespace TTD
- {
- namespace JsSupport
- {
- bool IsVarTaggedInline(Js::Var v)
- {
- return Js::TaggedNumber::Is(v);
- }
- bool IsVarPtrValued(Js::Var v)
- {
- return !Js::TaggedNumber::Is(v);
- }
- bool IsVarPrimitiveKind(Js::Var v)
- {
- if(Js::TaggedNumber::Is(v))
- {
- return false;
- }
- Js::TypeId tid = Js::RecyclableObject::FromVar(v)->GetTypeId();
- return tid <= Js::TypeIds_LastToPrimitiveType;
- }
- bool IsVarComplexKind(Js::Var v)
- {
- if(Js::TaggedNumber::Is(v))
- {
- return false;
- }
- Js::TypeId tid = Js::RecyclableObject::FromVar(v)->GetTypeId();
- return tid > Js::TypeIds_LastToPrimitiveType;
- }
- #if ENABLE_TTD_INTERNAL_DIAGNOSTICS
- bool AreInlineVarsEquiv(Js::Var v1, Js::Var v2)
- {
- if(v1 == v2)
- {
- return true; //same bit pattern so no problem
- }
- if(v1 == nullptr || v2 == nullptr)
- {
- return false; //then they should be the same per above
- }
- if(Js::TaggedNumber::Is(v1) != Js::TaggedNumber::Is(v2))
- {
- return false;
- }
- double v1val = Js::TaggedInt::Is(v1) ? Js::TaggedInt::ToInt32(v1) : Js::JavascriptNumber::GetValue(v1);
- double v2val = Js::TaggedInt::Is(v2) ? Js::TaggedInt::ToInt32(v2) : Js::JavascriptNumber::GetValue(v2);
- if(Js::JavascriptNumber::IsNan(v1val) != Js::JavascriptNumber::IsNan(v2val))
- {
- return false;
- }
- return v1val == v2val;
- }
- #endif
- Js::FunctionBody* ForceAndGetFunctionBody(Js::ParseableFunctionInfo* pfi)
- {
- Js::FunctionBody* fb = nullptr;
- if(pfi->IsDeferredDeserializeFunction())
- {
- Js::DeferDeserializeFunctionInfo* deferDeserializeInfo = pfi->GetDeferDeserializeFunctionInfo();
- fb = deferDeserializeInfo->Deserialize();
- }
- else
- {
- if(pfi->IsDeferredParseFunction())
- {
- fb = pfi->GetParseableFunctionInfo()->Parse();
- }
- else
- {
- fb = pfi->GetFunctionBody();
- }
- }
- TTDAssert(fb != nullptr, "I just want a function body!!!");
- fb->EnsureDeserialized();
- return fb;
- }
- void WriteCodeToFile(ThreadContext* threadContext, bool fromEvent, uint32 bodyId, bool isUtf8Source, byte* sourceBuffer, uint32 length)
- {
- char asciiResourceName[64];
- sprintf_s(asciiResourceName, 64, "src%s_%I32u.js", (fromEvent ? "_ld" : ""), bodyId);
- TTDataIOInfo& iofp = threadContext->TTDContext->TTDataIOInfo;
- JsTTDStreamHandle srcStream = iofp.pfOpenResourceStream(iofp.ActiveTTUriLength, iofp.ActiveTTUri, strlen(asciiResourceName), asciiResourceName, false, true);
- TTDAssert(srcStream != nullptr, "Failed to open code resource stream for writing.");
- if(isUtf8Source)
- {
- byte byteOrderArray[3] = { 0xEF, 0xBB, 0xBF };
- size_t byteOrderCount = 0;
- bool okBOC = iofp.pfWriteBytesToStream(srcStream, byteOrderArray, _countof(byteOrderArray), &byteOrderCount);
- TTDAssert(okBOC && byteOrderCount == _countof(byteOrderArray), "Write Failed!!!");
- }
- else
- {
- byte byteOrderArray[2] = { 0xFF, 0xFE };
- size_t byteOrderCount = 0;
- bool okBOC = iofp.pfWriteBytesToStream(srcStream, byteOrderArray, _countof(byteOrderArray), &byteOrderCount);
- TTDAssert(okBOC && byteOrderCount == _countof(byteOrderArray), "Write Failed!!!");
- }
- size_t writtenCount = 0;
- bool ok = iofp.pfWriteBytesToStream(srcStream, sourceBuffer, length, &writtenCount);
- TTDAssert(ok && writtenCount == length, "Write Failed!!!");
- iofp.pfFlushAndCloseStream(srcStream, false, true);
- }
- void ReadCodeFromFile(ThreadContext* threadContext, bool fromEvent, uint32 bodyId, bool isUtf8Source, byte* sourceBuffer, uint32 length)
- {
- char asciiResourceName[64];
- sprintf_s(asciiResourceName, 64, "src%s_%I32u.js", (fromEvent ? "_ld" : ""), bodyId);
- TTDataIOInfo& iofp = threadContext->TTDContext->TTDataIOInfo;
- JsTTDStreamHandle srcStream = iofp.pfOpenResourceStream(iofp.ActiveTTUriLength, iofp.ActiveTTUri, strlen(asciiResourceName), asciiResourceName, true, false);
- TTDAssert(srcStream != nullptr, "Failed to open code resource stream for reading.");
- if(isUtf8Source)
- {
- byte byteOrderArray[3] = { 0x0, 0x0, 0x0 };
- size_t byteOrderCount = 0;
- bool okBOC = iofp.pfReadBytesFromStream(srcStream, byteOrderArray, _countof(byteOrderArray), &byteOrderCount);
- TTDAssert(okBOC && byteOrderCount == _countof(byteOrderArray) && byteOrderArray[0] == 0xEF && byteOrderArray[1] == 0xBB && byteOrderArray[2] == 0xBF, "Read Failed!!!");
- }
- else
- {
- byte byteOrderArray[2] = { 0x0, 0x0 };
- size_t byteOrderCount = 0;
- bool okBOC = iofp.pfReadBytesFromStream(srcStream, byteOrderArray, _countof(byteOrderArray), &byteOrderCount);
- TTDAssert(okBOC && byteOrderCount == _countof(byteOrderArray) && byteOrderArray[0] == 0xFF && byteOrderArray[1] == 0xFE, "Read Failed!!!");
- }
- size_t readCount = 0;
- bool ok = iofp.pfReadBytesFromStream(srcStream, sourceBuffer, length, &readCount);
- TTDAssert(ok && readCount == length, "Read Failed!!!");
- iofp.pfFlushAndCloseStream(srcStream, true, false);
- }
- }
- namespace NSSnapValues
- {
- void EmitTTDVar(TTDVar var, FileWriter* writer, NSTokens::Separator separator)
- {
- writer->WriteRecordStart(separator);
- if(var == nullptr)
- {
- writer->WriteTag<TTDVarEmitTag>(NSTokens::Key::ttdVarTag, TTDVarEmitTag::TTDVarNull);
- writer->WriteNull(NSTokens::Key::nullVal, NSTokens::Separator::CommaSeparator);
- }
- else if(Js::TaggedNumber::Is(var))
- {
- #if FLOATVAR
- if(Js::TaggedInt::Is(var))
- {
- #endif
- writer->WriteTag<TTDVarEmitTag>(NSTokens::Key::ttdVarTag, TTDVarEmitTag::TTDVarInt);
- writer->WriteInt32(NSTokens::Key::i32Val, Js::TaggedInt::ToInt32(var), NSTokens::Separator::CommaSeparator);
- #if FLOATVAR
- }
- else
- {
- TTDAssert(Js::JavascriptNumber::Is_NoTaggedIntCheck(var), "Only other tagged value we support!!!");
- writer->WriteTag<TTDVarEmitTag>(NSTokens::Key::ttdVarTag, TTDVarEmitTag::TTDVarDouble);
- writer->WriteDouble(NSTokens::Key::doubleVal, Js::JavascriptNumber::GetValue(var), NSTokens::Separator::CommaSeparator);
- }
- #endif
- }
- else
- {
- writer->WriteTag<TTDVarEmitTag>(NSTokens::Key::ttdVarTag, TTDVarEmitTag::TTDVarAddr);
- writer->WriteAddr(NSTokens::Key::ptrIdVal, TTD_CONVERT_VAR_TO_PTR_ID(var), NSTokens::Separator::CommaSeparator);
- }
- writer->WriteRecordEnd();
- }
- TTDVar ParseTTDVar(bool readSeperator, FileReader* reader)
- {
- reader->ReadRecordStart(readSeperator);
- TTDVar res = nullptr;
- TTDVarEmitTag tag = reader->ReadTag<TTDVarEmitTag>(NSTokens::Key::ttdVarTag);
- if(tag == TTDVarEmitTag::TTDVarNull)
- {
- reader->ReadNull(NSTokens::Key::nullVal, true);
- res = nullptr;
- }
- else if(tag == TTDVarEmitTag::TTDVarInt)
- {
- int32 intVal = reader->ReadInt32(NSTokens::Key::i32Val, true);
- res = Js::TaggedInt::ToVarUnchecked(intVal);
- }
- #if FLOATVAR
- else if(tag == TTDVarEmitTag::TTDVarDouble)
- {
- double doubleVal = reader->ReadDouble(NSTokens::Key::doubleVal, true);
- res = Js::JavascriptNumber::NewInlined(doubleVal, nullptr);
- }
- #endif
- else
- {
- TTDAssert(tag == TTDVarEmitTag::TTDVarAddr, "Is there something else?");
- TTD_PTR_ID addrVal = reader->ReadAddr(NSTokens::Key::ptrIdVal, true);
- res = TTD_COERCE_PTR_ID_TO_VAR(addrVal);
- }
- reader->ReadRecordEnd();
- return res;
- }
- #if ENABLE_SNAPSHOT_COMPARE
- bool CheckSnapEquivTTDDouble(double d1, double d2)
- {
- if(Js::JavascriptNumber::IsNan(d1) || Js::JavascriptNumber::IsNan(d2))
- {
- return (Js::JavascriptNumber::IsNan(d1) && Js::JavascriptNumber::IsNan(d2));
- }
- else
- {
- return (d1 == d2);
- }
- }
- void AssertSnapEquivTTDVar_Helper(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, TTDComparePath::StepKind stepKind, const TTDComparePath::PathEntry& next)
- {
- if(v1 == nullptr || v2 == nullptr)
- {
- compareMap.DiagnosticAssert(v1 == v2);
- }
- else if(Js::TaggedNumber::Is(v1) || Js::TaggedNumber::Is(v2))
- {
- compareMap.DiagnosticAssert(JsSupport::AreInlineVarsEquiv(v1, v2));
- }
- else
- {
- compareMap.CheckConsistentAndAddPtrIdMapping_Helper(TTD_CONVERT_VAR_TO_PTR_ID(v1), TTD_CONVERT_VAR_TO_PTR_ID(v2), stepKind, next);
- }
- }
- void AssertSnapEquivTTDVar_Property(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, Js::PropertyId pid)
- {
- TTDComparePath::PathEntry next{ (uint32)pid, nullptr };
- AssertSnapEquivTTDVar_Helper(v1, v2, compareMap, TTDComparePath::StepKind::PropertyData, next);
- }
- void AssertSnapEquivTTDVar_PropertyGetter(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, Js::PropertyId pid)
- {
- TTDComparePath::PathEntry next{ (uint32)pid, nullptr };
- AssertSnapEquivTTDVar_Helper(v1, v2, compareMap, TTDComparePath::StepKind::PropertyGetter, next);
- }
- void AssertSnapEquivTTDVar_PropertySetter(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, Js::PropertyId pid)
- {
- TTDComparePath::PathEntry next{ (uint32)pid, nullptr };
- AssertSnapEquivTTDVar_Helper(v1, v2, compareMap, TTDComparePath::StepKind::PropertySetter, next);
- }
- void AssertSnapEquivTTDVar_Array(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, uint32 index)
- {
- TTDComparePath::PathEntry next{ index, nullptr };
- AssertSnapEquivTTDVar_Helper(v1, v2, compareMap, TTDComparePath::StepKind::Array, next);
- }
- void AssertSnapEquivTTDVar_SlotArray(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, uint32 index)
- {
- TTDComparePath::PathEntry next{ index, nullptr };
- AssertSnapEquivTTDVar_Helper(v1, v2, compareMap, TTDComparePath::StepKind::SlotArray, next);
- }
- void AssertSnapEquivTTDVar_Special(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, const char16* specialField)
- {
- TTDComparePath::PathEntry next{ -1, specialField };
- AssertSnapEquivTTDVar_Helper(v1, v2, compareMap, TTDComparePath::StepKind::Special, next);
- }
- void AssertSnapEquivTTDVar_SpecialArray(const TTDVar v1, const TTDVar v2, TTDCompareMap& compareMap, const char16* specialField, uint32 index)
- {
- TTDComparePath::PathEntry next{ index, specialField };
- AssertSnapEquivTTDVar_Helper(v1, v2, compareMap, TTDComparePath::StepKind::SpecialArray, next);
- }
- #endif
- //////////////////
- void ExtractSnapPrimitiveValue(SnapPrimitiveValue* snapValue, Js::RecyclableObject* jsValue, bool isWellKnown, const TTDIdentifierDictionary<TTD_PTR_ID, NSSnapType::SnapType*>& idToTypeMap, SlabAllocator& alloc)
- {
- snapValue->PrimitiveValueId = TTD_CONVERT_VAR_TO_PTR_ID(jsValue);
- Js::Type* objType = jsValue->GetType();
- snapValue->SnapType = idToTypeMap.LookupKnownItem(TTD_CONVERT_TYPEINFO_TO_PTR_ID(objType));
- TTD_WELLKNOWN_TOKEN lookupToken = isWellKnown ? jsValue->GetScriptContext()->TTDWellKnownInfo->ResolvePathForKnownObject(jsValue) : TTD_INVALID_WELLKNOWN_TOKEN;
- snapValue->OptWellKnownToken = alloc.CopyRawNullTerminatedStringInto(lookupToken);
- if(snapValue->OptWellKnownToken == TTD_INVALID_WELLKNOWN_TOKEN)
- {
- Js::JavascriptLibrary* jslib = jsValue->GetLibrary();
- switch(snapValue->SnapType->JsTypeId)
- {
- case Js::TypeIds_Undefined:
- case Js::TypeIds_Null:
- break;
- case Js::TypeIds_Boolean:
- snapValue->u_boolValue = Js::JavascriptBoolean::FromVar(jsValue)->GetValue();
- break;
- case Js::TypeIds_Number:
- snapValue->u_doubleValue = Js::JavascriptNumber::GetValue(jsValue);
- break;
- case Js::TypeIds_Int64Number:
- snapValue->u_int64Value = Js::JavascriptInt64Number::FromVar(jsValue)->GetValue();
- break;
- case Js::TypeIds_UInt64Number:
- snapValue->u_uint64Value = Js::JavascriptUInt64Number::FromVar(jsValue)->GetValue();
- break;
- case Js::TypeIds_String:
- snapValue->u_stringValue = alloc.SlabAllocateStruct<TTString>();
- alloc.CopyStringIntoWLength(Js::JavascriptString::FromVar(jsValue)->GetSz(), Js::JavascriptString::FromVar(jsValue)->GetLength(), *(snapValue->u_stringValue));
- break;
- case Js::TypeIds_Symbol:
- snapValue->u_propertyIdValue = jslib->ExtractPrimitveSymbolId_TTD(jsValue);
- break;
- default:
- TTDAssert(false, "These are supposed to be primitive values on the heap e.g., no pointers or properties.");
- break;
- }
- }
- }
- void InflateSnapPrimitiveValue(const SnapPrimitiveValue* snapValue, InflateMap* inflator)
- {
- Js::ScriptContext* ctx = inflator->LookupScriptContext(snapValue->SnapType->ScriptContextLogId);
- Js::JavascriptLibrary* jslib = ctx->GetLibrary();
- Js::Var res = nullptr;
- if(snapValue->OptWellKnownToken != TTD_INVALID_WELLKNOWN_TOKEN)
- {
- res = ctx->TTDWellKnownInfo->LookupKnownObjectFromPath(snapValue->OptWellKnownToken);
- }
- else
- {
- Js::RecyclableObject* rObj = inflator->FindReusableObjectIfExists(snapValue->PrimitiveValueId);
- if(rObj != nullptr)
- {
- res = rObj;
- }
- else
- {
- switch(snapValue->SnapType->JsTypeId)
- {
- case Js::TypeIds_Undefined:
- res = jslib->GetUndefined();
- break;
- case Js::TypeIds_Null:
- res = jslib->GetNull();
- break;
- case Js::TypeIds_Boolean:
- res = (snapValue->u_boolValue ? jslib->GetTrue() : jslib->GetFalse());
- break;
- case Js::TypeIds_Number:
- res = Js::JavascriptNumber::ToVarWithCheck(snapValue->u_doubleValue, ctx);
- break;
- case Js::TypeIds_Int64Number:
- res = Js::JavascriptInt64Number::ToVar(snapValue->u_int64Value, ctx);
- break;
- case Js::TypeIds_UInt64Number:
- res = Js::JavascriptUInt64Number::ToVar(snapValue->u_uint64Value, ctx);
- break;
- case Js::TypeIds_String:
- res = Js::JavascriptString::NewCopyBuffer(snapValue->u_stringValue->Contents, snapValue->u_stringValue->Length, ctx);
- break;
- case Js::TypeIds_Symbol:
- res = jslib->CreatePrimitveSymbol_TTD(snapValue->u_propertyIdValue);
- break;
- default:
- TTDAssert(false, "These are supposed to be primitive values e.g., no pointers or properties.");
- res = nullptr;
- }
- }
- }
- inflator->AddObject(snapValue->PrimitiveValueId, Js::RecyclableObject::FromVar(res));
- }
- void EmitSnapPrimitiveValue(const SnapPrimitiveValue* snapValue, FileWriter* writer, NSTokens::Separator separator)
- {
- writer->WriteRecordStart(separator);
- writer->WriteAddr(NSTokens::Key::primitiveId, snapValue->PrimitiveValueId);
- writer->WriteAddr(NSTokens::Key::typeId, snapValue->SnapType->TypePtrId, NSTokens::Separator::CommaSeparator);
- writer->WriteBool(NSTokens::Key::isWellKnownToken, snapValue->OptWellKnownToken != TTD_INVALID_WELLKNOWN_TOKEN, NSTokens::Separator::CommaSeparator);
- if(snapValue->OptWellKnownToken != TTD_INVALID_WELLKNOWN_TOKEN)
- {
- writer->WriteWellKnownToken(NSTokens::Key::wellKnownToken, snapValue->OptWellKnownToken, NSTokens::Separator::CommaSeparator);
- }
- else
- {
- switch(snapValue->SnapType->JsTypeId)
- {
- case Js::TypeIds_Undefined:
- case Js::TypeIds_Null:
- break;
- case Js::TypeIds_Boolean:
- writer->WriteBool(NSTokens::Key::boolVal, !!snapValue->u_boolValue, NSTokens::Separator::CommaSeparator);
- break;
- case Js::TypeIds_Number:
- writer->WriteDouble(NSTokens::Key::doubleVal, snapValue->u_doubleValue, NSTokens::Separator::CommaSeparator);
- break;
- case Js::TypeIds_Int64Number:
- writer->WriteInt64(NSTokens::Key::i64Val, snapValue->u_int64Value, NSTokens::Separator::CommaSeparator);
- break;
- case Js::TypeIds_UInt64Number:
- writer->WriteUInt64(NSTokens::Key::u64Val, snapValue->u_uint64Value, NSTokens::Separator::CommaSeparator);
- break;
- case Js::TypeIds_String:
- writer->WriteString(NSTokens::Key::stringVal, *(snapValue->u_stringValue), NSTokens::Separator::CommaSeparator);
- break;
- case Js::TypeIds_Symbol:
- writer->WriteInt32(NSTokens::Key::propertyId, snapValue->u_propertyIdValue, NSTokens::Separator::CommaSeparator);
- break;
- default:
- TTDAssert(false, "These are supposed to be primitive values e.g., no pointers or properties.");
- break;
- }
- }
- writer->WriteRecordEnd();
- }
- void ParseSnapPrimitiveValue(SnapPrimitiveValue* snapValue, bool readSeperator, FileReader* reader, SlabAllocator& alloc, const TTDIdentifierDictionary<TTD_PTR_ID, NSSnapType::SnapType*>& ptrIdToTypeMap)
- {
- reader->ReadRecordStart(readSeperator);
- snapValue->PrimitiveValueId = reader->ReadAddr(NSTokens::Key::primitiveId);
- TTD_PTR_ID snapTypeId = reader->ReadAddr(NSTokens::Key::typeId, true);
- snapValue->SnapType = ptrIdToTypeMap.LookupKnownItem(snapTypeId);
- bool isWellKnown = reader->ReadBool(NSTokens::Key::isWellKnownToken, true);
- if(isWellKnown)
- {
- snapValue->OptWellKnownToken = reader->ReadWellKnownToken(NSTokens::Key::wellKnownToken, alloc, true);
- //just clear it to help avoid any confusion later
- snapValue->u_uint64Value = 0;
- }
- else
- {
- snapValue->OptWellKnownToken = nullptr;
- switch(snapValue->SnapType->JsTypeId)
- {
- case Js::TypeIds_Undefined:
- case Js::TypeIds_Null:
- break;
- case Js::TypeIds_Boolean:
- snapValue->u_boolValue = reader->ReadBool(NSTokens::Key::boolVal, true);
- break;
- case Js::TypeIds_Number:
- snapValue->u_doubleValue = reader->ReadDouble(NSTokens::Key::doubleVal, true);
- break;
- case Js::TypeIds_Int64Number:
- snapValue->u_int64Value = reader->ReadInt64(NSTokens::Key::i64Val, true);
- break;
- case Js::TypeIds_UInt64Number:
- snapValue->u_uint64Value = reader->ReadUInt64(NSTokens::Key::u64Val, true);
- break;
- case Js::TypeIds_String:
- snapValue->u_stringValue = alloc.SlabAllocateStruct<TTString>();
- reader->ReadString(NSTokens::Key::stringVal, alloc, *(snapValue->u_stringValue), true);
- break;
- case Js::TypeIds_Symbol:
- snapValue->u_propertyIdValue = (Js::PropertyId)reader->ReadInt32(NSTokens::Key::propertyId, true);
- break;
- default:
- TTDAssert(false, "These are supposed to be primitive values e.g., no pointers or properties.");
- break;
- }
- }
- reader->ReadRecordEnd();
- }
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const SnapPrimitiveValue* v1, const SnapPrimitiveValue* v2, TTDCompareMap& compareMap)
- {
- compareMap.DiagnosticAssert(v1->SnapType->JsTypeId == v2->SnapType->JsTypeId);
- NSSnapType::AssertSnapEquiv(v1->SnapType, v2->SnapType, compareMap);
- if(v1->OptWellKnownToken != TTD_INVALID_WELLKNOWN_TOKEN || v2->OptWellKnownToken != TTD_INVALID_WELLKNOWN_TOKEN)
- {
- compareMap.DiagnosticAssert(v1->OptWellKnownToken != TTD_INVALID_WELLKNOWN_TOKEN && v2->OptWellKnownToken != TTD_INVALID_WELLKNOWN_TOKEN);
- compareMap.DiagnosticAssert(TTD_DIAGNOSTIC_COMPARE_WELLKNOWN_TOKENS(v1->OptWellKnownToken, v2->OptWellKnownToken));
- }
- else
- {
- switch(v1->SnapType->JsTypeId)
- {
- case Js::TypeIds_Undefined:
- case Js::TypeIds_Null:
- break;
- case Js::TypeIds_Boolean:
- compareMap.DiagnosticAssert((!!v1->u_boolValue) == (!!v2->u_boolValue));
- break;
- case Js::TypeIds_Number:
- compareMap.DiagnosticAssert(CheckSnapEquivTTDDouble(v1->u_doubleValue, v2->u_doubleValue));
- break;
- case Js::TypeIds_Int64Number:
- compareMap.DiagnosticAssert(v1->u_int64Value == v2->u_int64Value);
- break;
- case Js::TypeIds_UInt64Number:
- compareMap.DiagnosticAssert(v1->u_uint64Value == v2->u_uint64Value);
- break;
- case Js::TypeIds_String:
- compareMap.DiagnosticAssert(TTStringEQForDiagnostics(*(v1->u_stringValue), *(v2->u_stringValue)));
- break;
- case Js::TypeIds_Symbol:
- compareMap.DiagnosticAssert(v1->u_propertyIdValue == v2->u_propertyIdValue);
- break;
- default:
- TTDAssert(false, "These are supposed to be primitive values e.g., no pointers or properties.");
- break;
- }
- }
- }
- #endif
- //////////////////
- Js::Var* InflateSlotArrayInfo(const SlotArrayInfo* slotInfo, InflateMap* inflator)
- {
- Js::ScriptContext* ctx = inflator->LookupScriptContext(slotInfo->ScriptContextLogId);
- Field(Js::Var)* slotArray = RecyclerNewArray(ctx->GetRecycler(), Field(Js::Var), slotInfo->SlotCount + Js::ScopeSlots::FirstSlotIndex);
- Js::ScopeSlots scopeSlots((Js::Var*)slotArray);
- scopeSlots.SetCount(slotInfo->SlotCount);
- Js::Var undef = ctx->GetLibrary()->GetUndefined();
- for(uint32 j = 0; j < slotInfo->SlotCount; j++)
- {
- scopeSlots.Set(j, undef);
- }
- if(slotInfo->isFunctionBodyMetaData)
- {
- Js::FunctionBody* fbody = inflator->LookupFunctionBody(slotInfo->OptFunctionBodyId);
- scopeSlots.SetScopeMetadata(fbody->GetFunctionInfo());
- //This is a doubly nested lookup so if the scope slot array is large this could be expensive
- Js::PropertyId* propertyIds = fbody->GetPropertyIdsForScopeSlotArray();
- for(uint32 j = 0; j < slotInfo->SlotCount; j++)
- {
- Js::PropertyId trgtPid = slotInfo->PIDArray[j];
- for(uint32 i = 0; i < fbody->GetScopeSlotArraySize(); i++)
- {
- if(trgtPid == propertyIds[i])
- {
- Js::Var sval = inflator->InflateTTDVar(slotInfo->Slots[j]);
- scopeSlots.Set(i, sval);
- break;
- }
- }
- }
- }
- else
- {
- Js::DebuggerScope* dbgScope = nullptr;
- if(slotInfo->OptWellKnownDbgScope != TTD_INVALID_WELLKNOWN_TOKEN)
- {
- dbgScope = ctx->TTDWellKnownInfo->LookupKnownDebuggerScopeFromPath(slotInfo->OptWellKnownDbgScope);
- }
- else
- {
- Js::FunctionBody* scopeBody = nullptr;
- int32 scopeIndex = -1;
- inflator->LookupInfoForDebugScope(slotInfo->OptDebugScopeId, &scopeBody, &scopeIndex);
- dbgScope = scopeBody->GetScopeObjectChain()->pScopeChain->Item(scopeIndex);
- }
- scopeSlots.SetScopeMetadata(dbgScope);
- //This is a doubly nested lookup so if the scope slot array is large this could be expensive
- for(uint32 j = 0; j < slotInfo->SlotCount; j++)
- {
- Js::PropertyId trgtPid = slotInfo->PIDArray[j];
- for(uint32 i = 0; i < slotInfo->SlotCount; i++)
- {
- if(trgtPid == dbgScope->GetPropertyIdForSlotIndex_TTD(i))
- {
- Js::Var sval = inflator->InflateTTDVar(slotInfo->Slots[j]);
- scopeSlots.Set(i, sval);
- break;
- }
- }
- }
- }
- return (Js::Var*)slotArray;
- }
- void EmitSlotArrayInfo(const SlotArrayInfo* slotInfo, FileWriter* writer, NSTokens::Separator separator)
- {
- writer->WriteRecordStart(separator);
- writer->AdjustIndent(1);
- writer->WriteAddr(NSTokens::Key::slotId, slotInfo->SlotId, NSTokens::Separator::BigSpaceSeparator);
- writer->WriteLogTag(NSTokens::Key::ctxTag, slotInfo->ScriptContextLogId, NSTokens::Separator::CommaSeparator);
- writer->WriteBool(NSTokens::Key::isFunctionMetaData, slotInfo->isFunctionBodyMetaData, NSTokens::Separator::CommaSeparator);
- if(slotInfo->isFunctionBodyMetaData)
- {
- writer->WriteAddr(NSTokens::Key::functionBodyId, slotInfo->OptFunctionBodyId, NSTokens::Separator::CommaSeparator);
- }
- else
- {
- writer->WriteBool(NSTokens::Key::isWellKnownToken, slotInfo->OptWellKnownDbgScope != TTD_INVALID_WELLKNOWN_TOKEN, NSTokens::Separator::CommaSeparator);
- if(slotInfo->OptWellKnownDbgScope != TTD_INVALID_WELLKNOWN_TOKEN)
- {
- writer->WriteWellKnownToken(NSTokens::Key::wellKnownToken, slotInfo->OptWellKnownDbgScope, NSTokens::Separator::CommaSeparator);
- }
- else
- {
- writer->WriteAddr(NSTokens::Key::debuggerScopeId, slotInfo->OptDebugScopeId, NSTokens::Separator::CommaSeparator);
- }
- }
- writer->WriteLengthValue(slotInfo->SlotCount, NSTokens::Separator::CommaAndBigSpaceSeparator);
- writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaAndBigSpaceSeparator);
- writer->AdjustIndent(1);
- for(uint32 i = 0; i < slotInfo->SlotCount; ++i)
- {
- writer->WriteRecordStart(i != 0 ? NSTokens::Separator::CommaAndBigSpaceSeparator : NSTokens::Separator::BigSpaceSeparator);
- writer->WriteUInt32(NSTokens::Key::pid, slotInfo->PIDArray[i], NSTokens::Separator::NoSeparator);
- writer->WriteKey(NSTokens::Key::entry, NSTokens::Separator::CommaSeparator);
- EmitTTDVar(slotInfo->Slots[i], writer, NSTokens::Separator::NoSeparator);
- writer->WriteRecordEnd();
- }
- writer->AdjustIndent(-1);
- writer->WriteSequenceEnd(NSTokens::Separator::BigSpaceSeparator);
- writer->AdjustIndent(-1);
- writer->WriteRecordEnd(NSTokens::Separator::BigSpaceSeparator);
- }
- void ParseSlotArrayInfo(SlotArrayInfo* slotInfo, bool readSeperator, FileReader* reader, SlabAllocator& alloc)
- {
- reader->ReadRecordStart(readSeperator);
- slotInfo->SlotId = reader->ReadAddr(NSTokens::Key::slotId);
- slotInfo->ScriptContextLogId = reader->ReadLogTag(NSTokens::Key::ctxTag, true);
- slotInfo->isFunctionBodyMetaData = reader->ReadBool(NSTokens::Key::isFunctionMetaData, true);
- slotInfo->OptFunctionBodyId = TTD_INVALID_PTR_ID;
- slotInfo->OptDebugScopeId = TTD_INVALID_PTR_ID;
- slotInfo->OptWellKnownDbgScope = TTD_INVALID_WELLKNOWN_TOKEN;
- if(slotInfo->isFunctionBodyMetaData)
- {
- slotInfo->OptFunctionBodyId = reader->ReadAddr(NSTokens::Key::functionBodyId, true);
- }
- else
- {
- bool isWellKnown = reader->ReadBool(NSTokens::Key::isWellKnownToken, true);
- if(isWellKnown)
- {
- slotInfo->OptWellKnownDbgScope = reader->ReadWellKnownToken(NSTokens::Key::wellKnownToken, alloc, true);
- }
- else
- {
- slotInfo->OptDebugScopeId = reader->ReadAddr(NSTokens::Key::debuggerScopeId, true);
- }
- }
- slotInfo->SlotCount = reader->ReadLengthValue(true);
- reader->ReadSequenceStart_WDefaultKey(true);
- slotInfo->Slots = alloc.SlabAllocateArray<TTDVar>(slotInfo->SlotCount);
- slotInfo->PIDArray = alloc.SlabAllocateArray<Js::PropertyId>(slotInfo->SlotCount);
- for(uint32 i = 0; i < slotInfo->SlotCount; ++i)
- {
- reader->ReadRecordStart(i != 0);
- slotInfo->PIDArray[i] = (Js::PropertyId)reader->ReadUInt32(NSTokens::Key::pid);
- reader->ReadKey(NSTokens::Key::entry, true);
- slotInfo->Slots[i] = ParseTTDVar(false, reader);
- reader->ReadRecordEnd();
- }
- reader->ReadSequenceEnd();
- reader->ReadRecordEnd();
- }
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const SlotArrayInfo* sai1, const SlotArrayInfo* sai2, TTDCompareMap& compareMap)
- {
- compareMap.DiagnosticAssert(sai1->ScriptContextLogId == sai2->ScriptContextLogId);
- compareMap.DiagnosticAssert(sai1->isFunctionBodyMetaData == sai2->isFunctionBodyMetaData);
- if(sai1->isFunctionBodyMetaData)
- {
- compareMap.CheckConsistentAndAddPtrIdMapping_FunctionBody(sai1->OptFunctionBodyId, sai2->OptFunctionBodyId);
- }
- else
- {
- //TODO: emit debugger scope metadata
- }
- compareMap.DiagnosticAssert(sai1->SlotCount == sai2->SlotCount);
- for(uint32 i = 0; i < sai1->SlotCount; ++i)
- {
- Js::PropertyId id1 = sai1->PIDArray[i];
- bool found = false;
- for(uint32 j = 0; j < sai1->SlotCount; ++j)
- {
- if(id1 == sai2->PIDArray[j])
- {
- AssertSnapEquivTTDVar_SlotArray(sai1->Slots[i], sai2->Slots[j], compareMap, i);
- found = true;
- break;
- }
- }
- //TODO: We see this hit in a case where record has all values in a slot array when replaying --replay-debug (but not --replay).
- // In the debug version the propertyId is in a Js::DebuggerScopeProperty instead. So this needs to be investigated in both extract and inflate.
- compareMap.DiagnosticAssert(found);
- }
- }
- #endif
- Js::FrameDisplay* InflateScriptFunctionScopeInfo(const ScriptFunctionScopeInfo* funcScopeInfo, InflateMap* inflator)
- {
- Js::ScriptContext* ctx = inflator->LookupScriptContext(funcScopeInfo->ScriptContextLogId);
- Js::FrameDisplay* environment = RecyclerNewPlus(ctx->GetRecycler(), funcScopeInfo->ScopeCount * sizeof(Js::Var), Js::FrameDisplay, funcScopeInfo->ScopeCount);
- for(uint16 i = 0; i < funcScopeInfo->ScopeCount; ++i)
- {
- const ScopeInfoEntry& scp = funcScopeInfo->ScopeArray[i];
- switch(scp.Tag)
- {
- case Js::ScopeType::ScopeType_ActivationObject:
- case Js::ScopeType::ScopeType_WithScope:
- {
- Js::Var sval = inflator->LookupObject(scp.IDValue);
- environment->SetItem(i, sval);
- break;
- }
- case Js::ScopeType::ScopeType_SlotArray:
- {
- Js::Var* saval = inflator->LookupSlotArray(scp.IDValue);
- environment->SetItem(i, saval);
- break;
- }
- default:
- TTDAssert(false, "Unknown scope kind");
- break;
- }
- }
- return environment;
- }
- void EmitScriptFunctionScopeInfo(const ScriptFunctionScopeInfo* funcScopeInfo, FileWriter* writer, NSTokens::Separator separator)
- {
- writer->WriteRecordStart(separator);
- writer->WriteAddr(NSTokens::Key::scopeId, funcScopeInfo->ScopeId);
- writer->WriteLogTag(NSTokens::Key::ctxTag, funcScopeInfo->ScriptContextLogId, NSTokens::Separator::CommaSeparator);
- writer->WriteUInt32(NSTokens::Key::count, funcScopeInfo->ScopeCount, NSTokens::Separator::CommaSeparator);
- writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
- for(uint32 i = 0; i < funcScopeInfo->ScopeCount; ++i)
- {
- writer->WriteRecordStart(i != 0 ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator);
- writer->WriteTag<Js::ScopeType>(NSTokens::Key::scopeType, funcScopeInfo->ScopeArray[i].Tag);
- writer->WriteAddr(NSTokens::Key::subscopeId, funcScopeInfo->ScopeArray[i].IDValue, NSTokens::Separator::CommaSeparator);
- writer->WriteRecordEnd();
- }
- writer->WriteSequenceEnd();
- writer->WriteRecordEnd();
- }
- void ParseScriptFunctionScopeInfo(ScriptFunctionScopeInfo* funcScopeInfo, bool readSeperator, FileReader* reader, SlabAllocator& alloc)
- {
- reader->ReadRecordStart(readSeperator);
- funcScopeInfo->ScopeId = reader->ReadAddr(NSTokens::Key::scopeId);
- funcScopeInfo->ScriptContextLogId = reader->ReadLogTag(NSTokens::Key::ctxTag, true);
- funcScopeInfo->ScopeCount = (uint16)reader->ReadUInt32(NSTokens::Key::count, true);
- reader->ReadSequenceStart_WDefaultKey(true);
- funcScopeInfo->ScopeArray = alloc.SlabAllocateArray<ScopeInfoEntry>(funcScopeInfo->ScopeCount);
- for(uint32 i = 0; i < funcScopeInfo->ScopeCount; ++i)
- {
- reader->ReadRecordStart(i != 0);
- funcScopeInfo->ScopeArray[i].Tag = reader->ReadTag<Js::ScopeType>(NSTokens::Key::scopeType);
- funcScopeInfo->ScopeArray[i].IDValue = reader->ReadAddr(NSTokens::Key::subscopeId, true);
- reader->ReadRecordEnd();
- }
- reader->ReadSequenceEnd();
- reader->ReadRecordEnd();
- }
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const ScriptFunctionScopeInfo* funcScopeInfo1, const ScriptFunctionScopeInfo* funcScopeInfo2, TTDCompareMap& compareMap)
- {
- compareMap.DiagnosticAssert(funcScopeInfo1->ScriptContextLogId == funcScopeInfo2->ScriptContextLogId);
- compareMap.DiagnosticAssert(funcScopeInfo1->ScopeCount == funcScopeInfo2->ScopeCount);
- for(uint32 i = 0; i < funcScopeInfo1->ScopeCount; ++i)
- {
- compareMap.DiagnosticAssert(funcScopeInfo1->ScopeArray[i].Tag == funcScopeInfo2->ScopeArray[i].Tag);
- compareMap.CheckConsistentAndAddPtrIdMapping_Scope(funcScopeInfo1->ScopeArray[i].IDValue, funcScopeInfo2->ScopeArray[i].IDValue, i);
- }
- }
- #endif
- //////////////////
- Js::JavascriptPromiseCapability* InflatePromiseCapabilityInfo(const SnapPromiseCapabilityInfo* capabilityInfo, Js::ScriptContext* ctx, InflateMap* inflator)
- {
- if(!inflator->IsPromiseInfoDefined<Js::JavascriptPromiseCapability>(capabilityInfo->CapabilityId))
- {
- Js::Var promise = inflator->InflateTTDVar(capabilityInfo->PromiseVar);
- Js::Var resolve = inflator->InflateTTDVar(capabilityInfo->ResolveVar);
- Js::Var reject = inflator->InflateTTDVar(capabilityInfo->RejectVar);
- Js::JavascriptPromiseCapability* res = ctx->GetLibrary()->CreatePromiseCapability_TTD(promise, resolve, reject);
- inflator->AddInflatedPromiseInfo<Js::JavascriptPromiseCapability>(capabilityInfo->CapabilityId, res);
- }
- return inflator->LookupInflatedPromiseInfo<Js::JavascriptPromiseCapability>(capabilityInfo->CapabilityId);
- }
- void EmitPromiseCapabilityInfo(const SnapPromiseCapabilityInfo* capabilityInfo, FileWriter* writer, NSTokens::Separator separator)
- {
- writer->WriteRecordStart(separator);
- writer->WriteAddr(NSTokens::Key::ptrIdVal, capabilityInfo->CapabilityId);
- writer->WriteKey(NSTokens::Key::entry, NSTokens::Separator::CommaSeparator);
- EmitTTDVar(capabilityInfo->PromiseVar, writer, NSTokens::Separator::NoSeparator);
- writer->WriteKey(NSTokens::Key::entry, NSTokens::Separator::CommaSeparator);
- EmitTTDVar(capabilityInfo->ResolveVar, writer, NSTokens::Separator::NoSeparator);
- writer->WriteKey(NSTokens::Key::entry, NSTokens::Separator::CommaSeparator);
- EmitTTDVar(capabilityInfo->RejectVar, writer, NSTokens::Separator::NoSeparator);
- writer->WriteRecordEnd();
- }
- void ParsePromiseCapabilityInfo(SnapPromiseCapabilityInfo* capabilityInfo, bool readSeperator, FileReader* reader, SlabAllocator& alloc)
- {
- reader->ReadRecordStart(readSeperator);
- capabilityInfo->CapabilityId = reader->ReadAddr(NSTokens::Key::ptrIdVal);
- reader->ReadKey(NSTokens::Key::entry, true);
- capabilityInfo->PromiseVar = ParseTTDVar(false, reader);
- reader->ReadKey(NSTokens::Key::entry, true);
- capabilityInfo->ResolveVar = ParseTTDVar(false, reader);
- reader->ReadKey(NSTokens::Key::entry, true);
- capabilityInfo->RejectVar = ParseTTDVar(false, reader);
- reader->ReadRecordEnd();
- }
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const SnapPromiseCapabilityInfo* capabilityInfo1, const SnapPromiseCapabilityInfo* capabilityInfo2, TTDCompareMap& compareMap)
- {
- compareMap.CheckConsistentAndAddPtrIdMapping_NoEnqueue(capabilityInfo1->CapabilityId, capabilityInfo2->CapabilityId);
- AssertSnapEquivTTDVar_Special(capabilityInfo1->PromiseVar, capabilityInfo2->PromiseVar, compareMap, _u("promiseVar"));
- AssertSnapEquivTTDVar_Special(capabilityInfo1->ResolveVar, capabilityInfo2->ResolveVar, compareMap, _u("resolveObjId"));
- AssertSnapEquivTTDVar_Special(capabilityInfo1->RejectVar, capabilityInfo2->RejectVar, compareMap, _u("rejectObjId"));
- }
- #endif
- Js::JavascriptPromiseReaction* InflatePromiseReactionInfo(const SnapPromiseReactionInfo* reactionInfo, Js::ScriptContext* ctx, InflateMap* inflator)
- {
- if(!inflator->IsPromiseInfoDefined<Js::JavascriptPromiseReaction>(reactionInfo->PromiseReactionId))
- {
- Js::RecyclableObject* handler = inflator->LookupObject(reactionInfo->HandlerObjId);
- Js::JavascriptPromiseCapability* capabilities = InflatePromiseCapabilityInfo(&reactionInfo->Capabilities, ctx, inflator);
- Js::JavascriptPromiseReaction* res = ctx->GetLibrary()->CreatePromiseReaction_TTD(handler, capabilities);
- inflator->AddInflatedPromiseInfo<Js::JavascriptPromiseReaction>(reactionInfo->PromiseReactionId, res);
- }
- return inflator->LookupInflatedPromiseInfo<Js::JavascriptPromiseReaction>(reactionInfo->PromiseReactionId);
- }
- void EmitPromiseReactionInfo(const SnapPromiseReactionInfo* reactionInfo, FileWriter* writer, NSTokens::Separator separator)
- {
- writer->WriteRecordStart(separator);
- writer->WriteAddr(NSTokens::Key::ptrIdVal, reactionInfo->PromiseReactionId);
- writer->WriteAddr(NSTokens::Key::ptrIdVal, reactionInfo->HandlerObjId, NSTokens::Separator::CommaSeparator);
- writer->WriteKey(NSTokens::Key::entry, NSTokens::Separator::CommaSeparator);
- EmitPromiseCapabilityInfo(&reactionInfo->Capabilities, writer, NSTokens::Separator::NoSeparator);
- writer->WriteRecordEnd();
- }
- void ParsePromiseReactionInfo(SnapPromiseReactionInfo* reactionInfo, bool readSeperator, FileReader* reader, SlabAllocator& alloc)
- {
- reader->ReadRecordStart(readSeperator);
- reactionInfo->PromiseReactionId = reader->ReadAddr(NSTokens::Key::ptrIdVal);
- reactionInfo->HandlerObjId = reader->ReadAddr(NSTokens::Key::ptrIdVal, true);
- reader->ReadKey(NSTokens::Key::entry, true);
- ParsePromiseCapabilityInfo(&reactionInfo->Capabilities, false, reader, alloc);
- reader->ReadRecordEnd();
- }
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const SnapPromiseReactionInfo* reactionInfo1, const SnapPromiseReactionInfo* reactionInfo2, TTDCompareMap& compareMap)
- {
- compareMap.CheckConsistentAndAddPtrIdMapping_NoEnqueue(reactionInfo1->PromiseReactionId, reactionInfo2->PromiseReactionId);
- compareMap.CheckConsistentAndAddPtrIdMapping_Special(reactionInfo1->HandlerObjId, reactionInfo2->HandlerObjId, _u("handlerObjId"));
- AssertSnapEquiv(&(reactionInfo1->Capabilities), &(reactionInfo2->Capabilities), compareMap);
- }
- #endif
- //////////////////
- void ExtractSnapFunctionBodyScopeChain(bool isWellKnownFunction, SnapFunctionBodyScopeChain& scopeChain, Js::FunctionBody* fb, SlabAllocator& alloc)
- {
- scopeChain.ScopeCount = 0;
- scopeChain.ScopeArray = nullptr;
- if(!isWellKnownFunction && fb->GetScopeObjectChain() != nullptr)
- {
- Js::ScopeObjectChain* scChain = fb->GetScopeObjectChain();
- scopeChain.ScopeCount = (uint32)scChain->pScopeChain->Count();
- if(scopeChain.ScopeCount == 0)
- {
- scopeChain.ScopeArray = nullptr;
- }
- else
- {
- scopeChain.ScopeArray = alloc.SlabAllocateArray<TTD_PTR_ID>(scopeChain.ScopeCount);
- for(int32 i = 0; i < scChain->pScopeChain->Count(); ++i)
- {
- Js::DebuggerScope* dbgScope = scChain->pScopeChain->Item(i);
- scopeChain.ScopeArray[i] = TTD_CONVERT_DEBUGSCOPE_TO_PTR_ID(dbgScope);
- }
- }
- }
- }
- void EmitSnapFunctionBodyScopeChain(const SnapFunctionBodyScopeChain& scopeChain, FileWriter* writer)
- {
- writer->WriteRecordStart();
- writer->WriteLengthValue(scopeChain.ScopeCount);
- writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
- for(uint32 i = 0; i < scopeChain.ScopeCount; ++i)
- {
- writer->WriteNakedAddr(scopeChain.ScopeArray[i], (i != 0) ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator);
- }
- writer->WriteSequenceEnd();
- writer->WriteRecordEnd();
- }
- void ParseSnapFunctionBodyScopeChain(SnapFunctionBodyScopeChain& scopeChain, FileReader* reader, SlabAllocator& alloc)
- {
- reader->ReadRecordStart();
- scopeChain.ScopeCount = reader->ReadLengthValue();
- scopeChain.ScopeArray = (scopeChain.ScopeCount != 0) ? alloc.SlabAllocateArray<TTD_PTR_ID>(scopeChain.ScopeCount) : nullptr;
- reader->ReadSequenceStart_WDefaultKey(true);
- for(uint32 i = 0; i < scopeChain.ScopeCount; ++i)
- {
- scopeChain.ScopeArray[i] = reader->ReadNakedAddr(i != 0);
- }
- reader->ReadSequenceEnd();
- reader->ReadRecordEnd();
- }
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const SnapFunctionBodyScopeChain& chain1, const SnapFunctionBodyScopeChain& chain2, TTDCompareMap& compareMap)
- {
- compareMap.DiagnosticAssert(chain1.ScopeCount == chain2.ScopeCount);
- //Not sure if there is a way to compare the pointer ids in the two scopes
- }
- #endif
- //////////////////
- void ExtractTopLevelCommonBodyResolveInfo(TopLevelCommonBodyResolveInfo* fbInfo, Js::FunctionBody* fb, uint32 topLevelCtr, Js::ModuleID moduleId, uint64 sourceContextId, bool isUtf8source, const byte* source, uint32 sourceLen, SlabAllocator& alloc)
- {
- fbInfo->ScriptContextLogId = fb->GetScriptContext()->ScriptContextLogTag;
- fbInfo->TopLevelBodyCtr = topLevelCtr;
- alloc.CopyNullTermStringInto(fb->GetDisplayName(), fbInfo->FunctionName);
- fbInfo->ModuleId = moduleId;
- fbInfo->SourceContextId = sourceContextId;
- alloc.CopyNullTermStringInto(fb->GetSourceContextInfo()->url, fbInfo->SourceUri);
- fbInfo->IsUtf8 = isUtf8source;
- fbInfo->ByteLength = sourceLen;
- fbInfo->SourceBuffer = alloc.SlabAllocateArray<byte>(fbInfo->ByteLength);
- js_memcpy_s(fbInfo->SourceBuffer, fbInfo->ByteLength, source, sourceLen);
- fbInfo->DbgSerializedBytecodeSize = 0;
- fbInfo->DbgSerializedBytecodeBuffer = nullptr;
- ExtractSnapFunctionBodyScopeChain(false, fbInfo->ScopeChainInfo, fb, alloc);
- }
- void EmitTopLevelCommonBodyResolveInfo(const TopLevelCommonBodyResolveInfo* fbInfo, bool emitInline, ThreadContext* threadContext, FileWriter* writer, NSTokens::Separator separator)
- {
- writer->WriteRecordStart(separator);
- writer->WriteUInt32(NSTokens::Key::functionBodyId, fbInfo->TopLevelBodyCtr);
- writer->WriteLogTag(NSTokens::Key::ctxTag, fbInfo->ScriptContextLogId, NSTokens::Separator::CommaSeparator);
- writer->WriteString(NSTokens::Key::name, fbInfo->FunctionName, NSTokens::Separator::CommaSeparator);
- writer->WriteUInt64(NSTokens::Key::moduleId, fbInfo->ModuleId, NSTokens::Separator::CommaSeparator);
- writer->WriteUInt64(NSTokens::Key::sourceContextId, fbInfo->SourceContextId, NSTokens::Separator::CommaSeparator);
- writer->WriteString(NSTokens::Key::uri, fbInfo->SourceUri, NSTokens::Separator::CommaSeparator);
- writer->WriteBool(NSTokens::Key::boolVal, fbInfo->IsUtf8, NSTokens::Separator::CommaSeparator);
- writer->WriteLengthValue(fbInfo->ByteLength, NSTokens::Separator::CommaSeparator);
- writer->WriteKey(NSTokens::Key::scopeChain, NSTokens::Separator::CommaSeparator);
- EmitSnapFunctionBodyScopeChain(fbInfo->ScopeChainInfo, writer);
- if(emitInline || IsNullPtrTTString(fbInfo->SourceUri))
- {
- TTDAssert(!fbInfo->IsUtf8, "Should only emit char16 encoded data in inline mode.");
- writer->WriteInlineCode((char16*)fbInfo->SourceBuffer, fbInfo->ByteLength / sizeof(char16), NSTokens::Separator::CommaSeparator);
- }
- else
- {
- JsSupport::WriteCodeToFile(threadContext, false, fbInfo->TopLevelBodyCtr, fbInfo->IsUtf8, fbInfo->SourceBuffer, fbInfo->ByteLength);
- }
- }
- void ParseTopLevelCommonBodyResolveInfo(TopLevelCommonBodyResolveInfo* fbInfo, bool readSeperator, bool parseInline, ThreadContext* threadContext, FileReader* reader, SlabAllocator& alloc)
- {
- reader->ReadRecordStart(readSeperator);
- fbInfo->TopLevelBodyCtr = reader->ReadUInt32(NSTokens::Key::functionBodyId);
- fbInfo->ScriptContextLogId = reader->ReadLogTag(NSTokens::Key::ctxTag, true);
- reader->ReadString(NSTokens::Key::name, alloc, fbInfo->FunctionName, true);
- fbInfo->ModuleId = (Js::ModuleID)reader->ReadUInt64(NSTokens::Key::moduleId, true);
- fbInfo->SourceContextId = reader->ReadUInt64(NSTokens::Key::sourceContextId, true);
- reader->ReadString(NSTokens::Key::uri, alloc, fbInfo->SourceUri, true);
- fbInfo->IsUtf8 = reader->ReadBool(NSTokens::Key::boolVal, true);
- fbInfo->ByteLength = reader->ReadLengthValue(true);
- fbInfo->SourceBuffer = alloc.SlabAllocateArray<byte>(fbInfo->ByteLength);
- reader->ReadKey(NSTokens::Key::scopeChain, true);
- ParseSnapFunctionBodyScopeChain(fbInfo->ScopeChainInfo, reader, alloc);
- if(parseInline || IsNullPtrTTString(fbInfo->SourceUri))
- {
- TTDAssert(!fbInfo->IsUtf8, "Should only emit char16 encoded data in inline mode.");
- reader->ReadInlineCode((char16*)fbInfo->SourceBuffer, fbInfo->ByteLength / sizeof(char16), true);
- }
- else
- {
- JsSupport::ReadCodeFromFile(threadContext, false, fbInfo->TopLevelBodyCtr, fbInfo->IsUtf8, fbInfo->SourceBuffer, fbInfo->ByteLength);
- }
- fbInfo->DbgSerializedBytecodeSize = 0;
- fbInfo->DbgSerializedBytecodeBuffer = nullptr;
- }
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const TopLevelCommonBodyResolveInfo* fbInfo1, const TopLevelCommonBodyResolveInfo* fbInfo2, TTDCompareMap& compareMap)
- {
- compareMap.DiagnosticAssert(fbInfo1->ScriptContextLogId == fbInfo2->ScriptContextLogId);
- compareMap.DiagnosticAssert(fbInfo1->TopLevelBodyCtr == fbInfo2->TopLevelBodyCtr);
- compareMap.DiagnosticAssert(TTStringEQForDiagnostics(fbInfo1->FunctionName, fbInfo2->FunctionName));
- compareMap.DiagnosticAssert(fbInfo1->ModuleId == fbInfo2->ModuleId);
- compareMap.DiagnosticAssert(fbInfo1->SourceContextId == fbInfo2->SourceContextId);
- compareMap.DiagnosticAssert(TTStringEQForDiagnostics(fbInfo1->SourceUri, fbInfo2->SourceUri));
- compareMap.DiagnosticAssert(fbInfo1->IsUtf8 == fbInfo2->IsUtf8);
- compareMap.DiagnosticAssert(fbInfo1->ByteLength == fbInfo2->ByteLength);
- for(uint32 i = 0; i < fbInfo1->ByteLength; ++i)
- {
- compareMap.DiagnosticAssert(fbInfo1->SourceBuffer[i] == fbInfo2->SourceBuffer[i]);
- }
- AssertSnapEquiv(fbInfo1->ScopeChainInfo, fbInfo2->ScopeChainInfo, compareMap);
- }
- #endif
- ////
- //Regular script-load functions
- 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)
- {
- NSSnapValues::ExtractTopLevelCommonBodyResolveInfo(&fbInfo->TopLevelBase, fb, topLevelCtr, moduleId, sourceContextId, isUtf8, source, sourceLen, alloc);
- fbInfo->LoadFlag = loadFlag;
- }
- Js::FunctionBody* InflateTopLevelLoadedFunctionBodyInfo(const TopLevelScriptLoadFunctionBodyResolveInfo* fbInfo, Js::ScriptContext* ctx)
- {
- byte* script = fbInfo->TopLevelBase.SourceBuffer;
- uint32 scriptLength = fbInfo->TopLevelBase.ByteLength;
- uint64 sourceContext = fbInfo->TopLevelBase.SourceContextId;
- TTDAssert(ctx->GetSourceContextInfo((DWORD_PTR)sourceContext, nullptr) == nullptr, "On inflate we should either have clean ctxts or we want to optimize the inflate process by skipping redoing this work!!!");
- TTDAssert(fbInfo->TopLevelBase.IsUtf8 == ((fbInfo->LoadFlag & LoadScriptFlag_Utf8Source) == LoadScriptFlag_Utf8Source), "Utf8 status is inconsistent!!!");
- const char16* srcUri = fbInfo->TopLevelBase.SourceUri.Contents;
- uint32 srcUriLength = fbInfo->TopLevelBase.SourceUri.Length;
- SourceContextInfo * sourceContextInfo = ctx->CreateSourceContextInfo((DWORD_PTR)sourceContext, srcUri, srcUriLength, nullptr);
- TTDAssert(fbInfo->TopLevelBase.IsUtf8 || sizeof(wchar) == sizeof(char16), "Non-utf8 code only allowed on windows!!!");
- const int chsize = (fbInfo->LoadFlag & LoadScriptFlag_Utf8Source) ? sizeof(char) : sizeof(char16);
- SRCINFO si = {
- /* sourceContextInfo */ sourceContextInfo,
- /* dlnHost */ 0,
- /* ulColumnHost */ 0,
- /* lnMinHost */ 0,
- /* ichMinHost */ 0,
- /* ichLimHost */ static_cast<ULONG>(scriptLength / chsize), // OK to truncate since this is used to limit sourceText in debugDocument/compilation errors.
- /* ulCharOffset */ 0,
- /* mod */ fbInfo->TopLevelBase.ModuleId,
- /* grfsi */ 0
- };
- Js::Utf8SourceInfo* utf8SourceInfo = nullptr;
- CompileScriptException se;
- Js::JavascriptFunction* scriptFunction = nullptr;
- Js::FunctionBody* globalBody = nullptr;
- if(fbInfo->TopLevelBase.DbgSerializedBytecodeSize != 0)
- {
- //
- //TODO: Bytecode serializer does not support debug bytecode (StatementMaps vs Positions) so add this to serializer code.
- // Then we can add code do optimized bytecode reload here.
- //
- TTDAssert(false, "Not implemented yet -- this branch should never be taken.");
- }
- else
- {
- scriptFunction = ctx->LoadScript(script, scriptLength, &si, &se, &utf8SourceInfo, Js::Constants::GlobalCode, fbInfo->LoadFlag, nullptr);
- TTDAssert(scriptFunction != nullptr, "Something went wrong");
- globalBody = TTD::JsSupport::ForceAndGetFunctionBody(scriptFunction->GetParseableFunctionInfo());
- //
- //TODO: Bytecode serializer does not suppper debug bytecode (StatementMaps vs Positions) so add this to serializer code.
- // Then we can add code to do optimized bytecode reload here.
- //
- }
- ////
- //We don't do this automatically in the load script helper so do it here
- BEGIN_JS_RUNTIME_CALL(ctx);
- {
- ctx->TTDContextInfo->ProcessFunctionBodyOnLoad(globalBody, nullptr);
- ctx->TTDContextInfo->RegisterLoadedScript(globalBody, fbInfo->TopLevelBase.TopLevelBodyCtr);
- globalBody->GetUtf8SourceInfo()->SetSourceInfoForDebugReplay_TTD(fbInfo->TopLevelBase.TopLevelBodyCtr);
- }
- END_JS_RUNTIME_CALL(ctx);
- bool isLibraryCode = ((fbInfo->LoadFlag & LoadScriptFlag_LibraryCode) == LoadScriptFlag_LibraryCode);
- if(ctx->GetThreadContext()->TTDExecutionInfo != nullptr && !isLibraryCode)
- {
- ctx->GetThreadContext()->TTDExecutionInfo->ProcessScriptLoad(ctx, fbInfo->TopLevelBase.TopLevelBodyCtr, globalBody, utf8SourceInfo, &se);
- }
- ////
- return globalBody;
- }
- void EmitTopLevelLoadedFunctionBodyInfo(const TopLevelScriptLoadFunctionBodyResolveInfo* fbInfo, ThreadContext* threadContext, FileWriter* writer, NSTokens::Separator separator)
- {
- NSSnapValues::EmitTopLevelCommonBodyResolveInfo(&fbInfo->TopLevelBase, false, threadContext, writer, separator);
- writer->WriteTag<LoadScriptFlag>(NSTokens::Key::loadFlag, fbInfo->LoadFlag, NSTokens::Separator::CommaSeparator);
- writer->WriteRecordEnd();
- }
- void ParseTopLevelLoadedFunctionBodyInfo(TopLevelScriptLoadFunctionBodyResolveInfo* fbInfo, bool readSeperator, ThreadContext* threadContext, FileReader* reader, SlabAllocator& alloc)
- {
- NSSnapValues::ParseTopLevelCommonBodyResolveInfo(&fbInfo->TopLevelBase, readSeperator, false, threadContext, reader, alloc);
- fbInfo->LoadFlag = reader->ReadTag<LoadScriptFlag>(NSTokens::Key::loadFlag, true);
- reader->ReadRecordEnd();
- }
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const TopLevelScriptLoadFunctionBodyResolveInfo* fbInfo1, const TopLevelScriptLoadFunctionBodyResolveInfo* fbInfo2, TTDCompareMap& compareMap)
- {
- compareMap.DiagnosticAssert(fbInfo1->LoadFlag == fbInfo2->LoadFlag);
- AssertSnapEquiv(&(fbInfo1->TopLevelBase), &(fbInfo2->TopLevelBase), compareMap);
- }
- #endif
- ////
- //'new Function(...)' functions
- void ExtractTopLevelNewFunctionBodyInfo(TopLevelNewFunctionBodyResolveInfo* fbInfo, Js::FunctionBody* fb, uint32 topLevelCtr, Js::ModuleID moduleId, const char16* source, uint32 sourceLen, SlabAllocator& alloc)
- {
- NSSnapValues::ExtractTopLevelCommonBodyResolveInfo(&fbInfo->TopLevelBase, fb, topLevelCtr, moduleId, 0, false, (const byte*)source, sourceLen * sizeof(char16), alloc);
- }
- Js::FunctionBody* InflateTopLevelNewFunctionBodyInfo(const TopLevelNewFunctionBodyResolveInfo* fbInfo, Js::ScriptContext* ctx)
- {
- // Bug 1105479. Get the module id from the caller
- Js::ModuleID moduleID = kmodGlobal;
- BOOL strictMode = FALSE;
- char16* source = (char16*)fbInfo->TopLevelBase.SourceBuffer;
- int32 length = (int32)(fbInfo->TopLevelBase.ByteLength / sizeof(char16));
- Js::JavascriptFunction* pfuncScript = ctx->GetGlobalObject()->EvalHelper(ctx, source, length, moduleID, fscrNil, Js::Constants::FunctionCode, TRUE, TRUE, strictMode);
- TTDAssert(pfuncScript != nullptr, "Something went wrong!!!");
- // Indicate that this is a top-level function. We don't pass the fscrGlobalCode flag to the eval helper,
- // or it will return the global function that wraps the declared function body, as though it were an eval.
- // But we want, for instance, to be able to verify that we did the right amount of deferred parsing.
- Js::ParseableFunctionInfo* functionInfo = pfuncScript->GetParseableFunctionInfo();
- functionInfo->SetGrfscr(functionInfo->GetGrfscr() | fscrGlobalCode);
- Js::FunctionBody* fb = JsSupport::ForceAndGetFunctionBody(pfuncScript->GetParseableFunctionInfo());
- //We don't do this automatically in the eval helper so do it here
- ctx->TTDContextInfo->ProcessFunctionBodyOnLoad(fb, nullptr);
- ctx->TTDContextInfo->RegisterNewScript(fb, fbInfo->TopLevelBase.TopLevelBodyCtr);
- return fb;
- }
- void EmitTopLevelNewFunctionBodyInfo(const TopLevelNewFunctionBodyResolveInfo* fbInfo, ThreadContext* threadContext, FileWriter* writer, NSTokens::Separator separator)
- {
- NSSnapValues::EmitTopLevelCommonBodyResolveInfo(&fbInfo->TopLevelBase, true, threadContext, writer, separator);
- writer->WriteRecordEnd();
- }
- void ParseTopLevelNewFunctionBodyInfo(TopLevelNewFunctionBodyResolveInfo* fbInfo, bool readSeperator, ThreadContext* threadContext, FileReader* reader, SlabAllocator& alloc)
- {
- NSSnapValues::ParseTopLevelCommonBodyResolveInfo(&fbInfo->TopLevelBase, readSeperator, false, threadContext, reader, alloc);
- reader->ReadRecordEnd();
- }
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const TopLevelNewFunctionBodyResolveInfo* fbInfo1, const TopLevelNewFunctionBodyResolveInfo* fbInfo2, TTDCompareMap& compareMap)
- {
- AssertSnapEquiv(&(fbInfo1->TopLevelBase), &(fbInfo2->TopLevelBase), compareMap);
- }
- #endif
- ////
- //'eval(...)' functions
- 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)
- {
- NSSnapValues::ExtractTopLevelCommonBodyResolveInfo(&fbInfo->TopLevelBase, fb, topLevelCtr, moduleId, 0, false, (const byte*)source, sourceLen * sizeof(char16), alloc);
- fbInfo->EvalFlags = grfscr;
- fbInfo->RegisterDocument = registerDocument;
- fbInfo->IsIndirect = !!isIndirect;
- fbInfo->IsStrictMode = !!strictMode;
- }
- Js::FunctionBody* InflateTopLevelEvalFunctionBodyInfo(const TopLevelEvalFunctionBodyResolveInfo* fbInfo, Js::ScriptContext* ctx)
- {
- uint32 grfscr = ((uint32)fbInfo->EvalFlags) | fscrReturnExpression | fscrEval | fscrEvalCode | fscrGlobalCode;
- char16* source = (char16*)fbInfo->TopLevelBase.SourceBuffer;
- int32 sourceLen = (int32)(fbInfo->TopLevelBase.ByteLength / sizeof(char16));
- Js::ScriptFunction* pfuncScript = ctx->GetLibrary()->GetGlobalObject()->EvalHelper(ctx, source, sourceLen, fbInfo->TopLevelBase.ModuleId, grfscr, Js::Constants::EvalCode, fbInfo->RegisterDocument, fbInfo->IsIndirect, fbInfo->IsStrictMode);
- Assert(!pfuncScript->GetFunctionInfo()->IsGenerator());
- Js::FastEvalMapString key(source, sourceLen, fbInfo->TopLevelBase.ModuleId, fbInfo->IsStrictMode, false);
- ctx->AddToEvalMap(key, fbInfo->IsIndirect, pfuncScript);
- Js::FunctionBody* fb = JsSupport::ForceAndGetFunctionBody(pfuncScript->GetParseableFunctionInfo());
- //We don't do this automatically ing the eval helper so do it here
- ctx->TTDContextInfo->ProcessFunctionBodyOnLoad(fb, nullptr);
- ctx->TTDContextInfo->RegisterEvalScript(fb, fbInfo->TopLevelBase.TopLevelBodyCtr);
- return fb;
- }
- void EmitTopLevelEvalFunctionBodyInfo(const TopLevelEvalFunctionBodyResolveInfo* fbInfo, ThreadContext* threadContext, FileWriter* writer, NSTokens::Separator separator)
- {
- NSSnapValues::EmitTopLevelCommonBodyResolveInfo(&fbInfo->TopLevelBase, true, threadContext, writer, separator);
- writer->WriteUInt64(NSTokens::Key::u64Val, fbInfo->EvalFlags, NSTokens::Separator::CommaSeparator);
- writer->WriteBool(NSTokens::Key::boolVal, fbInfo->RegisterDocument, NSTokens::Separator::CommaSeparator);
- writer->WriteBool(NSTokens::Key::boolVal, fbInfo->IsIndirect, NSTokens::Separator::CommaSeparator);
- writer->WriteBool(NSTokens::Key::boolVal, fbInfo->IsStrictMode, NSTokens::Separator::CommaSeparator);
- writer->WriteRecordEnd();
- }
- void ParseTopLevelEvalFunctionBodyInfo(TopLevelEvalFunctionBodyResolveInfo* fbInfo, bool readSeperator, ThreadContext* threadContext, FileReader* reader, SlabAllocator& alloc)
- {
- NSSnapValues::ParseTopLevelCommonBodyResolveInfo(&fbInfo->TopLevelBase, readSeperator, false, threadContext, reader, alloc);
- fbInfo->EvalFlags = reader->ReadUInt64(NSTokens::Key::u64Val, true);
- fbInfo->RegisterDocument = reader->ReadBool(NSTokens::Key::boolVal, true);
- fbInfo->IsIndirect = reader->ReadBool(NSTokens::Key::boolVal, true);
- fbInfo->IsStrictMode = reader->ReadBool(NSTokens::Key::boolVal, true);
- reader->ReadRecordEnd();
- }
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const TopLevelEvalFunctionBodyResolveInfo* fbInfo1, const TopLevelEvalFunctionBodyResolveInfo* fbInfo2, TTDCompareMap& compareMap)
- {
- compareMap.DiagnosticAssert(fbInfo1->EvalFlags == fbInfo2->EvalFlags);
- compareMap.DiagnosticAssert(fbInfo1->RegisterDocument == fbInfo2->RegisterDocument);
- compareMap.DiagnosticAssert(fbInfo1->IsIndirect == fbInfo2->IsIndirect);
- compareMap.DiagnosticAssert(fbInfo1->IsStrictMode == fbInfo2->IsStrictMode);
- AssertSnapEquiv(&(fbInfo1->TopLevelBase), &(fbInfo2->TopLevelBase), compareMap);
- }
- #endif
- void ExtractFunctionBodyInfo(FunctionBodyResolveInfo* fbInfo, Js::FunctionBody* fb, bool isWellKnown, SlabAllocator& alloc)
- {
- fbInfo->FunctionBodyId = TTD_CONVERT_FUNCTIONBODY_TO_PTR_ID(fb);
- fbInfo->ScriptContextLogId = fb->GetScriptContext()->ScriptContextLogTag;
- alloc.CopyStringIntoWLength(fb->GetDisplayName(), fb->GetDisplayNameLength(), fbInfo->FunctionName);
- TTDAssert(wcscmp(fbInfo->FunctionName.Contents, Js::Constants::GlobalCode) != 0, "Why are we snapshotting global code??");
- if(isWellKnown)
- {
- fbInfo->OptKnownPath = alloc.CopyRawNullTerminatedStringInto(fb->GetScriptContext()->TTDWellKnownInfo->ResolvePathForKnownFunctionBody(fb));
- fbInfo->OptParentBodyId = TTD_INVALID_PTR_ID;
- fbInfo->OptLine = -1;
- fbInfo->OptColumn = -1;
- }
- else
- {
- fbInfo->OptKnownPath = TTD_INVALID_WELLKNOWN_TOKEN;
- Js::FunctionBody* parentBody = fb->GetScriptContext()->TTDContextInfo->ResolveParentBody(fb);
- TTDAssert(parentBody != nullptr, "We missed something!!!");
- fbInfo->OptParentBodyId = TTD_CONVERT_FUNCTIONBODY_TO_PTR_ID(parentBody);
- fbInfo->OptLine = fb->GetLineNumber();
- fbInfo->OptColumn = fb->GetColumnNumber();
- }
- ExtractSnapFunctionBodyScopeChain(fbInfo->OptKnownPath != TTD_INVALID_WELLKNOWN_TOKEN, fbInfo->ScopeChainInfo, fb, alloc);
- }
- void InflateFunctionBody(const FunctionBodyResolveInfo* fbInfo, InflateMap* inflator, const TTDIdentifierDictionary<TTD_PTR_ID, FunctionBodyResolveInfo*>& idToFbResolveMap)
- {
- if(inflator->IsFunctionBodyAlreadyInflated(fbInfo->FunctionBodyId))
- {
- return;
- }
- Js::ScriptContext* ctx = inflator->LookupScriptContext(fbInfo->ScriptContextLogId);
- Js::FunctionBody* resfb = nullptr;
- if(fbInfo->OptKnownPath != TTD_INVALID_WELLKNOWN_TOKEN)
- {
- resfb = ctx->TTDWellKnownInfo->LookupKnownFunctionBodyFromPath(fbInfo->OptKnownPath);
- }
- else
- {
- resfb = inflator->FindReusableFunctionBodyIfExists(fbInfo->FunctionBodyId);
- if(resfb == nullptr)
- {
- //Find and inflate the parent body
- if(!inflator->IsFunctionBodyAlreadyInflated(fbInfo->OptParentBodyId))
- {
- const FunctionBodyResolveInfo* pBodyInfo = idToFbResolveMap.LookupKnownItem(fbInfo->OptParentBodyId);
- InflateFunctionBody(pBodyInfo, inflator, idToFbResolveMap);
- }
- Js::FunctionBody* parentBody = inflator->LookupFunctionBody(fbInfo->OptParentBodyId);
- //
- //TODO: this is a potentially expensive linear search (but needed since classes dump implicit functions out-of-text order).
- // May want to add sort and save in inflator or our shaddow info in script context if this is looking expensive.
- //
- uint32 blength = parentBody->GetNestedCount();
- for(uint32 i = 0; i < blength; ++i)
- {
- Js::ParseableFunctionInfo* pfi = parentBody->GetNestedFunctionForExecution(i);
- Js::FunctionBody* currfb = JsSupport::ForceAndGetFunctionBody(pfi);
- if(fbInfo->OptLine == currfb->GetLineNumber() && fbInfo->OptColumn == currfb->GetColumnNumber())
- {
- resfb = currfb;
- break;
- }
- }
- TTDAssert(resfb != nullptr && fbInfo->OptLine == resfb->GetLineNumber() && fbInfo->OptColumn == resfb->GetColumnNumber(), "We are missing something");
- TTDAssert(resfb != nullptr && (wcscmp(fbInfo->FunctionName.Contents, resfb->GetDisplayName()) == 0 || wcscmp(_u("get"), resfb->GetDisplayName()) == 0 || wcscmp(_u("set"), resfb->GetDisplayName()) == 0), "We are missing something");
- }
- //Make sure to register any scopes the found function body has (but *not* for well known functions)
- inflator->UpdateFBScopes(fbInfo->ScopeChainInfo, resfb);
- }
- bool updateName = false;
- if(fbInfo->FunctionName.Length != resfb->GetDisplayNameLength())
- {
- updateName = true;
- }
- else
- {
- const char16* fname = resfb->GetDisplayName();
- for(uint32 i = 0; i < fbInfo->FunctionName.Length; ++i)
- {
- updateName |= (fbInfo->FunctionName.Contents[i] != fname[i]);
- }
- }
- if(updateName)
- {
- uint32 suffixWDotPos = (fbInfo->FunctionName.Length - 4);
- uint32 suffixPos = (fbInfo->FunctionName.Length - 3);
- TTDAssert(wcsstr(fbInfo->FunctionName.Contents, _u(".get")) == (fbInfo->FunctionName.Contents + suffixWDotPos) || wcsstr(fbInfo->FunctionName.Contents, _u(".set")) == (fbInfo->FunctionName.Contents + suffixWDotPos), "Does not start with get or set");
- resfb->SetDisplayName(fbInfo->FunctionName.Contents, fbInfo->FunctionName.Length, suffixPos, Js::FunctionProxy::SetDisplayNameFlagsRecyclerAllocated);
- }
- inflator->AddInflationFunctionBody(fbInfo->FunctionBodyId, resfb);
- }
- void EmitFunctionBodyInfo(const FunctionBodyResolveInfo* fbInfo, FileWriter* writer, NSTokens::Separator separator)
- {
- writer->WriteRecordStart(separator);
- writer->WriteAddr(NSTokens::Key::functionBodyId, fbInfo->FunctionBodyId);
- writer->WriteLogTag(NSTokens::Key::ctxTag, fbInfo->ScriptContextLogId, NSTokens::Separator::CommaSeparator);
- writer->WriteString(NSTokens::Key::name, fbInfo->FunctionName, NSTokens::Separator::CommaSeparator);
- writer->WriteBool(NSTokens::Key::isWellKnownToken, fbInfo->OptKnownPath != nullptr, NSTokens::Separator::CommaSeparator);
- if(fbInfo->OptKnownPath != TTD_INVALID_WELLKNOWN_TOKEN)
- {
- writer->WriteWellKnownToken(NSTokens::Key::wellKnownToken, fbInfo->OptKnownPath, NSTokens::Separator::CommaSeparator);
- }
- else
- {
- writer->WriteAddr(NSTokens::Key::parentBodyId, fbInfo->OptParentBodyId, NSTokens::Separator::CommaSeparator);
- writer->WriteInt64(NSTokens::Key::line, fbInfo->OptLine, NSTokens::Separator::CommaSeparator);
- writer->WriteInt64(NSTokens::Key::column, fbInfo->OptColumn, NSTokens::Separator::CommaSeparator);
- }
- writer->WriteKey(NSTokens::Key::scopeChain, NSTokens::Separator::CommaSeparator);
- EmitSnapFunctionBodyScopeChain(fbInfo->ScopeChainInfo, writer);
- writer->WriteRecordEnd();
- }
- void ParseFunctionBodyInfo(FunctionBodyResolveInfo* fbInfo, bool readSeperator, FileReader* reader, SlabAllocator& alloc)
- {
- reader->ReadRecordStart(readSeperator);
- fbInfo->FunctionBodyId = reader->ReadAddr(NSTokens::Key::functionBodyId);
- fbInfo->ScriptContextLogId = reader->ReadLogTag(NSTokens::Key::ctxTag, true);
- reader->ReadString(NSTokens::Key::name, alloc, fbInfo->FunctionName, true);
- bool isWellKnown = reader->ReadBool(NSTokens::Key::isWellKnownToken, true);
- if(isWellKnown)
- {
- fbInfo->OptKnownPath = reader->ReadWellKnownToken(NSTokens::Key::wellKnownToken, alloc, true);
- fbInfo->OptParentBodyId = TTD_INVALID_PTR_ID;
- fbInfo->OptLine = -1;
- fbInfo->OptColumn = -1;
- }
- else
- {
- fbInfo->OptKnownPath = TTD_INVALID_WELLKNOWN_TOKEN;
- fbInfo->OptParentBodyId = reader->ReadAddr(NSTokens::Key::parentBodyId, true);
- fbInfo->OptLine = reader->ReadInt64(NSTokens::Key::line, true);
- fbInfo->OptColumn = reader->ReadInt64(NSTokens::Key::column, true);
- }
- reader->ReadKey(NSTokens::Key::scopeChain, true);
- ParseSnapFunctionBodyScopeChain(fbInfo->ScopeChainInfo, reader, alloc);
- reader->ReadRecordEnd();
- }
- #if ENABLE_SNAPSHOT_COMPARE
- void AssertSnapEquiv(const FunctionBodyResolveInfo* fbInfo1, const FunctionBodyResolveInfo* fbInfo2, TTDCompareMap& compareMap)
- {
- compareMap.DiagnosticAssert(fbInfo1->ScriptContextLogId == fbInfo2->ScriptContextLogId);
- compareMap.DiagnosticAssert(TTStringEQForDiagnostics(fbInfo1->FunctionName, fbInfo2->FunctionName));
- compareMap.DiagnosticAssert(TTD_DIAGNOSTIC_COMPARE_WELLKNOWN_TOKENS(fbInfo1->OptKnownPath, fbInfo2->OptKnownPath));
- if(fbInfo1->OptKnownPath == TTD_INVALID_WELLKNOWN_TOKEN)
- {
- compareMap.CheckConsistentAndAddPtrIdMapping_FunctionBody(fbInfo1->OptParentBodyId, fbInfo2->OptParentBodyId);
- compareMap.DiagnosticAssert(fbInfo1->OptLine == fbInfo2->OptLine);
- compareMap.DiagnosticAssert(fbInfo1->OptColumn == fbInfo2->OptColumn);
- }
- AssertSnapEquiv(fbInfo1->ScopeChainInfo, fbInfo1->ScopeChainInfo, compareMap);
- }
- #endif
- //////////////////
- void ExtractScriptContext(SnapContext* snapCtx, Js::ScriptContext* ctx, const JsUtil::BaseDictionary<Js::RecyclableObject*, TTD_LOG_PTR_ID, HeapAllocator>& objToLogIdMap, SlabAllocator& alloc)
- {
- snapCtx->ScriptContextLogId = ctx->ScriptContextLogTag;
- snapCtx->IsPNRGSeeded = ctx->GetLibrary()->IsPRNGSeeded();
- snapCtx->RandomSeed0 = ctx->GetLibrary()->GetRandSeed0();
- snapCtx->RandomSeed1 = ctx->GetLibrary()->GetRandSeed1();
- alloc.CopyNullTermStringInto(ctx->GetUrl(), snapCtx->ContextSRC);
- JsUtil::List<TopLevelFunctionInContextRelation, HeapAllocator> topLevelScriptLoad(&HeapAllocator::Instance);
- JsUtil::List<TopLevelFunctionInContextRelation, HeapAllocator> topLevelNewFunction(&HeapAllocator::Instance);
- JsUtil::List<TopLevelFunctionInContextRelation, HeapAllocator> topLevelEval(&HeapAllocator::Instance);
- ctx->TTDContextInfo->GetLoadedSources(topLevelScriptLoad, topLevelNewFunction, topLevelEval);
- snapCtx->LoadedTopLevelScriptCount = topLevelScriptLoad.Count();
- if(snapCtx->LoadedTopLevelScriptCount == 0)
- {
- snapCtx->LoadedTopLevelScriptArray = nullptr;
- }
- else
- {
- snapCtx->LoadedTopLevelScriptArray = alloc.SlabAllocateArray<TopLevelFunctionInContextRelation>(snapCtx->LoadedTopLevelScriptCount);
- for(int32 i = 0; i < topLevelScriptLoad.Count(); ++i)
- {
- snapCtx->LoadedTopLevelScriptArray[i] = topLevelScriptLoad.Item(i);
- }
- }
- snapCtx->NewFunctionTopLevelScriptCount = topLevelNewFunction.Count();
- if(snapCtx->NewFunctionTopLevelScriptCount == 0)
- {
- snapCtx->NewFunctionTopLevelScriptArray = nullptr;
- }
- else
- {
- snapCtx->NewFunctionTopLevelScriptArray = alloc.SlabAllocateArray<TopLevelFunctionInContextRelation>(snapCtx->NewFunctionTopLevelScriptCount);
- for(int32 i = 0; i < topLevelNewFunction.Count(); ++i)
- {
- snapCtx->NewFunctionTopLevelScriptArray[i] = topLevelNewFunction.Item(i);
- }
- }
- snapCtx->EvalTopLevelScriptCount = topLevelEval.Count();
- if(snapCtx->EvalTopLevelScriptCount == 0)
- {
- snapCtx->EvalTopLevelScriptArray = nullptr;
- }
- else
- {
- snapCtx->EvalTopLevelScriptArray = alloc.SlabAllocateArray<TopLevelFunctionInContextRelation>(snapCtx->EvalTopLevelScriptCount);
- for(int32 i = 0; i < topLevelEval.Count(); ++i)
- {
- snapCtx->EvalTopLevelScriptArray[i] = topLevelEval.Item(i);
- }
- }
- //Extract pending async modification info
- const JsUtil::List<TTDPendingAsyncBufferModification, HeapAllocator>& pendingAsyncList = ctx->TTDContextInfo->GetPendingAsyncModListForSnapshot();
- snapCtx->PendingAsyncModCount = pendingAsyncList.Count();
- if(snapCtx->PendingAsyncModCount == 0)
- {
- snapCtx->PendingAsyncModArray = nullptr;
- }
- else
- {
- snapCtx->PendingAsyncModArray = alloc.SlabAllocateArray<SnapPendingAsyncBufferModification>(snapCtx->PendingAsyncModCount);
- for(int32 k = 0; k < pendingAsyncList.Count(); ++k)
- {
- const TTDPendingAsyncBufferModification& pk = pendingAsyncList.Item(k);
- snapCtx->PendingAsyncModArray[k].LogId = objToLogIdMap.Item(Js::RecyclableObject::FromVar(pk.ArrayBufferVar));
- snapCtx->PendingAsyncModArray[k].Index = pk.Index;
- }
- }
- }
- 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)
- {
- TTDAssert(wcscmp(snpCtx->ContextSRC.Contents, intoCtx->GetUrl()) == 0, "Make sure the src uri values are the same.");
- intoCtx->GetLibrary()->SetIsPRNGSeeded(snpCtx->IsPNRGSeeded);
- intoCtx->GetLibrary()->SetRandSeed0(snpCtx->RandomSeed0);
- intoCtx->GetLibrary()->SetRandSeed1(snpCtx->RandomSeed1);
- inflator->AddScriptContext(snpCtx->ScriptContextLogId, intoCtx);
- intoCtx->TTDContextInfo->ClearLoadedSourcesForSnapshotRestore();
- if(intoCtx->HasRecordedException())
- {
- intoCtx->GetAndClearRecordedException(nullptr);
- }
- for(uint32 i = 0; i < snpCtx->LoadedTopLevelScriptCount; ++i)
- {
- const TopLevelFunctionInContextRelation& cri = snpCtx->LoadedTopLevelScriptArray[i];
- Js::FunctionBody* fb = inflator->FindReusableFunctionBodyIfExists(cri.ContextSpecificBodyPtrId);
- const TopLevelScriptLoadFunctionBodyResolveInfo* fbInfo = topLevelLoadScriptMap.LookupKnownItem(cri.TopLevelBodyCtr);
- if(fb == nullptr)
- {
- fb = NSSnapValues::InflateTopLevelLoadedFunctionBodyInfo(fbInfo, intoCtx);
- }
- else
- {
- intoCtx->TTDContextInfo->ProcessFunctionBodyOnLoad(fb, nullptr);
- intoCtx->TTDContextInfo->RegisterLoadedScript(fb, cri.TopLevelBodyCtr);
- intoCtx->GetThreadContext()->TTDExecutionInfo->ProcessScriptLoad_InflateReuseBody(cri.TopLevelBodyCtr, fb);
- }
- inflator->UpdateFBScopes(fbInfo->TopLevelBase.ScopeChainInfo, fb);
- inflator->AddInflationFunctionBody(cri.ContextSpecificBodyPtrId, fb);
- }
- //The inflation code for NewFunction and Eval uses the paths in the runtime (which assume they are in script) -- so enter here to make them happy
- BEGIN_ENTER_SCRIPT(intoCtx, true, true, true)
- {
- for(uint32 i = 0; i < snpCtx->NewFunctionTopLevelScriptCount; ++i)
- {
- const TopLevelFunctionInContextRelation& cri = snpCtx->NewFunctionTopLevelScriptArray[i];
- Js::FunctionBody* fb = inflator->FindReusableFunctionBodyIfExists(cri.ContextSpecificBodyPtrId);
- const TopLevelNewFunctionBodyResolveInfo* fbInfo = topLevelNewScriptMap.LookupKnownItem(cri.TopLevelBodyCtr);
- if(fb == nullptr)
- {
- fb = NSSnapValues::InflateTopLevelNewFunctionBodyInfo(fbInfo, intoCtx);
- }
- else
- {
- intoCtx->TTDContextInfo->ProcessFunctionBodyOnLoad(fb, nullptr);
- intoCtx->TTDContextInfo->RegisterNewScript(fb, cri.TopLevelBodyCtr);
- intoCtx->GetThreadContext()->TTDExecutionInfo->ProcessScriptLoad_InflateReuseBody(cri.TopLevelBodyCtr, fb);
- }
- inflator->UpdateFBScopes(fbInfo->TopLevelBase.ScopeChainInfo, fb);
- inflator->AddInflationFunctionBody(cri.ContextSpecificBodyPtrId, fb);
- }
- for(uint32 i = 0; i < snpCtx->EvalTopLevelScriptCount; ++i)
- {
- const TopLevelFunctionInContextRelation& cri = snpCtx->EvalTopLevelScriptArray[i];
- Js::FunctionBody* fb = inflator->FindReusableFunctionBodyIfExists(cri.ContextSpecificBodyPtrId);
- const TopLevelEvalFunctionBodyResolveInfo* fbInfo = topLevelEvalScriptMap.LookupKnownItem(cri.TopLevelBodyCtr);
- if(fb == nullptr)
- {
- fb = NSSnapValues::InflateTopLevelEvalFunctionBodyInfo(fbInfo, intoCtx);
- }
- else
- {
- intoCtx->TTDContextInfo->ProcessFunctionBodyOnLoad(fb, nullptr);
- intoCtx->TTDContextInfo->RegisterEvalScript(fb, cri.TopLevelBodyCtr);
- intoCtx->GetThreadContext()->TTDExecutionInfo->ProcessScriptLoad_InflateReuseBody(cri.TopLevelBodyCtr, fb);
- }
- inflator->UpdateFBScopes(fbInfo->TopLevelBase.ScopeChainInfo, fb);
- inflator->AddInflationFunctionBody(cri.ContextSpecificBodyPtrId, fb);
- }
- }
- END_ENTER_SCRIPT
- }
- void ResetPendingAsyncBufferModInfo(const SnapContext* snpCtx, Js::ScriptContext* intoCtx, InflateMap* inflator)
- {
- intoCtx->TTDContextInfo->ClearPendingAsyncModListForSnapRestore();
- for(uint32 i = 0; i < snpCtx->PendingAsyncModCount; ++i)
- {
- Js::RecyclableObject* buff = intoCtx->GetThreadContext()->TTDContext->LookupObjectForLogID(snpCtx->PendingAsyncModArray[i].LogId);
- uint32 index = snpCtx->PendingAsyncModArray[i].Index;
- TTDAssert(Js::ArrayBuffer::Is(buff), "Not an ArrayBuffer!!!");
- intoCtx->TTDContextInfo->AddToAsyncPendingList(Js::ArrayBuffer::FromVar(buff), index);
- }
- }
- void EmitSnapContext(const SnapContext* snapCtx, FileWriter* writer, NSTokens::Separator separator)
- {
- writer->WriteRecordStart(separator);
- writer->WriteLogTag(NSTokens::Key::ctxTag, snapCtx->ScriptContextLogId);
- writer->WriteBool(NSTokens::Key::boolVal, snapCtx->IsPNRGSeeded, NSTokens::Separator::CommaSeparator);
- writer->WriteUInt64(NSTokens::Key::u64Val, snapCtx->RandomSeed0, NSTokens::Separator::CommaSeparator);
- writer->WriteUInt64(NSTokens::Key::u64Val, snapCtx->RandomSeed1, NSTokens::Separator::CommaSeparator);
- writer->WriteString(NSTokens::Key::ctxUri, snapCtx->ContextSRC, NSTokens::Separator::CommaSeparator);
- writer->WriteLengthValue(snapCtx->LoadedTopLevelScriptCount, NSTokens::Separator::CommaSeparator);
- writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
- for(uint32 i = 0; i < snapCtx->LoadedTopLevelScriptCount; ++i)
- {
- const TopLevelFunctionInContextRelation* cri = snapCtx->LoadedTopLevelScriptArray + i;
- NSTokens::Separator sep = (i != 0) ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator;
- writer->WriteRecordStart(sep);
- writer->WriteUInt32(NSTokens::Key::bodyCounterId, cri->TopLevelBodyCtr);
- writer->WriteAddr(NSTokens::Key::functionBodyId, cri->ContextSpecificBodyPtrId, NSTokens::Separator::CommaSeparator);
- writer->WriteRecordEnd();
- }
- writer->WriteSequenceEnd();
- writer->WriteLengthValue(snapCtx->NewFunctionTopLevelScriptCount, NSTokens::Separator::CommaSeparator);
- writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
- for(uint32 i = 0; i < snapCtx->NewFunctionTopLevelScriptCount; ++i)
- {
- const TopLevelFunctionInContextRelation* cri = snapCtx->NewFunctionTopLevelScriptArray + i;
- NSTokens::Separator sep = (i != 0) ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator;
- writer->WriteRecordStart(sep);
- writer->WriteUInt32(NSTokens::Key::bodyCounterId, cri->TopLevelBodyCtr);
- writer->WriteAddr(NSTokens::Key::functionBodyId, cri->ContextSpecificBodyPtrId, NSTokens::Separator::CommaSeparator);
- writer->WriteRecordEnd();
- }
- writer->WriteSequenceEnd();
- writer->WriteLengthValue(snapCtx->EvalTopLevelScriptCount, NSTokens::Separator::CommaSeparator);
- writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
- for(uint32 i = 0; i < snapCtx->EvalTopLevelScriptCount; ++i)
- {
- const TopLevelFunctionInContextRelation* cri = snapCtx->EvalTopLevelScriptArray + i;
- NSTokens::Separator sep = (i != 0) ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator;
- writer->WriteRecordStart(sep);
- writer->WriteUInt32(NSTokens::Key::bodyCounterId, cri->TopLevelBodyCtr);
- writer->WriteAddr(NSTokens::Key::functionBodyId, cri->ContextSpecificBodyPtrId, NSTokens::Separator::CommaSeparator);
- writer->WriteRecordEnd();
- }
- writer->WriteSequenceEnd();
- writer->WriteLengthValue(snapCtx->PendingAsyncModCount, NSTokens::Separator::CommaSeparator);
- writer->WriteSequenceStart_DefaultKey(NSTokens::Separator::CommaSeparator);
- for(uint32 i = 0; i < snapCtx->PendingAsyncModCount; ++i)
- {
- NSTokens::Separator sep = (i != 0) ? NSTokens::Separator::CommaSeparator : NSTokens::Separator::NoSeparator;
- writer->WriteRecordStart(sep);
- writer->WriteLogTag(NSTokens::Key::logTag, snapCtx->PendingAsyncModArray[i].LogId);
- writer->WriteUInt32(NSTokens::Key::u32Val, snapCtx->PendingAsyncModArray[i].Index, NSTokens::Separator::CommaSeparator);
- writer->WriteRecordEnd();
- }
- writer->WriteSequenceEnd();
- writer->WriteRecordEnd();
- }
- void ParseSnapContext(SnapContext* intoCtx, bool readSeperator, FileReader* reader, SlabAllocator& alloc)
- {
- reader->ReadRecordStart(readSeperator);
- intoCtx->ScriptContextLogId = reader->ReadLogTag(NSTokens::Key::ctxTag);
- intoCtx->IsPNRGSeeded = reader->ReadBool(NSTokens::Key::boolVal, true);
- intoCtx->RandomSeed0 = reader->ReadUInt64(NSTokens::Key::u64Val, true);
- intoCtx->RandomSeed1 = reader->ReadUInt64(NSTokens::Key::u64Val, true);
- reader->ReadString(NSTokens::Key::ctxUri, alloc, intoCtx->ContextSRC, true);
- intoCtx->LoadedTopLevelScriptCount = reader->ReadLengthValue(true);
- intoCtx->LoadedTopLevelScriptArray = (intoCtx->LoadedTopLevelScriptCount != 0) ? alloc.SlabAllocateArray<TopLevelFunctionInContextRelation>(intoCtx->LoadedTopLevelScriptCount) : nullptr;
- reader->ReadSequenceStart_WDefaultKey(true);
- for(uint32 i = 0; i < intoCtx->LoadedTopLevelScriptCount; ++i)
- {
- TopLevelFunctionInContextRelation* cri = intoCtx->LoadedTopLevelScriptArray + i;
- reader->ReadRecordStart(i != 0);
- cri->TopLevelBodyCtr = reader->ReadUInt32(NSTokens::Key::bodyCounterId);
- cri->ContextSpecificBodyPtrId = reader->ReadAddr(NSTokens::Key::functionBodyId, true);
- reader->ReadRecordEnd();
- }
- reader->ReadSequenceEnd();
- intoCtx->NewFunctionTopLevelScriptCount = reader->ReadLengthValue(true);
- intoCtx->NewFunctionTopLevelScriptArray = (intoCtx->NewFunctionTopLevelScriptCount != 0) ? alloc.SlabAllocateArray<TopLevelFunctionInContextRelation>(intoCtx->NewFunctionTopLevelScriptCount) : nullptr;
- reader->ReadSequenceStart_WDefaultKey(true);
- for(uint32 i = 0; i < intoCtx->NewFunctionTopLevelScriptCount; ++i)
- {
- TopLevelFunctionInContextRelation* cri = intoCtx->NewFunctionTopLevelScriptArray + i;
- reader->ReadRecordStart(i != 0);
- cri->TopLevelBodyCtr = reader->ReadUInt32(NSTokens::Key::bodyCounterId);
- cri->ContextSpecificBodyPtrId = reader->ReadAddr(NSTokens::Key::functionBodyId, true);
- reader->ReadRecordEnd();
- }
- reader->ReadSequenceEnd();
- intoCtx->EvalTopLevelScriptCount = reader->ReadLengthValue(true);
- intoCtx->EvalTopLevelScriptArray = (intoCtx->EvalTopLevelScriptCount != 0) ? alloc.SlabAllocateArray<TopLevelFunctionInContextRelation>(intoCtx->EvalTopLevelScriptCount) : nullptr;
- reader->ReadSequenceStart_WDefaultKey(true);
- for(uint32 i = 0; i < intoCtx->EvalTopLevelScriptCount; ++i)
- {
- TopLevelFunctionInContextRelation* cri = intoCtx->EvalTopLevelScriptArray + i;
- reader->ReadRecordStart(i != 0);
- cri->TopLevelBodyCtr = reader->ReadUInt32(NSTokens::Key::bodyCounterId);
- cri->ContextSpecificBodyPtrId = reader->ReadAddr(NSTokens::Key::functionBodyId, true);
- reader->ReadRecordEnd();
- }
- reader->ReadSequenceEnd();
- intoCtx->PendingAsyncModCount = reader->ReadLengthValue(true);
- intoCtx->PendingAsyncModArray = (intoCtx->PendingAsyncModCount != 0) ? alloc.SlabAllocateArray<SnapPendingAsyncBufferModification>(intoCtx->PendingAsyncModCount) : nullptr;
- reader->ReadSequenceStart_WDefaultKey(true);
- for(uint32 i = 0; i < intoCtx->PendingAsyncModCount; ++i)
- {
- reader->ReadRecordStart(i != 0);
- intoCtx->PendingAsyncModArray[i].LogId = reader->ReadLogTag(NSTokens::Key::logTag);
- intoCtx->PendingAsyncModArray[i].Index = reader->ReadUInt32(NSTokens::Key::u32Val, true);
- reader->ReadRecordEnd();
- }
- reader->ReadSequenceEnd();
- reader->ReadRecordEnd();
- }
- #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)
- {
- compareMap.DiagnosticAssert(snapCtx1->ScriptContextLogId == snapCtx2->ScriptContextLogId);
- compareMap.DiagnosticAssert(snapCtx1->IsPNRGSeeded == snapCtx2->IsPNRGSeeded);
- compareMap.DiagnosticAssert(snapCtx1->RandomSeed0 == snapCtx2->RandomSeed0);
- compareMap.DiagnosticAssert(snapCtx1->RandomSeed1 == snapCtx2->RandomSeed1);
- compareMap.DiagnosticAssert(TTStringEQForDiagnostics(snapCtx1->ContextSRC, snapCtx2->ContextSRC));
- //
- //TODO: For now just sanity check the number of top-level functions and let the FunctionBody matching drive any matching.
- //
- compareMap.DiagnosticAssert(snapCtx1->LoadedTopLevelScriptCount == snapCtx2->LoadedTopLevelScriptCount);
- //TopLevelScriptLoadFunctionBodyResolveInfo* m_loadedScriptArray;
- compareMap.DiagnosticAssert(snapCtx1->NewFunctionTopLevelScriptCount == snapCtx2->NewFunctionTopLevelScriptCount);
- //TopLevelNewFunctionBodyResolveInfo* m_newScriptArray;
- compareMap.DiagnosticAssert(snapCtx1->EvalTopLevelScriptCount == snapCtx2->EvalTopLevelScriptCount);
- //TopLevelEvalFunctionBodyResolveInfo* m_evalScriptArray;
- compareMap.DiagnosticAssert(snapCtx1->PendingAsyncModCount == snapCtx2->PendingAsyncModCount);
- for(uint32 i = 0; i < snapCtx1->PendingAsyncModCount; ++i)
- {
- const SnapPendingAsyncBufferModification& pendEntry1 = snapCtx1->PendingAsyncModArray[i];
- const SnapPendingAsyncBufferModification& pendEntry2 = snapCtx2->PendingAsyncModArray[i];
- compareMap.DiagnosticAssert(pendEntry1.LogId == pendEntry2.LogId && pendEntry1.Index == pendEntry2.Index);
- compareMap.H1PendingAsyncModBufferSet.AddNew(allRootMap1.Item(pendEntry1.LogId)->LogObject);
- compareMap.H2PendingAsyncModBufferSet.AddNew(allRootMap2.Item(pendEntry2.LogId)->LogObject);
- }
- }
- #endif
- }
- }
- #endif
|