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