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}