Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/tools/jdi/ConcreteMethodImpl.java
38920 views
1
/*
2
* Copyright (c) 2000, 2011, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package com.sun.tools.jdi;
27
28
import com.sun.jdi.*;
29
30
import java.util.List;
31
import java.util.Map;
32
import java.util.Iterator;
33
import java.util.ListIterator;
34
import java.util.HashMap;
35
import java.util.ArrayList;
36
import java.util.Collections;
37
import java.lang.ref.SoftReference;
38
39
/**
40
* Represents methods with method bodies.
41
* That is, non-native non-abstract methods.
42
* Private to MethodImpl.
43
*/
44
public class ConcreteMethodImpl extends MethodImpl {
45
46
/*
47
* A subset of the line number info that is softly cached
48
*/
49
static private class SoftLocationXRefs {
50
final String stratumID; // The stratum of this information
51
final Map<Integer, List<Location>> lineMapper; // Maps line number to location(s)
52
final List<Location> lineLocations; // List of locations ordered by code index
53
54
/*
55
* Note: these do not necessarily correspond to
56
* the line numbers of the first and last elements
57
* in the lineLocations list. Use these only for bounds
58
* checking and with lineMapper.
59
*/
60
final int lowestLine;
61
final int highestLine;
62
63
SoftLocationXRefs(String stratumID, Map<Integer, List<Location>> lineMapper, List<Location> lineLocations,
64
int lowestLine, int highestLine) {
65
this.stratumID = stratumID;
66
this.lineMapper = Collections.unmodifiableMap(lineMapper);
67
this.lineLocations =
68
Collections.unmodifiableList(lineLocations);
69
this.lowestLine = lowestLine;
70
this.highestLine = highestLine;
71
}
72
}
73
74
private Location location = null;
75
private SoftReference<SoftLocationXRefs> softBaseLocationXRefsRef;
76
private SoftReference<SoftLocationXRefs> softOtherLocationXRefsRef;
77
private SoftReference<List<LocalVariable>> variablesRef = null;
78
private boolean absentVariableInformation = false;
79
private long firstIndex = -1;
80
private long lastIndex = -1;
81
private SoftReference<byte[]> bytecodesRef = null;
82
private int argSlotCount = -1;
83
84
ConcreteMethodImpl(VirtualMachine vm, ReferenceTypeImpl declaringType,
85
long ref,
86
String name, String signature,
87
String genericSignature, int modifiers) {
88
89
// The generic signature is set when this is created
90
super(vm, declaringType, ref, name, signature,
91
genericSignature, modifiers);
92
}
93
94
public Location location() {
95
if (location == null) {
96
getBaseLocations();
97
}
98
return location;
99
}
100
101
List<Location> sourceNameFilter(List<Location> list,
102
SDE.Stratum stratum,
103
String sourceName)
104
throws AbsentInformationException {
105
if (sourceName == null) {
106
return list;
107
} else {
108
/* needs sourceName filteration */
109
List<Location> locs = new ArrayList<Location>();
110
for (Location loc : list) {
111
if (((LocationImpl)loc).sourceName(stratum).equals(sourceName)) {
112
locs.add(loc);
113
}
114
}
115
return locs;
116
}
117
}
118
119
List<Location> allLineLocations(SDE.Stratum stratum,
120
String sourceName)
121
throws AbsentInformationException {
122
List<Location> lineLocations = getLocations(stratum).lineLocations;
123
124
if (lineLocations.size() == 0) {
125
throw new AbsentInformationException();
126
}
127
128
return Collections.unmodifiableList(
129
sourceNameFilter(lineLocations, stratum, sourceName));
130
}
131
132
List<Location> locationsOfLine(SDE.Stratum stratum,
133
String sourceName,
134
int lineNumber)
135
throws AbsentInformationException {
136
SoftLocationXRefs info = getLocations(stratum);
137
138
if (info.lineLocations.size() == 0) {
139
throw new AbsentInformationException();
140
}
141
142
/*
143
* Find the locations which match the line number
144
* passed in.
145
*/
146
List<Location> list = info.lineMapper.get(new Integer(lineNumber));
147
148
if (list == null) {
149
list = new ArrayList<Location>(0);
150
}
151
return Collections.unmodifiableList(
152
sourceNameFilter(list, stratum, sourceName));
153
}
154
155
156
public Location locationOfCodeIndex(long codeIndex) {
157
if (firstIndex == -1) {
158
getBaseLocations();
159
}
160
161
/*
162
* Check for invalid code index.
163
*/
164
if (codeIndex < firstIndex || codeIndex > lastIndex) {
165
return null;
166
}
167
168
return new LocationImpl(virtualMachine(), this, codeIndex);
169
}
170
171
172
LineInfo codeIndexToLineInfo(SDE.Stratum stratum,
173
long codeIndex) {
174
if (firstIndex == -1) {
175
getBaseLocations();
176
}
177
178
/*
179
* Check for invalid code index.
180
*/
181
if (codeIndex < firstIndex || codeIndex > lastIndex) {
182
throw new InternalError(
183
"Location with invalid code index");
184
}
185
186
List<Location> lineLocations = getLocations(stratum).lineLocations;
187
188
/*
189
* Check for absent line numbers.
190
*/
191
if (lineLocations.size() == 0) {
192
return super.codeIndexToLineInfo(stratum, codeIndex);
193
}
194
195
Iterator<Location> iter = lineLocations.iterator();
196
/*
197
* Treat code before the beginning of the first line table
198
* entry as part of the first line. javac will generate
199
* code like this for some local classes. This "prolog"
200
* code contains assignments from locals in the enclosing
201
* scope to synthetic fields in the local class. Same for
202
* other language prolog code.
203
*/
204
LocationImpl bestMatch = (LocationImpl)iter.next();
205
while (iter.hasNext()) {
206
LocationImpl current = (LocationImpl)iter.next();
207
if (current.codeIndex() > codeIndex) {
208
break;
209
}
210
bestMatch = current;
211
}
212
return bestMatch.getLineInfo(stratum);
213
}
214
215
216
public List<LocalVariable> variables() throws AbsentInformationException {
217
return getVariables();
218
}
219
220
public List<LocalVariable> variablesByName(String name) throws AbsentInformationException {
221
List<LocalVariable> variables = getVariables();
222
223
List<LocalVariable> retList = new ArrayList<LocalVariable>(2);
224
Iterator<LocalVariable> iter = variables.iterator();
225
while(iter.hasNext()) {
226
LocalVariable variable = iter.next();
227
if (variable.name().equals(name)) {
228
retList.add(variable);
229
}
230
}
231
return retList;
232
}
233
234
public List<LocalVariable> arguments() throws AbsentInformationException {
235
List<LocalVariable> variables = getVariables();
236
237
List<LocalVariable> retList = new ArrayList<LocalVariable>(variables.size());
238
Iterator<LocalVariable> iter = variables.iterator();
239
while(iter.hasNext()) {
240
LocalVariable variable = iter.next();
241
if (variable.isArgument()) {
242
retList.add(variable);
243
}
244
}
245
return retList;
246
}
247
248
public byte[] bytecodes() {
249
byte[] bytecodes = (bytecodesRef == null) ? null :
250
bytecodesRef.get();
251
if (bytecodes == null) {
252
try {
253
bytecodes = JDWP.Method.Bytecodes.
254
process(vm, declaringType, ref).bytes;
255
} catch (JDWPException exc) {
256
throw exc.toJDIException();
257
}
258
bytecodesRef = new SoftReference<byte[]>(bytecodes);
259
}
260
/*
261
* Arrays are always modifiable, so it is a little unsafe
262
* to return the cached bytecodes directly; instead, we
263
* make a clone at the cost of using more memory.
264
*/
265
return bytecodes.clone();
266
}
267
268
int argSlotCount() throws AbsentInformationException {
269
if (argSlotCount == -1) {
270
getVariables();
271
}
272
return argSlotCount;
273
}
274
275
private SoftLocationXRefs getLocations(SDE.Stratum stratum) {
276
if (stratum.isJava()) {
277
return getBaseLocations();
278
}
279
String stratumID = stratum.id();
280
SoftLocationXRefs info =
281
(softOtherLocationXRefsRef == null) ? null :
282
softOtherLocationXRefsRef.get();
283
if (info != null && info.stratumID.equals(stratumID)) {
284
return info;
285
}
286
287
List<Location> lineLocations = new ArrayList<Location>();
288
Map<Integer, List<Location>> lineMapper = new HashMap<Integer, List<Location>>();
289
int lowestLine = -1;
290
int highestLine = -1;
291
SDE.LineStratum lastLineStratum = null;
292
SDE.Stratum baseStratum =
293
declaringType.stratum(SDE.BASE_STRATUM_NAME);
294
Iterator<Location> it = getBaseLocations().lineLocations.iterator();
295
while(it.hasNext()) {
296
LocationImpl loc = (LocationImpl)it.next();
297
int baseLineNumber = loc.lineNumber(baseStratum);
298
SDE.LineStratum lineStratum =
299
stratum.lineStratum(declaringType,
300
baseLineNumber);
301
302
if (lineStratum == null) {
303
// location not mapped in this stratum
304
continue;
305
}
306
307
int lineNumber = lineStratum.lineNumber();
308
309
// remove unmapped and dup lines
310
if ((lineNumber != -1) &&
311
(!lineStratum.equals(lastLineStratum))) {
312
lastLineStratum = lineStratum;
313
314
// Remember the largest/smallest line number
315
if (lineNumber > highestLine) {
316
highestLine = lineNumber;
317
}
318
if ((lineNumber < lowestLine) || (lowestLine == -1)) {
319
lowestLine = lineNumber;
320
}
321
322
loc.addStratumLineInfo(
323
new StratumLineInfo(stratumID,
324
lineNumber,
325
lineStratum.sourceName(),
326
lineStratum.sourcePath()));
327
328
// Add to the location list
329
lineLocations.add(loc);
330
331
// Add to the line -> locations map
332
Integer key = new Integer(lineNumber);
333
List<Location> mappedLocs = lineMapper.get(key);
334
if (mappedLocs == null) {
335
mappedLocs = new ArrayList<Location>(1);
336
lineMapper.put(key, mappedLocs);
337
}
338
mappedLocs.add(loc);
339
}
340
}
341
342
info = new SoftLocationXRefs(stratumID,
343
lineMapper, lineLocations,
344
lowestLine, highestLine);
345
softOtherLocationXRefsRef = new SoftReference<SoftLocationXRefs>(info);
346
return info;
347
}
348
349
private SoftLocationXRefs getBaseLocations() {
350
SoftLocationXRefs info = (softBaseLocationXRefsRef == null) ? null :
351
softBaseLocationXRefsRef.get();
352
if (info != null) {
353
return info;
354
}
355
356
JDWP.Method.LineTable lntab = null;
357
try {
358
lntab = JDWP.Method.LineTable.process(vm, declaringType, ref);
359
} catch (JDWPException exc) {
360
/*
361
* Note: the absent info error shouldn't happen here
362
* because the first and last index are always available.
363
*/
364
throw exc.toJDIException();
365
}
366
367
int count = lntab.lines.length;
368
369
List<Location> lineLocations = new ArrayList<Location>(count);
370
Map<Integer, List<Location>>lineMapper = new HashMap<Integer, List<Location>>();
371
int lowestLine = -1;
372
int highestLine = -1;
373
for (int i = 0; i < count; i++) {
374
long bci = lntab.lines[i].lineCodeIndex;
375
int lineNumber = lntab.lines[i].lineNumber;
376
377
/*
378
* Some compilers will point multiple consecutive
379
* lines at the same location. We need to choose
380
* one of them so that we can consistently map back
381
* and forth between line and location. So we choose
382
* to record only the last line entry at a particular
383
* location.
384
*/
385
if ((i + 1 == count) || (bci != lntab.lines[i+1].lineCodeIndex)) {
386
// Remember the largest/smallest line number
387
if (lineNumber > highestLine) {
388
highestLine = lineNumber;
389
}
390
if ((lineNumber < lowestLine) || (lowestLine == -1)) {
391
lowestLine = lineNumber;
392
}
393
LocationImpl loc =
394
new LocationImpl(virtualMachine(), this, bci);
395
loc.addBaseLineInfo(
396
new BaseLineInfo(lineNumber, declaringType));
397
398
// Add to the location list
399
lineLocations.add(loc);
400
401
// Add to the line -> locations map
402
Integer key = new Integer(lineNumber);
403
List<Location> mappedLocs = lineMapper.get(key);
404
if (mappedLocs == null) {
405
mappedLocs = new ArrayList<Location>(1);
406
lineMapper.put(key, mappedLocs);
407
}
408
mappedLocs.add(loc);
409
}
410
}
411
412
/*
413
* firstIndex, lastIndex, and startLocation need to be
414
* retrieved only once since they are strongly referenced.
415
*/
416
if (location == null) {
417
firstIndex = lntab.start;
418
lastIndex = lntab.end;
419
/*
420
* The startLocation is the first one in the
421
* location list if we have one;
422
* otherwise, we construct a location for a
423
* method start with no line info
424
*/
425
if (count > 0) {
426
location = lineLocations.get(0);
427
} else {
428
location = new LocationImpl(virtualMachine(), this,
429
firstIndex);
430
}
431
}
432
433
info = new SoftLocationXRefs(SDE.BASE_STRATUM_NAME,
434
lineMapper, lineLocations,
435
lowestLine, highestLine);
436
softBaseLocationXRefsRef = new SoftReference<SoftLocationXRefs>(info);
437
return info;
438
}
439
440
private List<LocalVariable> getVariables1_4() throws AbsentInformationException {
441
JDWP.Method.VariableTable vartab = null;
442
try {
443
vartab = JDWP.Method.VariableTable.
444
process(vm, declaringType, ref);
445
} catch (JDWPException exc) {
446
if (exc.errorCode() == JDWP.Error.ABSENT_INFORMATION) {
447
absentVariableInformation = true;
448
throw new AbsentInformationException();
449
} else {
450
throw exc.toJDIException();
451
}
452
}
453
454
// Get the number of slots used by argument variables
455
argSlotCount = vartab.argCnt;
456
int count = vartab.slots.length;
457
List<LocalVariable> variables = new ArrayList<LocalVariable>(count);
458
for (int i=0; i<count; i++) {
459
JDWP.Method.VariableTable.SlotInfo si = vartab.slots[i];
460
461
/*
462
* Skip "this*" entries because they are never real
463
* variables from the JLS perspective.
464
*/
465
if (!si.name.startsWith("this$") && !si.name.equals("this")) {
466
Location scopeStart = new LocationImpl(virtualMachine(),
467
this, si.codeIndex);
468
Location scopeEnd =
469
new LocationImpl(virtualMachine(), this,
470
si.codeIndex + si.length - 1);
471
LocalVariable variable =
472
new LocalVariableImpl(virtualMachine(), this,
473
si.slot, scopeStart, scopeEnd,
474
si.name, si.signature, null);
475
// Add to the variable list
476
variables.add(variable);
477
}
478
}
479
return variables;
480
}
481
482
private List<LocalVariable> getVariables1() throws AbsentInformationException {
483
484
if (!vm.canGet1_5LanguageFeatures()) {
485
return getVariables1_4();
486
}
487
488
JDWP.Method.VariableTableWithGeneric vartab = null;
489
try {
490
vartab = JDWP.Method.VariableTableWithGeneric.
491
process(vm, declaringType, ref);
492
} catch (JDWPException exc) {
493
if (exc.errorCode() == JDWP.Error.ABSENT_INFORMATION) {
494
absentVariableInformation = true;
495
throw new AbsentInformationException();
496
} else {
497
throw exc.toJDIException();
498
}
499
}
500
501
// Get the number of slots used by argument variables
502
argSlotCount = vartab.argCnt;
503
int count = vartab.slots.length;
504
List<LocalVariable> variables = new ArrayList<LocalVariable>(count);
505
for (int i=0; i<count; i++) {
506
JDWP.Method.VariableTableWithGeneric.SlotInfo si = vartab.slots[i];
507
508
/*
509
* Skip "this*" entries because they are never real
510
* variables from the JLS perspective.
511
*/
512
if (!si.name.startsWith("this$") && !si.name.equals("this")) {
513
Location scopeStart = new LocationImpl(virtualMachine(),
514
this, si.codeIndex);
515
Location scopeEnd =
516
new LocationImpl(virtualMachine(), this,
517
si.codeIndex + si.length - 1);
518
LocalVariable variable =
519
new LocalVariableImpl(virtualMachine(), this,
520
si.slot, scopeStart, scopeEnd,
521
si.name, si.signature,
522
si.genericSignature);
523
// Add to the variable list
524
variables.add(variable);
525
}
526
}
527
return variables;
528
}
529
530
private List<LocalVariable> getVariables() throws AbsentInformationException {
531
if (absentVariableInformation) {
532
throw new AbsentInformationException();
533
}
534
535
List<LocalVariable> variables = (variablesRef == null) ? null :
536
variablesRef.get();
537
if (variables != null) {
538
return variables;
539
}
540
variables = getVariables1();
541
variables = Collections.unmodifiableList(variables);
542
variablesRef = new SoftReference<List<LocalVariable>>(variables);
543
return variables;
544
}
545
}
546
547