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.ir;
014
015import java.util.List;
016
017/**
018 *  This class holds each element in the GCIRMap
019 */
020public final class GCIRMapElement {
021
022  /**
023   *  The instruction, i.e., GC point
024   */
025  private final Instruction inst;
026
027  /**
028   *  The list of references (either symbolic regs or physical regs & spills)
029   */
030  private final List<RegSpillListElement> regSpillList;
031
032  /**
033   * @param inst the instruction of interest
034   * @param regSpillList the list of references either symbolic (before regalloc)
035   *                or physical/spill location (after regalloc)
036   */
037  public GCIRMapElement(Instruction inst, List<RegSpillListElement> regSpillList) {
038    this.inst = inst;
039    this.regSpillList = regSpillList;
040  }
041
042  /**
043   * Creates a twin entry: required when the same MIR GC point
044   * is split into two instructions, both of which are PEIs
045   * after register allocation/GCIRMap creation.
046   *
047   * @param inst the instruction which needs a twin element
048   * @return the twin entry
049   */
050  public GCIRMapElement createTwin(Instruction inst) {
051    return new GCIRMapElement(inst, this.regSpillList);
052  }
053
054  /**
055   * @return the instruction with this entry
056   */
057  public Instruction getInstruction() {
058    return inst;
059  }
060
061  /**
062   * returns an enumerator to access the registers/spills for this entry
063   * @return an enumerator to access the registers/spills for this entry
064   */
065  public List<RegSpillListElement> regSpillList() {
066    return regSpillList;
067  }
068
069  public void addRegSpillElement(RegSpillListElement e) {
070    regSpillList.add(e);
071  }
072
073  public void deleteRegSpillElement(RegSpillListElement e) {
074    regSpillList.remove(e);
075  }
076
077  /**
078   * Counts and returns the number of references for this map
079   * @return the number of references, either regs or spills for this map
080   */
081  public int countNumElements() {
082    return regSpillList.size();
083  }
084
085  /**
086   * Counts and returns the number of register elements (not spills)
087   *     for this entry
088   * @return the number of register elements for this entry
089   */
090  public int countNumRegElements() {
091    int count = 0;
092
093    for (RegSpillListElement elem : regSpillList) {
094      if (!elem.isSpill()) {
095        count++;
096      }
097    }
098    return count;
099  }
100
101  /**
102   * Counts and returns the number of spill for this entry
103   * @return the number of spill for this entry
104   */
105  public int countNumSpillElements() {
106    int count = 0;
107    // traverse the list and compute how many spills exist
108    for (RegSpillListElement elem : regSpillList) {
109      if (elem.isSpill()) {
110        count++;
111      }
112    }
113    return count;
114  }
115
116  /**
117   * Return a string version of this object
118   * @return a string version of this object
119   */
120  @Override
121  public String toString() {
122    StringBuilder buf = new StringBuilder();
123    buf.append(" Instruction: ").append(inst.bcIndex).append(", ").append(inst);
124    for (RegSpillListElement elem : regSpillList) {
125      buf.append(elem).append("  ");
126    }
127    buf.append("\n");
128    return buf.toString();
129  }
130}