0
|
1 /*
|
331
|
2 * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
0
|
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.code;
|
|
26
|
|
27 import java.io.*;
|
|
28 import java.util.*;
|
|
29
|
|
30 import sun.jvm.hotspot.runtime.*;
|
|
31 import sun.jvm.hotspot.types.*;
|
|
32 import sun.jvm.hotspot.utilities.*;
|
|
33
|
|
34 /** <P> A Location describes a concrete machine variable location
|
|
35 (such as integer or floating point register or a stack-held
|
|
36 variable). Used when generating debug-information for
|
|
37 nmethods. </P>
|
|
38
|
|
39 <P> Encoding: </P>
|
|
40 <PRE>
|
|
41 bits:
|
331
|
42 Type: [3..0]
|
|
43 Where: [4]
|
|
44 Offset: [31..5]
|
0
|
45 </PRE>
|
|
46 */
|
|
47
|
|
48 public class Location {
|
|
49 static {
|
|
50 VM.registerVMInitializedObserver(new Observer() {
|
|
51 public void update(Observable o, Object data) {
|
|
52 initialize(VM.getVM().getTypeDataBase());
|
|
53 }
|
|
54 });
|
|
55 }
|
|
56
|
|
57 private static void initialize(TypeDataBase db) {
|
|
58 if (Assert.ASSERTS_ENABLED) {
|
|
59 Assert.that(!VM.getVM().isCore(), "Debug info not used in core build");
|
|
60 }
|
|
61
|
|
62 OFFSET_MASK = db.lookupIntConstant("Location::OFFSET_MASK").intValue();
|
|
63 OFFSET_SHIFT = db.lookupIntConstant("Location::OFFSET_SHIFT").intValue();
|
|
64 TYPE_MASK = db.lookupIntConstant("Location::TYPE_MASK").intValue();
|
|
65 TYPE_SHIFT = db.lookupIntConstant("Location::TYPE_SHIFT").intValue();
|
|
66 WHERE_MASK = db.lookupIntConstant("Location::WHERE_MASK").intValue();
|
|
67 WHERE_SHIFT = db.lookupIntConstant("Location::WHERE_SHIFT").intValue();
|
|
68
|
|
69 // Location::Type constants
|
|
70 TYPE_NORMAL = db.lookupIntConstant("Location::normal").intValue();
|
|
71 TYPE_OOP = db.lookupIntConstant("Location::oop").intValue();
|
331
|
72 TYPE_NARROWOOP = db.lookupIntConstant("Location::narrowoop").intValue();
|
0
|
73 TYPE_INT_IN_LONG = db.lookupIntConstant("Location::int_in_long").intValue();
|
|
74 TYPE_LNG = db.lookupIntConstant("Location::lng").intValue();
|
|
75 TYPE_FLOAT_IN_DBL = db.lookupIntConstant("Location::float_in_dbl").intValue();
|
|
76 TYPE_DBL = db.lookupIntConstant("Location::dbl").intValue();
|
|
77 TYPE_ADDR = db.lookupIntConstant("Location::addr").intValue();
|
|
78 TYPE_INVALID = db.lookupIntConstant("Location::invalid").intValue();
|
|
79
|
|
80 // Location::Where constants
|
|
81 WHERE_ON_STACK = db.lookupIntConstant("Location::on_stack").intValue();
|
|
82 WHERE_IN_REGISTER = db.lookupIntConstant("Location::in_register").intValue();
|
|
83 }
|
|
84
|
|
85 private int value;
|
|
86
|
|
87 // type safe enum for "Where"
|
|
88 public static class Where {
|
|
89 public static final Where ON_STACK = new Where("on_stack");
|
|
90 public static final Where IN_REGISTER = new Where("in_register");
|
|
91
|
|
92 private Where(String value) {
|
|
93 this.value = value;
|
|
94 }
|
|
95
|
|
96 public String toString() {
|
|
97 return value;
|
|
98 }
|
|
99
|
|
100 private String value;
|
|
101
|
|
102 public int getValue() {
|
|
103 if (this == ON_STACK) {
|
|
104 return WHERE_ON_STACK;
|
|
105 } else if (this == IN_REGISTER) {
|
|
106 return WHERE_IN_REGISTER;
|
|
107 } else {
|
|
108 throw new RuntimeException("should not reach here");
|
|
109 }
|
|
110 }
|
|
111 }
|
|
112
|
|
113 // type safe enum for "Type"
|
|
114 public static class Type {
|
|
115 /** Ints, floats, double halves */
|
|
116 public static final Type NORMAL = new Type("normal");
|
|
117 /** Oop (please GC me!) */
|
|
118 public static final Type OOP = new Type("oop");
|
331
|
119 /** NarrowOop (please GC me!) */
|
|
120 public static final Type NARROWOOP = new Type("narrowoop");
|
0
|
121 /** Long held in one register */
|
|
122 public static final Type INT_IN_LONG = new Type("int_in_long");
|
|
123 /** Long held in one register */
|
|
124 public static final Type LNG = new Type("lng");
|
|
125 /** Float held in double register */
|
|
126 public static final Type FLOAT_IN_DBL = new Type("float_in_dbl");
|
|
127 /** Double held in one register */
|
|
128 public static final Type DBL = new Type("dbl");
|
|
129 /** JSR return address */
|
|
130 public static final Type ADDR = new Type("addr");
|
|
131 /** Invalid location */
|
|
132 public static final Type INVALID = new Type("invalid");
|
|
133
|
|
134 private Type(String value) {
|
|
135 this.value = value;
|
|
136 }
|
|
137 private String value;
|
|
138
|
|
139 public String toString() {
|
|
140 return value;
|
|
141 }
|
|
142
|
|
143 public int getValue() {
|
|
144 if (this == NORMAL) {
|
|
145 return TYPE_NORMAL;
|
|
146 } else if (this == OOP) {
|
|
147 return TYPE_OOP;
|
331
|
148 } else if (this == NARROWOOP) {
|
|
149 return TYPE_NARROWOOP;
|
0
|
150 } else if (this == INT_IN_LONG) {
|
|
151 return TYPE_INT_IN_LONG;
|
|
152 } else if (this == LNG) {
|
|
153 return TYPE_LNG;
|
|
154 } else if (this == FLOAT_IN_DBL) {
|
|
155 return TYPE_FLOAT_IN_DBL;
|
|
156 } else if (this == DBL) {
|
|
157 return TYPE_DBL;
|
|
158 } else if (this == ADDR) {
|
|
159 return TYPE_ADDR;
|
|
160 } else if (this == INVALID) {
|
|
161 return TYPE_INVALID;
|
|
162 } else {
|
|
163 throw new RuntimeException("should not reach here");
|
|
164 }
|
|
165 }
|
|
166 }
|
|
167
|
|
168 private static int OFFSET_MASK;
|
|
169 private static int OFFSET_SHIFT;
|
|
170 private static int TYPE_MASK;
|
|
171 private static int TYPE_SHIFT;
|
|
172 private static int WHERE_MASK;
|
|
173 private static int WHERE_SHIFT;
|
|
174
|
|
175 // constants in Type enum
|
|
176 private static int TYPE_NORMAL;
|
|
177 private static int TYPE_OOP;
|
331
|
178 private static int TYPE_NARROWOOP;
|
0
|
179 private static int TYPE_INT_IN_LONG;
|
|
180 private static int TYPE_LNG;
|
|
181 private static int TYPE_FLOAT_IN_DBL;
|
|
182 private static int TYPE_DBL;
|
|
183 private static int TYPE_ADDR;
|
|
184 private static int TYPE_INVALID;
|
|
185
|
|
186 // constants in Where enum
|
|
187 private static int WHERE_ON_STACK;
|
|
188 private static int WHERE_IN_REGISTER;
|
|
189
|
|
190 /** Create a bit-packed Location */
|
|
191 Location(Where where, Type type, int offset) {
|
|
192 setWhere(where);
|
|
193 setType(type);
|
331
|
194 setOffset(offset);
|
0
|
195 }
|
|
196
|
|
197 public Where getWhere() {
|
|
198 int where = (value & WHERE_MASK) >> WHERE_SHIFT;
|
|
199 if (where == WHERE_ON_STACK) {
|
|
200 return Where.ON_STACK;
|
|
201 } else if (where == WHERE_IN_REGISTER) {
|
|
202 return Where.IN_REGISTER;
|
|
203 } else {
|
|
204 throw new RuntimeException("should not reach here");
|
|
205 }
|
|
206 }
|
|
207
|
|
208 public Type getType() {
|
|
209 int type = (value & TYPE_MASK) >> TYPE_SHIFT;
|
|
210 if (type == TYPE_NORMAL) {
|
|
211 return Type.NORMAL;
|
|
212 } else if (type == TYPE_OOP) {
|
|
213 return Type.OOP;
|
331
|
214 } else if (type == TYPE_NARROWOOP) {
|
|
215 return Type.NARROWOOP;
|
0
|
216 } else if (type == TYPE_INT_IN_LONG) {
|
|
217 return Type.INT_IN_LONG;
|
|
218 } else if (type == TYPE_LNG) {
|
|
219 return Type.LNG;
|
|
220 } else if (type == TYPE_FLOAT_IN_DBL) {
|
|
221 return Type.FLOAT_IN_DBL;
|
|
222 } else if (type == TYPE_DBL) {
|
|
223 return Type.DBL;
|
|
224 } else if (type == TYPE_ADDR) {
|
|
225 return Type.ADDR;
|
|
226 } else if (type == TYPE_INVALID) {
|
|
227 return Type.INVALID;
|
|
228 } else {
|
|
229 throw new RuntimeException("should not reach here");
|
|
230 }
|
|
231 }
|
|
232
|
|
233 public short getOffset() {
|
|
234 return (short) ((value & OFFSET_MASK) >> OFFSET_SHIFT);
|
|
235 }
|
|
236
|
|
237 public boolean isRegister() {
|
|
238 return getWhere() == Where.IN_REGISTER;
|
|
239 }
|
|
240
|
|
241 public boolean isStack() {
|
|
242 return getWhere() == Where.ON_STACK;
|
|
243 }
|
|
244
|
|
245 public boolean holdsOop() {
|
|
246 return getType() == Type.OOP;
|
|
247 }
|
|
248
|
331
|
249 public boolean holdsNarrowOop() {
|
|
250 return getType() == Type.NARROWOOP;
|
|
251 }
|
|
252
|
0
|
253 public boolean holdsInt() {
|
|
254 return getType() == Type.INT_IN_LONG;
|
|
255 }
|
|
256
|
|
257 public boolean holdsLong() {
|
|
258 return getType() == Type.LNG;
|
|
259 }
|
|
260
|
|
261 public boolean holdsFloat() {
|
|
262 return getType() == Type.FLOAT_IN_DBL;
|
|
263 }
|
|
264
|
|
265 public boolean holdsDouble() {
|
|
266 return getType() == Type.DBL;
|
|
267 }
|
|
268
|
|
269 public boolean holdsAddr() {
|
|
270 return getType() == Type.ADDR;
|
|
271 }
|
|
272
|
|
273 public boolean isIllegal() {
|
|
274 return getType() == Type.INVALID;
|
|
275 }
|
|
276
|
|
277 public int getStackOffset() {
|
|
278 if (Assert.ASSERTS_ENABLED) {
|
|
279 Assert.that(getWhere() == Where.ON_STACK, "wrong Where");
|
|
280 }
|
331
|
281 return getOffset() * (int)VM.getVM().getIntSize();
|
0
|
282 }
|
|
283
|
|
284 public int getRegisterNumber() {
|
|
285 if (Assert.ASSERTS_ENABLED) {
|
|
286 Assert.that(getWhere() == Where.IN_REGISTER, "wrong Where");
|
|
287 }
|
|
288 return getOffset();
|
|
289 }
|
|
290
|
|
291 public void print() {
|
|
292 printOn(System.out);
|
|
293 }
|
|
294
|
|
295 public void printOn(PrintStream tty) {
|
|
296 tty.print("Value " + value + ", ");
|
|
297 if (isIllegal()) {
|
|
298 tty.print("Illegal");
|
|
299 } else {
|
|
300 Where w = getWhere();
|
|
301 if (w == Where.ON_STACK) {
|
|
302 tty.print("stack[" + getStackOffset() + "]");
|
|
303 } else if (w == Where.IN_REGISTER) {
|
|
304 tty.print("reg " + getRegisterNumber());
|
|
305 }
|
|
306
|
|
307 Type type = getType();
|
|
308 if (type == Type.NORMAL) {
|
|
309 } else if (type == Type.OOP) {
|
|
310 tty.print(",oop");
|
331
|
311 } else if (type == Type.NARROWOOP) {
|
|
312 tty.print(",narrowoop");
|
0
|
313 } else if (type == Type.INT_IN_LONG) {
|
|
314 tty.print(",int");
|
|
315 } else if (type == Type.LNG) {
|
|
316 tty.print(",long");
|
|
317 } else if (type == Type.FLOAT_IN_DBL) {
|
|
318 tty.print(",float");
|
|
319 } else if (type == Type.DBL) {
|
|
320 tty.print(",double");
|
|
321 } else if (type == Type.ADDR) {
|
|
322 tty.print(",address");
|
|
323 } else if (type == Type.INVALID) {
|
|
324 tty.print(",invalid");
|
|
325 }
|
|
326 }
|
|
327 }
|
|
328
|
|
329 /** Serialization of debugging information */
|
|
330 public Location(DebugInfoReadStream stream) {
|
331
|
331 value = stream.readInt();
|
0
|
332 }
|
|
333
|
|
334 // FIXME: not yet implementable
|
|
335 // void write_on(DebugInfoWriteStream* stream);
|
|
336
|
|
337
|
331
|
338 //-----------------------------------------------------------------------------
|
0
|
339 // Internals only below this point
|
|
340 //
|
|
341
|
|
342 private void setWhere(Where where) {
|
331
|
343 value |= ((where.getValue() << WHERE_SHIFT) & WHERE_MASK);
|
0
|
344 }
|
|
345
|
|
346 private void setType(Type type) {
|
331
|
347 value |= ((type.getValue() << TYPE_SHIFT) & TYPE_MASK);
|
0
|
348 }
|
|
349
|
|
350 private void setOffset(int offset) {
|
331
|
351 value |= ((offset << OFFSET_SHIFT) & OFFSET_MASK);
|
0
|
352 }
|
|
353 }
|