From 86b5e65015bf0bfbe8aad0066d3c2e7feaa37ae9 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Thu, 31 Dec 2020 11:31:19 -0800 Subject: [PATCH] Fixed const eval dependency issues --- IDEHelper/Compiler/BfCompiler.cpp | 11 +++++++++ IDEHelper/Compiler/BfContext.cpp | 30 +++++++++++++++++++++++- IDEHelper/Compiler/BfContext.h | 3 ++- IDEHelper/Compiler/BfDefBuilder.cpp | 21 ++++++++++------- IDEHelper/Compiler/BfResolvedTypeUtils.h | 26 +++++++++++--------- IDEHelper/Compiler/BfSystem.cpp | 2 ++ IDEHelper/Compiler/BfSystem.h | 1 + IDEHelper/Compiler/CeMachine.cpp | 9 ++++++- IDEHelper/Compiler/CeMachine.h | 1 + 9 files changed, 82 insertions(+), 22 deletions(-) diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 48d9ac1f..7f1c74a6 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -2175,6 +2175,8 @@ void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork) } } + depType->mDependencyMap.mFlagsUnion = BfDependencyMap::DependencyFlag_None; + // Not combined with previous loop because PopulateType could modify typeInst->mDependencyMap for (auto itr = depType->mDependencyMap.begin(); itr != depType->mDependencyMap.end();) { @@ -2240,6 +2242,8 @@ void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork) ++itr; } + + depType->mDependencyMap.mFlagsUnion = (BfDependencyMap::DependencyFlags)(depType->mDependencyMap.mFlagsUnion | depData.mFlags); } if ((!depType->IsGenericTypeInstance() && (!depType->IsBoxed())) || @@ -3336,6 +3340,13 @@ void BfCompiler::UpdateRevisedTypes() (compositeTypeDef->mDefState != BfTypeDef::DefState_InlinedInternals_Changed)) compositeTypeDef->mDefState = BfTypeDef::DefState_Internals_Changed; } + else if (checkTypeDef->mDefState == BfTypeDef::DefState_Refresh) + { + if ((compositeTypeDef->mDefState != BfTypeDef::DefState_Signature_Changed) && + (compositeTypeDef->mDefState != BfTypeDef::DefState_InlinedInternals_Changed) && + (compositeTypeDef->mDefState != BfTypeDef::DefState_Internals_Changed)) + compositeTypeDef->mDefState = BfTypeDef::DefState_Refresh; + } BF_ASSERT(checkTypeDef->mIsPartial); if (checkTypeDef->mNextRevision != NULL) diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index 29acb5f3..11e8e392 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -1219,13 +1219,36 @@ void BfContext::TypeInlineMethodInternalsChanged(BfTypeInstance* typeInst) auto dependencyFlags = depItr.mValue.mFlags; // We don't need to cascade rebuilding for method-based usage - just rebuild the type directly (unlike TypeDataChanged, which cascades) - if (dependencyFlags & BfDependencyMap::DependencyFlag_InlinedCall) + if ((dependencyFlags & BfDependencyMap::DependencyFlag_InlinedCall) != 0) { RebuildType(dependentType); } } } +void BfContext::TypeConstEvalChanged(BfTypeInstance* typeInst) +{ + if (typeInst->mRebuildFlags & BfTypeRebuildFlag_ConstEvalChange) // Already did change? + return; + typeInst->mRebuildFlags = (BfTypeRebuildFlags)(typeInst->mRebuildFlags | BfTypeRebuildFlag_ConstEvalChange); + + // These don't happen in TypeDataChanged because we don't need to cascade + for (auto& depItr : typeInst->mDependencyMap) + { + auto dependentType = depItr.mKey; + auto dependencyFlags = depItr.mValue.mFlags; + + // We don't need to cascade rebuilding for method-based usage - just rebuild the type directly (unlike TypeDataChanged, which cascades) + if ((dependencyFlags & BfDependencyMap::DependencyFlag_ConstEval) != 0) + { + auto depTypeInst = dependentType->ToTypeInstance(); + if (depTypeInst != NULL) + TypeConstEvalChanged(depTypeInst); + RebuildType(dependentType); + } + } +} + void BfContext::PopulateHotTypeDataVTable(BfTypeInstance* typeInstance) { BP_ZONE("BfContext::PopulateHotTypeDataVTable"); @@ -1870,6 +1893,11 @@ void BfContext::UpdateRevisedTypes() isSignatureChange = true; } + if ((typeDef->mDefState != BfTypeDef::DefState_Refresh) && ((typeInst->mDependencyMap.mFlagsUnion & BfDependencyMap::DependencyFlag_ConstEval) != 0)) + { + TypeConstEvalChanged(typeInst); + } + if (isSignatureChange) { TypeDataChanged(typeInst, true); diff --git a/IDEHelper/Compiler/BfContext.h b/IDEHelper/Compiler/BfContext.h index 4fbc3616..d4ea8b2a 100644 --- a/IDEHelper/Compiler/BfContext.h +++ b/IDEHelper/Compiler/BfContext.h @@ -440,7 +440,8 @@ public: void RebuildDependentTypes(BfDependedType* dType); void TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChange); void TypeMethodSignaturesChanged(BfTypeInstance* typeInst); - void TypeInlineMethodInternalsChanged(BfTypeInstance* typeInst); + void TypeInlineMethodInternalsChanged(BfTypeInstance* typeInst); + void TypeConstEvalChanged(BfTypeInstance* typeInst); void CheckSpecializedErrorData(); void TryUnreifyModules(); void MarkUsedModules(BfProject* project, BfModule* module); diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index cdbf2ad7..5ae400ce 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -1841,21 +1841,26 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) { BF_ASSERT(mCurTypeDef->mTypeCode == prevRevisionTypeDef->mTypeCode); - if ((mCurTypeDef->mFullHash == prevRevisionTypeDef->mFullHash) && (!mFullRefresh)) + if (mCurTypeDef->mFullHash == prevRevisionTypeDef->mFullHash) { - BfLogSys(bfParser->mSystem, "DefBuilder deleting typeDef with no changes %p\n", prevRevisionTypeDef); - prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Defined; - BF_ASSERT(prevRevisionTypeDef->mNextRevision == mCurTypeDef); - prevRevisionTypeDef->mNextRevision = NULL; - delete mCurTypeDef; - mCurTypeDef = NULL; + if (!mFullRefresh) + { + BfLogSys(bfParser->mSystem, "DefBuilder deleting typeDef with no changes %p\n", prevRevisionTypeDef); + prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Defined; + BF_ASSERT(prevRevisionTypeDef->mNextRevision == mCurTypeDef); + prevRevisionTypeDef->mNextRevision = NULL; + delete mCurTypeDef; + mCurTypeDef = NULL; + } + else + prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Refresh; } else if (mCurTypeDef->mSignatureHash != prevRevisionTypeDef->mSignatureHash) prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Signature_Changed; else if (mCurTypeDef->mInlineHash != prevRevisionTypeDef->mInlineHash) prevRevisionTypeDef->mDefState = BfTypeDef::DefState_InlinedInternals_Changed; else - prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Internals_Changed; + prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Internals_Changed; } // There's a new type with this name... diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 6c63e97a..324c70a2 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -109,6 +109,7 @@ public: DependencyFlag_NameReference = 0x400000, DependencyFlag_VirtualCall = 0x800000, DependencyFlag_WeakReference = 0x1000000, // Keeps alive but won't rebuild + DependencyFlag_ConstEval = 0x2000000, DependencyFlag_DependentUsageMask = ~(DependencyFlag_UnspecializedType | DependencyFlag_MethodGenericArg | DependencyFlag_GenericArgRef) }; @@ -127,6 +128,7 @@ public: public: typedef Dictionary TypeMap; + DependencyFlags mFlagsUnion; TypeMap mTypeSet; int mMinDependDepth; @@ -134,6 +136,7 @@ public: BfDependencyMap() { mMinDependDepth = 0; + mFlagsUnion = DependencyFlag_None; } bool AddUsedBy(BfType* dependentType, DependencyFlags flags); @@ -401,16 +404,17 @@ enum BfTypeRebuildFlags BfTypeRebuildFlag_NonStaticChange = 2, BfTypeRebuildFlag_MethodInlineInternalsChange = 4, BfTypeRebuildFlag_MethodSignatureChange = 8, - BfTypeRebuildFlag_DeleteQueued = 0x10, - BfTypeRebuildFlag_Deleted = 0x20, - BfTypeRebuildFlag_AddedToWorkList = 0x40, - BfTypeRebuildFlag_AwaitingReference = 0x80, - BfTypeRebuildFlag_SpecializedMethodRebuild = 0x100, // Temporarily set - BfTypeRebuildFlag_SpecializedByAutocompleteMethod = 0x200, - BfTypeRebuildFlag_UnderlyingTypeDeferred = 0x400, - BfTypeRebuildFlag_TypeDataSaved = 0x800, - BfTypeRebuildFlag_InTempPool = 0x1000, - BfTypeRebuildFlag_ResolvingBase = 0x2000 + BfTypeRebuildFlag_ConstEvalChange = 0x10, + BfTypeRebuildFlag_DeleteQueued = 0x20, + BfTypeRebuildFlag_Deleted = 0x40, + BfTypeRebuildFlag_AddedToWorkList = 0x80, + BfTypeRebuildFlag_AwaitingReference = 0x100, + BfTypeRebuildFlag_SpecializedMethodRebuild = 0x200, // Temporarily set + BfTypeRebuildFlag_SpecializedByAutocompleteMethod = 0x400, + BfTypeRebuildFlag_UnderlyingTypeDeferred = 0x800, + BfTypeRebuildFlag_TypeDataSaved = 0x1000, + BfTypeRebuildFlag_InTempPool = 0x2000, + BfTypeRebuildFlag_ResolvingBase = 0x4000 }; class BfTypeDIReplaceCallback; @@ -1820,7 +1824,7 @@ public: bool mIsFinishingType; bool mHasPackingHoles; bool mWantsGCMarking; - bool mHasDeclError; + bool mHasDeclError; public: BfTypeInstance() diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index 94c6a82a..6bce4b36 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -3053,6 +3053,8 @@ void BfSystem::FinishCompositePartial(BfTypeDef* compositeTypeDef) compositeTypeDef->mDefState = BfTypeDef::DefState_InlinedInternals_Changed; else if ((nextRevision->mDefState == BfTypeDef::DefState_Internals_Changed) || (compositeTypeDef->mFullHash != nextRevision->mFullHash)) compositeTypeDef->mDefState = BfTypeDef::DefState_Internals_Changed; + else if (nextRevision->mDefState == BfTypeDef::DefState_Refresh) + compositeTypeDef->mDefState = BfTypeDef::DefState_Refresh; //InjectNewRevision(compositeTypeDef); VerifyTypeDef(compositeTypeDef); diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index c2f83db9..9ecb2b82 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -908,6 +908,7 @@ public: DefState_Signature_Changed, DefState_InlinedInternals_Changed, // Code within methods, including inlined methods, changed DefState_Internals_Changed, // Only code within a non-inlined methods changed + DefState_Refresh, DefState_Deleted }; diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index 1a32d9c6..115c4fc2 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -2630,6 +2630,7 @@ CeMachine::CeMachine(BfCompiler* compiler) mCurFunctionId = 0; mRevisionExecuteTime = 0; mCurTargetSrc = NULL; + mCurCEFunction = NULL; mCurModule = NULL; mCurMethodInstance = NULL; mCurExpectingType = NULL; @@ -5243,6 +5244,7 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder) { AutoTimer autoTimer(mRevisionExecuteTime); + SetAndRestoreValue prevCEFunction(mCurCEFunction, ceFunction); if (mHeap == NULL) mHeap = new ContiguousHeap(); @@ -5441,7 +5443,10 @@ CeFunction* CeMachine::GetPreparedFunction(BfMethodInstance* methodInstance) } void CeMachine::QueueMethod(BfMethodInstance* methodInstance, BfIRValue func) -{ +{ + auto curOwner = mCurCEFunction->mMethodInstance->GetOwner(); + curOwner->mModule->AddDependency(methodInstance->GetOwner(), curOwner, BfDependencyMap::DependencyFlag_ConstEval); + bool added = false; auto ceFunction = GetFunction(methodInstance, func, added); } @@ -5738,5 +5743,7 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns mStaticFieldMap.Clear(); mHeap->Clear(BF_CE_MAX_CARRYOVER_HEAP); + module->AddDependency(methodInstance->GetOwner(), module->mCurTypeInstance, BfDependencyMap::DependencyFlag_ConstEval); + return returnValue; } diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index 6d53c964..f654e663 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -627,6 +627,7 @@ public: HashSet mStaticCtorExecSet; CeAppendAllocInfo* mAppendAllocInfo; + CeFunction* mCurCEFunction; BfAstNode* mCurTargetSrc; BfMethodInstance* mCurMethodInstance; BfModule* mCurModule;