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