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}