diff --git a/IDE/src/ui/SourceViewPanel.bf b/IDE/src/ui/SourceViewPanel.bf index 64b3692a..387a0b04 100644 --- a/IDE/src/ui/SourceViewPanel.bf +++ b/IDE/src/ui/SourceViewPanel.bf @@ -1916,7 +1916,7 @@ namespace IDE.ui //mProcessResolveCharIdSpan.Dispose(); resolveParams.mCancelled = true; - if (resolveType == ResolveType.ClassifyFullRefresh) + if ((resolveType == ResolveType.Classify) || (resolveType == ResolveType.ClassifyFullRefresh)) { QueueFullRefresh(false); } diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index b8ecc72f..b5e5e702 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -346,6 +346,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) memset(&mStats, 0, sizeof(mStats)); mCompletionPct = 0; mCanceling = false; + mNeedsFullRefresh = false; mFastFinish = false; mHasQueuedTypeRebuilds = false; mIsResolveOnly = isResolveOnly; @@ -7396,6 +7397,12 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mContext->ValidateDependencies(); + if (mNeedsFullRefresh) + { + mNeedsFullRefresh = false; + return false; + } + return !didCancel && !mHasQueuedTypeRebuilds; } diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index ef2f36f6..24aba505 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -323,6 +323,7 @@ public: BfCodeGen mCodeGen; String mOutputDirectory; bool mCanceling; + bool mNeedsFullRefresh; bool mFastFinish; bool mHasQueuedTypeRebuilds; // Infers we had a fast finish that requires a type rebuild bool mHadCancel; diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index a398ca06..d4b81a39 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -829,7 +829,8 @@ void BfContext::ValidateDependencies() void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuildModule, bool placeSpecializiedInPurgatory) { BfTypeInstance* typeInst = type->ToTypeInstance(); - + + if (type->IsDeleting()) { return; @@ -865,7 +866,7 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild return; } - + // We need to verify lookups before we rebuild the type, because a type lookup change needs to count as a TypeDataChanged VerifyTypeLookups(typeInst); @@ -1136,7 +1137,12 @@ void BfContext::TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChang { auto dependentType = depItr.mKey; auto dependencyFlags = depItr.mValue.mFlags; - + + if (dependentType->mRevision == mCompiler->mRevision) + { + continue; + } + auto dependentDType = dependentType->ToDependedType(); if (dependentDType != NULL) { @@ -1218,6 +1224,11 @@ void BfContext::TypeMethodSignaturesChanged(BfTypeInstance* typeInst) auto dependentType = depItr.mKey; auto dependencyFlags = depItr.mValue.mFlags; + if (dependentType->mRevision == mCompiler->mRevision) + { + continue; + } + // We don't need to cascade rebuilding for method-based usage - just rebuild the type directly (unlike TypeDataChanged, which cascades) if ((dependencyFlags & BfDependencyMap::DependencyFlag_Calls) || (dependencyFlags & BfDependencyMap::DependencyFlag_VirtualCall) || diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index fc0897d4..7082afd3 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -18163,6 +18163,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) SetAndRestoreValue prevFilePos(mCurFilePosition); SetAndRestoreValue prevHadBuildError(mHadBuildError, false); SetAndRestoreValue prevHadWarning(mHadBuildWarning, false); + SetAndRestoreValue prevIgnoreErrors(mIgnoreErrors); SetAndRestoreValue prevIgnoreWarnings(mIgnoreWarnings, mIsComptimeModule); if ((methodInstance->mIsReified) && @@ -19810,6 +19811,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } DoCEEmit(methodInstance); + if (methodInstance->mCeCancelled) + mIgnoreErrors = true; if (auto fieldDtorBody = BfNodeDynCast(methodDef->mBody)) { diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 90e2af06..c1a4f780 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -2042,15 +2042,47 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* // We populated before we could finish AssertErrorState(); } - else if (!ceEmitContext->mEmitData.IsEmpty()) + else { - String ctxStr = "comptime ApplyToType of "; - ctxStr += TypeToString(attrType); - ctxStr += " to "; - ctxStr += TypeToString(typeInstance); - ctxStr += " "; - ctxStr += customAttribute.mRef->LocationToString(); - UpdateCEEmit(ceEmitContext, typeInstance, typeInstance->mTypeDef, ctxStr, customAttribute.mRef); + auto owner = methodInstance->GetOwner(); + int typeId = owner->mTypeId; + if ((!result) && (mCompiler->mFastFinish)) + { + if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext == NULL)) + typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo(); + if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext != NULL)) + typeInstance->mCeTypeInfo->mNext->mFailed = true; + if (typeInstance->mCeTypeInfo != NULL) + { + BfCeTypeEmitEntry* entry = NULL; + if (typeInstance->mCeTypeInfo->mTypeIFaceMap.TryGetValue(typeId, &entry)) + { + ceEmitContext->mEmitData = entry->mEmitData; + } + } + } + else if (!ceEmitContext->mEmitData.IsEmpty()) + { + if (typeInstance->mCeTypeInfo == NULL) + typeInstance->mCeTypeInfo = new BfCeTypeInfo(); + if (typeInstance->mCeTypeInfo->mNext == NULL) + typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo(); + + BfCeTypeEmitEntry entry; + entry.mEmitData = ceEmitContext->mEmitData; + typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap[typeId] = entry; + } + + if (!ceEmitContext->mEmitData.IsEmpty()) + { + String ctxStr = "comptime ApplyToType of "; + ctxStr += TypeToString(attrType); + ctxStr += " to "; + ctxStr += TypeToString(typeInstance); + ctxStr += " "; + ctxStr += customAttribute.mRef->LocationToString(); + UpdateCEEmit(ceEmitContext, typeInstance, typeInstance->mTypeDef, ctxStr, customAttribute.mRef); + } } mCompiler->mCEMachine->ReleaseContext(ceContext); @@ -2211,19 +2243,49 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* auto methodInstance = GetRawMethodInstanceAtIdx(typeInstance, methodDef->mIdx); auto result = mCompiler->mCEMachine->Call(methodDef->GetRefNode(), this, methodInstance, {}, (CeEvalFlags)(CeEvalFlags_PersistantError | CeEvalFlags_DeferIfNotOnlyError), NULL); - + if (typeInstance->mDefineState != BfTypeDefineState_CETypeInit) { // We populated before we could finish AssertErrorState(); } - else if (!ceEmitContext->mEmitData.IsEmpty()) - { - String ctxStr = "OnCompile execution of "; - ctxStr += MethodToString(methodInstance); - ctxStr += " "; - ctxStr += methodInstance->mMethodDef->GetRefNode()->LocationToString(); - UpdateCEEmit(ceEmitContext, typeInstance, methodInstance->mMethodDef->mDeclaringType, ctxStr, methodInstance->mMethodDef->GetRefNode()); + else + { + if ((!result) && (mCompiler->mFastFinish)) + { + if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext == NULL)) + typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo(); + if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext != NULL)) + typeInstance->mCeTypeInfo->mNext->mFailed = true; + if (typeInstance->mCeTypeInfo != NULL) + { + BfCeTypeEmitEntry* entry = NULL; + if (typeInstance->mCeTypeInfo->mOnCompileMap.TryGetValue(methodDef->mIdx, &entry)) + { + ceEmitContext->mEmitData = entry->mEmitData; + } + } + } + else if (!ceEmitContext->mEmitData.IsEmpty()) + { + if (typeInstance->mCeTypeInfo == NULL) + typeInstance->mCeTypeInfo = new BfCeTypeInfo(); + if (typeInstance->mCeTypeInfo->mNext == NULL) + typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo(); + + BfCeTypeEmitEntry entry; + entry.mEmitData = ceEmitContext->mEmitData; + typeInstance->mCeTypeInfo->mNext->mOnCompileMap[methodDef->mIdx] = entry; + } + + if (!ceEmitContext->mEmitData.IsEmpty()) + { + String ctxStr = "OnCompile execution of "; + ctxStr += MethodToString(methodInstance); + ctxStr += " "; + ctxStr += methodInstance->mMethodDef->GetRefNode()->LocationToString(); + UpdateCEEmit(ceEmitContext, typeInstance, methodInstance->mMethodDef->mDeclaringType, ctxStr, methodInstance->mMethodDef->GetRefNode()); + } } if (mCompiler->mCanceling) @@ -2241,9 +2303,9 @@ void BfModule::DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers) int startFieldCount = typeInstance->mTypeDef->mFields.mSize; int startPropCount = typeInstance->mTypeDef->mProperties.mSize; - CeEmitContext emitContext; - emitContext.mType = typeInstance; - ExecuteCEOnCompile(&emitContext, typeInstance, BfCEOnCompileKind_TypeInit); + CeEmitContext ceEmitContext; + ceEmitContext.mType = typeInstance; + ExecuteCEOnCompile(&ceEmitContext, typeInstance, BfCEOnCompileKind_TypeInit); if ((startMethodCount != typeInstance->mTypeDef->mMethods.mSize) || (startFieldCount != typeInstance->mTypeDef->mFields.mSize) || @@ -2306,6 +2368,11 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance) auto activeTypeDef = typeInstance->mTypeDef; auto result = ceContext->Call(customAttribute.mRef, this, applyMethodInstance, args, CeEvalFlags_None, NULL); + if ((!result) && (mCompiler->mFastFinish)) + { + methodInstance->mCeCancelled = true; + } + if ((!ceEmitContext.mEmitData.IsEmpty()) || (!ceEmitContext.mExitEmitData.IsEmpty())) { String src; @@ -3711,6 +3778,45 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit) typeInstance->mDefineState = BfTypeDefineState_CEPostTypeInit; + if (typeInstance->mCeTypeInfo != NULL) + { + if (typeInstance->mCeTypeInfo->mNext != NULL) + { + auto ceInfo = typeInstance->mCeTypeInfo->mNext; + HashContext hashCtx; + hashCtx.Mixin(ceInfo->mOnCompileMap.mCount); + for (auto& kv : ceInfo->mOnCompileMap) + { + hashCtx.Mixin(kv.mKey); + hashCtx.MixinStr(kv.mValue.mEmitData); + } + hashCtx.Mixin(ceInfo->mTypeIFaceMap.mCount); + for (auto& kv : ceInfo->mTypeIFaceMap) + { + hashCtx.Mixin(kv.mKey); + hashCtx.MixinStr(kv.mValue.mEmitData); + } + + typeInstance->mCeTypeInfo->mNext->mHash = hashCtx.Finish128(); + + if (!typeInstance->mCeTypeInfo->mNext->mFailed) + { + if ((typeInstance->mCeTypeInfo->mHash != typeInstance->mCeTypeInfo->mNext->mHash) && (!typeInstance->mCeTypeInfo->mHash.IsZero())) + { + if (mCompiler->mIsResolveOnly) + mCompiler->mNeedsFullRefresh = true; + mContext->RebuildDependentTypes(typeInstance); + } + typeInstance->mCeTypeInfo->mOnCompileMap = typeInstance->mCeTypeInfo->mNext->mOnCompileMap; + typeInstance->mCeTypeInfo->mTypeIFaceMap = typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap; + typeInstance->mCeTypeInfo->mHash = typeInstance->mCeTypeInfo->mNext->mHash; + } + + delete typeInstance->mCeTypeInfo->mNext; + typeInstance->mCeTypeInfo->mNext = NULL; + } + } + if (hadNewMembers) { typeInstance->mTypeDef->mHasEmitMembers = true; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 8d47d964..b8ad2a5a 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -1539,6 +1539,7 @@ BfTypeInstance::~BfTypeInstance() ReleaseData(); delete mTypeInfoEx; delete mGenericTypeInfo; + delete mCeTypeInfo; delete mCustomAttributes; delete mAttributeData; for (auto methodInst : mInternalMethods) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index ce966df6..7cc8a9bc 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -396,7 +396,6 @@ public: class BfDependedType; class BfTypeInstance; -class BfTypeInstance; class BfPrimitiveType; enum BfTypeRebuildFlags @@ -839,6 +838,7 @@ public: bool mDisallowCalling:1; bool mIsInnerOverride:1; bool mInCEMachine:1; + bool mCeCancelled:1; bool mIsDisposed:1; BfMethodChainType mChainType; BfComptimeFlags mComptimeFlags; @@ -879,6 +879,7 @@ public: mDisallowCalling = false; mIsInnerOverride = false; mInCEMachine = false; + mCeCancelled = false; mIsDisposed = false; mChainType = BfMethodChainType_None; mComptimeFlags = BfComptimeFlag_None; @@ -1787,6 +1788,28 @@ public: void ReportMemory(MemReporter* memReporter); }; +class BfCeTypeEmitEntry +{ +public: + String mEmitData; +}; + +class BfCeTypeInfo +{ +public: + Dictionary mOnCompileMap; + Dictionary mTypeIFaceMap; + Val128 mHash; + bool mFailed; + BfCeTypeInfo* mNext; + +public: + BfCeTypeInfo() + { + mFailed = false; + mNext = NULL; + } +}; // Instance of struct or class class BfTypeInstance : public BfDependedType @@ -1804,6 +1827,7 @@ public: BfAttributeData* mAttributeData; BfTypeInfoEx* mTypeInfoEx; BfGenericTypeInfo* mGenericTypeInfo; + BfCeTypeInfo* mCeTypeInfo; Array mInterfaces; Array mInterfaceMethodTable; @@ -1876,6 +1900,7 @@ public: mAttributeData = NULL; mTypeInfoEx = NULL; mGenericTypeInfo = NULL; + mCeTypeInfo = NULL; //mClassVData = NULL; mVirtualMethodTableSize = 0; mHotTypeData = NULL;