/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.opt.ir; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import org.jikesrvm.compilers.opt.OptimizingCompilerException; import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; import org.jikesrvm.compilers.opt.liveness.LiveSet; import org.jikesrvm.compilers.opt.liveness.LiveSetEnumerator; import org.jikesrvm.util.LinkedListRVM; /** * * This class holds GC maps for various program points. * This data structure is IR-based. In a later phase, this information * will be used to create the final GC map (see OptMachineCodeMap.java) */ public final class GCIRMap implements Iterable<GCIRMapElement> { /** * This is the list of maps * Each element on the list is an GCIRMapElement, which is a pair * - an IR instruction (the GC point) * - a list of RegSpillListElement, which initially hold symbolic * registers that are references * (these are expanded to either physical regs or spills * by the register allocator) */ private final LinkedListRVM<GCIRMapElement> list = new LinkedListRVM<GCIRMapElement>(); /** * Used for class-wide debugging */ private static final boolean DEBUG = false; /** * returns the number of GC points in this map, i.e., the number of * instructions we have maps for. * @return the number of GC points in this map */ public int getNumInstructionMaps() { return list.size(); } /** * Calculates the number of spill entries in this GCIRMap * This is the total number of spills for all instructions * in this map. * @return the number of spill entries in this map */ public int countNumSpillElements() { // Since spill locations are not determined until after // register allocation occurs, i.e., after the initial // IR-based maps are created, we actually count the // number of spills. int count = 0; for (GCIRMapElement elem : this) { count += elem.countNumSpillElements(); } return count; } /** * TODO What is this method doing in this class ?? RJG * * This method creates a regSpillList from the passed live set. * @param set the set of registers, encoded as a LiveSet object * @return a list corresponding to the set passed */ public List<RegSpillListElement> createDU(LiveSet set) { if (DEBUG) { System.out.println("creating a RegList for " + set); } // construct register list List<RegSpillListElement> regList = new LinkedListRVM<RegSpillListElement>(); LiveSetEnumerator lsEnum = set.enumerator(); while (lsEnum.hasMoreElements()) { RegisterOperand regOp = lsEnum.nextElement(); // add this register to the regList, if it is a reference // and not a physcial register if (regOp.getType().isReferenceType() && !regOp.getRegister().isPhysical()) { RegSpillListElement elem = new RegSpillListElement(regOp.getRegister()); regList.add(elem); } } return regList; } /** * This method inserts a new entry into the GCIRMap * @param inst the IR instruction we care about * @param regList the set of symbolic registers as a list */ public void insert(Instruction inst, List<RegSpillListElement> regList) { // make a GCIRMapElement and put it on the big list GCIRMapElement item = new GCIRMapElement(inst, regList); if (DEBUG) { System.out.println("Inserting new item: " + item); } list.add(item); } /** * This method removes an entry in the GCIRMap that is specified * by inst. Only one element of the list will be removed per call. * If the instruction is not found in the GC Map and exeception is thrown. * @param inst the IR instruction we want to remove */ public void delete(Instruction inst) { Iterator<GCIRMapElement> iter = list.iterator(); while (iter.hasNext()) { GCIRMapElement ptr = iter.next(); if (ptr.getInstruction() == inst) { iter.remove(); return; } } throw new OptimizingCompilerException("GCIRMap.delete(" + inst + ") did not delete instruction from GC Map "); } /** * This method moves an entry in the GCIRMap that is specified * by inst to the end of the list. Only one element of the list will be moved per call. * If the instruction is not found in the GC Map and exeception is thrown. * @param inst the IR instruction we want to remove */ public void moveToEnd(Instruction inst) { Iterator<GCIRMapElement> iter = list.iterator(); while (iter.hasNext()) { GCIRMapElement newPtr = iter.next(); if (newPtr.getInstruction() == inst) { iter.remove(); list.add(newPtr); return; } } throw new OptimizingCompilerException("GCIRMap.moveToEnd(" + inst + ") did not delete instruction from GC Map "); } /** * This method inserts an entry for a "twin" instruction immediately after the * original entry. * If the instruction is not found in the GC Map an exeception is thrown. * @param inst the orignal IR instruction * @param twin the new twin IR instruction */ public void insertTwin(Instruction inst, Instruction twin) { ListIterator<GCIRMapElement> iter = list.listIterator(); while (iter.hasNext()) { GCIRMapElement newPtr = iter.next(); if (newPtr.getInstruction() == inst) { iter.add(newPtr.createTwin(twin)); return; } } throw new OptimizingCompilerException("GCIRMap.createTwin: " + inst + " not found"); } public Iterator<GCIRMapElement> iterator() { return list.iterator(); } /** * dumps the map */ public void dump() { System.out.println(toString()); } /** * @return string version of this object */ public String toString() { StringBuilder buf = new StringBuilder(""); if (list.isEmpty()) { buf.append("empty"); } else { for (GCIRMapElement ptr : list) { buf.append(ptr); } } return buf.toString(); } }