Location.java revision 9883:903a2e023ffb
1/*
2 * Copyright (c) 2000, 2008, 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.code;
26
27import java.io.*;
28import java.util.*;
29
30import sun.jvm.hotspot.runtime.*;
31import sun.jvm.hotspot.types.*;
32import 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:
42    Type:   [3..0]
43    Where:  [4]
44    Offset: [31..5]
45    </PRE>
46*/
47
48public 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();
72    TYPE_NARROWOOP = db.lookupIntConstant("Location::narrowoop").intValue();
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");
119    /** NarrowOop (please GC me!) */
120    public static final Type NARROWOOP    = new Type("narrowoop");
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;
148      } else if (this == NARROWOOP) {
149        return TYPE_NARROWOOP;
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;
178  private static int TYPE_NARROWOOP;
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);
194    setOffset(offset);
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;
214    } else if (type == TYPE_NARROWOOP) {
215       return Type.NARROWOOP;
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
249  public boolean holdsNarrowOop() {
250    return getType() == Type.NARROWOOP;
251  }
252
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    }
281    return getOffset() * (int)VM.getVM().getIntSize();
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");
311      } else if (type == Type.NARROWOOP) {
312        tty.print(",narrowoop");
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    value = stream.readInt();
332  }
333
334  // FIXME: not yet implementable
335  // void write_on(DebugInfoWriteStream* stream);
336
337
338  //-----------------------------------------------------------------------------
339  // Internals only below this point
340  //
341
342  private void setWhere(Where where) {
343    value |= ((where.getValue() << WHERE_SHIFT) & WHERE_MASK);
344  }
345
346  private void setType(Type type) {
347    value |= ((type.getValue() << TYPE_SHIFT) & TYPE_MASK);
348  }
349
350  private void setOffset(int offset) {
351    value |= ((offset << OFFSET_SHIFT) & OFFSET_MASK);
352  }
353}
354