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