Пример #1
0
 /// <summary>
 /// Mark this low register as in use by the given original register.
 /// </summary>
 public void SetInUseBy(Register originalRegister, RType type)
 {
     if (OriginalRegister != null)
     {
         throw new InvalidOperationException("Register state is still in use");
     }
     if (type == RType.Wide)
     {
         if (next == null)
         {
             throw new InvalidOperationException("Register state cannot hold a wide");
         }
         if (next.OriginalRegister != null)
         {
             throw new InvalidOperationException("Register state.next is still in use");
         }
     }
     OriginalRegister = originalRegister;
     isWide           = (type == RType.Wide);
     this.type        = type;
     if (isWide)
     {
         next.isWide           = false;
         next.OriginalRegister = originalRegister;
         next.type             = RType.Wide2;
         next.wideStart        = this;
     }
     Mapping = new RegisterSpillingMapping(OriginalRegister, LowRegister);
 }
Пример #2
0
            /// <summary>
            /// Create a move instruction.
            /// </summary>
            private static Instruction CreateMove(Register from, Register to, RType type)
            {
                if (from == null)
                {
                    throw new ArgumentNullException("from");
                }
                if (to == null)
                {
                    throw new ArgumentNullException("to");
                }
                OpCodes opcode;

                switch (type)
                {
                case RType.Value:
                    opcode = OpCodes.Move;
                    break;

                case RType.Wide:
                    opcode = OpCodes.Move_wide;
                    break;

                case RType.Wide2:
                    return(new Instruction(OpCodes.Nop));

                case RType.Object:
                    opcode = OpCodes.Move_object;
                    break;

                default:
                    throw new ArgumentException("Unknown type: " + (int)type);
                }
                return(new Instruction(opcode, to, @from));
            }
Пример #3
0
            /// <summary>
            /// Allocate a low register and map it to the given original register.
            /// </summary>
            private LowRegisterState AllocateLowRegister(Instruction ins, Register register, MethodBody body)
            {
                // Prepare
                var type       = GetType(register);
                var isWide     = (type == RType.Wide);
                var regsNeeded = isWide ? 2 : 1;

                LowRegisterState   regState = null;
                HashSet <Register> allRegistersUsedInIns = null;

                while (true)
                {
                    // Try to allocate free spilling register
                    regState = lowRegisters.FirstOrDefault(x => x.IsFreeFor(type));
                    if (regState != null)
                    {
                        break; // Found a free low register
                    }
                    // No spilling register is available.
                    // Free another register first
                    // If wide, free 2 registers
                    if (nextSpillIndex + regsNeeded > lowRegisters.Length)
                    {
                        nextSpillIndex = 0;
                    }
                    regState = lowRegisters[nextSpillIndex];
                    var regStateNext = isWide ? lowRegisters[nextSpillIndex + 1] : null;

                    // Update index so we take another the next time
                    nextSpillIndex = (nextSpillIndex + regsNeeded) % (lowRegisters.Length - 1);

                    // Do not allocate registers already used in the current instruction
                    allRegistersUsedInIns = allRegistersUsedInIns ?? GetAllUsedRegisters(ins);
                    if (allRegistersUsedInIns.Contains(regState.LowRegister))
                    {
                        continue;
                    }
                    if ((regStateNext != null) && allRegistersUsedInIns.Contains(regStateNext.LowRegister))
                    {
                        continue;
                    }

                    // Save sReg back to original register
                    var map = mapper.RegisterSpillingMap;
                    regState.SaveToOriginalAndClear(ins, block, body, map);
                    if (regStateNext != null)
                    {
                        regStateNext.SaveToOriginalAndClear(ins, block, body, map);
                    }
                }
                // Add mapping
                regState.SetInUseBy(register, type);
                return(regState);
            }
Пример #4
0
            /// <summary>
            /// Replace all occurrences of from to to in the register list of the given instruction.
            /// </summary>
            private static void ReplaceRegister(Instruction ins, Register from, Register to)
            {
                if (from == null)
                {
                    throw new ArgumentNullException("from");
                }
                if (to == null)
                {
                    throw new ArgumentNullException("to");
                }
                var registers = ins.Registers;
                var count     = registers.Count;

                for (var i = 0; i < count; i++)
                {
                    if (registers[i] == from)
                    {
                        registers[i] = to;
                    }
                }
            }
Пример #5
0
            /// <summary>
            /// Add instructions that spill the given register.
            /// </summary>
            private void AddCode(Instruction ins, Register register, MethodBody body)
            {
                // Try to find an earlier map for the register
                {
                    Register         sReg;
                    LowRegisterState state;
                    if (TryGetLowRegister(register, out sReg, out state))
                    {
                        // Already mapped, just replace.
                        ReplaceRegister(ins, register, sReg);

                        // Should we save the low register now?
                        if ((!state.SaveToOriginalNeeded) && (sReg.IsDestinationIn(ins)))
                        {
                            state.SaveToOriginalNeeded = true;
                        }
                        return;
                    }
                }

                // Allocate low register
                var sRegState = AllocateLowRegister(ins, register, body);

                // We can now use sReg as replacement for register.
                // Add move (only if the register is a source of the instruction)
                if (register.IsSourceIn(ins))
                {
                    block.InsertBefore(ins, CreateMove(register, sRegState.LowRegister, GetType(register)));
                }
                // See if we need to save the low register afterwards
                if ((!sRegState.SaveToOriginalNeeded) && (register.IsDestinationIn(ins)))
                {
                    sRegState.SaveToOriginalNeeded = true;
                }
                // Replace the register
                ReplaceRegister(ins, register, sRegState.LowRegister);

                // Record start point in mapping
                sRegState.Mapping.FirstInstruction = ins;
            }
Пример #6
0
 /// <summary>
 /// Default ctor
 /// </summary>
 public LowRegisterState(Register lowRegister, LowRegisterState next)
 {
     LowRegister = lowRegister;
     this.next   = next;
 }
Пример #7
0
            /// <summary>
            /// Gets the type stored in the given register.
            /// </summary>
            private RType GetType(Register register)
            {
                var lowState = lowRegisters.FirstOrDefault(x => x.LowRegister == register);

                return(mapper.GetType(lowState != null ? lowState.OriginalRegister : register));
            }
Пример #8
0
 /// <summary>
 /// Mark this low register as in use by the given original register.
 /// </summary>
 public void SetInUseBy(Register originalRegister, RType type)
 {
     if (OriginalRegister != null)
         throw new InvalidOperationException("Register state is still in use");
     if (type == RType.Wide)
     {
         if (next == null)
             throw new InvalidOperationException("Register state cannot hold a wide");
         if (next.OriginalRegister != null)
             throw new InvalidOperationException("Register state.next is still in use");
     }
     OriginalRegister = originalRegister;
     isWide = (type == RType.Wide);
     this.type = type;
     if (isWide)
     {
         next.isWide = false;
         next.OriginalRegister = originalRegister;
         next.type = RType.Wide2;
         next.wideStart = this;
     }
     Mapping = new RegisterSpillingMapping(OriginalRegister, LowRegister);
 }
Пример #9
0
 /// <summary>
 /// Try to get the low register that the given original register is mapped onto.
 /// </summary>
 private bool TryGetLowRegister(Register originalRegister, out Register lowRegister, out LowRegisterState lowRegisterState)
 {
     lowRegisterState = lowRegisters.FirstOrDefault(x => x.OriginalRegister == originalRegister);
     lowRegister      = (lowRegisterState != null) ? lowRegisterState.LowRegister : null;
     return(lowRegister != null);
 }
Пример #10
0
 /// <summary>
 /// Replace all occurrences of from to to in the register list of the given instruction.
 /// </summary>
 private static void ReplaceRegister(Instruction ins, Register from, Register to)
 {
     if (from == null)
         throw new ArgumentNullException("from");
     if (to == null)
         throw new ArgumentNullException("to");
     var registers = ins.Registers;
     var count = registers.Count;
     for (var i = 0; i < count; i++)
     {
         if (registers[i] == from)
         {
             registers[i] = to;
         }
     }
 }
Пример #11
0
 /// <summary>
 /// Default ctor
 /// </summary>
 public LowRegisterState(Register lowRegister, LowRegisterState next)
 {
     LowRegister = lowRegister;
     this.next = next;
 }
Пример #12
0
 /// <summary>
 /// Create a move instruction.
 /// </summary>
 private static Instruction CreateMove(Register from, Register to, RType type)
 {
     if (from == null)
         throw new ArgumentNullException("from");
     if (to == null)
         throw new ArgumentNullException("to");
     OpCodes opcode;
     switch (type)
     {
         case RType.Value:
             opcode = OpCodes.Move;
             break;
         case RType.Wide:
             opcode = OpCodes.Move_wide;
             break;
         case RType.Wide2:
             return new Instruction(OpCodes.Nop);
         case RType.Object:
             opcode = OpCodes.Move_object;
             break;
         default:
             throw new ArgumentException("Unknown type: " + (int)type);
     }
     return new Instruction(opcode, to, @from);
 }
Пример #13
0
            /// <summary>
            /// Allocate a low register and map it to the given original register.
            /// </summary>
            private LowRegisterState AllocateLowRegister(Instruction ins, Register register, MethodBody body)
            {
                // Prepare
                var type = GetType(register);
                var isWide = (type == RType.Wide);
                var regsNeeded = isWide ? 2 : 1;

                LowRegisterState regState = null;
                HashSet<Register> allRegistersUsedInIns = null;
                while (true)
                {
                    // Try to allocate free spilling register
                    regState = lowRegisters.FirstOrDefault(x => x.IsFreeFor(type));
                    if (regState != null)
                        break; // Found a free low register

                    // No spilling register is available.
                    // Free another register first
                    // If wide, free 2 registers
                    if (nextSpillIndex + regsNeeded > lowRegisters.Length) nextSpillIndex = 0;
                    regState = lowRegisters[nextSpillIndex];
                    var regStateNext = isWide ? lowRegisters[nextSpillIndex + 1] : null;

                    // Update index so we take another the next time
                    nextSpillIndex = (nextSpillIndex + regsNeeded) % (lowRegisters.Length - 1);

                    // Do not allocate registers already used in the current instruction
                    allRegistersUsedInIns = allRegistersUsedInIns ?? GetAllUsedRegisters(ins);
                    if (allRegistersUsedInIns.Contains(regState.LowRegister))
                        continue;
                    if ((regStateNext != null) && allRegistersUsedInIns.Contains(regStateNext.LowRegister))
                        continue;
             
                    // Save sReg back to original register
                    var map = mapper.RegisterSpillingMap;
                    regState.SaveToOriginalAndClear(ins, block, body, map);
                    if (regStateNext != null) regStateNext.SaveToOriginalAndClear(ins, block, body, map);
                }
                // Add mapping
                regState.SetInUseBy(register, type);
                return regState;
            }
Пример #14
0
            /// <summary>
            /// Add instructions that spill the given register.
            /// </summary>
            private void AddCode(Instruction ins, Register register, MethodBody body)
            {
                // Try to find an earlier map for the register
                {
                    Register sReg;
                    LowRegisterState state;
                    if (TryGetLowRegister(register, out sReg, out state))
                    {
                        // Already mapped, just replace.
                        ReplaceRegister(ins, register, sReg);

                        // Should we save the low register now?
                        if ((!state.SaveToOriginalNeeded) && (sReg.IsDestinationIn(ins)))
                        {
                            state.SaveToOriginalNeeded = true;
                        }
                        return;
                    }
                }

                // Allocate low register
                var sRegState = AllocateLowRegister(ins, register, body);

                // We can now use sReg as replacement for register.
                // Add move (only if the register is a source of the instruction)
                if (register.IsSourceIn(ins))
                {
                    block.InsertBefore(ins, CreateMove(register, sRegState.LowRegister, GetType(register)));
                }
                // See if we need to save the low register afterwards
                if ((!sRegState.SaveToOriginalNeeded) && (register.IsDestinationIn(ins)))
                {
                    sRegState.SaveToOriginalNeeded = true;
                }
                // Replace the register
                ReplaceRegister(ins, register, sRegState.LowRegister);

                // Record start point in mapping
                sRegState.Mapping.FirstInstruction = ins;
            }
Пример #15
0
 /// <summary>
 /// Gets the type stored in the given register.
 /// </summary>
 private RType GetType(Register register)
 {
     var lowState = lowRegisters.FirstOrDefault(x => x.LowRegister == register);
     return mapper.GetType(lowState != null ? lowState.OriginalRegister : register);                
 }
Пример #16
0
 /// <summary>
 /// Try to get the low register that the given original register is mapped onto.
 /// </summary>
 private bool TryGetLowRegister(Register originalRegister, out Register lowRegister, out LowRegisterState lowRegisterState)
 {
     lowRegisterState = lowRegisters.FirstOrDefault(x => x.OriginalRegister == originalRegister);
     lowRegister = (lowRegisterState != null) ? lowRegisterState.LowRegister : null;
     return (lowRegister != null);
 }