private void CallInterface(Context context) { var call = context.Operand1; var method = call.Method; var result = context.Result; var thisPtr = context.Operand2; var operands = context.GetOperands(); Debug.Assert(method != null); operands.RemoveAt(0); Debug.Assert(method.DeclaringType.IsInterface); // FUTURE: This can be optimized to skip Method Definition lookup. // Offset to MethodTable from thisPtr var typeDefOffset = CreateConstant32(-NativePointerSize); // Offset for InterfaceSlotTable in TypeDef/MethodTable var interfaceSlotTableOffset = CreateConstant32(NativePointerSize * 11); // Offset for InterfaceMethodTable in InterfaceSlotTable var interfaceMethodTableOffset = CreateConstant32(CalculateInterfaceSlotOffset(method)); // Offset for Method Def in InterfaceMethodTable var methodDefinitionOffset = CreateConstant32(CalculateInterfaceMethodTableOffset(method)); // Offset for Method pointer in MethodDef var methodPointerOffset = CreateConstant32(NativePointerSize * 4); // Operands to hold pointers var typeDef = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer); var callTarget = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer); var interfaceSlotPtr = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer); var interfaceMethodTablePtr = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer); var methodDefinition = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer); // Get the MethodTable pointer context.SetInstruction(LoadInstruction, typeDef, thisPtr, typeDefOffset); // Get the InterfaceSlotTable pointer context.AppendInstruction(LoadInstruction, interfaceSlotPtr, typeDef, interfaceSlotTableOffset); // Get the InterfaceMethodTable pointer context.AppendInstruction(LoadInstruction, interfaceMethodTablePtr, interfaceSlotPtr, interfaceMethodTableOffset); // Get the MethodDef pointer context.AppendInstruction(LoadInstruction, methodDefinition, interfaceMethodTablePtr, methodDefinitionOffset); // Get the address of the method context.AppendInstruction(LoadInstruction, callTarget, methodDefinition, methodPointerOffset); MakeCall(context, callTarget, result, operands, method); MethodScanner.InterfaceMethodInvoked(method, Method); }
private void CallInterface(InstructionNode node) { var call = node.Operand1; var method = call.Method; var result = node.Result; var thisPtr = node.Operand2; var operands = node.GetOperands(); Debug.Assert(method != null); operands.RemoveAt(0); var typeDefinition = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer); var callTarget = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer); Debug.Assert(method.DeclaringType.IsInterface); // Offset for InterfaceSlotTable in TypeDef int interfaceSlotTableOffset = (NativePointerSize * 11); // Offset for InterfaceMethodTable in InterfaceSlotTable int interfaceMethodTableOffset = (NativePointerSize * 1) + CalculateInterfaceSlotOffset(method); // Offset for MethodDef in InterfaceMethodTable int methodDefinitionOffset = (NativePointerSize * 2) + CalculateMethodTableOffset(method); // Offset for Method pointer in MethodDef int methodPointerOffset = (NativePointerSize * 4); // Operands to hold pointers var interfaceSlotPtr = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer); var interfaceMethodTablePtr = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer); var methodDefinition = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer); var context = new Context(node); // Get the TypeDef pointer context.SetInstruction(loadInstruction, typeDefinition, thisPtr, ConstantZero); // Get the Interface Slot Table pointer context.AppendInstruction(loadInstruction, interfaceSlotPtr, typeDefinition, CreateConstant(interfaceSlotTableOffset)); // Get the Interface Method Table pointer context.AppendInstruction(loadInstruction, interfaceMethodTablePtr, interfaceSlotPtr, CreateConstant(interfaceMethodTableOffset)); // Get the MethodDef pointer context.AppendInstruction(loadInstruction, methodDefinition, interfaceMethodTablePtr, CreateConstant(methodDefinitionOffset)); // Get the address of the method context.AppendInstruction(loadInstruction, callTarget, methodDefinition, CreateConstant(methodPointerOffset)); MakeCall(context, callTarget, result, operands); MethodScanner.InterfaceMethodInvoked(method, Method); }