private void CallVirtual(Context context) { var call = context.Operand1; var result = context.Result; var method = call.Method; var thisPtr = context.Operand2; var operands = context.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); // Same as above except for methodPointer int methodPointerOffset = CalculateMethodTableOffset(method) + (NativePointerSize * 14); // Get the TypeDef pointer context.SetInstruction(loadInstruction, typeDefinition, thisPtr, ConstantZero); // Get the address of the method context.AppendInstruction(loadInstruction, callTarget, typeDefinition, CreateConstant(methodPointerOffset)); MakeCall(context, callTarget, result, operands); MethodScanner.MethodInvoked(method, Method); }
private void CallVirtual(InstructionNode node) { var method = node.Operand1.Method; // Next lines are not necessary but faster then getting the method data if (!method.HasImplementation && method.IsAbstract) { return; } var methodData = MethodCompiler.Compiler.GetMethodData(method); if (!methodData.IsDevirtualized) { return; } var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem); var operands = node.GetOperands(); operands.RemoveAt(0); trace?.Log($"De-virtualize: {method}"); DevirtualizedMethodCallsCount++; node.SetInstruction(IRInstruction.CallStatic, node.Result, symbol, operands); MethodScanner.MethodInvoked(method, Method); }
protected override void Setup() { var startUpType = TypeSystem.GetTypeByName("Mosa.Runtime", "StartUp"); var startUpMethod = startUpType.FindMethodByName("StartApplication"); Compiler.PlugSystem.CreatePlug(startUpMethod, TypeSystem.EntryPoint); Compiler.GetMethodData(startUpMethod).DoNotInline = true; MethodScanner.MethodInvoked(startUpMethod, startUpMethod); if (Linker.EntryPoint == null) { var initializeMethod = startUpType.FindMethodByName("Initialize"); Linker.EntryPoint = Linker.GetSymbol(initializeMethod.FullName); Compiler.GetMethodData(initializeMethod).DoNotInline = true; MethodScanner.MethodInvoked(initializeMethod, initializeMethod); } else { Compiler.GetMethodData(TypeSystem.EntryPoint).DoNotInline = true; MethodScanner.MethodInvoked(TypeSystem.EntryPoint, TypeSystem.EntryPoint); } }
protected override void Setup() { typeInitializerMethod = Compiler.CreateLinkerMethod(TypeInitializerName); var startUpType = TypeSystem.GetTypeByName("Mosa.Runtime", "StartUp"); var initializeAssemblyMethod = startUpType.FindMethodByName("InitializeAssembly"); Compiler.PlugSystem.CreatePlug(initializeAssemblyMethod, typeInitializerMethod); Compiler.GetMethodData(initializeAssemblyMethod).DoNotInline = true; Compiler.GetMethodData(typeInitializerMethod).DoNotInline = true; MethodScanner.MethodInvoked(initializeAssemblyMethod, initializeAssemblyMethod); MethodScanner.MethodInvoked(typeInitializerMethod, typeInitializerMethod); foreach (var type in TypeSystem.AllTypes) { foreach (var method in type.Methods) { if (method.IsTypeConstructor && !method.HasOpenGenericParams) { Schedule(method); MethodScanner.MethodInvoked(method, method); } } } }
private void CallVirtual(Context context) { var call = context.Operand1; var result = context.Result; var method = call.Method; var thisPtr = context.Operand2; var operands = context.GetOperands(); Debug.Assert(method != null); Debug.Assert(!method.DeclaringType.IsInterface); operands.RemoveAt(0); // Offset to TypeDef/MethodTable from thisPtr var typeDefOffset = CreateConstant32(-NativePointerSize); // Offset to the method pointer on the MethodTable var methodPointerOffset = CreateConstant32(CalculateMethodTableOffset(method)); var typeDef = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer); var callTarget = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer); // Get the Method Table pointer context.SetInstruction(LoadInstruction, typeDef, thisPtr, typeDefOffset); // Get the address of the method context.AppendInstruction(LoadInstruction, callTarget, typeDef, methodPointerOffset); MakeCall(context, callTarget, result, operands, method); MethodScanner.MethodInvoked(method, Method); }
private List <InstructionNode> ScanForNewOperators() { var list = new List <InstructionNode>(); foreach (var block in BasicBlocks) { for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmpty) { continue; } if (node.Instruction is NewobjInstruction) { if (!MosaTypeLayout.IsStoredOnStack(node.Result.Type)) { list.Add(node); MethodScanner.TypeAllocated(node.InvokeMethod.DeclaringType, Method); } } else if (node.Instruction is NewarrInstruction) { list.Add(node); MethodScanner.TypeAllocated(node.Result.Type, Method); } } } return(list); }
private void CallVirtual(InstructionNode node) { var call = node.Operand1; var method = call.Method; if (TypeLayout.IsMethodOverridden(method)) { return; } if (!method.HasImplementation && method.IsAbstract) { return; } var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem); var operands = node.GetOperands(); operands.RemoveAt(0); trace?.Log($"De-virtualize: {method}"); DevirtualizedCount++; node.SetInstruction(IRInstruction.CallStatic, node.Result, symbol, operands); MethodScanner.MethodInvoked(method, Method); }
private void CallStatic(InstructionNode node) { var call = node.Operand1; var result = node.Result; var method = call.Method; var operands = node.GetOperands(); Debug.Assert(method != null); if (MethodCompiler.Compiler.CompilerData.IsMethodInlined(method)) { // If above is true, then a race condition occurred between: // 1) after inline stage of this method, and // 2) theinline evaluation stage of the target method // the only best option at this point is to stop compiling this method. // Note: It should already be scheduled to be re-compiled! //MethodCompiler.Stop(); //return; } //Debug.Assert(!MethodCompiler.Compiler.CompilerData.IsMethodInlined(method)); operands.RemoveAt(0); var context = new Context(node); context.Empty(); MakeCall(context, call, result, operands); Debug.Assert(method == call.Method); MethodScanner.MethodDirectInvoked(call.Method, Method); }
private void PerformStaticAllocation(InstructionNode node) { var allocatedType = node.MosaType; // node.Result.Type; //Debug.WriteLine($"Method: {Method} : {node}"); //Debug.WriteLine($" --> {allocatedType}"); MethodScanner.TypeAllocated(allocatedType, Method); int allocationSize; if (node.Instruction == IRInstruction.NewObject) { allocationSize = TypeLayout.GetTypeSize(allocatedType); } else { var elements = (int)GetConstant(node.Operand3); allocationSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * elements) + (TypeLayout.NativePointerSize * 3); } var symbolName = Linker.DefineSymbol(StaticSymbolPrefix + allocatedType.FullName, SectionKind.BSS, Architecture.NativeAlignment, allocationSize); string typeDefinitionSymbol = Metadata.TypeDefinition + allocatedType.FullName; Linker.Link(LinkType.AbsoluteAddress, Is32BitPlatform ? PatchType.I32 : PatchType.I64, symbolName, 0, typeDefinitionSymbol, 0); var staticAddress = Operand.CreateSymbol(allocatedType, symbolName.Name); var move = Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64; node.SetInstruction(move, node.Result, staticAddress); }
public void Subscriptions_are_built_for_object_method_based() { var builder = new MethodScanner("Handle").MakeBuilder(); var subs = builder.BuildSubscriptions(new SomeHandler()); subs.ShouldNotBeNull(); subs.ShouldHaveCount(1); }
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 ThrowInstruction(Context context) { var method = PlatformInternalRuntimeType.FindMethodByName("ExceptionHandler"); context.SetInstruction(Select(exceptionRegister, IRInstruction.MoveInt32, IRInstruction.MoveInt64), exceptionRegister, context.Operand1); context.AppendInstruction(IRInstruction.CallStatic, null, Operand.CreateSymbolFromMethod(method, TypeSystem)); MethodScanner.MethodInvoked(method, Method); }
protected override void Setup() { setupMethod = Compiler.CreateLinkerMethod(SetupStagerName); Compiler.CompilerData.GetMethodData(setupMethod).DoNotInline = true; MethodScanner.MethodInvoked(setupMethod, setupMethod); Linker.EntryPoint = Linker.GetSymbol(setupMethod.FullName); }
public void publishing_method_subscription_correct_returns_known_instance() { var h = new SomeHandler(); var sb = new MethodScanner("Route").MakeBuilder(); var subs = sb.BuildSubscriptions(h).OfType <IKnowsSubscribedInstance>().ToList(); subs.ShouldHaveCount(1); subs.All(s => s.Instance.Equals(h)).ShouldBeTrue("Not all known instances are the correct one"); }
private void NewArray(InstructionNode node) { var method = GetVMCallMethod(VmCall.AllocateArray); var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem); var arrayType = node.MosaType; node.SetInstruction(IRInstruction.CallStatic, node.Result, symbol, node.GetOperands()); MethodScanner.TypeAllocated(arrayType, method); }
private void NewArray(Context context) { var method = GetVMCallMethod(VmCall.AllocateArray); var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem); var arrayType = context.MosaType; context.SetInstruction(IRInstruction.CallStatic, context.Result, symbol, context.GetOperands()); MethodScanner.TypeAllocated(arrayType, 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); }
public void Subscriptions_for_object_method_based_work_correctly() { var builder = new MethodScanner("Handle").MakeBuilder(); var handler = new SomeHandler(); var subs = builder.BuildSubscriptions(handler); var subscription = subs.First(); subscription.Handles(typeof(MessageA)).ShouldBeTrue(); subscription.Push(new MessageA()); handler.MsgACalls.ShouldBeEqualTo(1); }
private MosaMethod GetVMCallMethod(VmCall vmcall) { string methodName = vmcall.ToString(); var method = InternalRuntimeType.FindMethodByName(methodName) ?? PlatformInternalRuntimeType.FindMethodByName(methodName); Debug.Assert(method != null, "Cannot find method: " + methodName); MethodScanner.MethodInvoked(method, Method); return(method); }
private void ThrowInstruction(InstructionNode node) { var method = PlatformInternalRuntimeType.FindMethodByName("ExceptionHandler"); var ctx = new Context(node); ctx.SetInstruction(Select(exceptionRegister, IRInstruction.MoveInt32, IRInstruction.MoveInt64), exceptionRegister, node.Operand1); //ctx.AppendInstruction(IRInstruction.KillAllExcept, null, exceptionRegister); ctx.AppendInstruction(IRInstruction.CallStatic, null, Operand.CreateSymbolFromMethod(method, TypeSystem)); MethodScanner.MethodInvoked(method, Method); }
public void SetupScanner() { _scanner = new MethodScanner(Module, ModelFactory, Logger); var assembly = new NetAssembly { Name = "TestLibrary" }; var typeScanner = new TypeScanner(Module, ModelFactory, Logger); typeScanner.ScanType(GetTypeDefintion <ClassWithMembers>(), assembly); typeScanner.ScanType(GetTypeDefintion <InheritedFromClassWithMembers>(), assembly); }
private void CallDynamic(Context context) { var call = context.Operand1; var result = context.Result; var method = context.InvokeMethod; var operands = context.GetOperands(); operands.RemoveAt(0); context.Empty(); MakeCall(context, call, result, operands, method); MethodScanner.MethodInvoked(call.Method, method); }
private void CallStatic(Context context) { var call = context.Operand1; var result = context.Result; var method = call.Method; var operands = context.GetOperands(); Debug.Assert(method != null); operands.RemoveAt(0); context.Empty(); MakeCall(context, call, result, operands); MethodScanner.MethodDirectInvoked(call.Method, Method); }
private void ReplaceWithPlatformDivisionCall(InstructionNode node, string methodName, Operand result, Operand operand1, Operand operand2) { var type = TypeSystem.GetTypeByName("Mosa.Runtime.x86", "Division"); Debug.Assert(type != null, "Cannot find type: Mosa.Runtime.x86.Division type"); var method = type.FindMethodByName(methodName); Debug.Assert(method != null, "Cannot find method: " + methodName); var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem); node.SetInstruction(IRInstruction.CallStatic, result, symbol, operand1, operand2); MethodScanner.MethodInvoked(method, this.Method); }
public void Adapter_subscriptions_can_also_be_disposed() { var b = new MethodScanner("Handle").MakeBuilder(); var disposableSub = new DisposableSubscription(b.BuildSubscriptions(new SomeHandler()).First()); ISubscriptionResolver resolver = new CompositeSubscription(); resolver.Add(disposableSub); var subs = resolver.GetSubscriptionsFor(new MessageA()); subs.ShouldHaveCount(1); disposableSub.GetDisposer().Dispose(); subs = resolver.GetSubscriptionsFor(new MessageA()); subs.ShouldHaveCount(0); }
protected override void CreateMultibootMethod() { var startUpType = TypeSystem.GetTypeByName("Mosa.Runtime", "StartUp"); var initializeMethod = startUpType.FindMethodByName("Initialize"); var entryPoint = Operand.CreateSymbolFromMethod(initializeMethod, TypeSystem); var eax = Operand.CreateCPURegister(TypeSystem.BuiltIn.I8, GeneralPurposeRegister.EAX); var ebx = Operand.CreateCPURegister(TypeSystem.BuiltIn.I8, GeneralPurposeRegister.EBX); var ebp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I8, GeneralPurposeRegister.EBP); var esp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I8, GeneralPurposeRegister.ESP); var multibootEAX = Operand.CreateUnmanagedSymbolPointer(MultibootEAX, TypeSystem); var multibootEBX = Operand.CreateUnmanagedSymbolPointer(MultibootEBX, TypeSystem); var stackTop = CreateConstant(STACK_ADDRESS); var zero = CreateConstant(0); var offset = CreateConstant(8); var basicBlocks = new BasicBlocks(); var block = basicBlocks.CreateBlock(BasicBlock.PrologueLabel); basicBlocks.AddHeadBlock(block); var ctx = new Context(block); //ctx.AppendInstruction(X64.Cli); // Setup the stack and place the sentinel on the stack to indicate the start of the stack ctx.AppendInstruction(X64.Mov64, esp, stackTop); ctx.AppendInstruction(X64.Mov64, ebp, stackTop); ctx.AppendInstruction(X64.MovStore64, null, esp, zero, zero); ctx.AppendInstruction(X64.MovStore64, null, esp, offset, zero); // Place the multiboot address into a static field ctx.AppendInstruction(X64.MovStore64, null, multibootEAX, zero, eax); ctx.AppendInstruction(X64.MovStore64, null, multibootEBX, zero, ebx); //ctx.AppendInstruction(X64.Sti); ctx.AppendInstruction(X64.Call, null, entryPoint); ctx.AppendInstruction(X64.Ret); Compiler.CompileMethod(multibootMethod, basicBlocks); MethodScanner.MethodInvoked(initializeMethod, multibootMethod); MethodScanner.MethodInvoked(multibootMethod, multibootMethod); }
protected override void RunPreCompile() { multibootHeader = Linker.DefineSymbol(MultibootHeaderSymbolName, SectionKind.Text, 1, 0x30); Linker.DefineSymbol(MultibootEAX, SectionKind.BSS, Architecture.NativeAlignment, Architecture.NativePointerSize); Linker.DefineSymbol(MultibootEBX, SectionKind.BSS, Architecture.NativeAlignment, Architecture.NativePointerSize); multibootMethod = Compiler.CreateLinkerMethod("MultibootInit"); Linker.EntryPoint = Linker.GetSymbol(multibootMethod.FullName); MethodScanner.MethodInvoked(multibootMethod, multibootMethod); var startUpType = TypeSystem.GetTypeByName("Mosa.Runtime", "StartUp"); var initializeMethod = startUpType.FindMethodByName("Initialize"); MethodScanner.MethodInvoked(initializeMethod, multibootMethod); }
private void PerformStaticAllocation(Context context) { var allocatedType = context.MosaType; // node.Result.Type; var handle = context.Operand1; bool newObject = context.Instruction == IRInstruction.NewObject; int elements = 0; //Debug.WriteLine($"Method: {Method} : {node}"); //Debug.WriteLine($" --> {allocatedType}"); MethodScanner.TypeAllocated(allocatedType, Method); int allocationSize; if (newObject) { allocationSize = TypeLayout.GetTypeSize(allocatedType); } else { elements = (int)GetConstant(context.Operand3); allocationSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * elements) + (TypeLayout.NativePointerSize * 3); } var symbolName = Linker.DefineSymbol(StaticSymbolPrefix + allocatedType.FullName, SectionKind.BSS, Architecture.NativeAlignment, allocationSize); string typeDefinitionSymbol = Metadata.TypeDefinition + allocatedType.FullName; Linker.Link(LinkType.AbsoluteAddress, Is32BitPlatform ? PatchType.I32 : PatchType.I64, symbolName, 0, typeDefinitionSymbol, 0); var staticAddress = Operand.CreateSymbol(allocatedType, symbolName.Name); var move = Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64; var store = Is32BitPlatform ? (BaseInstruction)IRInstruction.Store32 : IRInstruction.Store64; context.SetInstruction(move, context.Result, staticAddress); context.AppendInstruction(store, null, staticAddress, ConstantZero, handle); if (!newObject) { context.AppendInstruction(store, null, staticAddress, CreateConstant32(2 * (Is32BitPlatform ? 4 : 8)), CreateConstant32(elements)); } }
private void CallDynamic(InstructionNode node) { var call = node.Operand1; var result = node.Result; var operands = node.GetOperands(); operands.RemoveAt(0); var context = new Context(node); context.Empty(); MakeCall(context, call, result, operands); if (call.Method != null) { MethodScanner.MethodInvoked(call.Method, Method); } }
private void CallStatic(InstructionNode node) { var call = node.Operand1; var result = node.Result; var method = call.Method; var operands = node.GetOperands(); Debug.Assert(method != null); operands.RemoveAt(0); var context = new Context(node); context.Empty(); MakeCall(context, call, result, operands); MethodScanner.MethodDirectInvoked(call.Method, Method); }