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.osr;
014
015import static org.jikesrvm.osr.OSRConstants.KIND_MASK;
016import static org.jikesrvm.osr.OSRConstants.KIND_SHIFT;
017import static org.jikesrvm.osr.OSRConstants.NEXT_BIT;
018import static org.jikesrvm.osr.OSRConstants.NUM_MASK;
019import static org.jikesrvm.osr.OSRConstants.NUM_SHIFT;
020import static org.jikesrvm.osr.OSRConstants.TCODE_MASK;
021import static org.jikesrvm.osr.OSRConstants.TCODE_SHIFT;
022import static org.jikesrvm.osr.OSRConstants.VTYPE_MASK;
023import static org.jikesrvm.osr.OSRConstants.VTYPE_SHIFT;
024
025import org.jikesrvm.VM;
026
027/**
028 * An iterator over an encoded OSR map.
029 * It is a bit odd to used now.
030 * <pre>
031 *     while (it.hasMore()) {
032 *       it.getKind();
033 *       it.getNumber();
034 *       it.getMethodId();
035 *       it.getBcIndex();
036 *       ....
037 *
038 *       it.moveToNext();
039 *     }
040 *</pre>
041 */
042
043public class OSRMapIterator {
044  private int curidx;
045  private final int[] maps;
046  private int curmid;
047  private int curmpc;
048
049  private boolean moreMethId = false;
050  private boolean moreElemnt = false;
051
052  public OSRMapIterator(int[] mapcode, int index) {
053    // skip over the map of registers which are references.
054    this.curidx = index + 1;
055    this.maps = mapcode;
056
057    if ((mapcode[index] & NEXT_BIT) != 0) {
058      this.moreMethId = true;
059      moveToNextMethodId();
060    }
061  }
062
063  public boolean hasMore() {
064    return this.moreElemnt;
065  }
066
067  /**
068   * after finishing iteration of one method, move to the next,
069   * it if is empty, move further.
070   */
071  private void moveToNextMethodId() {
072//    VM.sysWriteln("move to next method id "+this.curidx);
073
074    this.curmid = maps[curidx] & ~NEXT_BIT;
075    this.moreMethId = (maps[curidx] & NEXT_BIT) != 0;
076
077    this.curidx++;
078    this.curmpc = maps[curidx] & ~NEXT_BIT;
079    this.moreElemnt = (maps[curidx] & NEXT_BIT) != 0;
080
081    this.curidx++;
082
083    // if this method id entry is empty, skip to the next
084    if (!hasMoreElements() && hasMoreMethodId()) {
085      moveToNextMethodId();
086    }
087  }
088
089  /** @return whether another method id is available */
090  private boolean hasMoreMethodId() {
091    return this.moreMethId;
092  }
093
094  /** @return whether there's more elements for the current method id */
095  private boolean hasMoreElements() {
096    return this.moreElemnt;
097  }
098
099  /**
100   * Moves the index to the next element, update more first because
101   * we use last element's bit to indicate whether this element is
102   * available.
103   */
104  public void moveToNext() {
105    if (VM.VerifyAssertions) VM._assert(this.hasMore());
106
107    this.moreElemnt = (maps[curidx] & NEXT_BIT) != 0;
108    this.curidx += 2;
109    if (!hasMoreElements() && hasMoreMethodId()) {
110      moveToNextMethodId();
111    }
112  }
113
114  /* for the current element, provide a list of queries. */
115
116  public boolean getKind() {
117    return (maps[curidx] & KIND_MASK) >> KIND_SHIFT != 0;
118  }
119
120  public byte getTypeCode() {
121    return (byte)((maps[curidx] & TCODE_MASK) >> TCODE_SHIFT);
122  }
123
124  public char getNumber() {
125    return (char)((maps[curidx] & NUM_MASK) >> NUM_SHIFT);
126  }
127
128  public byte getValueType() {
129    return (byte)((maps[curidx] & VTYPE_MASK) >> VTYPE_SHIFT);
130  }
131
132  public int getValue() {
133    return maps[curidx + 1];
134  }
135
136  public int getMethodId() {
137    return this.curmid;
138  }
139
140  /** @return the current program counter */
141  public int getBcIndex() {
142    return this.curmpc;
143  }
144}