mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Use cached CE emission on fastFinish
This commit is contained in:
parent
8406e00a60
commit
afd5b29127
8 changed files with 178 additions and 24 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) ||
|
||||
|
|
|
@ -18163,6 +18163,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
SetAndRestoreValue<BfFilePosition> prevFilePos(mCurFilePosition);
|
||||
SetAndRestoreValue<bool> prevHadBuildError(mHadBuildError, false);
|
||||
SetAndRestoreValue<bool> prevHadWarning(mHadBuildWarning, false);
|
||||
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors);
|
||||
SetAndRestoreValue<bool> 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<BfFieldDtorDeclaration>(methodDef->mBody))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1539,6 +1539,7 @@ BfTypeInstance::~BfTypeInstance()
|
|||
ReleaseData();
|
||||
delete mTypeInfoEx;
|
||||
delete mGenericTypeInfo;
|
||||
delete mCeTypeInfo;
|
||||
delete mCustomAttributes;
|
||||
delete mAttributeData;
|
||||
for (auto methodInst : mInternalMethods)
|
||||
|
|
|
@ -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<int, BfCeTypeEmitEntry> mOnCompileMap;
|
||||
Dictionary<int, BfCeTypeEmitEntry> 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<BfTypeInterfaceEntry> mInterfaces;
|
||||
Array<BfTypeInterfaceMethodEntry> mInterfaceMethodTable;
|
||||
|
@ -1876,6 +1900,7 @@ public:
|
|||
mAttributeData = NULL;
|
||||
mTypeInfoEx = NULL;
|
||||
mGenericTypeInfo = NULL;
|
||||
mCeTypeInfo = NULL;
|
||||
//mClassVData = NULL;
|
||||
mVirtualMethodTableSize = 0;
|
||||
mHotTypeData = NULL;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue