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 
25 package sun.jvm.hotspot.oops;
26 
27 import java.io.*;
28 import sun.jvm.hotspot.utilities.*;
29 
30 /** Auxiliary class for GenerateOopMap */
31 public 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 
CellTypeState()73   private CellTypeState() {}
74 
CellTypeState(int state)75   private CellTypeState(int state) {
76     _state = state;
77   }
78 
copy()79   public CellTypeState copy() {
80     return new CellTypeState(_state);
81   }
82 
makeAny(int state)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 
makeBottom()91   public static CellTypeState makeBottom() {
92     return makeAny(0);
93   }
94 
makeTop()95   public static CellTypeState makeTop() {
96     return makeAny(Bits.AllBits);
97   }
98 
makeAddr(int bci)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 
makeSlotRef(int slot_num)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 
makeLineRef(int bci)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 
makeLockRef(int bci)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:
isBottom()131   public boolean isBottom()     { return _state == 0; }
isLive()132   public boolean isLive()       { return ((_state & live_bits_mask) != 0); }
isValidState()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 
isAddress()149   public boolean isAddress()      { return ((_state & bits_mask) == addr_bit); }
isReference()150   public boolean isReference()    { return ((_state & bits_mask) == ref_bit); }
isValue()151   public boolean isValue()        { return ((_state & bits_mask) == val_bit); }
isUninit()152   public boolean isUninit()       { return ((_state & bits_mask) == uninit_bit); }
153 
canBeAddress()154   public boolean canBeAddress()   { return ((_state & addr_bit) != 0); }
canBeReference()155   public boolean canBeReference() { return ((_state & ref_bit) != 0); }
canBeValue()156   public boolean canBeValue()     { return ((_state & val_bit) != 0); }
canBeUninit()157   public boolean canBeUninit()    { return ((_state & uninit_bit) != 0); }
158 
isInfoBottom()159   public boolean isInfoBottom()   { return ((_state & not_bottom_info_bit) == 0); }
isInfoTop()160   public boolean isInfoTop()      { return ((_state & top_info_bit) != 0); }
getInfo()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 
getMonitorSource()169   public int     getMonitorSource() {
170     if (Assert.ASSERTS_ENABLED) {
171       Assert.that(isLockReference(), "must be lock");
172     }
173     return getInfo();
174   }
175 
isGoodAddress()176   public boolean isGoodAddress()   { return isAddress() && !isInfoTop(); }
isLockReference()177   public boolean isLockReference() {
178     return ((_state & (bits_mask | top_info_bit | ref_not_lock_bit)) == ref_bit);
179   }
isNonlockReference()180   public boolean isNonlockReference() {
181     return ((_state & (bits_mask | top_info_bit | ref_not_lock_bit)) == (ref_bit | ref_not_lock_bit));
182   }
183 
equal(CellTypeState a)184   public boolean equal(CellTypeState a)     { return _state == a._state; }
equalKind(CellTypeState a)185   public boolean equalKind(CellTypeState a) {
186     return (_state & bits_mask) == (a._state & bits_mask);
187   }
188 
toChar()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
set(CellTypeState cts)206   public void set(CellTypeState cts) {
207     _state = cts._state;
208   }
209 
210   // Merge
merge(CellTypeState cts, int slot)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
print(PrintStream tty)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