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