From 9972ff32abded6c364ea7eac6c0c4dcf6d21faf4 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Wed, 4 May 2022 06:40:26 -0700 Subject: [PATCH] Move mid-compile rebuild request into a work list --- IDEHelper/Compiler/BfCompiler.cpp | 4 + IDEHelper/Compiler/BfContext.cpp | 93 ++++++++++++++++++++---- IDEHelper/Compiler/BfContext.h | 8 ++ IDEHelper/Compiler/BfModule.cpp | 8 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 8 +- IDEHelper/Compiler/BfSystem.h | 11 +++ 6 files changed, 112 insertions(+), 20 deletions(-) diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index eb076579..7438110f 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -2592,7 +2592,11 @@ void BfCompiler::ProcessPurgatory(bool reifiedOnly) { auto module = type->GetModule(); if (module != NULL) + { + if (!module->mIsModuleMutable) + module->StartExtension(); module->PopulateType(type, BfPopulateType_Full); + } } if (reifiedOnly) diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index dc779256..0d26309e 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -382,6 +382,43 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods) didWork = true; } + // Do this before mPopulateTypeWorkList so we can populate any types that need rebuilding + // in the mPopulateTypeWorkList loop next - this is required for mFinishedModuleWorkList handling + for (int workIdx = 0; workIdx < (int)mMidCompileWorkList.size(); workIdx++) + { + //BP_ZONE("PWL_PopulateType"); + if (IsCancellingAndYield()) + break; + + auto workItemRef = mMidCompileWorkList[workIdx]; + if (workItemRef == NULL) + { + workIdx = mMidCompileWorkList.RemoveAt(workIdx); + continue; + } + + BfType* type = workItemRef->mType; + String reason = workItemRef->mReason; + + if ((onlyReifiedTypes) && (!type->IsReified())) + { + continue; + } + + auto typeInst = type->ToTypeInstance(); + if ((typeInst != NULL) && (resolveParser != NULL)) + { + if (!typeInst->mTypeDef->GetLatest()->HasSource(resolveParser)) + { + continue; + } + } + + workIdx = mMidCompileWorkList.RemoveAt(workIdx); + RebuildDependentTypes_MidCompile(type->ToDependedType(), reason); + didWork = true; + } + for (int workIdx = 0; workIdx < (int)mPopulateTypeWorkList.size(); workIdx++) { //BP_ZONE("PWL_PopulateType"); @@ -430,7 +467,7 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods) mCompiler->mStats.mQueuedTypesProcessed++; mCompiler->UpdateCompletion(); didWork = true; - } + } for (int workIdx = 0; workIdx < (int)mTypeRefVerifyWorkList.size(); workIdx++) { @@ -487,6 +524,9 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods) auto typeInst = methodSpecializationRequest.mType->ToTypeInstance(); + if (typeInst->IsDeleting()) + continue; + BfMethodDef* methodDef = NULL; if (methodSpecializationRequest.mForeignType != NULL) { @@ -529,10 +569,12 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods) auto module = workItem->mFromModule; auto methodInstance = workItem->mMethodInstance; - + bool wantProcessMethod = methodInstance != NULL; if ((workItem->mFromModuleRebuildIdx != -1) && (workItem->mFromModuleRebuildIdx != module->mRebuildIdx)) - wantProcessMethod = false; + wantProcessMethod = false; + else if (workItem->mType->IsDeleting()) + wantProcessMethod = false; if (methodInstance != NULL) BF_ASSERT(methodInstance->mMethodProcessRequest == workItem); @@ -710,6 +752,11 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods) dupMethodInstance.mInCEMachine = false; // Only have the original one BF_ASSERT(module->mIsReified); // We should only bother inlining in reified modules + bool wantProcessMethod = true; + if (owner->IsDeleting()) + wantProcessMethod = false; + + if (wantProcessMethod) { // These errors SHOULD be duplicates, but if we have no other errors at all then we don't ignoreErrors, which // may help unveil some kinds of compiler bugs @@ -1201,8 +1248,27 @@ void BfContext::RebuildDependentTypes(BfDependedType* dType) TypeMethodSignaturesChanged(typeInst); } +void BfContext::QueueMidCompileRebuildDependentTypes(BfDependedType* dType, const String& reason) +{ + BfLogSysM("QueueMidCompileRebuildDependentTypes Type:%p Reason:%s\n", dType, reason.c_str()); + + auto workEntry = mMidCompileWorkList.Alloc(); + workEntry->mType = dType; + workEntry->mReason = reason; +} + void BfContext::RebuildDependentTypes_MidCompile(BfDependedType* dType, const String& reason) { + BF_ASSERT(!dType->IsDeleting()); + auto module = dType->GetModule(); + if ((module != NULL) && (!module->mIsSpecialModule)) + { + BF_ASSERT(!module->mIsDeleting); + BF_ASSERT(!module->mOwnedTypeInstances.IsEmpty()); + } + + + dType->mRebuildFlags = (BfTypeRebuildFlags)(dType->mRebuildFlags | BfTypeRebuildFlag_ChangedMidCompile); int prevDeletedTypes = mCompiler->mStats.mTypesDeleted; if (mCompiler->mIsResolveOnly) @@ -1249,9 +1315,9 @@ bool BfContext::CanRebuild(BfType* type) // (obviously) doesn't change the data layout of ClassC // Calls: non-cascading dependency, since it's independent of data layout ConstValue: non-cascading data change void BfContext::TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChange) -{ +{ BfLogSysM("TypeDataChanged %p\n", dType); - + auto rebuildFlag = isNonStaticDataChange ? BfTypeRebuildFlag_NonStaticChange : BfTypeRebuildFlag_StaticChange; if ((dType->mRebuildFlags & rebuildFlag) != 0) // Already did this change? return; @@ -1345,7 +1411,7 @@ void BfContext::TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChang } void BfContext::TypeMethodSignaturesChanged(BfTypeInstance* typeInst) -{ +{ if (typeInst->mRebuildFlags & BfTypeRebuildFlag_MethodSignatureChange) // Already did change? return; typeInst->mRebuildFlags = (BfTypeRebuildFlags) (typeInst->mRebuildFlags | BfTypeRebuildFlag_MethodSignatureChange); @@ -1715,18 +1781,18 @@ void BfContext::DeleteType(BfType* type, bool deferDepRebuilds) BF_ASSERT(module->mOwnedTypeInstances.size() == 0); } else - { - auto itr = std::find(module->mOwnedTypeInstances.begin(), module->mOwnedTypeInstances.end(), typeInst); - module->mOwnedTypeInstances.erase(itr); + { + module->mOwnedTypeInstances.Remove(typeInst); if ((module->mOwnedTypeInstances.size() == 0) && (module != mScratchModule)) - { + { + BfLogSysM("Setting module mIsDeleting %p due to mOwnedTypeInstances being empty\n", module); + // This module is no longer needed module->RemoveModuleData(); module->mIsDeleting = true; - auto itr = std::find(mModules.begin(), mModules.end(), module); - mModules.erase(itr); - + mModules.Remove(module); + // This was only needed for 'zombie modules', which we don't need anymore? // To avoid linking errors. Used instead of directly removing from mModules. mDeletingModules.push_back(module); @@ -2980,6 +3046,7 @@ void BfContext::RemoveInvalidWorkItems() // so we're passing false in here now. Don't just switch it back and forth - find why 'false' was causing an issue. // Same with mMethodSpecializationWorkList DoRemoveInvalidWorkItems(this, mPopulateTypeWorkList, false); + DoRemoveInvalidWorkItems(this, mMidCompileWorkList, false); DoRemoveInvalidWorkItems(this, mMethodSpecializationWorkList, false/*true*/); DoRemoveInvalidWorkItems(this, mTypeRefVerifyWorkList, false); diff --git a/IDEHelper/Compiler/BfContext.h b/IDEHelper/Compiler/BfContext.h index fe7ef4bb..431ff94d 100644 --- a/IDEHelper/Compiler/BfContext.h +++ b/IDEHelper/Compiler/BfContext.h @@ -113,6 +113,12 @@ public: BfAstNode* mRefNode; }; +class BfMidCompileRequest : public BfWorkListEntry +{ +public: + String mReason; +}; + struct BfStringPoolEntry { String mString; @@ -397,6 +403,7 @@ public: WorkQueue mPopulateTypeWorkList; WorkQueue mMethodSpecializationWorkList; WorkQueue mTypeRefVerifyWorkList; + WorkQueue mMidCompileWorkList; PtrWorkQueue mFinishedSlotAwaitModuleWorkList; PtrWorkQueue mFinishedModuleWorkList; bool mHasReifiedQueuedRebuildTypes; @@ -476,6 +483,7 @@ public: void ValidateDependencies(); void RebuildType(BfType* type, bool deleteOnDemandTypes = true, bool rebuildModule = true, bool placeSpecializiedInPurgatory = true); void RebuildDependentTypes(BfDependedType* dType); + void QueueMidCompileRebuildDependentTypes(BfDependedType* dType, const String& reason); void RebuildDependentTypes_MidCompile(BfDependedType* dType, const String& reason); bool CanRebuild(BfType* type); void TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChange); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 3efceb0f..19841629 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -1225,8 +1225,8 @@ void BfModule::EnsureIRBuilder(bool dbgVerifyCodeGen) /*if (mCompiler->mIsResolveOnly) BF_ASSERT(mIsResolveOnly);*/ - mBfIRBuilder = new BfIRBuilder(this); + BfLogSysM("Created mBfIRBuilder %p in %p %s Reified: %d\n", mBfIRBuilder, this, mModuleName.c_str(), mIsReified); SetupIRBuilder(dbgVerifyCodeGen); } @@ -1509,8 +1509,10 @@ BfTypedValue BfModule::GetFakeTypedValue(BfType* type) // This is a conservative "IsValueless", since it's not an error to use a fakeVal even if we don't need one if (type->mSize == 0) return BfTypedValue(BfIRValue::sValueless, type); - else + else if (mBfIRBuilder != NULL) return BfTypedValue(mBfIRBuilder->GetFakeVal(), type); + else + return BfTypedValue(BfIRValue(BfIRValueFlags_Value, -1), type); } BfTypedValue BfModule::GetDefaultTypedValue(BfType* type, bool allowRef, BfDefaultValueKind defaultValueKind) @@ -25318,7 +25320,7 @@ void BfModule::ReportMemory(MemReporter* memReporter) // ClearModuleData is called immediately after the module is compiled, so don't clear out any data that needs to // be transient through the next compile void BfModule::ClearModuleData(bool clearTransientData) -{ +{ BfLogSysM("ClearModuleData %p\n", this); if (mAddedToCount) diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 6a5f3ddd..677bea45 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -286,7 +286,7 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef) auto genericExtensionInfo = genericTypeInst->mGenericTypeInfo->mGenericExtensionInfo; if ((extensionCount > 0) && (!prevConstraintsPassedSet.IsEmpty()) && (genericExtensionInfo->mConstraintsPassedSet != prevConstraintsPassedSet)) { - mContext->RebuildDependentTypes_MidCompile(genericTypeInst, "mConstraintsPassedSet changed"); + mContext->QueueMidCompileRebuildDependentTypes(genericTypeInst, "mConstraintsPassedSet changed"); } } else @@ -3114,7 +3114,7 @@ void BfModule::DoPopulateType_TypeAlias(BfTypeAliasType* typeAlias) aliasToType = NULL; if ((typeAlias->mAliasToType != NULL) && (typeAlias->mAliasToType != aliasToType) && (!typeAlias->mDependencyMap.IsEmpty())) - mContext->RebuildDependentTypes_MidCompile(typeAlias, "type alias remapped"); + mContext->QueueMidCompileRebuildDependentTypes(typeAlias, "type alias remapped"); typeAlias->mAliasToType = aliasToType; @@ -4792,7 +4792,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if (!typeInstance->mCeTypeInfo->mNext->mFailed) { if ((typeInstance->mCeTypeInfo->mHash != typeInstance->mCeTypeInfo->mNext->mHash) && (!typeInstance->mCeTypeInfo->mHash.IsZero())) - mContext->RebuildDependentTypes_MidCompile(typeInstance, "comptime hash changed"); + mContext->QueueMidCompileRebuildDependentTypes(typeInstance, "comptime hash changed"); typeInstance->mCeTypeInfo->mEmitSourceMap = typeInstance->mCeTypeInfo->mNext->mEmitSourceMap; typeInstance->mCeTypeInfo->mOnCompileMap = typeInstance->mCeTypeInfo->mNext->mOnCompileMap; typeInstance->mCeTypeInfo->mTypeIFaceMap = typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap; @@ -4806,7 +4806,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy { // Removed emissions if (!typeInstance->mCeTypeInfo->mHash.IsZero()) - mContext->RebuildDependentTypes_MidCompile(typeInstance, "comptime hash changed"); + mContext->QueueMidCompileRebuildDependentTypes(typeInstance, "comptime hash changed"); typeInstance->mCeTypeInfo->mEmitSourceMap.Clear(); typeInstance->mCeTypeInfo->mOnCompileMap.Clear(); typeInstance->mCeTypeInfo->mTypeIFaceMap.Clear(); diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index 77ea3128..69cde81a 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -1833,6 +1833,7 @@ public: #ifdef _DEBUG #ifdef BF_PLATFORM_WINDOWS +#define BF_WANTS_LOG_HI #define BF_WANTS_LOG #define BF_WANTS_LOG_SYS //#define BF_WANTS_LOG2 @@ -1843,7 +1844,9 @@ public: #endif #else +#define BF_WANTS_LOG_HI //#define BF_WANTS_LOG +//#define BF_WANTS_LOG_SYS //#define BF_WANTS_LOG2 //#define BF_WANTS_LOG_CLANG //#define BF_WANTS_LOG_DBGEXPR @@ -1866,6 +1869,14 @@ public: #define BfLogSysM(...) {} // Nothing #endif +#ifdef BF_WANTS_LOG_HI +#define BfLogSysHI(sys, fmt, ...) DoBfLog((sys)->mIsResolveOnly ? 1 : 2, fmt, ##__VA_ARGS__) +#define BfLogSysMHI(fmt, ...) DoBfLog(mSystem->mIsResolveOnly ? 1 : 2, fmt, ##__VA_ARGS__) +#else +#define BfLogSysHI(...) {} // Nothing +#define BfLogSysMHI(...) {} // Nothing +#endif + #ifdef BF_WANTS_LOG_CLANG //#define BfLogClang(fmt) DoBfLog(fmt) #define BfLogClang(fmt, ...) DoBfLog(0, fmt, ##__VA_ARGS__)