Преглед изворни кода

Fixed hot vtable index adjustment with override

Brian Fiete пре 6 месеци
родитељ
комит
45ff0b341b

+ 13 - 0
IDE/Tests/Test1/scripts/HotSwap_Virtual02.txt

@@ -0,0 +1,13 @@
+ShowFile("src/HotSwap_Virtuals02.bf")
+GotoText("//Test_Start")
+ToggleBreakpoint()
+RunWithCompiling()
+StepOver()
+
+ToggleCommentAt("ClassA_GetVal01")
+Compile()
+StepOver()
+
+ToggleCommentAt("ClassB_GetVal04")
+Compile()
+StepOver()

+ 67 - 0
IDE/Tests/Test1/src/HotSwap_Virtuals02.bf

@@ -0,0 +1,67 @@
+using System;
+#pragma warning disable 168
+
+namespace IDETest;
+
+
+
+class Virtuals02
+{
+	class ClassA
+	{
+		public virtual int GetVal01() => 100;
+		public
+			/*ClassA_GetVal01
+			virtual
+			*/
+			int GetVal02() => 200;
+		public virtual int GetVal03() => 300;
+	}
+
+	class ClassB : ClassA
+	{
+		public override int GetVal03()
+		{
+			return 301;
+		}
+		public virtual int GetVal04() => 400;
+		public
+			/*ClassB_GetVal04
+			virtual
+			*/
+			int GetVal05() => 500;
+	}
+
+	static void TestFuncs()
+	{
+		ClassA ca = scope .();
+		ClassB cb = scope .();
+		int val;
+
+		void** funcs = (.)(void*)(cb.[Friend]mClassVData & ~0xFF);
+		int valA1 = ca.GetVal01();
+		
+		int valA2 = ca.GetVal02();
+		int valB1 = cb.GetVal01();
+		int valB2 = cb.GetVal02();
+		int valB3 = cb.GetVal03();
+		int valB4 = cb.GetVal04();
+		int valB5 = cb.GetVal05();
+
+		Runtime.Assert(valA1 == 100);
+		Runtime.Assert(valA2 == 200);
+		Runtime.Assert(valB1 == 100);
+		Runtime.Assert(valB2 == 200);
+		Runtime.Assert(valB3 == 301);
+		Runtime.Assert(valB4 == 400);
+		Runtime.Assert(valB5 == 500);
+	}
+
+	public static void Test()
+	{
+		//Test_Start
+		TestFuncs();
+		TestFuncs();
+		TestFuncs();
+	}
+}

+ 1 - 0
IDE/Tests/Test1/src/Program.bf

@@ -33,6 +33,7 @@ namespace IDETest
 			Unions.Test();
 			UsingFields.Test();
 			Virtuals.Test();
+			Virtuals02.Test();
 
 			Bug001.Test();
 			Bug002.Test();

+ 13 - 8
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -6799,20 +6799,25 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 					else
 					{
 						// Map this new virtual index back to the original index
-						//vDataIdx += (methodInstance->mVirtualTableIdx - typeInst->GetBaseVTableSize()) + typeInst->GetOrigBaseVTableSize();
-
-						//vDataIdx = mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 1 + methodInstance->GetOwner()->GetDynCastVDataCount() + mModule->mCompiler->mMaxInterfaceSlots);
+						
+						// Find the type instance that declared the original method
+						auto declTypeInst = typeInst;
+						while (declTypeInst->mBaseType != NULL)
+						{
+							mModule->PopulateType(declTypeInst->mBaseType, BfPopulateType_DataAndMethods);
+							if (methodInstance->mVirtualTableIdx >= declTypeInst->mBaseType->mVirtualMethodTableSize)
+								break;
+							BF_ASSERT(methodInstance->mMethodDef->mIsOverride);
+							declTypeInst = declTypeInst->mBaseType;							
+						}
 
 						vDataIdx = mModule->mBfIRBuilder->GetConfigConst(BfIRConfigConst_VirtualMethodOfs, BfTypeCode_Int32);
 						vDataIdx = mModule->mBfIRBuilder->CreateAdd(vDataIdx, mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32,
-							(methodInstance->mVirtualTableIdx - typeInst->GetImplBaseVTableSize()) + typeInst->GetOrigImplBaseVTableSize()));
+							(methodInstance->mVirtualTableIdx - declTypeInst->GetImplBaseVTableSize()) + declTypeInst->GetOrigImplBaseVTableSize()));
 					}
 				}
 				else
-				{
-					//vDataIdx += methodInstance->mVirtualTableIdx;
-
-					//vDataIdx = mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 1 + methodInstance->GetOwner()->GetDynCastVDataCount() + mModule->mCompiler->mMaxInterfaceSlots);
+				{					
 					vDataIdx = mModule->mBfIRBuilder->GetConfigConst(BfIRConfigConst_VirtualMethodOfs, BfTypeCode_Int32);
 					vDataIdx = mModule->mBfIRBuilder->CreateAdd(vDataIdx, mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, methodInstance->mVirtualTableIdx));
 				}