0
|
1 /*
|
|
2 * Copyright 2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or
|
|
21 * have any 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
|
|
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 }
|