001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.compilers.opt.regalloc;
014
015import static org.jikesrvm.classloader.ClassLoaderConstants.LongTypeCode;
016import static org.jikesrvm.osr.OSRConstants.ACONST;
017import static org.jikesrvm.osr.OSRConstants.ICONST;
018import static org.jikesrvm.osr.OSRConstants.LCONST;
019import static org.jikesrvm.osr.OSRConstants.PHYREG;
020import static org.jikesrvm.osr.OSRConstants.SPILL;
021
022import org.jikesrvm.VM;
023import org.jikesrvm.compilers.opt.OptOptions;
024import org.jikesrvm.compilers.opt.OptimizingCompilerException;
025import org.jikesrvm.compilers.opt.driver.CompilerPhase;
026import org.jikesrvm.compilers.opt.ir.IR;
027import org.jikesrvm.compilers.opt.ir.Register;
028import org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand;
029import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand;
030import org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand;
031import org.jikesrvm.compilers.opt.ir.operand.Operand;
032import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
033import org.jikesrvm.osr.LocalRegPair;
034import org.jikesrvm.osr.MethodVariables;
035import org.jikesrvm.osr.VariableMapElement;
036import org.vmmagic.unboxed.Word;
037
038/**
039 * Update GC maps after register allocation but before inserting spill
040 * code.
041 */
042public final class UpdateOSRMaps extends CompilerPhase {
043
044  @Override
045  public boolean shouldPerform(OptOptions options) {
046    return true;
047  }
048
049  /**
050   * Return this instance of this phase. This phase contains no
051   * per-compilation instance fields.
052   * @param ir not used
053   * @return this
054   */
055  @Override
056  public CompilerPhase newExecution(IR ir) {
057    return this;
058  }
059
060  @Override
061  public String getName() {
062    return "Update OSRMaps";
063  }
064
065  @Override
066  public boolean printingEnabled(OptOptions options, boolean before) {
067    return false;
068  }
069
070  /**
071   * Iterate over the IR-based OSR map, and update symbolic registers
072   * with real reg number or spill locations.
073   * Verify there are only two types of operands:
074   *    ConstantOperand
075   *    RegisterOperand
076   *        for integer constant, we save the value of the integer
077   *
078   * The LONG register has another half part.
079   *
080   * CodeSpill replaces any allocated symbolic register by
081   * physical registers.
082   */
083  @Override
084  public void perform(IR ir) throws OptimizingCompilerException {
085    // list of OsrVariableMapElement
086    //LinkedList<VariableMapElement> mapList = ir.MIRInfo.osrVarMap.list;
087    //for (int numOsrs=0, m=mapList.size(); numOsrs<m; numOsrs++) {
088    //  VariableMapElement elm = mapList.get(numOsrs);
089    /* for each osr instruction */
090    for (VariableMapElement elm : ir.MIRInfo.osrVarMap.list) {
091
092      // for each inlined method
093      //LinkedList<MethodVariables> mvarsList = elm.mvars;                   XXX Remove once proven correct
094      //for (int numMvars=0, n=mvarsList.size(); numMvars<n; numMvars++) {
095      //  MethodVariables mvar = mvarsList.get(numMvars);
096      for (MethodVariables mvar : elm.mvars) {
097
098        // for each tuple
099        //LinkedList<LocalRegPair> tupleList = mvar.tupleList;
100        //for (int numTuple=0, k=tupleList.size(); numTuple<k; numTuple++) {
101        //LocalRegPair tuple = tupleList.get(numTuple);
102        for (LocalRegPair tuple : mvar.tupleList) {
103
104          Operand op = tuple.operand;
105          if (op.isRegister()) {
106            Register sym_reg = ((RegisterOperand) op).getRegister();
107
108            setRealPosition(ir, tuple, sym_reg);
109
110            // get another half part of long register
111            if (VM.BuildFor32Addr && (tuple.typeCode == LongTypeCode)) {
112
113              LocalRegPair other = tuple._otherHalf;
114              Operand other_op = other.operand;
115
116              if (VM.VerifyAssertions) VM._assert(other_op.isRegister());
117
118              Register other_reg = ((RegisterOperand) other_op).getRegister();
119              setRealPosition(ir, other, other_reg);
120            }
121            /* According to ConvertToLowLevelIR, StringConstant, LongConstant,
122            * NullConstant, FloatConstant, and DoubleConstant are all materialized
123            * The only thing left is the integer constants which could encode
124            * non-moveable objects.
125            * POTENTIAL DRAWBACKS: since any long, float, and double are moved
126            * to register and treated as use, it may consume more registers and
127            * add unnecessary MOVEs.
128            *
129            * Perhaps, ConvertToLowLevelIR can skip OsrPoint instruction.
130            */
131          } else if (op.isIntConstant()) {
132            setTupleValue(tuple, ICONST, ((IntConstantOperand) op).value);
133            if (VM.BuildFor32Addr && (tuple.typeCode == LongTypeCode)) {
134              LocalRegPair other = tuple._otherHalf;
135              Operand other_op = other.operand;
136
137              if (VM.VerifyAssertions) VM._assert(other_op.isIntConstant());
138              setTupleValue(other, ICONST, ((IntConstantOperand) other_op).value);
139            }
140          } else if (op.isAddressConstant()) {
141            setTupleValue(tuple, ACONST, ((AddressConstantOperand) op).value.toWord());
142          } else if (VM.BuildFor64Addr && op.isLongConstant()) {
143            setTupleValue(tuple, LCONST, Word.fromLong(((LongConstantOperand) op).value));
144          } else {
145            throw new OptimizingCompilerException("LinearScan", "Unexpected operand type at ", op.toString());
146          } // for the op type
147        } // for each tuple
148      } // for each inlined method
149    } // for each osr instruction
150  }
151
152  void setRealPosition(IR ir, LocalRegPair tuple, Register sym_reg) {
153    if (VM.VerifyAssertions) VM._assert(sym_reg != null);
154
155    int REG_MASK = 0x01F;
156
157    // now it is not symbolic register anymore.
158    // is is really confusing that sometimes a sym reg is a phy,
159    // and sometimes not.
160    if (sym_reg.isAllocated()) {
161      setTupleValue(tuple, PHYREG, sym_reg.number & REG_MASK);
162    } else if (sym_reg.isPhysical()) {
163      setTupleValue(tuple, PHYREG, sym_reg.number & REG_MASK);
164    } else if (sym_reg.isSpilled()) {
165      int spillLocation = ir.MIRInfo.regAllocState.getSpill(sym_reg);
166      setTupleValue(tuple, SPILL, spillLocation);
167    } else {
168      dumpIR(ir, "PANIC");
169      throw new RuntimeException("LinearScan PANIC in OSRMAP, " + sym_reg + " is not alive");
170    }
171  }
172
173  static void setTupleValue(LocalRegPair tuple, byte type, int value) {
174    tuple.valueType = type;
175    tuple.value = Word.fromIntSignExtend(value);
176  }
177
178  static void setTupleValue(LocalRegPair tuple, byte type, Word value) {
179    tuple.valueType = type;
180    tuple.value = value;
181  }
182}