comparison agent/src/share/classes/sun/jvm/hotspot/jdi/ConcreteMethodImpl.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children c18cbe5936b8
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2003-2004 Sun Microsystems, Inc. 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 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.jdi;
26
27 import com.sun.jdi.*;
28 import sun.jvm.hotspot.oops.Symbol;
29 import sun.jvm.hotspot.oops.LocalVariableTableElement;
30 import sun.jvm.hotspot.oops.LineNumberTableElement;
31 import java.util.List;
32 import java.util.Iterator;
33 import java.util.Map;
34 import java.util.HashMap;
35 import java.util.ArrayList;
36 import java.util.Comparator;
37 import java.lang.ref.SoftReference;
38 import java.util.Collections;
39
40 public class ConcreteMethodImpl extends MethodImpl {
41
42 /*
43 * A subset of the line number info that is softly cached
44 */
45 static private class SoftLocationXRefs {
46 final String stratumID; // The stratum of this information
47 final Map lineMapper; // Maps line number to location(s)
48 final List lineLocations; // List of locations ordered by code index
49
50 /*
51 * Note: these do not necessarily correspond to
52 * the line numbers of the first and last elements
53 * in the lineLocations list. Use these only for bounds
54 * checking and with lineMapper.
55 */
56 final int lowestLine;
57 final int highestLine;
58
59 SoftLocationXRefs(String stratumID, Map lineMapper, List lineLocations,
60 int lowestLine, int highestLine) {
61 this.stratumID = stratumID;
62 this.lineMapper = Collections.unmodifiableMap(lineMapper);
63 this.lineLocations =
64 Collections.unmodifiableList(lineLocations);
65 this.lowestLine = lowestLine;
66 this.highestLine = highestLine;
67 }
68 }
69
70 private SoftReference softBaseLocationXRefsRef;
71 private SoftReference softOtherLocationXRefsRef;
72 private SoftReference variablesRef = null;
73 private int firstIndex = -1;
74 private int lastIndex = -1;
75 private Location location;
76 private SoftReference bytecodesRef = null;
77
78 ConcreteMethodImpl(VirtualMachine vm, ReferenceTypeImpl declaringType,
79 sun.jvm.hotspot.oops.Method saMethod ) {
80 super(vm, declaringType, saMethod);
81 }
82
83 int argSlotCount() throws AbsentInformationException {
84 return (int) saMethod.getSizeOfParameters();
85 }
86
87 private SoftLocationXRefs getLocations(SDE.Stratum stratum) {
88 if (stratum.isJava()) {
89 return getBaseLocations();
90 }
91 String stratumID = stratum.id();
92 SoftLocationXRefs info =
93 (softOtherLocationXRefsRef == null) ? null :
94 (SoftLocationXRefs)softOtherLocationXRefsRef.get();
95 if (info != null && info.stratumID.equals(stratumID)) {
96 return info;
97 }
98
99 List lineLocations = new ArrayList();
100 Map lineMapper = new HashMap();
101 int lowestLine = -1;
102 int highestLine = -1;
103 SDE.LineStratum lastLineStratum = null;
104 SDE.Stratum baseStratum =
105 declaringType.stratum(SDE.BASE_STRATUM_NAME);
106 Iterator it = getBaseLocations().lineLocations.iterator();
107 while(it.hasNext()) {
108 LocationImpl loc = (LocationImpl)it.next();
109 int baseLineNumber = loc.lineNumber(baseStratum);
110 SDE.LineStratum lineStratum =
111 stratum.lineStratum(declaringType,
112 baseLineNumber);
113
114 if (lineStratum == null) {
115 // location not mapped in this stratum
116 continue;
117 }
118
119 int lineNumber = lineStratum.lineNumber();
120
121 // remove unmapped and dup lines
122 if ((lineNumber != -1) &&
123 (!lineStratum.equals(lastLineStratum))) {
124 lastLineStratum = lineStratum;
125 // Remember the largest/smallest line number
126 if (lineNumber > highestLine) {
127 highestLine = lineNumber;
128 }
129 if ((lineNumber < lowestLine) || (lowestLine == -1)) {
130 lowestLine = lineNumber;
131 }
132
133 loc.addStratumLineInfo(
134 new StratumLineInfo(stratumID,
135 lineNumber,
136 lineStratum.sourceName(),
137 lineStratum.sourcePath()));
138
139 // Add to the location list
140 lineLocations.add(loc);
141
142 // Add to the line -> locations map
143 Integer key = new Integer(lineNumber);
144 List mappedLocs = (List)lineMapper.get(key);
145 if (mappedLocs == null) {
146 mappedLocs = new ArrayList(1);
147 lineMapper.put(key, mappedLocs);
148 }
149 mappedLocs.add(loc);
150 }
151 }
152
153 info = new SoftLocationXRefs(stratumID,
154 lineMapper, lineLocations,
155 lowestLine, highestLine);
156 softOtherLocationXRefsRef = new SoftReference(info);
157 return info;
158 }
159
160 private SoftLocationXRefs getBaseLocations() {
161 SoftLocationXRefs info = (softBaseLocationXRefsRef == null) ? null :
162 (SoftLocationXRefs)softBaseLocationXRefsRef.get();
163 if (info != null) {
164 return info;
165 }
166
167 byte[] codeBuf = bytecodes();
168 firstIndex = 0;
169 lastIndex = codeBuf.length - 1;
170 // This is odd; what is the Location of a Method?
171 // A StackFrame can have a location, but a Method?
172 // I guess it must be the Location for bci 0.
173 location = new LocationImpl(virtualMachine(), this, 0);
174
175 boolean hasLineInfo = saMethod.hasLineNumberTable();
176 LineNumberTableElement[] lntab = null;
177 int count;
178
179 if (hasLineInfo) {
180 lntab = saMethod.getLineNumberTable();
181 count = lntab.length;
182 } else {
183 count = 0;
184 }
185
186 List lineLocations = new ArrayList(count);
187 Map lineMapper = new HashMap();
188 int lowestLine = -1;
189 int highestLine = -1;
190 for (int i = 0; i < count; i++) {
191 long bci = lntab[i].getStartBCI();
192 int lineNumber = lntab[i].getLineNumber();
193
194 /*
195 * Some compilers will point multiple consecutive
196 * lines at the same location. We need to choose
197 * one of them so that we can consistently map back
198 * and forth between line and location. So we choose
199 * to record only the last line entry at a particular
200 * location.
201 */
202 if ((i + 1 == count) || (bci != lntab[i+1].getStartBCI())) {
203 // Remember the largest/smallest line number
204 if (lineNumber > highestLine) {
205 highestLine = lineNumber;
206 }
207 if ((lineNumber < lowestLine) || (lowestLine == -1)) {
208 lowestLine = lineNumber;
209 }
210 LocationImpl loc =
211 new LocationImpl(virtualMachine(), this, bci);
212 loc.addBaseLineInfo(
213 new BaseLineInfo(lineNumber, declaringType));
214
215 // Add to the location list
216 lineLocations.add(loc);
217
218 // Add to the line -> locations map
219 Integer key = new Integer(lineNumber);
220 List mappedLocs = (List)lineMapper.get(key);
221 if (mappedLocs == null) {
222 mappedLocs = new ArrayList(1);
223 lineMapper.put(key, mappedLocs);
224 }
225 mappedLocs.add(loc);
226 }
227 }
228
229 info = new SoftLocationXRefs(SDE.BASE_STRATUM_NAME,
230 lineMapper, lineLocations,
231 lowestLine, highestLine);
232 softBaseLocationXRefsRef = new SoftReference(info);
233 return info;
234 }
235
236 List sourceNameFilter(List list,
237 SDE.Stratum stratum,
238 String sourceName)
239 throws AbsentInformationException {
240 if (sourceName == null) {
241 return list;
242 } else {
243 /* needs sourceName filteration */
244 List locs = new ArrayList();
245 Iterator it = list.iterator();
246 while (it.hasNext()) {
247 LocationImpl loc = (LocationImpl)it.next();
248 if (loc.sourceName(stratum).equals(sourceName)) {
249 locs.add(loc);
250 }
251 }
252 return locs;
253 }
254 }
255
256 public List allLineLocations(SDE.Stratum stratum, String sourceName)
257 throws AbsentInformationException {
258 List lineLocations = getLocations(stratum).lineLocations;
259
260 if (lineLocations.size() == 0) {
261 throw new AbsentInformationException();
262 }
263
264 return Collections.unmodifiableList(
265 sourceNameFilter(lineLocations, stratum, sourceName));
266 }
267
268 public List locationsOfLine(SDE.Stratum stratum, String sourceName,
269 int lineNumber) throws AbsentInformationException {
270 SoftLocationXRefs info = getLocations(stratum);
271
272 if (info.lineLocations.size() == 0) {
273 throw new AbsentInformationException();
274 }
275
276 /*
277 * Find the locations which match the line number
278 * passed in.
279 */
280 List list = (List)info.lineMapper.get(
281 new Integer(lineNumber));
282
283 if (list == null) {
284 list = new ArrayList(0);
285 }
286 return Collections.unmodifiableList(
287 sourceNameFilter(list, stratum, sourceName));
288 }
289
290 LineInfo codeIndexToLineInfo(SDE.Stratum stratum,
291 long codeIndex) {
292 if (firstIndex == -1) {
293 getBaseLocations();
294 }
295
296 /*
297 * Check for invalid code index.
298 */
299 if (codeIndex < firstIndex || codeIndex > lastIndex) {
300 throw new InternalError(
301 "Location with invalid code index");
302 }
303
304 List lineLocations = getLocations(stratum).lineLocations;
305
306 /*
307 * Check for absent line numbers.
308 */
309 if (lineLocations.size() == 0) {
310 return super.codeIndexToLineInfo(stratum, codeIndex);
311 }
312
313 Iterator iter = lineLocations.iterator();
314 /*
315 * Treat code before the beginning of the first line table
316 * entry as part of the first line. javac will generate
317 * code like this for some local classes. This "prolog"
318 * code contains assignments from locals in the enclosing
319 * scope to synthetic fields in the local class. Same for
320 * other language prolog code.
321 */
322 LocationImpl bestMatch = (LocationImpl)iter.next();
323 while (iter.hasNext()) {
324 LocationImpl current = (LocationImpl)iter.next();
325 if (current.codeIndex() > codeIndex) {
326 break;
327 }
328 bestMatch = current;
329 }
330 return bestMatch.getLineInfo(stratum);
331 }
332
333 public Location locationOfCodeIndex(long codeIndex) {
334 if (firstIndex == -1) {
335 getBaseLocations();
336 }
337
338 /*
339 * Check for invalid code index.
340 */
341 if (codeIndex < firstIndex || codeIndex > lastIndex) {
342 return null;
343 }
344
345 return new LocationImpl(virtualMachine(), this, codeIndex);
346 }
347
348 public List variables() throws AbsentInformationException {
349 return getVariables();
350 }
351
352 public List variablesByName(String name) throws AbsentInformationException {
353 List variables = getVariables();
354
355 List retList = new ArrayList(2);
356 Iterator iter = variables.iterator();
357 while(iter.hasNext()) {
358 LocalVariable variable = (LocalVariable)iter.next();
359 if (variable.name().equals(name)) {
360 retList.add(variable);
361 }
362 }
363 return retList;
364 }
365
366 public List arguments() throws AbsentInformationException {
367 if (argumentTypeNames().size() == 0) {
368 return new ArrayList(0);
369 }
370 List variables = getVariables();
371 List retList = new ArrayList(variables.size());
372 Iterator iter = variables.iterator();
373 while(iter.hasNext()) {
374 LocalVariable variable = (LocalVariable)iter.next();
375 if (variable.isArgument()) {
376 retList.add(variable);
377 }
378 }
379 return retList;
380 }
381
382 public byte[] bytecodes() {
383 byte[] bytecodes = (bytecodesRef == null) ? null :
384 (byte[])bytecodesRef.get();
385 if (bytecodes == null) {
386 bytecodes = saMethod.getByteCode();
387 bytecodesRef = new SoftReference(bytecodes);
388 }
389 /*
390 * Arrays are always modifiable, so it is a little unsafe
391 * to return the cached bytecodes directly; instead, we
392 * make a clone at the cost of using more memory.
393 */
394 return (byte[])bytecodes.clone();
395 }
396
397 public Location location() {
398 if (location == null) {
399 getBaseLocations();
400 }
401 return location;
402 }
403
404 private List getVariables() throws AbsentInformationException {
405 List variables = (variablesRef == null) ? null :
406 (List)variablesRef.get();
407 if (variables != null) {
408 return variables;
409 }
410
411 // if there are no locals, there won't be a LVT
412 if (saMethod.getMaxLocals() == 0) {
413 variables = Collections.unmodifiableList(new ArrayList(0));
414 variablesRef = new SoftReference(variables);
415 return variables;
416 }
417
418 if (! saMethod.hasLocalVariableTable()) {
419 throw new AbsentInformationException();
420 }
421 //Build up the JDI view of local variable table.
422 LocalVariableTableElement[] locals = saMethod.getLocalVariableTable();
423 int localCount = locals.length;
424 variables = new ArrayList(localCount);
425 for (int ii = 0; ii < localCount; ii++) {
426 String name =
427 saMethod.getConstants().getSymbolAt(locals[ii].getNameCPIndex()).asString();
428 /*
429 * Skip "this$*", "this+*", "this" entries because they are never real
430 * variables from the JLS perspective. "this+*" is new with 1.5.
431 * Instead of using '+', we check for java letter or digit to avoid
432 * depending on javac's current choice of '+'.
433 */
434 boolean isInternalName = name.startsWith("this") &&
435 (name.length() == 4 || name.charAt(4)=='$' || !Character.isJavaIdentifierPart(name.charAt(4)));
436 if (! isInternalName) {
437 int slot = locals[ii].getSlot();
438 long codeIndex = locals[ii].getStartBCI();
439 int length = locals[ii].getLength();
440 Location scopeStart = new LocationImpl(virtualMachine(),
441 this, codeIndex);
442 Location scopeEnd =
443 new LocationImpl(virtualMachine(), this,
444 codeIndex + length - 1);
445 String signature =
446 saMethod.getConstants().getSymbolAt(locals[ii].getDescriptorCPIndex()).asString();
447
448 int genericSigIndex = locals[ii].getSignatureCPIndex();
449 String genericSignature = null;
450 if (genericSigIndex != 0) {
451 genericSignature = saMethod.getConstants().getSymbolAt(genericSigIndex).asString();
452 }
453
454 LocalVariable variable =
455 new LocalVariableImpl(virtualMachine(), this,
456 slot, scopeStart, scopeEnd,
457 name, signature, genericSignature);
458 // Add to the variable list
459 variables.add(variable);
460 }
461 }
462
463 variables = Collections.unmodifiableList(variables);
464 variablesRef = new SoftReference(variables);
465 return variables;
466 }
467 }