| //------------------------------------------------------------------------------------------------------- |
| // 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 |
| |
| #define PATH_BUFFER_COUNT 256 |
| |
| namespace TTD |
| { |
| InflateMap::InflateMap() |
| : m_typeMap(), m_handlerMap(), |
| m_tagToGlobalObjectMap(), m_objectMap(), |
| m_functionBodyMap(), m_environmentMap(), m_slotArrayMap(), m_promiseDataMap(&HeapAllocator::Instance), |
| m_debuggerScopeHomeBodyMap(), m_debuggerScopeChainIndexMap(), |
| m_inflatePinSet(), m_environmentPinSet(), m_oldInflatePinSet(), |
| m_oldObjectMap(), m_oldFunctionBodyMap(), m_propertyReset(&HeapAllocator::Instance) |
| { |
| ; |
| } |
| |
| InflateMap::~InflateMap() |
| { |
| if(this->m_inflatePinSet != nullptr) |
| { |
| this->m_inflatePinSet.Unroot(this->m_inflatePinSet->GetAllocator()); |
| } |
| |
| if(this->m_environmentPinSet != nullptr) |
| { |
| this->m_environmentPinSet.Unroot(this->m_environmentPinSet->GetAllocator()); |
| } |
| |
| if(this->m_slotArrayPinSet != nullptr) |
| { |
| this->m_slotArrayPinSet.Unroot(this->m_slotArrayPinSet->GetAllocator()); |
| } |
| |
| if(this->m_oldInflatePinSet != nullptr) |
| { |
| this->m_oldInflatePinSet.Unroot(this->m_oldInflatePinSet->GetAllocator()); |
| } |
| } |
| |
| void InflateMap::PrepForInitialInflate(ThreadContext* threadContext, uint32 ctxCount, uint32 handlerCount, uint32 typeCount, uint32 objectCount, uint32 bodyCount, uint32 dbgScopeCount, uint32 envCount, uint32 slotCount) |
| { |
| this->m_typeMap.Initialize(typeCount); |
| this->m_handlerMap.Initialize(handlerCount); |
| this->m_tagToGlobalObjectMap.Initialize(ctxCount); |
| this->m_objectMap.Initialize(objectCount); |
| this->m_functionBodyMap.Initialize(bodyCount); |
| this->m_debuggerScopeHomeBodyMap.Initialize(dbgScopeCount); |
| this->m_debuggerScopeChainIndexMap.Initialize(dbgScopeCount); |
| this->m_environmentMap.Initialize(envCount); |
| this->m_slotArrayMap.Initialize(slotCount); |
| this->m_promiseDataMap.Clear(); |
| |
| Recycler * recycler = threadContext->GetRecycler(); |
| this->m_inflatePinSet.Root(RecyclerNew(recycler, ObjectPinSet, recycler, objectCount), recycler); |
| this->m_environmentPinSet.Root(RecyclerNew(recycler, EnvironmentPinSet, recycler, objectCount), recycler); |
| this->m_slotArrayPinSet.Root(RecyclerNew(recycler, SlotArrayPinSet, recycler, objectCount), recycler); |
| } |
| |
| void InflateMap::PrepForReInflate(uint32 ctxCount, uint32 handlerCount, uint32 typeCount, uint32 objectCount, uint32 bodyCount, uint32 dbgScopeCount, uint32 envCount, uint32 slotCount) |
| { |
| this->m_typeMap.Initialize(typeCount); |
| this->m_handlerMap.Initialize(handlerCount); |
| this->m_tagToGlobalObjectMap.Initialize(ctxCount); |
| this->m_debuggerScopeHomeBodyMap.Initialize(dbgScopeCount); |
| this->m_debuggerScopeChainIndexMap.Initialize(dbgScopeCount); |
| this->m_environmentMap.Initialize(envCount); |
| this->m_slotArrayMap.Initialize(slotCount); |
| this->m_promiseDataMap.Clear(); |
| |
| //We re-use these values (and reset things below) so we don't neet to initialize them here |
| //m_objectMap |
| //m_functionBodyMap |
| |
| //copy info we want to reuse into the old maps |
| this->m_oldObjectMap.MoveDataInto(this->m_objectMap); |
| this->m_oldFunctionBodyMap.MoveDataInto(this->m_functionBodyMap); |
| |
| //allocate the old pin set and fill it |
| TTDAssert(this->m_oldInflatePinSet == nullptr, "Old pin set is not null."); |
| Recycler* pinRecycler = this->m_inflatePinSet->GetAllocator(); |
| this->m_oldInflatePinSet.Root(RecyclerNew(pinRecycler, ObjectPinSet, pinRecycler, this->m_inflatePinSet->Count()), pinRecycler); |
| |
| for(auto iter = this->m_inflatePinSet->GetIterator(); iter.IsValid(); iter.MoveNext()) |
| { |
| this->m_oldInflatePinSet->AddNew(iter.CurrentKey()); |
| } |
| |
| this->m_inflatePinSet->Clear(); |
| this->m_environmentPinSet->Clear(); |
| this->m_slotArrayPinSet->Clear(); |
| } |
| |
| void InflateMap::CleanupAfterInflate() |
| { |
| this->m_handlerMap.Unload(); |
| this->m_typeMap.Unload(); |
| this->m_tagToGlobalObjectMap.Unload(); |
| this->m_debuggerScopeHomeBodyMap.Unload(); |
| this->m_debuggerScopeChainIndexMap.Unload(); |
| this->m_environmentMap.Unload(); |
| this->m_slotArrayMap.Unload(); |
| this->m_promiseDataMap.Clear(); |
| |
| //We re-use these values (and reset things later) so we don't want to unload them here |
| //m_objectMap |
| //m_functionBodyMap |
| |
| this->m_oldObjectMap.Unload(); |
| this->m_oldFunctionBodyMap.Unload(); |
| this->m_propertyReset.Clear(); |
| |
| if(this->m_oldInflatePinSet != nullptr) |
| { |
| this->m_oldInflatePinSet.Unroot(this->m_oldInflatePinSet->GetAllocator()); |
| } |
| } |
| |
| bool InflateMap::IsObjectAlreadyInflated(TTD_PTR_ID objid) const |
| { |
| return this->m_objectMap.Contains(objid); |
| } |
| |
| bool InflateMap::IsFunctionBodyAlreadyInflated(TTD_PTR_ID fbodyid) const |
| { |
| return this->m_functionBodyMap.Contains(fbodyid); |
| } |
| |
| Js::RecyclableObject* InflateMap::FindReusableObjectIfExists(TTD_PTR_ID objid) const |
| { |
| if(!this->m_oldObjectMap.IsValid()) |
| { |
| return nullptr; |
| } |
| else |
| { |
| return this->m_oldObjectMap.LookupKnownItem(objid); |
| } |
| } |
| |
| Js::FunctionBody* InflateMap::FindReusableFunctionBodyIfExists(TTD_PTR_ID fbodyid) const |
| { |
| if(!this->m_oldFunctionBodyMap.IsValid()) |
| { |
| return nullptr; |
| } |
| else |
| { |
| return this->m_oldFunctionBodyMap.LookupKnownItem(fbodyid); |
| } |
| } |
| |
| Js::RecyclableObject* InflateMap::FindReusableObject_WellKnowReuseCheck(TTD_PTR_ID objid) const |
| { |
| return this->m_objectMap.LookupKnownItem(objid); |
| } |
| |
| Js::DynamicTypeHandler* InflateMap::LookupHandler(TTD_PTR_ID handlerId) const |
| { |
| return this->m_handlerMap.LookupKnownItem(handlerId); |
| } |
| |
| Js::Type* InflateMap::LookupType(TTD_PTR_ID typeId) const |
| { |
| return this->m_typeMap.LookupKnownItem(typeId); |
| } |
| |
| Js::ScriptContext* InflateMap::LookupScriptContext(TTD_LOG_PTR_ID sctag) const |
| { |
| return this->m_tagToGlobalObjectMap.LookupKnownItem(sctag)->GetScriptContext(); |
| } |
| |
| Js::RecyclableObject* InflateMap::LookupObject(TTD_PTR_ID objid) const |
| { |
| return this->m_objectMap.LookupKnownItem(objid); |
| } |
| |
| Js::FunctionBody* InflateMap::LookupFunctionBody(TTD_PTR_ID functionId) const |
| { |
| return this->m_functionBodyMap.LookupKnownItem(functionId); |
| } |
| |
| Js::FrameDisplay* InflateMap::LookupEnvironment(TTD_PTR_ID envid) const |
| { |
| return this->m_environmentMap.LookupKnownItem(envid); |
| } |
| |
| Js::Var* InflateMap::LookupSlotArray(TTD_PTR_ID slotid) const |
| { |
| return this->m_slotArrayMap.LookupKnownItem(slotid); |
| } |
| |
| void InflateMap::LookupInfoForDebugScope(TTD_PTR_ID dbgScopeId, Js::FunctionBody** homeBody, int32* chainIndex) const |
| { |
| *homeBody = this->m_debuggerScopeHomeBodyMap.LookupKnownItem(dbgScopeId); |
| *chainIndex = this->m_debuggerScopeChainIndexMap.LookupKnownItem(dbgScopeId); |
| } |
| |
| void InflateMap::AddDynamicHandler(TTD_PTR_ID handlerId, Js::DynamicTypeHandler* value) |
| { |
| this->m_handlerMap.AddItem(handlerId, value); |
| } |
| |
| void InflateMap::AddType(TTD_PTR_ID typeId, Js::Type* value) |
| { |
| this->m_typeMap.AddItem(typeId, value); |
| } |
| |
| void InflateMap::AddScriptContext(TTD_LOG_PTR_ID sctag, Js::ScriptContext* value) |
| { |
| Js::GlobalObject* globalObj = value->GetGlobalObject(); |
| |
| this->m_tagToGlobalObjectMap.AddItem(sctag, globalObj); |
| value->ScriptContextLogTag = sctag; |
| } |
| |
| void InflateMap::AddObject(TTD_PTR_ID objid, Js::RecyclableObject* value) |
| { |
| this->m_objectMap.AddItem(objid, value); |
| this->m_inflatePinSet->AddNew(value); |
| } |
| |
| void InflateMap::AddInflationFunctionBody(TTD_PTR_ID functionId, Js::FunctionBody* value) |
| { |
| this->m_functionBodyMap.AddItem(functionId, value); |
| //Function bodies are either root (and kept live by our root pin set in the script context/info) or are reachable from it |
| } |
| |
| void InflateMap::AddEnvironment(TTD_PTR_ID envId, Js::FrameDisplay* value) |
| { |
| this->m_environmentMap.AddItem(envId, value); |
| this->m_environmentPinSet->AddNew(value); |
| } |
| |
| void InflateMap::AddSlotArray(TTD_PTR_ID slotId, Js::Var* value) |
| { |
| this->m_slotArrayMap.AddItem(slotId, value); |
| this->m_slotArrayPinSet->AddNew(value); |
| } |
| |
| void InflateMap::UpdateFBScopes(const NSSnapValues::SnapFunctionBodyScopeChain& scopeChainInfo, Js::FunctionBody* fb) |
| { |
| TTDAssert((int32)scopeChainInfo.ScopeCount == (fb->GetScopeObjectChain() != nullptr ? fb->GetScopeObjectChain()->pScopeChain->Count() : 0), "Mismatch in scope counts!!!"); |
| |
| if(fb->GetScopeObjectChain() != nullptr) |
| { |
| Js::ScopeObjectChain* scChain = fb->GetScopeObjectChain(); |
| for(int32 i = 0; i < scChain->pScopeChain->Count(); ++i) |
| { |
| TTD_PTR_ID dbgScopeId = scopeChainInfo.ScopeArray[i]; |
| |
| if(!this->m_debuggerScopeHomeBodyMap.Contains(dbgScopeId)) |
| { |
| this->m_debuggerScopeHomeBodyMap.AddItem(dbgScopeId, fb); |
| this->m_debuggerScopeChainIndexMap.AddItem(dbgScopeId, i); |
| } |
| } |
| } |
| } |
| |
| JsUtil::BaseHashSet<Js::PropertyId, HeapAllocator>& InflateMap::GetPropertyResetSet() |
| { |
| return this->m_propertyReset; |
| } |
| |
| Js::Var InflateMap::InflateTTDVar(TTDVar var) const |
| { |
| if(Js::TaggedNumber::Is(var)) |
| { |
| return static_cast<Js::Var>(var); |
| } |
| else |
| { |
| return this->LookupObject(TTD_CONVERT_VAR_TO_PTR_ID(var)); |
| } |
| } |
| |
| ////////////////// |
| #if ENABLE_SNAPSHOT_COMPARE |
| TTDComparePath::TTDComparePath() |
| : m_prefix(nullptr), m_stepKind(StepKind::Empty), m_step() |
| { |
| ; |
| } |
| |
| TTDComparePath::TTDComparePath(const TTDComparePath* prefix, StepKind stepKind, const PathEntry& nextStep) |
| : m_prefix(prefix), m_stepKind(stepKind), m_step(nextStep) |
| { |
| ; |
| } |
| |
| TTDComparePath::~TTDComparePath() |
| { |
| ; |
| } |
| |
| void TTDComparePath::WritePathToConsole(ThreadContext* threadContext, bool printNewline, _Out_writes_z_(buffLength) char16* namebuff, charcount_t namebuffLength) const |
| { |
| if(this->m_prefix != nullptr) |
| { |
| this->m_prefix->WritePathToConsole(threadContext, false, namebuff, namebuffLength); |
| } |
| |
| if(this->m_stepKind == StepKind::PropertyData || this->m_stepKind == StepKind::PropertyGetter || this->m_stepKind == StepKind::PropertySetter) |
| { |
| const Js::PropertyRecord* pRecord = threadContext->GetPropertyName((Js::PropertyId)this->m_step.IndexOrPID); |
| js_memcpy_s(namebuff, namebuffLength * sizeof(char16), pRecord->GetBuffer(), pRecord->GetLength() * sizeof(char16)); |
| |
| // Don't allow the null to be written past the end of the buffer. |
| namebuff[min(namebuffLength - 1, pRecord->GetLength())] = _u('\0'); |
| } |
| |
| bool isFirst = (this->m_prefix == nullptr); |
| switch(this->m_stepKind) |
| { |
| case StepKind::Empty: |
| break; |
| case StepKind::Root: |
| wprintf(_u("root#%I64i"), this->m_step.IndexOrPID); |
| break; |
| case StepKind::PropertyData: |
| wprintf(_u("%ls%ls"), (isFirst ? _u("") : _u(".")), namebuff); |
| break; |
| case StepKind::PropertyGetter: |
| wprintf(_u("%ls<%ls"), (isFirst ? _u("") : _u(".")), namebuff); |
| break; |
| case StepKind::PropertySetter: |
| wprintf(_u("%ls>%ls"), (isFirst ? _u("") : _u(".")), namebuff); |
| break; |
| case StepKind::Array: |
| wprintf(_u("[%I64i]"), this->m_step.IndexOrPID); |
| break; |
| case StepKind::Scope: |
| wprintf(_u("%ls_scope[%I64i]"), (isFirst ? _u("") : _u(".")), this->m_step.IndexOrPID); |
| break; |
| case StepKind::SlotArray: |
| wprintf(_u("%ls_slots[%I64i]"), (isFirst ? _u("") : _u(".")), this->m_step.IndexOrPID); |
| break; |
| case StepKind::FunctionBody: |
| wprintf(_u("%ls%ls"), (isFirst ? _u("") : _u(".")), this->m_step.OptName); |
| break; |
| case StepKind::Special: |
| wprintf(_u("%ls_%ls"), (isFirst ? _u("") : _u(".")), this->m_step.OptName); |
| break; |
| case StepKind::SpecialArray: |
| wprintf(_u("%ls_%ls[%I64i]"), (isFirst ? _u("") : _u(".")), this->m_step.OptName, this->m_step.IndexOrPID); |
| break; |
| default: |
| TTDAssert(false, "Unknown tag in switch statement!!!"); |
| break; |
| } |
| |
| if(printNewline) |
| { |
| wprintf(_u("\n")); |
| } |
| } |
| |
| TTDCompareMap::TTDCompareMap(ThreadContext* threadContext) |
| : StrictCrossSite(false), H1PtrIdWorklist(&HeapAllocator::Instance), H1PtrToH2PtrMap(&HeapAllocator::Instance), SnapObjCmpVTable(nullptr), H1PtrToPathMap(&HeapAllocator::Instance), |
| CurrentPath(nullptr), CurrentH1Ptr(TTD_INVALID_PTR_ID), CurrentH2Ptr(TTD_INVALID_PTR_ID), Context(threadContext), |
| // |
| H1ValueMap(&HeapAllocator::Instance), H1SlotArrayMap(&HeapAllocator::Instance), H1FunctionScopeInfoMap(&HeapAllocator::Instance), |
| H1FunctionTopLevelLoadMap(&HeapAllocator::Instance), H1FunctionTopLevelNewMap(&HeapAllocator::Instance), H1FunctionTopLevelEvalMap(&HeapAllocator::Instance), |
| H1FunctionBodyMap(&HeapAllocator::Instance), H1ObjectMap(&HeapAllocator::Instance), H1PendingAsyncModBufferSet(&HeapAllocator::Instance), |
| // |
| H2ValueMap(&HeapAllocator::Instance), H2SlotArrayMap(&HeapAllocator::Instance), H2FunctionScopeInfoMap(&HeapAllocator::Instance), |
| H2FunctionTopLevelLoadMap(&HeapAllocator::Instance), H2FunctionTopLevelNewMap(&HeapAllocator::Instance), H2FunctionTopLevelEvalMap(&HeapAllocator::Instance), |
| H2FunctionBodyMap(&HeapAllocator::Instance), H2ObjectMap(&HeapAllocator::Instance), H2PendingAsyncModBufferSet(&HeapAllocator::Instance) |
| { |
| this->StrictCrossSite = !threadContext->TTDLog->IsDebugModeFlagSet(); |
| |
| this->PathBuffer = TT_HEAP_ALLOC_ARRAY_ZERO(char16, PATH_BUFFER_COUNT); |
| |
| this->SnapObjCmpVTable = TT_HEAP_ALLOC_ARRAY_ZERO(fPtr_AssertSnapEquivAddtlInfo, (int32)NSSnapObjects::SnapObjectType::Limit); |
| |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapScriptFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapScriptFunctionInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapExternalFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapExternalFunctionInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapRuntimeRevokerFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapRevokerFunctionInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapBoundFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapBoundFunctionInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapHeapArgumentsObject] = &NSSnapObjects::AssertSnapEquiv_SnapHeapArgumentsInfo<NSSnapObjects::SnapObjectType::SnapHeapArgumentsObject>; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapES5HeapArgumentsObject] = &NSSnapObjects::AssertSnapEquiv_SnapHeapArgumentsInfo<NSSnapObjects::SnapObjectType::SnapES5HeapArgumentsObject>; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapBoxedValueObject] = &NSSnapObjects::AssertSnapEquiv_SnapBoxedValue; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapDateObject] = &NSSnapObjects::AssertSnapEquiv_SnapDate; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapRegexObject] = &NSSnapObjects::AssertSnapEquiv_SnapRegexInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapArrayObject] = &NSSnapObjects::AssertSnapEquiv_SnapArrayInfo<TTDVar, NSSnapObjects::SnapObjectType::SnapArrayObject>; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapNativeIntArrayObject] = &NSSnapObjects::AssertSnapEquiv_SnapArrayInfo<int, NSSnapObjects::SnapObjectType::SnapNativeIntArrayObject>; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapNativeFloatArrayObject] = &NSSnapObjects::AssertSnapEquiv_SnapArrayInfo<double, NSSnapObjects::SnapObjectType::SnapNativeFloatArrayObject>; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapES5ArrayObject] = &NSSnapObjects::AssertSnapEquiv_SnapES5ArrayInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapArrayBufferObject] = &NSSnapObjects::AssertSnapEquiv_SnapArrayBufferInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapTypedArrayObject] = &NSSnapObjects::AssertSnapEquiv_SnapTypedArrayInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapSetObject] = &NSSnapObjects::AssertSnapEquiv_SnapSetInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapMapObject] = &NSSnapObjects::AssertSnapEquiv_SnapMapInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapProxyObject] = &NSSnapObjects::AssertSnapEquiv_SnapProxyInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapPromiseObject] = &NSSnapObjects::AssertSnapEquiv_SnapPromiseInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapPromiseResolveOrRejectFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapPromiseResolveOrRejectFunctionInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapPromiseReactionTaskFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapPromiseReactionTaskFunctionInfo; |
| this->SnapObjCmpVTable[(int32)NSSnapObjects::SnapObjectType::SnapPromiseAllResolveElementFunctionObject] = &NSSnapObjects::AssertSnapEquiv_SnapPromiseAllResolveElementFunctionInfo; |
| } |
| |
| TTDCompareMap::~TTDCompareMap() |
| { |
| TT_HEAP_FREE_ARRAY(char16, this->PathBuffer, PATH_BUFFER_COUNT); |
| |
| TT_HEAP_FREE_ARRAY(TTD::fPtr_AssertSnapEquivAddtlInfo, this->SnapObjCmpVTable, (int32)NSSnapObjects::SnapObjectType::Limit); |
| |
| //delete all the compare paths |
| for(auto iter = this->H1PtrToPathMap.GetIterator(); iter.IsValid(); iter.MoveNext()) |
| { |
| TT_HEAP_DELETE(TTDComparePath, iter.CurrentValue()); |
| } |
| } |
| |
| void TTDCompareMap::DiagnosticAssert(bool condition) |
| { |
| if(!condition) |
| { |
| if(this->CurrentPath != nullptr) |
| { |
| wprintf(_u("Snap1 ptrid: *0x%I64x\n"), this->CurrentH1Ptr); |
| wprintf(_u("Snap2 ptrid: *0x%I64x\n"), this->CurrentH2Ptr); |
| this->CurrentPath->WritePathToConsole(this->Context, true, this->PathBuffer, PATH_BUFFER_COUNT); |
| } |
| } |
| |
| TTDAssert(condition, "Diagnostic compare assertion failed!!!"); |
| } |
| |
| void TTDCompareMap::CheckConsistentAndAddPtrIdMapping_Helper(TTD_PTR_ID h1PtrId, TTD_PTR_ID h2PtrId, TTDComparePath::StepKind stepKind, const TTDComparePath::PathEntry& next) |
| { |
| if(h1PtrId == TTD_INVALID_PTR_ID || h2PtrId == TTD_INVALID_PTR_ID) |
| { |
| this->DiagnosticAssert(h1PtrId == TTD_INVALID_PTR_ID && h2PtrId == TTD_INVALID_PTR_ID); |
| } |
| else if(this->H1PtrToH2PtrMap.ContainsKey(h1PtrId)) |
| { |
| this->DiagnosticAssert(this->H1PtrToH2PtrMap.Item(h1PtrId) == h2PtrId); |
| } |
| else if(this->H1ValueMap.ContainsKey(h1PtrId)) |
| { |
| this->DiagnosticAssert(this->H2ValueMap.ContainsKey(h2PtrId)); |
| |
| const NSSnapValues::SnapPrimitiveValue* v1 = this->H1ValueMap.Item(h1PtrId); |
| const NSSnapValues::SnapPrimitiveValue* v2 = this->H2ValueMap.Item(h2PtrId); |
| NSSnapValues::AssertSnapEquiv(v1, v2, *this); |
| } |
| else |
| { |
| this->H1PtrIdWorklist.Enqueue(h1PtrId); |
| |
| TTDComparePath* objPath = TT_HEAP_NEW(TTDComparePath, this->CurrentPath, stepKind, next); |
| this->H1PtrToPathMap.AddNew(h1PtrId, objPath); |
| |
| this->H1PtrToH2PtrMap.AddNew(h1PtrId, h2PtrId); |
| } |
| } |
| |
| void TTDCompareMap::CheckConsistentAndAddPtrIdMapping_Scope(TTD_PTR_ID h1PtrId, TTD_PTR_ID h2PtrId, uint32 index) |
| { |
| TTDComparePath::PathEntry next{ index, nullptr }; |
| this->CheckConsistentAndAddPtrIdMapping_Helper(h1PtrId, h2PtrId, TTDComparePath::StepKind::Scope, next); |
| } |
| |
| void TTDCompareMap::CheckConsistentAndAddPtrIdMapping_FunctionBody(TTD_PTR_ID h1PtrId, TTD_PTR_ID h2PtrId) |
| { |
| TTDComparePath::PathEntry next{ -1, _u("!body") }; |
| this->CheckConsistentAndAddPtrIdMapping_Helper(h1PtrId, h2PtrId, TTDComparePath::StepKind::FunctionBody, next); |
| } |
| |
| void TTDCompareMap::CheckConsistentAndAddPtrIdMapping_Special(TTD_PTR_ID h1PtrId, TTD_PTR_ID h2PtrId, const char16* specialField) |
| { |
| TTDComparePath::PathEntry next{ -1, specialField }; |
| this->CheckConsistentAndAddPtrIdMapping_Helper(h1PtrId, h2PtrId, TTDComparePath::StepKind::Special, next); |
| } |
| |
| void TTDCompareMap::CheckConsistentAndAddPtrIdMapping_Root(TTD_PTR_ID h1PtrId, TTD_PTR_ID h2PtrId, TTD_LOG_PTR_ID tag) |
| { |
| TTDComparePath::PathEntry next{ (uint32)tag, nullptr }; |
| this->CheckConsistentAndAddPtrIdMapping_Helper(h1PtrId, h2PtrId, TTDComparePath::StepKind::Root, next); |
| } |
| |
| void TTDCompareMap::CheckConsistentAndAddPtrIdMapping_NoEnqueue(TTD_PTR_ID h1PtrId, TTD_PTR_ID h2PtrId) |
| { |
| if(h1PtrId == TTD_INVALID_PTR_ID || h2PtrId == TTD_INVALID_PTR_ID) |
| { |
| this->DiagnosticAssert(h1PtrId == TTD_INVALID_PTR_ID && h2PtrId == TTD_INVALID_PTR_ID); |
| } |
| else if(this->H1PtrToH2PtrMap.ContainsKey(h1PtrId)) |
| { |
| this->DiagnosticAssert(this->H1PtrToH2PtrMap.Item(h1PtrId) == h2PtrId); |
| } |
| else |
| { |
| this->H1PtrToH2PtrMap.AddNew(h1PtrId, h2PtrId); |
| } |
| } |
| |
| void TTDCompareMap::GetNextCompareInfo(TTDCompareTag* tag, TTD_PTR_ID* h1PtrId, TTD_PTR_ID* h2PtrId) |
| { |
| if(this->H1PtrIdWorklist.Empty()) |
| { |
| *tag = TTDCompareTag::Done; |
| *h1PtrId = TTD_INVALID_PTR_ID; |
| *h2PtrId = TTD_INVALID_PTR_ID; |
| } |
| else |
| { |
| *h1PtrId = this->H1PtrIdWorklist.Dequeue(); |
| *h2PtrId = this->H1PtrToH2PtrMap.Item(*h1PtrId); |
| |
| this->CurrentPath = this->H1PtrToPathMap.Item(*h1PtrId); |
| this->CurrentH1Ptr = *h1PtrId; |
| this->CurrentH2Ptr = *h2PtrId; |
| |
| if(this->H1SlotArrayMap.ContainsKey(*h1PtrId)) |
| { |
| this->DiagnosticAssert(this->H2SlotArrayMap.ContainsKey(*h2PtrId)); |
| *tag = TTDCompareTag::SlotArray; |
| } |
| else if(this->H1FunctionScopeInfoMap.ContainsKey(*h1PtrId)) |
| { |
| this->DiagnosticAssert(this->H2FunctionScopeInfoMap.ContainsKey(*h2PtrId)); |
| *tag = TTDCompareTag::FunctionScopeInfo; |
| } |
| else if(this->H1FunctionTopLevelLoadMap.ContainsKey(*h1PtrId)) |
| { |
| this->DiagnosticAssert(this->H2FunctionTopLevelLoadMap.ContainsKey(*h2PtrId)); |
| *tag = TTDCompareTag::TopLevelLoadFunction; |
| } |
| else if(this->H1FunctionTopLevelNewMap.ContainsKey(*h1PtrId)) |
| { |
| this->DiagnosticAssert(this->H2FunctionTopLevelNewMap.ContainsKey(*h2PtrId)); |
| *tag = TTDCompareTag::TopLevelNewFunction; |
| } |
| else if(this->H1FunctionTopLevelEvalMap.ContainsKey(*h1PtrId)) |
| { |
| this->DiagnosticAssert(this->H2FunctionTopLevelEvalMap.ContainsKey(*h2PtrId)); |
| *tag = TTDCompareTag::TopLevelEvalFunction; |
| } |
| else if(this->H1FunctionBodyMap.ContainsKey(*h1PtrId)) |
| { |
| this->DiagnosticAssert(this->H2FunctionBodyMap.ContainsKey(*h2PtrId)); |
| *tag = TTDCompareTag::FunctionBody; |
| } |
| else if(this->H1ObjectMap.ContainsKey(*h1PtrId)) |
| { |
| this->DiagnosticAssert(this->H2ObjectMap.ContainsKey(*h2PtrId)); |
| *tag = TTDCompareTag::SnapObject; |
| } |
| else |
| { |
| TTDAssert(!this->H1ValueMap.ContainsKey(*h1PtrId), "Should be comparing by value!!!"); |
| TTDAssert(false, "Id not found in any of the maps!!!"); |
| *tag = TTDCompareTag::Done; |
| } |
| } |
| } |
| |
| void TTDCompareMap::GetCompareValues(TTDCompareTag compareTag, TTD_PTR_ID h1PtrId, const NSSnapValues::SlotArrayInfo** val1, TTD_PTR_ID h2PtrId, const NSSnapValues::SlotArrayInfo** val2) |
| { |
| TTDAssert(compareTag == TTDCompareTag::SlotArray, "Should be a type"); |
| *val1 = this->H1SlotArrayMap.Item(h1PtrId); |
| *val2 = this->H2SlotArrayMap.Item(h2PtrId); |
| } |
| |
| void TTDCompareMap::GetCompareValues(TTDCompareTag compareTag, TTD_PTR_ID h1PtrId, const NSSnapValues::ScriptFunctionScopeInfo** val1, TTD_PTR_ID h2PtrId, const NSSnapValues::ScriptFunctionScopeInfo** val2) |
| { |
| TTDAssert(compareTag == TTDCompareTag::FunctionScopeInfo, "Should be a type"); |
| *val1 = this->H1FunctionScopeInfoMap.Item(h1PtrId); |
| *val2 = this->H2FunctionScopeInfoMap.Item(h2PtrId); |
| } |
| |
| void TTDCompareMap::GetCompareValues(TTDCompareTag compareTag, TTD_PTR_ID h1PtrId, uint64* val1, TTD_PTR_ID h2PtrId, uint64* val2) |
| { |
| if(compareTag == TTDCompareTag::TopLevelLoadFunction) |
| { |
| *val1 = this->H1FunctionTopLevelLoadMap.Item(h1PtrId); |
| *val2 = this->H2FunctionTopLevelLoadMap.Item(h2PtrId); |
| } |
| else if(compareTag == TTDCompareTag::TopLevelNewFunction) |
| { |
| *val1 = this->H1FunctionTopLevelNewMap.Item(h1PtrId); |
| *val2 = this->H2FunctionTopLevelNewMap.Item(h2PtrId); |
| } |
| else |
| { |
| TTDAssert(compareTag == TTDCompareTag::TopLevelEvalFunction, "Should be a type"); |
| *val1 = this->H1FunctionTopLevelEvalMap.Item(h1PtrId); |
| *val2 = this->H2FunctionTopLevelEvalMap.Item(h2PtrId); |
| } |
| } |
| |
| void TTDCompareMap::GetCompareValues(TTDCompareTag compareTag, TTD_PTR_ID h1PtrId, const NSSnapValues::FunctionBodyResolveInfo** val1, TTD_PTR_ID h2PtrId, const NSSnapValues::FunctionBodyResolveInfo** val2) |
| { |
| TTDAssert(compareTag == TTDCompareTag::FunctionBody, "Should be a type"); |
| *val1 = this->H1FunctionBodyMap.Item(h1PtrId); |
| *val2 = this->H2FunctionBodyMap.Item(h2PtrId); |
| } |
| |
| void TTDCompareMap::GetCompareValues(TTDCompareTag compareTag, TTD_PTR_ID h1PtrId, const NSSnapObjects::SnapObject** val1, TTD_PTR_ID h2PtrId, const NSSnapObjects::SnapObject** val2) |
| { |
| TTDAssert(compareTag == TTDCompareTag::SnapObject, "Should be a type"); |
| *val1 = this->H1ObjectMap.Item(h1PtrId); |
| *val2 = this->H2ObjectMap.Item(h2PtrId); |
| } |
| #endif |
| } |
| |
| #endif |