Exemplo n.º 1
0
        private void NewArray(InstructionNode node)
        {
            var method = GetVMCallMethod(VmCall.AllocateArray);
            var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem);

            node.SetInstruction(IRInstruction.CallStatic, node.Result, symbol, node.GetOperands());
        }
Exemplo n.º 2
0
        private void CallVirtual(InstructionNode node)
        {
            var call     = node.Operand1;
            var result   = node.Result;
            var method   = call.Method;
            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);

            var context = new Context(node);

            // 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);
        }
Exemplo n.º 3
0
        private void CallVirtual(InstructionNode node)
        {
            var call   = node.Operand1;
            var method = call.Method;

            if (TypeLayout.IsMethodOverridden(method))
            {
                return;
            }

            var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem);

            var operands = node.GetOperands();

            operands.RemoveAt(0);

            if (trace.Active)
            {
                trace.Log("De-virtualize: " + method);
            }

            DevirtualizedCount++;

            node.SetInstruction(IRInstruction.CallStatic, node.Result, symbol, operands);
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
        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);
        }
Exemplo n.º 6
0
        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);
        }
Exemplo n.º 7
0
        private void NewObject(InstructionNode node)
        {
            var method    = GetVMCallMethod(VmCall.AllocateObject);
            var symbol    = Operand.CreateSymbolFromMethod(method, TypeSystem);
            var classType = node.MosaType;

            node.SetInstruction(IRInstruction.CallStatic, node.Result, symbol, node.GetOperands());

            MethodScanner.TypeAllocated(classType, Method);
        }
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
        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);
        }
Exemplo n.º 10
0
        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);
        }
Exemplo n.º 11
0
        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);
            }
        }
Exemplo n.º 12
0
        protected void Inline(InstructionNode callSiteNode, BasicBlocks blocks)
        {
            var mapBlocks = new Dictionary <BasicBlock, BasicBlock>(blocks.Count);
            var map       = new Dictionary <Operand, Operand>();

            var nextBlock = Split(callSiteNode);

            // create basic blocks
            foreach (var block in blocks)
            {
                var newBlock = CreateNewBlock();
                mapBlocks.Add(block, newBlock);
            }

            // copy instructions
            foreach (var block in blocks)
            {
                var newBlock = mapBlocks[block];

                for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next)
                {
                    if (node.IsEmpty)
                    {
                        continue;
                    }

                    if (node.Instruction == IRInstruction.Prologue)
                    {
                        continue;
                    }

                    if (node.Instruction == IRInstruction.Epilogue)
                    {
                        newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Jmp, nextBlock));
                        continue;
                    }

                    if (node.Instruction == IRInstruction.SetReturn32 ||
                        node.Instruction == IRInstruction.SetReturn64 ||
                        node.Instruction == IRInstruction.SetReturnR4 ||
                        node.Instruction == IRInstruction.SetReturnR8 ||
                        node.Instruction == IRInstruction.SetReturnCompound)
                    {
                        if (callSiteNode.Result != null)
                        {
                            var newOperand = Map(node.Operand1, map, callSiteNode);

                            BaseInstruction moveInstruction = null;

                            if (node.Instruction == IRInstruction.SetReturn32)
                            {
                                moveInstruction = IRInstruction.Move32;
                            }
                            else if (node.Instruction == IRInstruction.SetReturn64)
                            {
                                moveInstruction = IRInstruction.Move64;
                            }
                            else if (node.Instruction == IRInstruction.SetReturnR4)
                            {
                                moveInstruction = IRInstruction.MoveR4;
                            }
                            else if (node.Instruction == IRInstruction.SetReturnR8)
                            {
                                moveInstruction = IRInstruction.MoveR8;
                            }
                            else if (node.Instruction == IRInstruction.SetReturnCompound)
                            {
                                moveInstruction = IRInstruction.MoveCompound;
                            }

                            Debug.Assert(moveInstruction != null);

                            var moveNode = new InstructionNode(moveInstruction, callSiteNode.Result, newOperand);

                            newBlock.BeforeLast.Insert(moveNode);
                        }

                        continue;
                    }

                    var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount)
                    {
                        ConditionCode = node.ConditionCode,
                        Label         = callSiteNode.Label
                    };

                    if (node.BranchTargets != null)
                    {
                        // copy targets
                        foreach (var target in node.BranchTargets)
                        {
                            newNode.AddBranchTarget(mapBlocks[target]);
                        }
                    }

                    // copy results
                    for (int i = 0; i < node.ResultCount; i++)
                    {
                        var op = node.GetResult(i);

                        var newOp = Map(op, map, callSiteNode);

                        newNode.SetResult(i, newOp);
                    }

                    // copy operands
                    for (int i = 0; i < node.OperandCount; i++)
                    {
                        var op = node.GetOperand(i);

                        var newOp = Map(op, map, callSiteNode);

                        newNode.SetOperand(i, newOp);
                    }

                    // copy other
                    if (node.MosaType != null)
                    {
                        newNode.MosaType = node.MosaType;
                    }
                    if (node.MosaField != null)
                    {
                        newNode.MosaField = node.MosaField;
                    }

                    UpdateParameterInstructions(newNode);

                    newBlock.BeforeLast.Insert(newNode);
                }
            }

            var prologue = mapBlocks[blocks.PrologueBlock];

            var callSiteOperands = callSiteNode.GetOperands();

            if (callSiteOperands.Count > 1)
            {
                var context = new Context(prologue);

                for (int i = 1; i < callSiteOperands.Count; i++)
                {
                    var operand = callSiteOperands[i];

                    if (!operand.IsVirtualRegister || operand.Low == null)
                    {
                        continue;
                    }

                    context.AppendInstruction(IRInstruction.GetLow64, operand.Low, operand);
                    context.AppendInstruction(IRInstruction.GetHigh64, operand.High, operand);
                }
            }

            callSiteNode.SetInstruction(IRInstruction.Jmp, prologue);
        }
Exemplo n.º 13
0
 private void Box64(InstructionNode node)
 {
     SetVMCall(node, VmCall.Box64, node.Result, node.GetOperands());
 }
Exemplo n.º 14
0
 private void MemoryCopy(InstructionNode node)
 {
     SetVMCall(node, VmCall.MemoryCopy, node.Result, node.GetOperands());
 }
Exemplo n.º 15
0
 private void Rethrow(InstructionNode node)
 {
     SetVMCall(node, VmCall.Rethrow, node.Result, node.GetOperands());
 }
Exemplo n.º 16
0
 private void GetVirtualFunctionPtr(InstructionNode node)
 {
     SetVMCall(node, VmCall.GetVirtualFunctionPtr, node.Result, node.GetOperands());
 }
Exemplo n.º 17
0
 private void IsInstanceOfInterfaceType(InstructionNode node)
 {
     SetVMCall(node, VmCall.IsInstanceOfInterfaceType, node.Result, node.GetOperands());
 }
Exemplo n.º 18
0
 private void Unbox32(InstructionNode node)
 {
     SetVMCall(node, VmCall.Unbox32, node.Result, node.GetOperands());
 }