View Javadoc
1   /*
2    * Copyright (c) 2000, 2012, 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.code;
26  
27  import java.io.*;
28  import java.util.*;
29  
30  import sun.jvm.hotspot.debugger.*;
31  import sun.jvm.hotspot.oops.*;
32  import sun.jvm.hotspot.runtime.*;
33  import sun.jvm.hotspot.utilities.*;
34  
35  /** ScopeDescs contain the information that makes source-level
36      debugging of nmethods possible; each scopeDesc describes a method
37      activation */
38  
39  public class ScopeDesc {
40    /** NMethod information */
41    private NMethod code;
42    private Method  method;
43    private int     bci;
44    private boolean reexecute;
45    /** Decoding offsets */
46    private int     decodeOffset;
47    private int     senderDecodeOffset;
48    private int     localsDecodeOffset;
49    private int     expressionsDecodeOffset;
50    private int     monitorsDecodeOffset;
51    /** Scalar replaced bjects pool */
52    private List    objects; // ArrayList<ScopeValue>
53  
54    private ScopeDesc(NMethod code, int decodeOffset, List objects, boolean reexecute) {
55      this.code = code;
56      this.decodeOffset = decodeOffset;
57      this.objects      = objects;
58      this.reexecute    = reexecute;
59  
60      // Decode header
61      DebugInfoReadStream stream  = streamAt(decodeOffset);
62  
63      senderDecodeOffset = stream.readInt();
64      method = stream.readMethod();
65      bci    = stream.readBCI();
66      // Decode offsets for body and sender
67      localsDecodeOffset      = stream.readInt();
68      expressionsDecodeOffset = stream.readInt();
69      monitorsDecodeOffset    = stream.readInt();
70    }
71  
72    public ScopeDesc(NMethod code, int decodeOffset, int objectDecodeOffset, boolean reexecute) {
73      this.code = code;
74      this.decodeOffset = decodeOffset;
75      this.objects      = decodeObjectValues(objectDecodeOffset);
76      this.reexecute    = reexecute;
77  
78      // Decode header
79      DebugInfoReadStream stream  = streamAt(decodeOffset);
80  
81      senderDecodeOffset = stream.readInt();
82      method = stream.readMethod();
83      bci    = stream.readBCI();
84      // Decode offsets for body and sender
85      localsDecodeOffset      = stream.readInt();
86      expressionsDecodeOffset = stream.readInt();
87      monitorsDecodeOffset    = stream.readInt();
88    }
89  
90    public NMethod getNMethod()   { return code; }
91    public Method getMethod()     { return method; }
92    public int    getBCI()        { return bci;    }
93    public boolean getReexecute() { return reexecute;}
94  
95    /** Returns a List&lt;ScopeValue&gt; */
96    public List getLocals() {
97      return decodeScopeValues(localsDecodeOffset);
98    }
99  
100   /** Returns a List&lt;ScopeValue&gt; */
101   public List getExpressions() {
102     return decodeScopeValues(expressionsDecodeOffset);
103   }
104 
105   /** Returns a List&lt;MonitorValue&gt; */
106   public List getMonitors() {
107     return decodeMonitorValues(monitorsDecodeOffset);
108   }
109 
110   /** Returns a List&lt;ObjectValue&gt; */
111   public List getObjects() {
112     return objects;
113   }
114 
115   /** Stack walking. Returns null if this is the outermost scope. */
116   public ScopeDesc sender() {
117     if (isTop()) {
118       return null;
119     }
120 
121     return new ScopeDesc(code, senderDecodeOffset, objects, false);
122   }
123 
124   /** Returns where the scope was decoded */
125   public int getDecodeOffset() {
126     return decodeOffset;
127   }
128 
129   /** Tells whether sender() returns null */
130   public boolean isTop() {
131     return (senderDecodeOffset == DebugInformationRecorder.SERIALIZED_NULL);
132   }
133 
134   public boolean equals(Object arg) {
135     if (arg == null) {
136       return false;
137     }
138 
139     if (!(arg instanceof ScopeDesc)) {
140       return false;
141     }
142 
143     ScopeDesc sd = (ScopeDesc) arg;
144 
145     return (sd.method.equals(method) && (sd.bci == bci));
146   }
147 
148   public void printValue() {
149     printValueOn(System.out);
150   }
151 
152   public void printValueOn(PrintStream tty) {
153     tty.print("ScopeDesc for ");
154     method.printValueOn(tty);
155     tty.print(" @bci " + bci);
156     tty.println(" reexecute=" + reexecute);
157   }
158 
159   // FIXME: add more accessors
160 
161   //--------------------------------------------------------------------------------
162   // Internals only below this point
163   //
164   private DebugInfoReadStream streamAt(int decodeOffset) {
165     return new DebugInfoReadStream(code, decodeOffset, objects);
166   }
167 
168   /** Returns a List&lt;ScopeValue&gt; or null if no values were present */
169   private List decodeScopeValues(int decodeOffset) {
170     if (decodeOffset == DebugInformationRecorder.SERIALIZED_NULL) {
171       return null;
172     }
173     DebugInfoReadStream stream = streamAt(decodeOffset);
174     int length = stream.readInt();
175     List res = new ArrayList(length);
176     for (int i = 0; i < length; i++) {
177       res.add(ScopeValue.readFrom(stream));
178     }
179     return res;
180   }
181 
182   /** Returns a List&lt;MonitorValue&gt; or null if no values were present */
183   private List decodeMonitorValues(int decodeOffset) {
184     if (decodeOffset == DebugInformationRecorder.SERIALIZED_NULL) {
185       return null;
186     }
187     DebugInfoReadStream stream = streamAt(decodeOffset);
188     int length = stream.readInt();
189     List res = new ArrayList(length);
190     for (int i = 0; i < length; i++) {
191       res.add(new MonitorValue(stream));
192     }
193     return res;
194   }
195 
196   /** Returns a List&lt;ObjectValue&gt; or null if no values were present */
197   private List decodeObjectValues(int decodeOffset) {
198     if (decodeOffset == DebugInformationRecorder.SERIALIZED_NULL) {
199       return null;
200     }
201     List res = new ArrayList();
202     DebugInfoReadStream stream = new DebugInfoReadStream(code, decodeOffset, res);
203     int length = stream.readInt();
204     for (int i = 0; i < length; i++) {
205       // Objects values are pushed to 'res' array during read so that
206       // object's fields could reference it (OBJECT_ID_CODE).
207       ScopeValue.readFrom(stream);
208       // res.add(ScopeValue.readFrom(stream));
209     }
210     Assert.that(res.size() == length, "inconsistent debug information");
211     return res;
212   }
213 }