| /* |
| * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| * |
| */ |
| |
| package sun.jvm.hotspot.oops; |
| |
| import java.io.*; |
| import sun.jvm.hotspot.utilities.*; |
| |
| /** Auxiliary class for GenerateOopMap */ |
| public class CellTypeState { |
| private int _state; |
| |
| // Masks for separating the BITS and INFO portions of a |
| // CellTypeState |
| private static final int info_mask = Bits.rightNBits(28); |
| private static final int bits_mask = ~info_mask; |
| |
| // These constant are used for manipulating the BITS portion of a |
| // CellTypeState |
| private static final int uninit_bit = Bits.nthBit(31); |
| private static final int ref_bit = Bits.nthBit(30); |
| private static final int val_bit = Bits.nthBit(29); |
| private static final int addr_bit = Bits.nthBit(28); |
| private static final int live_bits_mask = bits_mask & ~uninit_bit; |
| |
| // These constants are used for manipulating the INFO portion of a |
| // CellTypeState |
| private static final int top_info_bit = Bits.nthBit(27); |
| private static final int not_bottom_info_bit = Bits.nthBit(26); |
| private static final int info_data_mask = Bits.rightNBits(26); |
| private static final int info_conflict = info_mask; |
| |
| // Within the INFO data, these values are used to distinguish |
| // different kinds of references. |
| // 0 if this reference is locked as a monitor |
| private static final int ref_not_lock_bit = Bits.nthBit(25); |
| // 1 if this reference is a "slot" reference |
| private static final int ref_slot_bit = Bits.nthBit(24); |
| // 0 if it is a "line" reference. |
| private static final int ref_data_mask = Bits.rightNBits(24); |
| |
| // These values are used to initialize commonly used CellTypeState |
| // constants. |
| private static final int bottom_value = 0; |
| private static final int uninit_value = uninit_bit | info_conflict; |
| private static final int ref_value = ref_bit; |
| private static final int ref_conflict = ref_bit | info_conflict; |
| private static final int val_value = val_bit | info_conflict; |
| private static final int addr_value = addr_bit; |
| private static final int addr_conflict = addr_bit | info_conflict; |
| |
| private CellTypeState() {} |
| |
| private CellTypeState(int state) { |
| _state = state; |
| } |
| |
| public CellTypeState copy() { |
| return new CellTypeState(_state); |
| } |
| |
| public static CellTypeState makeAny(int state) { |
| CellTypeState s = new CellTypeState(state); |
| if (Assert.ASSERTS_ENABLED) { |
| Assert.that(s.isValidState(), "check to see if CellTypeState is valid"); |
| } |
| return s; |
| } |
| |
| public static CellTypeState makeBottom() { |
| return makeAny(0); |
| } |
| |
| public static CellTypeState makeTop() { |
| return makeAny(Bits.AllBits); |
| } |
| |
| public static CellTypeState makeAddr(int bci) { |
| if (Assert.ASSERTS_ENABLED) { |
| Assert.that((bci >= 0) && (bci < info_data_mask), |
| "check to see if ret addr is valid"); |
| } |
| return makeAny(addr_bit | not_bottom_info_bit | (bci & info_data_mask)); |
| } |
| |
| public static CellTypeState makeSlotRef(int slot_num) { |
| if (Assert.ASSERTS_ENABLED) { |
| Assert.that(slot_num >= 0 && slot_num < ref_data_mask, "slot out of range"); |
| } |
| return makeAny(ref_bit | not_bottom_info_bit | ref_not_lock_bit | ref_slot_bit | |
| (slot_num & ref_data_mask)); |
| } |
| |
| public static CellTypeState makeLineRef(int bci) { |
| if (Assert.ASSERTS_ENABLED) { |
| Assert.that(bci >= 0 && bci < ref_data_mask, "line out of range"); |
| } |
| return makeAny(ref_bit | not_bottom_info_bit | ref_not_lock_bit | |
| (bci & ref_data_mask)); |
| } |
| |
| public static CellTypeState makeLockRef(int bci) { |
| if (Assert.ASSERTS_ENABLED) { |
| Assert.that(bci >= 0 && bci < ref_data_mask, "line out of range"); |
| } |
| return makeAny(ref_bit | not_bottom_info_bit | (bci & ref_data_mask)); |
| } |
| |
| // Query methods: |
| public boolean isBottom() { return _state == 0; } |
| public boolean isLive() { return ((_state & live_bits_mask) != 0); } |
| public boolean isValidState() { |
| // Uninitialized and value cells must contain no data in their info field: |
| if ((canBeUninit() || canBeValue()) && !isInfoTop()) { |
| return false; |
| } |
| // The top bit is only set when all info bits are set: |
| if (isInfoTop() && ((_state & info_mask) != info_mask)) { |
| return false; |
| } |
| // The not_bottom_bit must be set when any other info bit is set: |
| if (isInfoBottom() && ((_state & info_mask) != 0)) { |
| return false; |
| } |
| return true; |
| } |
| |
| public boolean isAddress() { return ((_state & bits_mask) == addr_bit); } |
| public boolean isReference() { return ((_state & bits_mask) == ref_bit); } |
| public boolean isValue() { return ((_state & bits_mask) == val_bit); } |
| public boolean isUninit() { return ((_state & bits_mask) == uninit_bit); } |
| |
| public boolean canBeAddress() { return ((_state & addr_bit) != 0); } |
| public boolean canBeReference() { return ((_state & ref_bit) != 0); } |
| public boolean canBeValue() { return ((_state & val_bit) != 0); } |
| public boolean canBeUninit() { return ((_state & uninit_bit) != 0); } |
| |
| public boolean isInfoBottom() { return ((_state & not_bottom_info_bit) == 0); } |
| public boolean isInfoTop() { return ((_state & top_info_bit) != 0); } |
| public int getInfo() { |
| if (Assert.ASSERTS_ENABLED) { |
| Assert.that((!isInfoTop() && !isInfoBottom()), |
| "check to make sure top/bottom info is not used"); |
| } |
| return (_state & info_data_mask); |
| } |
| |
| public int getMonitorSource() { |
| if (Assert.ASSERTS_ENABLED) { |
| Assert.that(isLockReference(), "must be lock"); |
| } |
| return getInfo(); |
| } |
| |
| public boolean isGoodAddress() { return isAddress() && !isInfoTop(); } |
| public boolean isLockReference() { |
| return ((_state & (bits_mask | top_info_bit | ref_not_lock_bit)) == ref_bit); |
| } |
| public boolean isNonlockReference() { |
| return ((_state & (bits_mask | top_info_bit | ref_not_lock_bit)) == (ref_bit | ref_not_lock_bit)); |
| } |
| |
| public boolean equal(CellTypeState a) { return _state == a._state; } |
| public boolean equalKind(CellTypeState a) { |
| return (_state & bits_mask) == (a._state & bits_mask); |
| } |
| |
| public char toChar() { |
| if (canBeReference()) { |
| if (canBeValue() || canBeAddress()) |
| return '#'; // Conflict that needs to be rewritten |
| else |
| return 'r'; |
| } else if (canBeValue()) |
| return 'v'; |
| else if (canBeAddress()) |
| return 'p'; |
| else if (canBeUninit()) |
| return ' '; |
| else |
| return '@'; |
| } |
| |
| // Set |
| public void set(CellTypeState cts) { |
| _state = cts._state; |
| } |
| |
| // Merge |
| public CellTypeState merge (CellTypeState cts, int slot) { |
| CellTypeState result = new CellTypeState(); |
| |
| if (Assert.ASSERTS_ENABLED) { |
| Assert.that(!isBottom() && !cts.isBottom(), |
| "merge of bottom values is handled elsewhere"); |
| } |
| |
| result._state = _state | cts._state; |
| |
| // If the top bit is set, we don't need to do any more work. |
| if (!result.isInfoTop()) { |
| Assert.that((result.canBeAddress() || result.canBeReference()), |
| "only addresses and references have non-top info"); |
| |
| if (!equal(cts)) { |
| // The two values being merged are different. Raise to top. |
| if (result.isReference()) { |
| result = CellTypeState.makeSlotRef(slot); |
| } else { |
| result._state |= info_conflict; |
| } |
| } |
| } |
| if (Assert.ASSERTS_ENABLED) { |
| Assert.that(result.isValidState(), "checking that CTS merge maintains legal state"); |
| } |
| |
| return result; |
| } |
| |
| // Debugging output |
| public void print(PrintStream tty) { |
| if (canBeAddress()) { |
| tty.print("(p"); |
| } else { |
| tty.print("( "); |
| } |
| if (canBeReference()) { |
| tty.print("r"); |
| } else { |
| tty.print(" "); |
| } |
| if (canBeValue()) { |
| tty.print("v"); |
| } else { |
| tty.print(" "); |
| } |
| if (canBeUninit()) { |
| tty.print("u|"); |
| } else { |
| tty.print(" |"); |
| } |
| if (isInfoTop()) { |
| tty.print("Top)"); |
| } else if (isInfoBottom()) { |
| tty.print("Bot)"); |
| } else { |
| if (isReference()) { |
| int info = getInfo(); |
| int data = info & ~(ref_not_lock_bit | ref_slot_bit); |
| if ((info & ref_not_lock_bit) != 0) { |
| // Not a monitor lock reference. |
| if ((info & ref_slot_bit) != 0) { |
| // slot |
| tty.print("slot" + data + ")"); |
| } else { |
| // line |
| tty.print("line" + data + ")"); |
| } |
| } else { |
| // lock |
| tty.print("lock" + data + ")"); |
| } |
| } else { |
| tty.print("" + getInfo() + ")"); |
| } |
| } |
| } |
| |
| // Default values of common values |
| public static CellTypeState bottom = CellTypeState.makeBottom(); |
| public static CellTypeState uninit = CellTypeState.makeAny(uninit_value); |
| public static CellTypeState ref = CellTypeState.makeAny(ref_conflict); |
| public static CellTypeState value = CellTypeState.makeAny(val_value); |
| public static CellTypeState refUninit = CellTypeState.makeAny(ref_conflict | uninit_value); |
| public static CellTypeState top = CellTypeState.makeTop(); |
| public static CellTypeState addr = CellTypeState.makeAny(addr_conflict); |
| } |