1/*
2 * Copyright (c) 2000, 2015, 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.utilities;
26
27import java.io.*;
28import sun.jvm.hotspot.code.*;
29import sun.jvm.hotspot.debugger.*;
30import sun.jvm.hotspot.gc.shared.*;
31import sun.jvm.hotspot.interpreter.*;
32import sun.jvm.hotspot.runtime.*;
33import sun.jvm.hotspot.memory.*;
34
35/** This class attempts to describe possible locations of pointers in
36    the VM. */
37
38public class PointerLocation {
39  //////////////////////////////////////////////////////////////////
40  //                                                              //
41  // These are package private to simplify the implementation and //
42  // interaction with PointerFinder                               //
43  //                                                              //
44  //////////////////////////////////////////////////////////////////
45
46  Address addr;
47
48  CollectedHeap heap;
49  Generation gen;
50
51  // If UseTLAB was enabled and the pointer was found in a
52  // currently-active TLAB, these will be set
53  boolean inTLAB;
54  JavaThread tlabThread;
55  ThreadLocalAllocBuffer tlab;
56
57  // Generated code locations
58  boolean inInterpreter;
59  boolean inCodeCache;
60
61  // FIXME: add other locations like VTableStubs, StubRoutines, maybe
62  // even "on thread x's stack"
63
64  InterpreterCodelet interpreterCodelet;
65  CodeBlob blob;
66  // FIXME: add more detail about CodeBlob
67  boolean inBlobCode;
68  boolean inBlobData;
69  boolean inBlobOops;
70  boolean inBlobUnknownLocation;
71
72  boolean inStrongGlobalJNIHandleBlock;
73  boolean inWeakGlobalJNIHandleBlock;
74  boolean inLocalJNIHandleBlock;
75  JNIHandleBlock handleBlock;
76  sun.jvm.hotspot.runtime.Thread handleThread;
77
78  public PointerLocation(Address addr) {
79    this.addr = addr;
80  }
81
82  public boolean isInHeap() {
83    return (heap != null || (gen != null));
84  }
85
86  public boolean isInNewGen() {
87    return ((gen != null) && (gen == ((GenCollectedHeap)heap).getGen(0)));
88  }
89
90  public boolean isInOldGen() {
91    return ((gen != null) && (gen == ((GenCollectedHeap)heap).getGen(1)));
92  }
93
94  public boolean inOtherGen() {
95    return (!isInNewGen() && !isInOldGen());
96  }
97
98  /** Only valid if isInHeap() */
99  public Generation getGeneration() {
100      return gen;
101  }
102
103  /** This may be true if isInNewGen is also true */
104  public boolean isInTLAB() {
105    return inTLAB;
106  }
107
108  /** Only valid if isInTLAB() returns true */
109  public JavaThread getTLABThread() {
110    return tlabThread;
111  }
112
113  /** Only valid if isInTLAB() returns true */
114  public ThreadLocalAllocBuffer getTLAB() {
115    return tlab;
116  }
117
118  public boolean isInInterpreter() {
119    return inInterpreter;
120  }
121
122  /** For now, only valid if isInInterpreter is true */
123  public InterpreterCodelet getInterpreterCodelet() {
124    return interpreterCodelet;
125  }
126
127  public boolean isInCodeCache() {
128    return inCodeCache;
129  }
130
131  /** For now, only valid if isInCodeCache is true */
132  public CodeBlob getCodeBlob() {
133    return blob;
134  }
135
136  public boolean isInBlobCode() {
137    return inBlobCode;
138  }
139
140  public boolean isInBlobData() {
141    return inBlobData;
142  }
143
144  public boolean isInBlobOops() {
145    return inBlobOops;
146  }
147
148  public boolean isInBlobUnknownLocation() {
149    return inBlobUnknownLocation;
150  }
151
152  public boolean isInStrongGlobalJNIHandleBlock() {
153    return inStrongGlobalJNIHandleBlock;
154  }
155
156  public boolean isInWeakGlobalJNIHandleBlock() {
157    return inWeakGlobalJNIHandleBlock;
158  }
159
160  public boolean isInLocalJNIHandleBlock() {
161    return inLocalJNIHandleBlock;
162  }
163
164  /** Only valid if isInStrongGlobalJNIHandleBlock,
165      isInWeakGlobalJNIHandleBlock, or isInLocalJNIHandleBlock is true */
166  public JNIHandleBlock getJNIHandleBlock() {
167    return handleBlock;
168  }
169
170  /** Only valid if isInLocalJNIHandleBlock is true */
171  public sun.jvm.hotspot.runtime.Thread getJNIHandleThread() {
172    return handleThread;
173  }
174
175  public boolean isUnknown() {
176    return (!(isInHeap() || isInInterpreter() || isInCodeCache() ||
177              isInStrongGlobalJNIHandleBlock() || isInWeakGlobalJNIHandleBlock() || isInLocalJNIHandleBlock()));
178  }
179
180  public String toString() {
181    ByteArrayOutputStream bos = new ByteArrayOutputStream();
182    printOn(new PrintStream(bos));
183    return bos.toString();
184  }
185
186  public void print() {
187    printOn(System.out);
188  }
189
190  public void printOn(PrintStream tty) {
191    tty.print("Address ");
192    if (addr == null) {
193      tty.print("0x0");
194    } else {
195      tty.print(addr.toString());
196    }
197    tty.print(": ");
198    if (isInHeap()) {
199      if (isInTLAB()) {
200        tty.print("In thread-local allocation buffer for thread \"" +
201                  getTLABThread().getThreadName() + "\" (");
202        getTLABThread().printThreadIDOn(tty);
203        tty.print(") ");
204        getTLAB().printOn(tty);
205      } else {
206        if (isInNewGen()) {
207          tty.print("In new generation ");
208        } else if (isInOldGen()) {
209          tty.print("In old generation ");
210        } else {
211          tty.print("In unknown section of Java heap");
212        }
213        if (getGeneration() != null) {
214          getGeneration().printOn(tty);
215        }
216      }
217    } else if (isInInterpreter()) {
218      tty.println("In interpreter codelet \"" + interpreterCodelet.getDescription() + "\"");
219      interpreterCodelet.printOn(tty);
220    } else if (isInCodeCache()) {
221      CodeBlob b = getCodeBlob();
222      tty.print("In ");
223      if (isInBlobCode()) {
224        tty.print("code");
225      } else if (isInBlobData()) {
226        tty.print("data");
227      } else if (isInBlobOops()) {
228        tty.print("oops");
229      } else {
230        if (Assert.ASSERTS_ENABLED) {
231          Assert.that(isInBlobUnknownLocation(), "Should have known location in CodeBlob");
232        }
233        tty.print("unknown location");
234      }
235      tty.print(" in ");
236      b.printOn(tty);
237
238      // FIXME: add more detail
239    } else if (isInStrongGlobalJNIHandleBlock() ||
240               isInWeakGlobalJNIHandleBlock() ||
241               isInLocalJNIHandleBlock()) {
242      tty.print("In ");
243      if (isInStrongGlobalJNIHandleBlock()) {
244        tty.print("strong global");
245      } else if (isInWeakGlobalJNIHandleBlock()) {
246        tty.print("weak global");
247      } else {
248        tty.print("thread-local");
249      }
250      tty.print(" JNI handle block (" + handleBlock.top() + " handle slots present)");
251      if (isInLocalJNIHandleBlock()) {
252        if (handleThread.isJavaThread()) {
253          tty.print(" for JavaThread ");
254          ((JavaThread) handleThread).printThreadIDOn(tty);
255        } else {
256          tty.print("for a non-Java Thread");
257        }
258      }
259    } else {
260      // This must be last
261      if (Assert.ASSERTS_ENABLED) {
262        Assert.that(isUnknown(), "Should have unknown location");
263      }
264      tty.print("In unknown location");
265    }
266  }
267}
268