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 
  25 package sun.jvm.hotspot.utilities;
  26 
  27 import java.io.*;
  28 import sun.jvm.hotspot.code.*;
  29 import sun.jvm.hotspot.debugger.*;
  30 import sun.jvm.hotspot.gc.shared.*;
  31 import sun.jvm.hotspot.interpreter.*;
  32 import sun.jvm.hotspot.runtime.*;
  33 import sun.jvm.hotspot.memory.*;
  34 
  35 /** This class attempts to describe possible locations of pointers in
  36     the VM. */
  37 
  38 public 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.level() == 0));
  88   }
  89 
  90   public boolean isInOldGen() {
  91     return ((gen != null) && (gen.level() == 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 if (gen != null) {
 211           tty.print("In Generation " + getGeneration().level());
 212         } else {
 213           tty.print("In unknown section of Java heap");
 214         }
 215         if (getGeneration() != null) {
 216           getGeneration().printOn(tty);
 217         }
 218       }
 219     } else if (isInInterpreter()) {
 220       tty.println("In interpreter codelet \"" + interpreterCodelet.getDescription() + "\"");
 221       interpreterCodelet.printOn(tty);
 222     } else if (isInCodeCache()) {
 223       CodeBlob b = getCodeBlob();
 224       tty.print("In ");
 225       if (isInBlobCode()) {
 226         tty.print("code");
 227       } else if (isInBlobData()) {
 228         tty.print("data");
 229       } else if (isInBlobOops()) {
 230         tty.print("oops");
 231       } else {
 232         if (Assert.ASSERTS_ENABLED) {
 233           Assert.that(isInBlobUnknownLocation(), "Should have known location in CodeBlob");
 234         }
 235         tty.print("unknown location");
 236       }
 237       tty.print(" in ");
 238       b.printOn(tty);
 239 
 240       // FIXME: add more detail
 241     } else if (isInStrongGlobalJNIHandleBlock() ||
 242                isInWeakGlobalJNIHandleBlock() ||
 243                isInLocalJNIHandleBlock()) {
 244       tty.print("In ");
 245       if (isInStrongGlobalJNIHandleBlock()) {
 246         tty.print("strong global");
 247       } else if (isInWeakGlobalJNIHandleBlock()) {
 248         tty.print("weak global");
 249       } else {
 250         tty.print("thread-local");
 251       }
 252       tty.print(" JNI handle block (" + handleBlock.top() + " handle slots present)");
 253       if (isInLocalJNIHandleBlock()) {
 254         if (handleThread.isJavaThread()) {
 255           tty.print(" for JavaThread ");
 256           ((JavaThread) handleThread).printThreadIDOn(tty);
 257         } else {
 258           tty.print("for a non-Java Thread");
 259         }
 260       }
 261     } else {
 262       // This must be last
 263       if (Assert.ASSERTS_ENABLED) {
 264         Assert.that(isUnknown(), "Should have unknown location");
 265       }
 266       tty.print("In unknown location");
 267     }
 268   }
 269 }