1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00

Handled some method slotting reentrancy issues

This commit is contained in:
Brian Fiete 2021-08-02 10:44:39 -07:00
parent 879ac7f989
commit dd37d6c092
6 changed files with 55 additions and 21 deletions

View file

@ -838,7 +838,7 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
{ {
return; return;
} }
type->mDirty = true; type->mDirty = true;
bool wantDeleteType = (type->IsOnDemand()) && (deleteOnDemandTypes); bool wantDeleteType = (type->IsOnDemand()) && (deleteOnDemandTypes);
@ -870,6 +870,8 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
return; return;
} }
BF_ASSERT_REL(typeInst->mDefineState != BfTypeDefineState_DefinedAndMethodsSlotting);
// We need to verify lookups before we rebuild the type, because a type lookup change needs to count as a TypeDataChanged // We need to verify lookups before we rebuild the type, because a type lookup change needs to count as a TypeDataChanged
VerifyTypeLookups(typeInst); VerifyTypeLookups(typeInst);

View file

@ -3604,7 +3604,15 @@ void BfIRBuilder::CreateTypeDefinition(BfType* type, bool forceDbgDefine)
// isDefiningModule = true; // isDefiningModule = true;
if ((isDefiningModule) || (type->IsValueType())) if ((isDefiningModule) || (type->IsValueType()))
populateModule->PopulateType(type, BfPopulateType_DataAndMethods); {
if ((typeInstance != NULL) && (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotting))
{
// Don't re-enter
BfLogSys(mModule->mSystem, "BfIRBuilder::CreateTypeDefinition avoided PopulateType BfPopulateType_DataAndMethods re-entry typeInst: %p\n", typeInstance);
}
else
populateModule->PopulateType(type, BfPopulateType_DataAndMethods);
}
if ((!isDefiningModule) && (!type->IsUnspecializedType()) && (type->IsValueType()) && (mHasDebugInfo)) if ((!isDefiningModule) && (!type->IsUnspecializedType()) && (type->IsValueType()) && (mHasDebugInfo))
{ {

View file

@ -11079,8 +11079,10 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
BfTypeInstance* attrTypeInst = NULL; BfTypeInstance* attrTypeInst = NULL;
if (attrType == NULL) if (attrType == NULL)
continue; continue;
mContext->mUnreifiedModule->PopulateType(attrType, BfPopulateType_DataAndMethods);
attrTypeInst = attrType->ToTypeInstance(); attrTypeInst = attrType->ToTypeInstance();
if ((attrTypeInst != NULL) && (attrTypeInst->mDefineState != BfTypeDefineState_DefinedAndMethodsSlotting))
mContext->mUnreifiedModule->PopulateType(attrType, BfPopulateType_DataAndMethods);
if ((attrTypeInst == NULL) || (!TypeIsSubTypeOf(attrTypeInst, baseAttrTypeInst)) || (attrTypeInst->mAttributeData == NULL)) if ((attrTypeInst == NULL) || (!TypeIsSubTypeOf(attrTypeInst, baseAttrTypeInst)) || (attrTypeInst->mAttributeData == NULL))
{ {
Fail(StrFormat("'%s' is not an attribute class", TypeToString(attrType).c_str()), attributesDirective->mAttributeTypeRef); //CS0616 Fail(StrFormat("'%s' is not an attribute class", TypeToString(attrType).c_str()), attributesDirective->mAttributeTypeRef); //CS0616
@ -16315,8 +16317,8 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
addDeref = resolvedTypeRef->mSize; addDeref = resolvedTypeRef->mSize;
} }
else if ((methodInstance->WantsStructsAttribByVal()) && (!resolvedTypeRef->IsSizedArray())) else if ((methodInstance->WantsStructsAttribByVal()) && (!resolvedTypeRef->IsSizedArray()))
{ {
mBfIRBuilder->PopulateType(resolvedTypeRef); mBfIRBuilder->PopulateType(resolvedTypeRef, BfIRPopulateType_Full);
BF_ASSERT(resolvedTypeRef->mAlign > 0); BF_ASSERT(resolvedTypeRef->mAlign > 0);
mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_ByVal, mSystem->mPtrSize); mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_ByVal, mSystem->mPtrSize);
} }
@ -23546,7 +23548,7 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
} }
} }
} }
if (doesMethodSignatureMatch) if (doesMethodSignatureMatch)
{ {
usedMethod = true; usedMethod = true;
@ -23587,15 +23589,15 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
storeIFaceMethod = isBetter; storeIFaceMethod = isBetter;
} }
} }
} }
if (storeIFaceMethod) if (storeIFaceMethod)
{ {
if (methodInstance->GetNumGenericParams() != 0) if (methodInstance->GetNumGenericParams() != 0)
_AddVirtualDecl(iMethodInst); _AddVirtualDecl(iMethodInst);
*iMethodPtr = methodInstance; *iMethodPtr = methodInstance;
} }
checkMethodDef = checkMethodDef->mNextWithSameName; checkMethodDef = checkMethodDef->mNextWithSameName;
} }

View file

@ -4426,7 +4426,9 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
CheckAddFailType(); CheckAddFailType();
BfLogSysM("Setting mNeedsMethodProcessing on %p\n", typeInstance); BF_ASSERT_REL(typeInstance->mDefineState != BfTypeDefineState_DefinedAndMethodsSlotting);
BfLogSysM("Setting mNeedsMethodProcessing=true on %p\n", typeInstance);
typeInstance->mNeedsMethodProcessing = true; typeInstance->mNeedsMethodProcessing = true;
typeInstance->mIsFinishingType = false; typeInstance->mIsFinishingType = false;
@ -4830,7 +4832,17 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
{ {
if (typeInstance->IsSpecializedByAutoCompleteMethod()) if (typeInstance->IsSpecializedByAutoCompleteMethod())
return; return;
if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotting)
{
BfLogSysM("DoTypeInstanceMethodProcessing %p re-entrancy exit\n", typeInstance);
return;
}
BF_ASSERT_REL(typeInstance->mNeedsMethodProcessing);
BF_ASSERT_REL(typeInstance->mDefineState == BfTypeDefineState_Defined);
typeInstance->mDefineState = BfTypeDefineState_DefinedAndMethodsSlotting;
BF_ASSERT(typeInstance->mModule == this); BF_ASSERT(typeInstance->mModule == this);
//TODO: This is new, make sure this is in the right place //TODO: This is new, make sure this is in the right place
@ -4839,9 +4851,9 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
AutoDisallowYield disableYield(mSystem); AutoDisallowYield disableYield(mSystem);
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance); SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL); SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
BfLogSysM("DoTypeInstanceMethodProcessing: %p %s Revision:%d\n", typeInstance, TypeToString(typeInstance).c_str(), typeInstance->mRevision); BfLogSysM("DoTypeInstanceMethodProcessing: %p %s Revision:%d DefineState:%d\n", typeInstance, TypeToString(typeInstance).c_str(), typeInstance->mRevision, typeInstance->mDefineState);
auto typeDef = typeInstance->mTypeDef; auto typeDef = typeInstance->mTypeDef;
@ -4929,7 +4941,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
// Reserve empty entries // Reserve empty entries
for (int methodIdx = 0; methodIdx < (int)interfaceTypeDef->mMethods.size(); methodIdx++) for (int methodIdx = 0; methodIdx < (int)interfaceTypeDef->mMethods.size(); methodIdx++)
typeInstance->mInterfaceMethodTable.push_back(BfTypeInterfaceMethodEntry()); typeInstance->mInterfaceMethodTable.push_back(BfTypeInterfaceMethodEntry());
} }
} }
@ -5288,6 +5300,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
} }
} }
BF_ASSERT_REL(typeInstance->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted);
BfLogSysM("Starting DoTypeInstanceMethodProcessing %p GetMethodInstance pass. OnDemandMethods: %d\n", typeInstance, mOnDemandMethodCount); BfLogSysM("Starting DoTypeInstanceMethodProcessing %p GetMethodInstance pass. OnDemandMethods: %d\n", typeInstance, mOnDemandMethodCount);
// Def passes. First non-overrides then overrides (for in-place overrides in methods) // Def passes. First non-overrides then overrides (for in-place overrides in methods)
@ -5721,7 +5734,8 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
auto checkIFaceMethodInst = checkIFaceInst->mMethodInstanceGroups[checkIMethodIdx].mDefault; auto checkIFaceMethodInst = checkIFaceInst->mMethodInstanceGroups[checkIMethodIdx].mDefault;
if ((checkIFaceMethodInst != NULL) && (checkIFaceMethodInst->mMethodDef->mIsOverride)) if ((checkIFaceMethodInst != NULL) && (checkIFaceMethodInst->mMethodDef->mIsOverride))
{ {
if (CompareMethodSignatures(checkIFaceMethodInst, ifaceMethodInst)) bool cmpResult = CompareMethodSignatures(checkIFaceMethodInst, ifaceMethodInst);
if (cmpResult)
{ {
bool isBetter = TypeIsSubTypeOf(checkIFaceInst, bestInterface); bool isBetter = TypeIsSubTypeOf(checkIFaceInst, bestInterface);
bool isWorse = TypeIsSubTypeOf(bestInterface, checkIFaceInst); bool isWorse = TypeIsSubTypeOf(bestInterface, checkIFaceInst);
@ -5819,6 +5833,8 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
methodString = MethodToString(ifaceMethodInst); methodString = MethodToString(ifaceMethodInst);
} }
OutputDebugStrF("Failed in %s %p\n", mModuleName.c_str(), this);
BfTypeDeclaration* typeDecl = declTypeDef->mTypeDeclaration; BfTypeDeclaration* typeDecl = declTypeDef->mTypeDeclaration;
BfError* error = Fail(StrFormat("'%s' does not implement interface member '%s'", TypeToString(typeInstance).c_str(), methodString.c_str()), typeDecl->mNameNode, true); BfError* error = Fail(StrFormat("'%s' does not implement interface member '%s'", TypeToString(typeInstance).c_str(), methodString.c_str()), typeDecl->mNameNode, true);
if ((matchedMethod != NULL) && (error != NULL)) if ((matchedMethod != NULL) && (error != NULL))
@ -5880,7 +5896,9 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
mCompiler->mStats.mTypesPopulated++; mCompiler->mStats.mTypesPopulated++;
mCompiler->UpdateCompletion(); mCompiler->UpdateCompletion();
BfLogSysM("Finished DoTypeInstanceMethodProcessing %p. OnDemandMethods: %d Virtual Size: %d\n", typeInstance, mOnDemandMethodCount, typeInstance->mVirtualMethodTable.size()); BF_ASSERT_REL(!typeInstance->mNeedsMethodProcessing);
BfLogSysM("Finished DoTypeInstanceMethodProcessing %p. OnDemandMethods: %d Virtual Size: %d InterfaceMethodTableSize: %d\n", typeInstance, mOnDemandMethodCount, typeInstance->mVirtualMethodTable.size(), typeInstance->mInterfaceMethodTable.size());
} }
void BfModule::RebuildMethods(BfTypeInstance* typeInstance) void BfModule::RebuildMethods(BfTypeInstance* typeInstance)
@ -5888,6 +5906,9 @@ void BfModule::RebuildMethods(BfTypeInstance* typeInstance)
if (typeInstance->IsIncomplete()) if (typeInstance->IsIncomplete())
return; return;
BfLogSysM("RebuildMethods setting mNeedsMethodProcessing=true on %p\n", typeInstance);
BF_ASSERT_REL(typeInstance->mDefineState != BfTypeDefineState_DefinedAndMethodsSlotting);
typeInstance->mNeedsMethodProcessing = true; typeInstance->mNeedsMethodProcessing = true;
typeInstance->mDefineState = BfTypeDefineState_Defined; typeInstance->mDefineState = BfTypeDefineState_Defined;
typeInstance->mTypeIncomplete = true; typeInstance->mTypeIncomplete = true;

View file

@ -436,6 +436,7 @@ enum BfTypeDefineState : uint8
BfTypeDefineState_CEPostTypeInit, BfTypeDefineState_CEPostTypeInit,
BfTypeDefineState_Defined, BfTypeDefineState_Defined,
BfTypeDefineState_CEAfterFields, BfTypeDefineState_CEAfterFields,
BfTypeDefineState_DefinedAndMethodsSlotting,
BfTypeDefineState_DefinedAndMethodsSlotted, BfTypeDefineState_DefinedAndMethodsSlotted,
}; };

View file

@ -13,6 +13,9 @@
#include "BeefySysLib/util/AllocDebug.h" #include "BeefySysLib/util/AllocDebug.h"
#define STB_SPRINTF_DECORATE(name) BF_stbsp_##name
#include "../../third_party/stb/stb_sprintf.h"
USING_NS_BF; USING_NS_BF;
using namespace llvm; using namespace llvm;
@ -64,11 +67,8 @@ void Beefy::DoBfLog(int fileIdx, const char* fmt ...)
va_list argList; va_list argList;
va_start(argList, fmt); va_start(argList, fmt);
#ifdef _WIN32
int numChars = _vsnprintf(lineStr + strOfs, maxChars, fmt, argList); int numChars = BF_stbsp_vsnprintf(lineStr + strOfs, maxChars, fmt, argList);
#else
int numChars = vsnprintf(lineStr+ strOfs, maxChars, fmt, argList);
#endif
if (numChars <= maxChars) if (numChars <= maxChars)
{ {
if (strOfs + numChars > 0) if (strOfs + numChars > 0)