1/* 2 * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25package sun.jvm.hotspot.oops; 26 27import java.io.*; 28import sun.jvm.hotspot.utilities.*; 29 30/** Auxiliary class for GenerateOopMap */ 31public class CellTypeState { 32 private int _state; 33 34 // Masks for separating the BITS and INFO portions of a 35 // CellTypeState 36 private static final int info_mask = Bits.rightNBits(28); 37 private static final int bits_mask = ~info_mask; 38 39 // These constant are used for manipulating the BITS portion of a 40 // CellTypeState 41 private static final int uninit_bit = Bits.nthBit(31); 42 private static final int ref_bit = Bits.nthBit(30); 43 private static final int val_bit = Bits.nthBit(29); 44 private static final int addr_bit = Bits.nthBit(28); 45 private static final int live_bits_mask = bits_mask & ~uninit_bit; 46 47 // These constants are used for manipulating the INFO portion of a 48 // CellTypeState 49 private static final int top_info_bit = Bits.nthBit(27); 50 private static final int not_bottom_info_bit = Bits.nthBit(26); 51 private static final int info_data_mask = Bits.rightNBits(26); 52 private static final int info_conflict = info_mask; 53 54 // Within the INFO data, these values are used to distinguish 55 // different kinds of references. 56 // 0 if this reference is locked as a monitor 57 private static final int ref_not_lock_bit = Bits.nthBit(25); 58 // 1 if this reference is a "slot" reference 59 private static final int ref_slot_bit = Bits.nthBit(24); 60 // 0 if it is a "line" reference. 61 private static final int ref_data_mask = Bits.rightNBits(24); 62 63 // These values are used to initialize commonly used CellTypeState 64 // constants. 65 private static final int bottom_value = 0; 66 private static final int uninit_value = uninit_bit | info_conflict; 67 private static final int ref_value = ref_bit; 68 private static final int ref_conflict = ref_bit | info_conflict; 69 private static final int val_value = val_bit | info_conflict; 70 private static final int addr_value = addr_bit; 71 private static final int addr_conflict = addr_bit | info_conflict; 72 73 private CellTypeState() {} 74 75 private CellTypeState(int state) { 76 _state = state; 77 } 78 79 public CellTypeState copy() { 80 return new CellTypeState(_state); 81 } 82 83 public static CellTypeState makeAny(int state) { 84 CellTypeState s = new CellTypeState(state); 85 if (Assert.ASSERTS_ENABLED) { 86 Assert.that(s.isValidState(), "check to see if CellTypeState is valid"); 87 } 88 return s; 89 } 90 91 public static CellTypeState makeBottom() { 92 return makeAny(0); 93 } 94 95 public static CellTypeState makeTop() { 96 return makeAny(Bits.AllBits); 97 } 98 99 public static CellTypeState makeAddr(int bci) { 100 if (Assert.ASSERTS_ENABLED) { 101 Assert.that((bci >= 0) && (bci < info_data_mask), 102 "check to see if ret addr is valid"); 103 } 104 return makeAny(addr_bit | not_bottom_info_bit | (bci & info_data_mask)); 105 } 106 107 public static CellTypeState makeSlotRef(int slot_num) { 108 if (Assert.ASSERTS_ENABLED) { 109 Assert.that(slot_num >= 0 && slot_num < ref_data_mask, "slot out of range"); 110 } 111 return makeAny(ref_bit | not_bottom_info_bit | ref_not_lock_bit | ref_slot_bit | 112 (slot_num & ref_data_mask)); 113 } 114 115 public static CellTypeState makeLineRef(int bci) { 116 if (Assert.ASSERTS_ENABLED) { 117 Assert.that(bci >= 0 && bci < ref_data_mask, "line out of range"); 118 } 119 return makeAny(ref_bit | not_bottom_info_bit | ref_not_lock_bit | 120 (bci & ref_data_mask)); 121 } 122 123 public static CellTypeState makeLockRef(int bci) { 124 if (Assert.ASSERTS_ENABLED) { 125 Assert.that(bci >= 0 && bci < ref_data_mask, "line out of range"); 126 } 127 return makeAny(ref_bit | not_bottom_info_bit | (bci & ref_data_mask)); 128 } 129 130 // Query methods: 131 public boolean isBottom() { return _state == 0; } 132 public boolean isLive() { return ((_state & live_bits_mask) != 0); } 133 public boolean isValidState() { 134 // Uninitialized and value cells must contain no data in their info field: 135 if ((canBeUninit() || canBeValue()) && !isInfoTop()) { 136 return false; 137 } 138 // The top bit is only set when all info bits are set: 139 if (isInfoTop() && ((_state & info_mask) != info_mask)) { 140 return false; 141 } 142 // The not_bottom_bit must be set when any other info bit is set: 143 if (isInfoBottom() && ((_state & info_mask) != 0)) { 144 return false; 145 } 146 return true; 147 } 148 149 public boolean isAddress() { return ((_state & bits_mask) == addr_bit); } 150 public boolean isReference() { return ((_state & bits_mask) == ref_bit); } 151 public boolean isValue() { return ((_state & bits_mask) == val_bit); } 152 public boolean isUninit() { return ((_state & bits_mask) == uninit_bit); } 153 154 public boolean canBeAddress() { return ((_state & addr_bit) != 0); } 155 public boolean canBeReference() { return ((_state & ref_bit) != 0); } 156 public boolean canBeValue() { return ((_state & val_bit) != 0); } 157 public boolean canBeUninit() { return ((_state & uninit_bit) != 0); } 158 159 public boolean isInfoBottom() { return ((_state & not_bottom_info_bit) == 0); } 160 public boolean isInfoTop() { return ((_state & top_info_bit) != 0); } 161 public int getInfo() { 162 if (Assert.ASSERTS_ENABLED) { 163 Assert.that((!isInfoTop() && !isInfoBottom()), 164 "check to make sure top/bottom info is not used"); 165 } 166 return (_state & info_data_mask); 167 } 168 169 public int getMonitorSource() { 170 if (Assert.ASSERTS_ENABLED) { 171 Assert.that(isLockReference(), "must be lock"); 172 } 173 return getInfo(); 174 } 175 176 public boolean isGoodAddress() { return isAddress() && !isInfoTop(); } 177 public boolean isLockReference() { 178 return ((_state & (bits_mask | top_info_bit | ref_not_lock_bit)) == ref_bit); 179 } 180 public boolean isNonlockReference() { 181 return ((_state & (bits_mask | top_info_bit | ref_not_lock_bit)) == (ref_bit | ref_not_lock_bit)); 182 } 183 184 public boolean equal(CellTypeState a) { return _state == a._state; } 185 public boolean equalKind(CellTypeState a) { 186 return (_state & bits_mask) == (a._state & bits_mask); 187 } 188 189 public char toChar() { 190 if (canBeReference()) { 191 if (canBeValue() || canBeAddress()) 192 return '#'; // Conflict that needs to be rewritten 193 else 194 return 'r'; 195 } else if (canBeValue()) 196 return 'v'; 197 else if (canBeAddress()) 198 return 'p'; 199 else if (canBeUninit()) 200 return ' '; 201 else 202 return '@'; 203 } 204 205 // Set 206 public void set(CellTypeState cts) { 207 _state = cts._state; 208 } 209 210 // Merge 211 public CellTypeState merge (CellTypeState cts, int slot) { 212 CellTypeState result = new CellTypeState(); 213 214 if (Assert.ASSERTS_ENABLED) { 215 Assert.that(!isBottom() && !cts.isBottom(), 216 "merge of bottom values is handled elsewhere"); 217 } 218 219 result._state = _state | cts._state; 220 221 // If the top bit is set, we don't need to do any more work. 222 if (!result.isInfoTop()) { 223 Assert.that((result.canBeAddress() || result.canBeReference()), 224 "only addresses and references have non-top info"); 225 226 if (!equal(cts)) { 227 // The two values being merged are different. Raise to top. 228 if (result.isReference()) { 229 result = CellTypeState.makeSlotRef(slot); 230 } else { 231 result._state |= info_conflict; 232 } 233 } 234 } 235 if (Assert.ASSERTS_ENABLED) { 236 Assert.that(result.isValidState(), "checking that CTS merge maintains legal state"); 237 } 238 239 return result; 240 } 241 242 // Debugging output 243 public void print(PrintStream tty) { 244 if (canBeAddress()) { 245 tty.print("(p"); 246 } else { 247 tty.print("( "); 248 } 249 if (canBeReference()) { 250 tty.print("r"); 251 } else { 252 tty.print(" "); 253 } 254 if (canBeValue()) { 255 tty.print("v"); 256 } else { 257 tty.print(" "); 258 } 259 if (canBeUninit()) { 260 tty.print("u|"); 261 } else { 262 tty.print(" |"); 263 } 264 if (isInfoTop()) { 265 tty.print("Top)"); 266 } else if (isInfoBottom()) { 267 tty.print("Bot)"); 268 } else { 269 if (isReference()) { 270 int info = getInfo(); 271 int data = info & ~(ref_not_lock_bit | ref_slot_bit); 272 if ((info & ref_not_lock_bit) != 0) { 273 // Not a monitor lock reference. 274 if ((info & ref_slot_bit) != 0) { 275 // slot 276 tty.print("slot" + data + ")"); 277 } else { 278 // line 279 tty.print("line" + data + ")"); 280 } 281 } else { 282 // lock 283 tty.print("lock" + data + ")"); 284 } 285 } else { 286 tty.print("" + getInfo() + ")"); 287 } 288 } 289 } 290 291 // Default values of common values 292 public static CellTypeState bottom = CellTypeState.makeBottom(); 293 public static CellTypeState uninit = CellTypeState.makeAny(uninit_value); 294 public static CellTypeState ref = CellTypeState.makeAny(ref_conflict); 295 public static CellTypeState value = CellTypeState.makeAny(val_value); 296 public static CellTypeState refUninit = CellTypeState.makeAny(ref_conflict | uninit_value); 297 public static CellTypeState top = CellTypeState.makeTop(); 298 public static CellTypeState addr = CellTypeState.makeAny(addr_conflict); 299} 300