com.android.dx.ssa.NormalSsaInsn Java Examples

The following examples show how to use com.android.dx.ssa.NormalSsaInsn. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: FirstFitLocalCombiningAllocator.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Constructs instance.
 *
 * @param ssaMeth {@code non-null;} method to process
 * @param interference non-null interference graph for SSA registers
 * @param minimizeRegisters true if converter should take steps to
 * minimize rop-form registers
 */
public FirstFitLocalCombiningAllocator(
        SsaMethod ssaMeth, InterferenceGraph interference,
        boolean minimizeRegisters) {
    super(ssaMeth, interference);

    ssaRegsMapped = new BitSet(ssaMeth.getRegCount());

    mapper = new InterferenceRegisterMapper(
            interference, ssaMeth.getRegCount());

    this.minimizeRegisters = minimizeRegisters;

    /*
     * Reserve space for the params at the bottom of the register
     * space. Later, we'll flip the params to the end of the register
     * space.
     */

    paramRangeEnd = ssaMeth.getParamWidth();

    reservedRopRegs = new BitSet(paramRangeEnd * 2);
    reservedRopRegs.set(0, paramRangeEnd);
    usedRopRegs = new BitSet(paramRangeEnd * 2);
    localVariables = new TreeMap<LocalItem, ArrayList<RegisterSpec>>();
    moveResultPseudoInsns = new ArrayList<NormalSsaInsn>();
    invokeRangeInsns = new ArrayList<NormalSsaInsn>();
    phiInsns = new ArrayList<PhiInsn>();
}
 
Example #2
Source File: RegisterAllocator.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Returns true if the definition site of this register is a
 * move-param (ie, this is a method parameter).
 *
 * @param reg register in question
 * @return {@code true} if this is a method parameter
 */
protected boolean isDefinitionMoveParam(int reg) {
    SsaInsn defInsn = ssaMeth.getDefinitionForRegister(reg);

    if (defInsn instanceof NormalSsaInsn) {
        NormalSsaInsn ndefInsn = (NormalSsaInsn) defInsn;

        return ndefInsn.getOpcode().getOpcode() == RegOps.MOVE_PARAM;
    }

    return false;
}
 
Example #3
Source File: FirstFitLocalCombiningAllocator.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
/**
   * Constructs instance.
   *
   * @param ssaMeth {@code non-null;} method to process
   * @param interference non-null interference graph for SSA registers
   * @param minimizeRegisters true if converter should take steps to
   * minimize rop-form registers
   */
  public FirstFitLocalCombiningAllocator(
          SsaMethod ssaMeth, InterferenceGraph interference,
          boolean minimizeRegisters) {
      super(ssaMeth, interference);

      ssaRegsMapped = new BitSet(ssaMeth.getRegCount());

      mapper = new InterferenceRegisterMapper(
              interference, ssaMeth.getRegCount());

/*
       * Reserve space for the params at the bottom of the register
       * space. Later, we'll flip the params to the end of the register
       * space.
       */

      paramRangeEnd = ssaMeth.getParamWidth();

      reservedRopRegs = new BitSet(paramRangeEnd * 2);
      reservedRopRegs.set(0, paramRangeEnd);
      usedRopRegs = new BitSet(paramRangeEnd * 2);
      localVariables = new TreeMap<LocalItem, ArrayList<RegisterSpec>>();
      moveResultPseudoInsns = new ArrayList<NormalSsaInsn>();
      invokeRangeInsns = new ArrayList<NormalSsaInsn>();
      phiInsns = new ArrayList<PhiInsn>();
  }
 
Example #4
Source File: RegisterAllocator.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Returns true if the definition site of this register is a
 * move-param (ie, this is a method parameter).
 *
 * @param reg register in question
 * @return {@code true} if this is a method parameter
 */
protected boolean isDefinitionMoveParam(int reg) {
    SsaInsn defInsn = ssaMeth.getDefinitionForRegister(reg);

    if (defInsn instanceof NormalSsaInsn) {
        NormalSsaInsn ndefInsn = (NormalSsaInsn) defInsn;

        return ndefInsn.getOpcode().getOpcode() == RegOps.MOVE_PARAM;
    }

    return false;
}
 
Example #5
Source File: RegisterAllocator.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
/**
 * Returns true if the definition site of this register is a
 * move-param (ie, this is a method parameter).
 *
 * @param reg register in question
 * @return {@code true} if this is a method parameter
 */
protected boolean isDefinitionMoveParam(int reg) {
    SsaInsn defInsn = ssaMeth.getDefinitionForRegister(reg);

    if (defInsn instanceof NormalSsaInsn) {
        NormalSsaInsn ndefInsn = (NormalSsaInsn) defInsn;

        return ndefInsn.getOpcode().getOpcode() == RegOps.MOVE_PARAM;
    }

    return false;
}
 
Example #6
Source File: FirstFitLocalCombiningAllocator.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Constructs instance.
 *
 * @param ssaMeth {@code non-null;} method to process
 * @param interference non-null interference graph for SSA registers
 * @param minimizeRegisters true if converter should take steps to
 * minimize rop-form registers
 */
public FirstFitLocalCombiningAllocator(
        SsaMethod ssaMeth, InterferenceGraph interference,
        boolean minimizeRegisters) {
    super(ssaMeth, interference);

    ssaRegsMapped = new BitSet(ssaMeth.getRegCount());

    mapper = new InterferenceRegisterMapper(
            interference, ssaMeth.getRegCount());

    this.minimizeRegisters = minimizeRegisters;

    /*
     * Reserve space for the params at the bottom of the register
     * space. Later, we'll flip the params to the end of the register
     * space.
     */

    paramRangeEnd = ssaMeth.getParamWidth();

    reservedRopRegs = new BitSet(paramRangeEnd * 2);
    reservedRopRegs.set(0, paramRangeEnd);
    usedRopRegs = new BitSet(paramRangeEnd * 2);
    localVariables = new TreeMap<LocalItem, ArrayList<RegisterSpec>>();
    moveResultPseudoInsns = new ArrayList<NormalSsaInsn>();
    invokeRangeInsns = new ArrayList<NormalSsaInsn>();
    phiInsns = new ArrayList<PhiInsn>();
}
 
Example #7
Source File: RegisterAllocator.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Returns true if the definition site of this register is a
 * move-param (ie, this is a method parameter).
 *
 * @param reg register in question
 * @return {@code true} if this is a method parameter
 */
protected boolean isDefinitionMoveParam(int reg) {
    SsaInsn defInsn = ssaMeth.getDefinitionForRegister(reg);

    if (defInsn instanceof NormalSsaInsn) {
        NormalSsaInsn ndefInsn = (NormalSsaInsn) defInsn;

        return ndefInsn.getOpcode().getOpcode() == RegOps.MOVE_PARAM;
    }

    return false;
}
 
Example #8
Source File: FirstFitLocalCombiningAllocator.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Constructs instance.
 *
 * @param ssaMeth {@code non-null;} method to process
 * @param interference non-null interference graph for SSA registers
 * @param minimizeRegisters true if converter should take steps to
 * minimize rop-form registers
 */
public FirstFitLocalCombiningAllocator(
        SsaMethod ssaMeth, InterferenceGraph interference,
        boolean minimizeRegisters) {
    super(ssaMeth, interference);

    ssaRegsMapped = new BitSet(ssaMeth.getRegCount());

    mapper = new InterferenceRegisterMapper(
            interference, ssaMeth.getRegCount());

    this.minimizeRegisters = minimizeRegisters;

    /*
     * Reserve space for the params at the bottom of the register
     * space. Later, we'll flip the params to the end of the register
     * space.
     */

    paramRangeEnd = ssaMeth.getParamWidth();

    reservedRopRegs = new BitSet(paramRangeEnd * 2);
    reservedRopRegs.set(0, paramRangeEnd);
    usedRopRegs = new BitSet(paramRangeEnd * 2);
    localVariables = new TreeMap<LocalItem, ArrayList<RegisterSpec>>();
    moveResultPseudoInsns = new ArrayList<NormalSsaInsn>();
    invokeRangeInsns = new ArrayList<NormalSsaInsn>();
    phiInsns = new ArrayList<PhiInsn>();
}
 
Example #9
Source File: FirstFitLocalCombiningAllocator.java    From J2ME-Loader with Apache License 2.0 4 votes vote down vote up
/**
 * Finds an unreserved range that will fit the sources of the
 * specified instruction. Does not bother trying to center the range
 * around an already-mapped source register;
 *
 * @param insn {@code non-null;} insn to build range for
 * @param rangeLength {@code >=0;} length required in register units
 * @param categoriesForIndex {@code non-null;} indexed by source index;
 * the category for each source
 * @param outMovesRequired {@code non-null;} an output parameter indexed by
 * source index that will contain the set of sources which need
 * moves inserted
 * @return the rop register that starts the fitting range
 */
private int findAnyFittingRange(NormalSsaInsn insn, int rangeLength,
        int[] categoriesForIndex, BitSet outMovesRequired) {
    Alignment alignment = Alignment.UNSPECIFIED;

    if (DexOptions.ALIGN_64BIT_REGS_SUPPORT) {
      int regNumber = 0;
      int p64bitsAligned = 0;
      int p64bitsNotAligned = 0;
      for (int category : categoriesForIndex) {
        if (category == 2) {
          if (isEven(regNumber)) {
            p64bitsAligned++;
          } else {
            p64bitsNotAligned++;
          }
          regNumber += 2;
        } else {
          regNumber += 1;
        }
      }

      if (p64bitsNotAligned > p64bitsAligned) {
        if (isEven(paramRangeEnd)) {
          alignment = Alignment.ODD;
        } else {
          alignment = Alignment.EVEN;
        }
      } else if (p64bitsAligned > 0) {
        if (isEven(paramRangeEnd)) {
          alignment = Alignment.EVEN;
        } else {
          alignment = Alignment.ODD;
        }
      }
    }

    int rangeStart = paramRangeEnd;
    while (true) {
      rangeStart = findNextUnreservedRopReg(rangeStart, rangeLength, alignment);

      int fitWidth = fitPlanForRange(rangeStart, insn, categoriesForIndex, outMovesRequired);

      if (fitWidth >= 0) {
        break;
      }
      rangeStart++;
      outMovesRequired.clear();
    }

    return rangeStart;
}
 
Example #10
Source File: FirstFitAllocator.java    From buck with Apache License 2.0 4 votes vote down vote up
/**
 * Returns the parameter number that this move-param insn refers to
 * @param ndefInsn a move-param insn (otherwise, exceptions will be thrown)
 * @return parameter number (offset in the total parameter width)
 */
private int paramNumberFromMoveParam(NormalSsaInsn ndefInsn) {
    CstInsn origInsn = (CstInsn) ndefInsn.getOriginalRopInsn();

    return ((CstInteger) origInsn.getConstant()).getValue();
}
 
Example #11
Source File: FirstFitLocalCombiningAllocator.java    From J2ME-Loader with Apache License 2.0 4 votes vote down vote up
/**
 * Attempts to build a plan for fitting a range of sources into rop
 * registers.
 *
 * @param ropReg {@code >= 0;} rop reg that begins range
 * @param insn {@code non-null;} insn to plan range for
 * @param categoriesForIndex {@code non-null;} indexed by source index;
 * the category for each source
 * @param outMovesRequired {@code non-null;} an output parameter indexed by
 * source index that will contain the set of sources which need
 * moves inserted
 * @return the width of the fit that that does not involve added moves or
 * {@code -1} if "no fit possible"
 */
private int fitPlanForRange(int ropReg, NormalSsaInsn insn,
        int[] categoriesForIndex, BitSet outMovesRequired) {
    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    int fitWidth = 0;
    IntSet liveOut = insn.getBlock().getLiveOutRegs();
    RegisterSpecList liveOutSpecs = ssaSetToSpecs(liveOut);

    // An SSA reg may only be mapped into a range once.
    BitSet seen = new BitSet(ssaMeth.getRegCount());

    for (int i = 0; i < szSources ; i++) {
        RegisterSpec ssaSpec = sources.get(i);
        int ssaReg = ssaSpec.getReg();
        int category = categoriesForIndex[i];

        if (i != 0) {
            ropReg += categoriesForIndex[i-1];
        }

        if (ssaRegsMapped.get(ssaReg)
                && mapper.oldToNew(ssaReg) == ropReg) {
            // This is a register that is already mapped appropriately.
            fitWidth += category;
        } else if (rangeContainsReserved(ropReg, category)) {
            fitWidth = -1;
            break;
        } else if (!ssaRegsMapped.get(ssaReg)
                && canMapReg(ssaSpec, ropReg)
                && !seen.get(ssaReg)) {
            // This is a register that can be mapped appropriately.
            fitWidth += category;
        } else if (!mapper.areAnyPinned(liveOutSpecs, ropReg, category)
                && !mapper.areAnyPinned(sources, ropReg, category)) {
            /*
             * This is a source that can be moved. We can insert a
             * move as long as:
             *
             *   * no SSA register pinned to the desired rop reg
             *     is live out on the block
             *
             *   * no SSA register pinned to desired rop reg is
             *     a source of this insn (since this may require
             *     overlapping moves, which we can't presently handle)
             */

            outMovesRequired.set(i);
        } else {
            fitWidth = -1;
            break;
        }

        seen.set(ssaReg);
    }
    return fitWidth;
}
 
Example #12
Source File: FirstFitAllocator.java    From J2ME-Loader with Apache License 2.0 4 votes vote down vote up
/** {@inheritDoc} */
@Override
public RegisterMapper allocateRegisters() {
    int oldRegCount = ssaMeth.getRegCount();

    BasicRegisterMapper mapper
            = new BasicRegisterMapper(oldRegCount);

    int nextNewRegister = 0;

    if (PRESLOT_PARAMS) {
        /*
         * Reserve space for the params at the bottom of the register
         * space. Later, we'll flip the params to the end of the register
         * space.
         */

        nextNewRegister = ssaMeth.getParamWidth();
    }

    for (int i = 0; i < oldRegCount; i++) {
        if (mapped.get(i)) {
            // we already got this one
            continue;
        }

        int maxCategory = getCategoryForSsaReg(i);
        IntSet current = new BitIntSet(oldRegCount);

        interference.mergeInterferenceSet(i, current);

        boolean isPreslotted = false;
        int newReg = 0;

        if (PRESLOT_PARAMS && isDefinitionMoveParam(i)) {
            // Any move-param definition must be a NormalSsaInsn
            NormalSsaInsn defInsn = (NormalSsaInsn)
                   ssaMeth.getDefinitionForRegister(i);

            newReg = paramNumberFromMoveParam(defInsn);

            mapper.addMapping(i, newReg, maxCategory);
            isPreslotted = true;
        } else {
            mapper.addMapping(i, nextNewRegister, maxCategory);
            newReg = nextNewRegister;
        }

        for (int j = i + 1; j < oldRegCount; j++) {
            if (mapped.get(j) || isDefinitionMoveParam(j)) {
                continue;
            }

            /*
             * If reg j doesn't interfere with the current mapping.
             * Also, if this is a pre-slotted method parameter, we
             * can't use more than the original param width.
             */
            if (!current.has(j)
                    && !(isPreslotted
                        && (maxCategory < getCategoryForSsaReg(j)))) {

                interference.mergeInterferenceSet(j, current);

                maxCategory = Math.max(maxCategory,
                        getCategoryForSsaReg(j));

                mapper.addMapping(j, newReg, maxCategory);
                mapped.set(j);
            }
        }

        mapped.set(i);
        if (!isPreslotted) {
            nextNewRegister += maxCategory;
        }
    }

    return mapper;
}
 
Example #13
Source File: FirstFitAllocator.java    From J2ME-Loader with Apache License 2.0 4 votes vote down vote up
/**
 * Returns the parameter number that this move-param insn refers to
 * @param ndefInsn a move-param insn (otherwise, exceptions will be thrown)
 * @return parameter number (offset in the total parameter width)
 */
private int paramNumberFromMoveParam(NormalSsaInsn ndefInsn) {
    CstInsn origInsn = (CstInsn) ndefInsn.getOriginalRopInsn();

    return ((CstInteger) origInsn.getConstant()).getValue();
}
 
Example #14
Source File: FirstFitLocalCombiningAllocator.java    From buck with Apache License 2.0 4 votes vote down vote up
/**
 * Handles all insns that want a register range for their sources.
 */
private void handleInvokeRangeInsns() {
    for (NormalSsaInsn insn : invokeRangeInsns) {
        adjustAndMapSourceRangeRange(insn);
    }
}
 
Example #15
Source File: FirstFitLocalCombiningAllocator.java    From buck with Apache License 2.0 4 votes vote down vote up
/**
 * Maps the source registers of the specified instruction such that they
 * will fall in a contiguous range in rop form. Moves are inserted as
 * necessary to allow the range to be allocated.
 *
 * @param insn {@code non-null;} insn whos sources to process
 */
private void adjustAndMapSourceRangeRange(NormalSsaInsn insn) {
    int newRegStart = findRangeAndAdjust(insn);

    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    int nextRopReg = newRegStart;

    for (int i = 0; i < szSources; i++) {
        RegisterSpec source = sources.get(i);
        int sourceReg = source.getReg();
        int category = source.getCategory();
        int curRopReg = nextRopReg;
        nextRopReg += category;

        if (ssaRegsMapped.get(sourceReg)) {
            continue;
        }

        LocalItem localItem = getLocalItemForReg(sourceReg);
        addMapping(source, curRopReg);

        if (localItem != null) {
            markReserved(curRopReg, category);
            ArrayList<RegisterSpec> similarRegisters
                    = localVariables.get(localItem);

            int szSimilar = similarRegisters.size();

            /*
             * Try to map all SSA registers also associated with
             * this local.
             */
            for (int j = 0; j < szSimilar; j++) {
                RegisterSpec similarSpec = similarRegisters.get(j);
                int similarReg = similarSpec.getReg();

                // Don't map anything that's also a source.
                if (-1 != sources.indexOfRegister(similarReg)) {
                    continue;
                }

                // Registers left unmapped will get handled later.
                tryMapReg(similarSpec, curRopReg, category);
            }
        }
    }
}
 
Example #16
Source File: FirstFitLocalCombiningAllocator.java    From buck with Apache License 2.0 4 votes vote down vote up
/**
 * Finds an unreserved range that will fit the sources of the
 * specified instruction. Does not bother trying to center the range
 * around an already-mapped source register;
 *
 * @param insn {@code non-null;} insn to build range for
 * @param rangeLength {@code >=0;} length required in register units
 * @param categoriesForIndex {@code non-null;} indexed by source index;
 * the category for each source
 * @param outMovesRequired {@code non-null;} an output parameter indexed by
 * source index that will contain the set of sources which need
 * moves inserted
 * @return the rop register that starts the fitting range
 */
private int findAnyFittingRange(NormalSsaInsn insn, int rangeLength,
        int[] categoriesForIndex, BitSet outMovesRequired) {
    Alignment alignment = Alignment.UNSPECIFIED;

    if (DexOptions.ALIGN_64BIT_REGS_SUPPORT) {
      int regNumber = 0;
      int p64bitsAligned = 0;
      int p64bitsNotAligned = 0;
      for (int category : categoriesForIndex) {
        if (category == 2) {
          if (isEven(regNumber)) {
            p64bitsAligned++;
          } else {
            p64bitsNotAligned++;
          }
          regNumber += 2;
        } else {
          regNumber += 1;
        }
      }

      if (p64bitsNotAligned > p64bitsAligned) {
        if (isEven(paramRangeEnd)) {
          alignment = Alignment.ODD;
        } else {
          alignment = Alignment.EVEN;
        }
      } else if (p64bitsAligned > 0) {
        if (isEven(paramRangeEnd)) {
          alignment = Alignment.EVEN;
        } else {
          alignment = Alignment.ODD;
        }
      }
    }

    int rangeStart = paramRangeEnd;
    while (true) {
      rangeStart = findNextUnreservedRopReg(rangeStart, rangeLength, alignment);

      int fitWidth = fitPlanForRange(rangeStart, insn, categoriesForIndex, outMovesRequired);

      if (fitWidth >= 0) {
        break;
      }
      rangeStart++;
      outMovesRequired.clear();
    }

    return rangeStart;
}
 
Example #17
Source File: FirstFitLocalCombiningAllocator.java    From buck with Apache License 2.0 4 votes vote down vote up
/**
 * Attempts to build a plan for fitting a range of sources into rop
 * registers.
 *
 * @param ropReg {@code >= 0;} rop reg that begins range
 * @param insn {@code non-null;} insn to plan range for
 * @param categoriesForIndex {@code non-null;} indexed by source index;
 * the category for each source
 * @param outMovesRequired {@code non-null;} an output parameter indexed by
 * source index that will contain the set of sources which need
 * moves inserted
 * @return the width of the fit that that does not involve added moves or
 * {@code -1} if "no fit possible"
 */
private int fitPlanForRange(int ropReg, NormalSsaInsn insn,
        int[] categoriesForIndex, BitSet outMovesRequired) {
    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    int fitWidth = 0;
    IntSet liveOut = insn.getBlock().getLiveOutRegs();
    RegisterSpecList liveOutSpecs = ssaSetToSpecs(liveOut);

    // An SSA reg may only be mapped into a range once.
    BitSet seen = new BitSet(ssaMeth.getRegCount());

    for (int i = 0; i < szSources ; i++) {
        RegisterSpec ssaSpec = sources.get(i);
        int ssaReg = ssaSpec.getReg();
        int category = categoriesForIndex[i];

        if (i != 0) {
            ropReg += categoriesForIndex[i-1];
        }

        if (ssaRegsMapped.get(ssaReg)
                && mapper.oldToNew(ssaReg) == ropReg) {
            // This is a register that is already mapped appropriately.
            fitWidth += category;
        } else if (rangeContainsReserved(ropReg, category)) {
            fitWidth = -1;
            break;
        } else if (!ssaRegsMapped.get(ssaReg)
                && canMapReg(ssaSpec, ropReg)
                && !seen.get(ssaReg)) {
            // This is a register that can be mapped appropriately.
            fitWidth += category;
        } else if (!mapper.areAnyPinned(liveOutSpecs, ropReg, category)
                && !mapper.areAnyPinned(sources, ropReg, category)) {
            /*
             * This is a source that can be moved. We can insert a
             * move as long as:
             *
             *   * no SSA register pinned to the desired rop reg
             *     is live out on the block
             *
             *   * no SSA register pinned to desired rop reg is
             *     a source of this insn (since this may require
             *     overlapping moves, which we can't presently handle)
             */

            outMovesRequired.set(i);
        } else {
            fitWidth = -1;
            break;
        }

        seen.set(ssaReg);
    }
    return fitWidth;
}
 
Example #18
Source File: FirstFitAllocator.java    From buck with Apache License 2.0 4 votes vote down vote up
/** {@inheritDoc} */
@Override
public RegisterMapper allocateRegisters() {
    int oldRegCount = ssaMeth.getRegCount();

    BasicRegisterMapper mapper
            = new BasicRegisterMapper(oldRegCount);

    int nextNewRegister = 0;

    if (PRESLOT_PARAMS) {
        /*
         * Reserve space for the params at the bottom of the register
         * space. Later, we'll flip the params to the end of the register
         * space.
         */

        nextNewRegister = ssaMeth.getParamWidth();
    }

    for (int i = 0; i < oldRegCount; i++) {
        if (mapped.get(i)) {
            // we already got this one
            continue;
        }

        int maxCategory = getCategoryForSsaReg(i);
        IntSet current = new BitIntSet(oldRegCount);

        interference.mergeInterferenceSet(i, current);

        boolean isPreslotted = false;
        int newReg = 0;

        if (PRESLOT_PARAMS && isDefinitionMoveParam(i)) {
            // Any move-param definition must be a NormalSsaInsn
            NormalSsaInsn defInsn = (NormalSsaInsn)
                   ssaMeth.getDefinitionForRegister(i);

            newReg = paramNumberFromMoveParam(defInsn);

            mapper.addMapping(i, newReg, maxCategory);
            isPreslotted = true;
        } else {
            mapper.addMapping(i, nextNewRegister, maxCategory);
            newReg = nextNewRegister;
        }

        for (int j = i + 1; j < oldRegCount; j++) {
            if (mapped.get(j) || isDefinitionMoveParam(j)) {
                continue;
            }

            /*
             * If reg j doesn't interfere with the current mapping.
             * Also, if this is a pre-slotted method parameter, we
             * can't use more than the original param width.
             */
            if (!current.has(j)
                    && !(isPreslotted
                        && (maxCategory < getCategoryForSsaReg(j)))) {

                interference.mergeInterferenceSet(j, current);

                maxCategory = Math.max(maxCategory,
                        getCategoryForSsaReg(j));

                mapper.addMapping(j, newReg, maxCategory);
                mapped.set(j);
            }
        }

        mapped.set(i);
        if (!isPreslotted) {
            nextNewRegister += maxCategory;
        }
    }

    return mapper;
}
 
Example #19
Source File: FirstFitLocalCombiningAllocator.java    From J2ME-Loader with Apache License 2.0 4 votes vote down vote up
/**
 * Maps the source registers of the specified instruction such that they
 * will fall in a contiguous range in rop form. Moves are inserted as
 * necessary to allow the range to be allocated.
 *
 * @param insn {@code non-null;} insn whos sources to process
 */
private void adjustAndMapSourceRangeRange(NormalSsaInsn insn) {
    int newRegStart = findRangeAndAdjust(insn);

    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    int nextRopReg = newRegStart;

    for (int i = 0; i < szSources; i++) {
        RegisterSpec source = sources.get(i);
        int sourceReg = source.getReg();
        int category = source.getCategory();
        int curRopReg = nextRopReg;
        nextRopReg += category;

        if (ssaRegsMapped.get(sourceReg)) {
            continue;
        }

        LocalItem localItem = getLocalItemForReg(sourceReg);
        addMapping(source, curRopReg);

        if (localItem != null) {
            markReserved(curRopReg, category);
            ArrayList<RegisterSpec> similarRegisters
                    = localVariables.get(localItem);

            int szSimilar = similarRegisters.size();

            /*
             * Try to map all SSA registers also associated with
             * this local.
             */
            for (int j = 0; j < szSimilar; j++) {
                RegisterSpec similarSpec = similarRegisters.get(j);
                int similarReg = similarSpec.getReg();

                // Don't map anything that's also a source.
                if (-1 != sources.indexOfRegister(similarReg)) {
                    continue;
                }

                // Registers left unmapped will get handled later.
                tryMapReg(similarSpec, curRopReg, category);
            }
        }
    }
}
 
Example #20
Source File: FirstFitLocalCombiningAllocator.java    From J2ME-Loader with Apache License 2.0 4 votes vote down vote up
/**
 * Handles all insns that want a register range for their sources.
 */
private void handleInvokeRangeInsns() {
    for (NormalSsaInsn insn : invokeRangeInsns) {
        adjustAndMapSourceRangeRange(insn);
    }
}
 
Example #21
Source File: FirstFitAllocator.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * Returns the parameter number that this move-param insn refers to
 * @param ndefInsn a move-param insn (otherwise, exceptions will be thrown)
 * @return parameter number (offset in the total parameter width)
 */
private int paramNumberFromMoveParam(NormalSsaInsn ndefInsn) {
    CstInsn origInsn = (CstInsn) ndefInsn.getOriginalRopInsn();

    return ((CstInteger) origInsn.getConstant()).getValue();
}
 
Example #22
Source File: FirstFitAllocator.java    From Box with Apache License 2.0 4 votes vote down vote up
/** {@inheritDoc} */
@Override
public RegisterMapper allocateRegisters() {
    int oldRegCount = ssaMeth.getRegCount();

    BasicRegisterMapper mapper
            = new BasicRegisterMapper(oldRegCount);

    int nextNewRegister = 0;

    if (PRESLOT_PARAMS) {
        /*
         * Reserve space for the params at the bottom of the register
         * space. Later, we'll flip the params to the end of the register
         * space.
         */

        nextNewRegister = ssaMeth.getParamWidth();
    }

    for (int i = 0; i < oldRegCount; i++) {
        if (mapped.get(i)) {
            // we already got this one
            continue;
        }

        int maxCategory = getCategoryForSsaReg(i);
        IntSet current = new BitIntSet(oldRegCount);

        interference.mergeInterferenceSet(i, current);

        boolean isPreslotted = false;
        int newReg = 0;

        if (PRESLOT_PARAMS && isDefinitionMoveParam(i)) {
            // Any move-param definition must be a NormalSsaInsn
            NormalSsaInsn defInsn = (NormalSsaInsn)
                   ssaMeth.getDefinitionForRegister(i);

            newReg = paramNumberFromMoveParam(defInsn);

            mapper.addMapping(i, newReg, maxCategory);
            isPreslotted = true;
        } else {
            mapper.addMapping(i, nextNewRegister, maxCategory);
            newReg = nextNewRegister;
        }

        for (int j = i + 1; j < oldRegCount; j++) {
            if (mapped.get(j) || isDefinitionMoveParam(j)) {
                continue;
            }

            /*
             * If reg j doesn't interfere with the current mapping.
             * Also, if this is a pre-slotted method parameter, we
             * can't use more than the original param width.
             */
            if (!current.has(j)
                    && !(isPreslotted
                        && (maxCategory < getCategoryForSsaReg(j)))) {

                interference.mergeInterferenceSet(j, current);

                maxCategory = Math.max(maxCategory,
                        getCategoryForSsaReg(j));

                mapper.addMapping(j, newReg, maxCategory);
                mapped.set(j);
            }
        }

        mapped.set(i);
        if (!isPreslotted) {
            nextNewRegister += maxCategory;
        }
    }

    return mapper;
}
 
Example #23
Source File: FirstFitLocalCombiningAllocator.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * Attempts to build a plan for fitting a range of sources into rop
 * registers.
 *
 * @param ropReg {@code >= 0;} rop reg that begins range
 * @param insn {@code non-null;} insn to plan range for
 * @param categoriesForIndex {@code non-null;} indexed by source index;
 * the category for each source
 * @param outMovesRequired {@code non-null;} an output parameter indexed by
 * source index that will contain the set of sources which need
 * moves inserted
 * @return the width of the fit that that does not involve added moves or
 * {@code -1} if "no fit possible"
 */
private int fitPlanForRange(int ropReg, NormalSsaInsn insn,
        int[] categoriesForIndex, BitSet outMovesRequired) {
    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    int fitWidth = 0;
    IntSet liveOut = insn.getBlock().getLiveOutRegs();
    RegisterSpecList liveOutSpecs = ssaSetToSpecs(liveOut);

    // An SSA reg may only be mapped into a range once.
    BitSet seen = new BitSet(ssaMeth.getRegCount());

    for (int i = 0; i < szSources ; i++) {
        RegisterSpec ssaSpec = sources.get(i);
        int ssaReg = ssaSpec.getReg();
        int category = categoriesForIndex[i];

        if (i != 0) {
            ropReg += categoriesForIndex[i-1];
        }

        if (ssaRegsMapped.get(ssaReg)
                && mapper.oldToNew(ssaReg) == ropReg) {
            // This is a register that is already mapped appropriately.
            fitWidth += category;
        } else if (rangeContainsReserved(ropReg, category)) {
            fitWidth = -1;
            break;
        } else if (!ssaRegsMapped.get(ssaReg)
                && canMapReg(ssaSpec, ropReg)
                && !seen.get(ssaReg)) {
            // This is a register that can be mapped appropriately.
            fitWidth += category;
        } else if (!mapper.areAnyPinned(liveOutSpecs, ropReg, category)
                && !mapper.areAnyPinned(sources, ropReg, category)) {
            /*
             * This is a source that can be moved. We can insert a
             * move as long as:
             *
             *   * no SSA register pinned to the desired rop reg
             *     is live out on the block
             *
             *   * no SSA register pinned to desired rop reg is
             *     a source of this insn (since this may require
             *     overlapping moves, which we can't presently handle)
             */

            outMovesRequired.set(i);
        } else {
            fitWidth = -1;
            break;
        }

        seen.set(ssaReg);
    }
    return fitWidth;
}
 
Example #24
Source File: FirstFitLocalCombiningAllocator.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * Finds an unreserved range that will fit the sources of the
 * specified instruction. Does not bother trying to center the range
 * around an already-mapped source register;
 *
 * @param insn {@code non-null;} insn to build range for
 * @param rangeLength {@code >=0;} length required in register units
 * @param categoriesForIndex {@code non-null;} indexed by source index;
 * the category for each source
 * @param outMovesRequired {@code non-null;} an output parameter indexed by
 * source index that will contain the set of sources which need
 * moves inserted
 * @return the rop register that starts the fitting range
 */
private int findAnyFittingRange(NormalSsaInsn insn, int rangeLength,
        int[] categoriesForIndex, BitSet outMovesRequired) {
    Alignment alignment = Alignment.UNSPECIFIED;

    if (DexOptions.ALIGN_64BIT_REGS_SUPPORT) {
      int regNumber = 0;
      int p64bitsAligned = 0;
      int p64bitsNotAligned = 0;
      for (int category : categoriesForIndex) {
        if (category == 2) {
          if (isEven(regNumber)) {
            p64bitsAligned++;
          } else {
            p64bitsNotAligned++;
          }
          regNumber += 2;
        } else {
          regNumber += 1;
        }
      }

      if (p64bitsNotAligned > p64bitsAligned) {
        if (isEven(paramRangeEnd)) {
          alignment = Alignment.ODD;
        } else {
          alignment = Alignment.EVEN;
        }
      } else if (p64bitsAligned > 0) {
        if (isEven(paramRangeEnd)) {
          alignment = Alignment.EVEN;
        } else {
          alignment = Alignment.ODD;
        }
      }
    }

    int rangeStart = paramRangeEnd;
    while (true) {
      rangeStart = findNextUnreservedRopReg(rangeStart, rangeLength, alignment);

      int fitWidth = fitPlanForRange(rangeStart, insn, categoriesForIndex, outMovesRequired);

      if (fitWidth >= 0) {
        break;
      }
      rangeStart++;
      outMovesRequired.clear();
    }

    return rangeStart;
}
 
Example #25
Source File: FirstFitLocalCombiningAllocator.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * Maps the source registers of the specified instruction such that they
 * will fall in a contiguous range in rop form. Moves are inserted as
 * necessary to allow the range to be allocated.
 *
 * @param insn {@code non-null;} insn whos sources to process
 */
private void adjustAndMapSourceRangeRange(NormalSsaInsn insn) {
    int newRegStart = findRangeAndAdjust(insn);

    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    int nextRopReg = newRegStart;

    for (int i = 0; i < szSources; i++) {
        RegisterSpec source = sources.get(i);
        int sourceReg = source.getReg();
        int category = source.getCategory();
        int curRopReg = nextRopReg;
        nextRopReg += category;

        if (ssaRegsMapped.get(sourceReg)) {
            continue;
        }

        LocalItem localItem = getLocalItemForReg(sourceReg);
        addMapping(source, curRopReg);

        if (localItem != null) {
            markReserved(curRopReg, category);
            ArrayList<RegisterSpec> similarRegisters
                    = localVariables.get(localItem);

            int szSimilar = similarRegisters.size();

            /*
             * Try to map all SSA registers also associated with
             * this local.
             */
            for (int j = 0; j < szSimilar; j++) {
                RegisterSpec similarSpec = similarRegisters.get(j);
                int similarReg = similarSpec.getReg();

                // Don't map anything that's also a source.
                if (-1 != sources.indexOfRegister(similarReg)) {
                    continue;
                }

                // Registers left unmapped will get handled later.
                tryMapReg(similarSpec, curRopReg, category);
            }
        }
    }
}
 
Example #26
Source File: FirstFitLocalCombiningAllocator.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * Handles all insns that want a register range for their sources.
 */
private void handleInvokeRangeInsns() {
    for (NormalSsaInsn insn : invokeRangeInsns) {
        adjustAndMapSourceRangeRange(insn);
    }
}
 
Example #27
Source File: FirstFitAllocator.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * Returns the parameter number that this move-param insn refers to
 * @param ndefInsn a move-param insn (otherwise, exceptions will be thrown)
 * @return parameter number (offset in the total parameter width)
 */
private int paramNumberFromMoveParam(NormalSsaInsn ndefInsn) {
    CstInsn origInsn = (CstInsn) ndefInsn.getOriginalRopInsn();

    return ((CstInteger) origInsn.getConstant()).getValue();
}
 
Example #28
Source File: FirstFitAllocator.java    From Box with Apache License 2.0 4 votes vote down vote up
/** {@inheritDoc} */
@Override
public RegisterMapper allocateRegisters() {
    int oldRegCount = ssaMeth.getRegCount();

    BasicRegisterMapper mapper
            = new BasicRegisterMapper(oldRegCount);

    int nextNewRegister = 0;

    if (PRESLOT_PARAMS) {
        /*
         * Reserve space for the params at the bottom of the register
         * space. Later, we'll flip the params to the end of the register
         * space.
         */

        nextNewRegister = ssaMeth.getParamWidth();
    }

    for (int i = 0; i < oldRegCount; i++) {
        if (mapped.get(i)) {
            // we already got this one
            continue;
        }

        int maxCategory = getCategoryForSsaReg(i);
        IntSet current = new BitIntSet(oldRegCount);

        interference.mergeInterferenceSet(i, current);

        boolean isPreslotted = false;
        int newReg = 0;

        if (PRESLOT_PARAMS && isDefinitionMoveParam(i)) {
            // Any move-param definition must be a NormalSsaInsn
            NormalSsaInsn defInsn = (NormalSsaInsn)
                   ssaMeth.getDefinitionForRegister(i);

            newReg = paramNumberFromMoveParam(defInsn);

            mapper.addMapping(i, newReg, maxCategory);
            isPreslotted = true;
        } else {
            mapper.addMapping(i, nextNewRegister, maxCategory);
            newReg = nextNewRegister;
        }

        for (int j = i + 1; j < oldRegCount; j++) {
            if (mapped.get(j) || isDefinitionMoveParam(j)) {
                continue;
            }

            /*
             * If reg j doesn't interfere with the current mapping.
             * Also, if this is a pre-slotted method parameter, we
             * can't use more than the original param width.
             */
            if (!current.has(j)
                    && !(isPreslotted
                        && (maxCategory < getCategoryForSsaReg(j)))) {

                interference.mergeInterferenceSet(j, current);

                maxCategory = Math.max(maxCategory,
                        getCategoryForSsaReg(j));

                mapper.addMapping(j, newReg, maxCategory);
                mapped.set(j);
            }
        }

        mapped.set(i);
        if (!isPreslotted) {
            nextNewRegister += maxCategory;
        }
    }

    return mapper;
}
 
Example #29
Source File: FirstFitLocalCombiningAllocator.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * Attempts to build a plan for fitting a range of sources into rop
 * registers.
 *
 * @param ropReg {@code >= 0;} rop reg that begins range
 * @param insn {@code non-null;} insn to plan range for
 * @param categoriesForIndex {@code non-null;} indexed by source index;
 * the category for each source
 * @param outMovesRequired {@code non-null;} an output parameter indexed by
 * source index that will contain the set of sources which need
 * moves inserted
 * @return the width of the fit that that does not involve added moves or
 * {@code -1} if "no fit possible"
 */
private int fitPlanForRange(int ropReg, NormalSsaInsn insn,
        int[] categoriesForIndex, BitSet outMovesRequired) {
    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    int fitWidth = 0;
    IntSet liveOut = insn.getBlock().getLiveOutRegs();
    RegisterSpecList liveOutSpecs = ssaSetToSpecs(liveOut);

    // An SSA reg may only be mapped into a range once.
    BitSet seen = new BitSet(ssaMeth.getRegCount());

    for (int i = 0; i < szSources ; i++) {
        RegisterSpec ssaSpec = sources.get(i);
        int ssaReg = ssaSpec.getReg();
        int category = categoriesForIndex[i];

        if (i != 0) {
            ropReg += categoriesForIndex[i-1];
        }

        if (ssaRegsMapped.get(ssaReg)
                && mapper.oldToNew(ssaReg) == ropReg) {
            // This is a register that is already mapped appropriately.
            fitWidth += category;
        } else if (rangeContainsReserved(ropReg, category)) {
            fitWidth = -1;
            break;
        } else if (!ssaRegsMapped.get(ssaReg)
                && canMapReg(ssaSpec, ropReg)
                && !seen.get(ssaReg)) {
            // This is a register that can be mapped appropriately.
            fitWidth += category;
        } else if (!mapper.areAnyPinned(liveOutSpecs, ropReg, category)
                && !mapper.areAnyPinned(sources, ropReg, category)) {
            /*
             * This is a source that can be moved. We can insert a
             * move as long as:
             *
             *   * no SSA register pinned to the desired rop reg
             *     is live out on the block
             *
             *   * no SSA register pinned to desired rop reg is
             *     a source of this insn (since this may require
             *     overlapping moves, which we can't presently handle)
             */

            outMovesRequired.set(i);
        } else {
            fitWidth = -1;
            break;
        }

        seen.set(ssaReg);
    }
    return fitWidth;
}
 
Example #30
Source File: FirstFitLocalCombiningAllocator.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * Finds an unreserved range that will fit the sources of the
 * specified instruction. Does not bother trying to center the range
 * around an already-mapped source register;
 *
 * @param insn {@code non-null;} insn to build range for
 * @param rangeLength {@code >=0;} length required in register units
 * @param categoriesForIndex {@code non-null;} indexed by source index;
 * the category for each source
 * @param outMovesRequired {@code non-null;} an output parameter indexed by
 * source index that will contain the set of sources which need
 * moves inserted
 * @return the rop register that starts the fitting range
 */
private int findAnyFittingRange(NormalSsaInsn insn, int rangeLength,
        int[] categoriesForIndex, BitSet outMovesRequired) {
    Alignment alignment = Alignment.UNSPECIFIED;

    if (DexOptions.ALIGN_64BIT_REGS_SUPPORT) {
      int regNumber = 0;
      int p64bitsAligned = 0;
      int p64bitsNotAligned = 0;
      for (int category : categoriesForIndex) {
        if (category == 2) {
          if (isEven(regNumber)) {
            p64bitsAligned++;
          } else {
            p64bitsNotAligned++;
          }
          regNumber += 2;
        } else {
          regNumber += 1;
        }
      }

      if (p64bitsNotAligned > p64bitsAligned) {
        if (isEven(paramRangeEnd)) {
          alignment = Alignment.ODD;
        } else {
          alignment = Alignment.EVEN;
        }
      } else if (p64bitsAligned > 0) {
        if (isEven(paramRangeEnd)) {
          alignment = Alignment.EVEN;
        } else {
          alignment = Alignment.ODD;
        }
      }
    }

    int rangeStart = paramRangeEnd;
    while (true) {
      rangeStart = findNextUnreservedRopReg(rangeStart, rangeLength, alignment);

      int fitWidth = fitPlanForRange(rangeStart, insn, categoriesForIndex, outMovesRequired);

      if (fitWidth >= 0) {
        break;
      }
      rangeStart++;
      outMovesRequired.clear();
    }

    return rangeStart;
}