Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstMethod.java
41161 views
1
/*
2
* Copyright (c) 2003, 2020, 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.oops;
26
27
import java.io.*;
28
import java.util.*;
29
import sun.jvm.hotspot.code.*;
30
import sun.jvm.hotspot.debugger.*;
31
import sun.jvm.hotspot.interpreter.*;
32
import sun.jvm.hotspot.memory.*;
33
import sun.jvm.hotspot.runtime.*;
34
import sun.jvm.hotspot.types.*;
35
import sun.jvm.hotspot.utilities.*;
36
import sun.jvm.hotspot.utilities.Observable;
37
import sun.jvm.hotspot.utilities.Observer;
38
39
public class ConstMethod extends Metadata {
40
static {
41
VM.registerVMInitializedObserver(new Observer() {
42
public void update(Observable o, Object data) {
43
initialize(VM.getVM().getTypeDataBase());
44
}
45
});
46
}
47
48
// anon-enum constants for _flags.
49
private static int HAS_LINENUMBER_TABLE;
50
private static int HAS_CHECKED_EXCEPTIONS;
51
private static int HAS_LOCALVARIABLE_TABLE;
52
private static int HAS_EXCEPTION_TABLE;
53
private static int HAS_GENERIC_SIGNATURE;
54
private static int HAS_METHOD_ANNOTATIONS;
55
private static int HAS_PARAMETER_ANNOTATIONS;
56
private static int HAS_METHOD_PARAMETERS;
57
private static int HAS_DEFAULT_ANNOTATIONS;
58
private static int HAS_TYPE_ANNOTATIONS;
59
60
private static final int sizeofShort = 2;
61
62
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
63
Type type = db.lookupType("ConstMethod");
64
constants = new MetadataField(type.getAddressField("_constants"), 0);
65
constMethodSize = new CIntField(type.getCIntegerField("_constMethod_size"), 0);
66
flags = new CIntField(type.getCIntegerField("_flags"), 0);
67
68
// enum constants for flags
69
HAS_LINENUMBER_TABLE = db.lookupIntConstant("ConstMethod::_has_linenumber_table").intValue();
70
HAS_CHECKED_EXCEPTIONS = db.lookupIntConstant("ConstMethod::_has_checked_exceptions").intValue();
71
HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("ConstMethod::_has_localvariable_table").intValue();
72
HAS_EXCEPTION_TABLE = db.lookupIntConstant("ConstMethod::_has_exception_table").intValue();
73
HAS_GENERIC_SIGNATURE = db.lookupIntConstant("ConstMethod::_has_generic_signature").intValue();
74
HAS_METHOD_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_method_annotations").intValue();
75
HAS_PARAMETER_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_parameter_annotations").intValue();
76
HAS_METHOD_PARAMETERS = db.lookupIntConstant("ConstMethod::_has_method_parameters").intValue();
77
HAS_DEFAULT_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_default_annotations").intValue();
78
HAS_TYPE_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_type_annotations").intValue();
79
80
// Size of Java bytecodes allocated immediately after ConstMethod*.
81
codeSize = new CIntField(type.getCIntegerField("_code_size"), 0);
82
nameIndex = new CIntField(type.getCIntegerField("_name_index"), 0);
83
signatureIndex = new CIntField(type.getCIntegerField("_signature_index"), 0);
84
idnum = new CIntField(type.getCIntegerField("_method_idnum"), 0);
85
maxStack = new CIntField(type.getCIntegerField("_max_stack"), 0);
86
maxLocals = new CIntField(type.getCIntegerField("_max_locals"), 0);
87
sizeOfParameters = new CIntField(type.getCIntegerField("_size_of_parameters"), 0);
88
89
// start of byte code
90
bytecodeOffset = type.getSize();
91
92
type = db.lookupType("MethodParametersElement");
93
methodParametersElementSize = type.getSize();
94
95
type = db.lookupType("CheckedExceptionElement");
96
checkedExceptionElementSize = type.getSize();
97
98
type = db.lookupType("LocalVariableTableElement");
99
localVariableTableElementSize = type.getSize();
100
101
type = db.lookupType("ExceptionTableElement");
102
exceptionTableElementSize = type.getSize();
103
}
104
105
public ConstMethod(Address addr) {
106
super(addr);
107
}
108
109
// Fields
110
private static MetadataField constants;
111
private static CIntField constMethodSize;
112
private static CIntField flags;
113
private static CIntField codeSize;
114
private static CIntField nameIndex;
115
private static CIntField signatureIndex;
116
private static CIntField idnum;
117
private static CIntField maxStack;
118
private static CIntField maxLocals;
119
private static CIntField sizeOfParameters;
120
121
// start of bytecode
122
private static long bytecodeOffset;
123
private static long methodParametersElementSize;
124
private static long checkedExceptionElementSize;
125
private static long localVariableTableElementSize;
126
private static long exceptionTableElementSize;
127
128
public Method getMethod() {
129
InstanceKlass ik = (InstanceKlass)getConstants().getPoolHolder();
130
MethodArray methods = ik.getMethods();
131
return methods.at((int)getIdNum());
132
}
133
134
// Accessors for declared fields
135
public ConstantPool getConstants() {
136
return (ConstantPool) constants.getValue(this);
137
}
138
139
public long getConstMethodSize() {
140
return constMethodSize.getValue(this);
141
}
142
143
public long getFlags() {
144
return flags.getValue(this);
145
}
146
147
public long getCodeSize() {
148
return codeSize.getValue(this);
149
}
150
151
public long getNameIndex() {
152
return nameIndex.getValue(this);
153
}
154
155
public long getSignatureIndex() {
156
return signatureIndex.getValue(this);
157
}
158
159
public long getGenericSignatureIndex() {
160
if (hasGenericSignature()) {
161
return getAddress().getCIntegerAt(offsetOfGenericSignatureIndex(), 2, true);
162
} else {
163
return 0;
164
}
165
}
166
167
public long getIdNum() {
168
return idnum.getValue(this);
169
}
170
171
public long getMaxStack() {
172
return maxStack.getValue(this);
173
}
174
175
public long getMaxLocals() {
176
return maxLocals.getValue(this);
177
}
178
179
public long getSizeOfParameters() {
180
return sizeOfParameters.getValue(this);
181
}
182
183
public Symbol getName() {
184
return getMethod().getName();
185
}
186
187
public Symbol getSignature() {
188
return getMethod().getSignature();
189
}
190
191
public Symbol getGenericSignature() {
192
return getMethod().getGenericSignature();
193
}
194
195
// bytecode accessors
196
197
/** See if address is in the Method's bytecodes */
198
public boolean isAddressInMethod(Address bcp) {
199
Address bytecodeStart = getAddress().addOffsetTo(bytecodeOffset);
200
Address bytecodeEnd = bytecodeStart.addOffsetTo(getCodeSize() - 1);
201
if (bcp.greaterThanOrEqual(bytecodeStart) && bcp.lessThanOrEqual(bytecodeEnd)) {
202
return true;
203
} else {
204
return false;
205
}
206
}
207
208
/** Get a bytecode or breakpoint at the given bci */
209
public int getBytecodeOrBPAt(int bci) {
210
return getAddress().getJByteAt(bytecodeOffset + bci) & 0xFF;
211
}
212
213
public byte getBytecodeByteArg(int bci) {
214
return (byte) getBytecodeOrBPAt(bci);
215
}
216
217
/** Fetches a 16-bit big-endian ("Java ordered") value from the
218
bytecode stream */
219
public short getBytecodeShortArg(int bci) {
220
int hi = getBytecodeOrBPAt(bci);
221
int lo = getBytecodeOrBPAt(bci + 1);
222
return (short) ((hi << 8) | lo);
223
}
224
225
/** Fetches a 16-bit native ordered value from the
226
bytecode stream */
227
public short getNativeShortArg(int bci) {
228
int hi = getBytecodeOrBPAt(bci);
229
int lo = getBytecodeOrBPAt(bci + 1);
230
if (VM.getVM().isBigEndian()) {
231
return (short) ((hi << 8) | lo);
232
} else {
233
return (short) ((lo << 8) | hi);
234
}
235
}
236
237
/** Fetches a 32-bit big-endian ("Java ordered") value from the
238
bytecode stream */
239
public int getBytecodeIntArg(int bci) {
240
int b4 = getBytecodeOrBPAt(bci);
241
int b3 = getBytecodeOrBPAt(bci + 1);
242
int b2 = getBytecodeOrBPAt(bci + 2);
243
int b1 = getBytecodeOrBPAt(bci + 3);
244
245
return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
246
}
247
248
/** Fetches a 32-bit native ordered value from the
249
bytecode stream */
250
public int getNativeIntArg(int bci) {
251
int b4 = getBytecodeOrBPAt(bci);
252
int b3 = getBytecodeOrBPAt(bci + 1);
253
int b2 = getBytecodeOrBPAt(bci + 2);
254
int b1 = getBytecodeOrBPAt(bci + 3);
255
256
if (VM.getVM().isBigEndian()) {
257
return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
258
} else {
259
return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
260
}
261
}
262
263
public byte[] getByteCode() {
264
byte[] bc = new byte[ (int) getCodeSize() ];
265
for( int i=0; i < bc.length; i++ )
266
{
267
long offs = bytecodeOffset + i;
268
bc[i] = getAddress().getJByteAt( offs );
269
}
270
return bc;
271
}
272
273
public long getSize() {
274
return getConstMethodSize();
275
}
276
277
public void printValueOn(PrintStream tty) {
278
tty.print("ConstMethod " + getName().asString() + getSignature().asString() + "@" + getAddress());
279
}
280
281
public void iterateFields(MetadataVisitor visitor) {
282
visitor.doMetadata(constants, true);
283
visitor.doCInt(constMethodSize, true);
284
visitor.doCInt(flags, true);
285
visitor.doCInt(codeSize, true);
286
visitor.doCInt(nameIndex, true);
287
visitor.doCInt(signatureIndex, true);
288
visitor.doCInt(codeSize, true);
289
visitor.doCInt(maxStack, true);
290
visitor.doCInt(maxLocals, true);
291
visitor.doCInt(sizeOfParameters, true);
292
}
293
294
// Accessors
295
296
public boolean hasLineNumberTable() {
297
return (getFlags() & HAS_LINENUMBER_TABLE) != 0;
298
}
299
300
public int getLineNumberFromBCI(int bci) {
301
if (!VM.getVM().isCore()) {
302
if (bci == DebugInformationRecorder.SYNCHRONIZATION_ENTRY_BCI) bci = 0;
303
}
304
305
if (isNative()) {
306
return -1;
307
}
308
309
if (Assert.ASSERTS_ENABLED) {
310
Assert.that(0 <= bci && bci < getCodeSize(),
311
"illegal bci(" + bci + ") codeSize(" + getCodeSize() + ")");
312
}
313
int bestBCI = 0;
314
int bestLine = -1;
315
if (hasLineNumberTable()) {
316
// The line numbers are a short array of 2-tuples [start_pc, line_number].
317
// Not necessarily sorted and not necessarily one-to-one.
318
CompressedLineNumberReadStream stream =
319
new CompressedLineNumberReadStream(getAddress(), (int) offsetOfCompressedLineNumberTable());
320
while (stream.readPair()) {
321
if (stream.bci() == bci) {
322
// perfect match
323
return stream.line();
324
} else {
325
// update best_bci/line
326
if (stream.bci() < bci && stream.bci() >= bestBCI) {
327
bestBCI = stream.bci();
328
bestLine = stream.line();
329
}
330
}
331
}
332
}
333
return bestLine;
334
}
335
336
public LineNumberTableElement[] getLineNumberTable() {
337
if (Assert.ASSERTS_ENABLED) {
338
Assert.that(hasLineNumberTable(),
339
"should only be called if table is present");
340
}
341
int len = getLineNumberTableLength();
342
CompressedLineNumberReadStream stream =
343
new CompressedLineNumberReadStream(getAddress(), (int) offsetOfCompressedLineNumberTable());
344
LineNumberTableElement[] ret = new LineNumberTableElement[len];
345
346
for (int idx = 0; idx < len; idx++) {
347
stream.readPair();
348
ret[idx] = new LineNumberTableElement(stream.bci(), stream.line());
349
}
350
return ret;
351
}
352
353
public boolean hasLocalVariableTable() {
354
return (getFlags() & HAS_LOCALVARIABLE_TABLE) != 0;
355
}
356
357
public Symbol getLocalVariableName(int bci, int slot) {
358
return getMethod().getLocalVariableName(bci, slot);
359
}
360
361
/** Should only be called if table is present */
362
public LocalVariableTableElement[] getLocalVariableTable() {
363
if (Assert.ASSERTS_ENABLED) {
364
Assert.that(hasLocalVariableTable(), "should only be called if table is present");
365
}
366
LocalVariableTableElement[] ret = new LocalVariableTableElement[getLocalVariableTableLength()];
367
long offset = offsetOfLocalVariableTable();
368
for (int i = 0; i < ret.length; i++) {
369
ret[i] = new LocalVariableTableElement(getAddress(), offset);
370
offset += localVariableTableElementSize;
371
}
372
return ret;
373
}
374
375
public boolean hasExceptionTable() {
376
return (getFlags() & HAS_EXCEPTION_TABLE) != 0;
377
}
378
379
public ExceptionTableElement[] getExceptionTable() {
380
if (Assert.ASSERTS_ENABLED) {
381
Assert.that(hasExceptionTable(), "should only be called if table is present");
382
}
383
ExceptionTableElement[] ret = new ExceptionTableElement[getExceptionTableLength()];
384
long offset = offsetOfExceptionTable();
385
for (int i = 0; i < ret.length; i++) {
386
ret[i] = new ExceptionTableElement(getAddress(), offset);
387
offset += exceptionTableElementSize;
388
}
389
return ret;
390
}
391
392
public boolean hasCheckedExceptions() {
393
return (getFlags() & HAS_CHECKED_EXCEPTIONS) != 0;
394
}
395
396
public CheckedExceptionElement[] getCheckedExceptions() {
397
if (Assert.ASSERTS_ENABLED) {
398
Assert.that(hasCheckedExceptions(), "should only be called if table is present");
399
}
400
CheckedExceptionElement[] ret = new CheckedExceptionElement[getCheckedExceptionsLength()];
401
long offset = offsetOfCheckedExceptions();
402
for (int i = 0; i < ret.length; i++) {
403
ret[i] = new CheckedExceptionElement(getAddress(), offset);
404
offset += checkedExceptionElementSize;
405
}
406
return ret;
407
}
408
409
private boolean hasMethodParameters() {
410
return (getFlags() & HAS_METHOD_PARAMETERS) != 0;
411
}
412
413
private boolean hasGenericSignature() {
414
return (getFlags() & HAS_GENERIC_SIGNATURE) != 0;
415
}
416
417
private boolean hasMethodAnnotations() {
418
return (getFlags() & HAS_METHOD_ANNOTATIONS) != 0;
419
}
420
421
private boolean hasParameterAnnotations() {
422
return (getFlags() & HAS_PARAMETER_ANNOTATIONS) != 0;
423
}
424
425
private boolean hasDefaultAnnotations() {
426
return (getFlags() & HAS_DEFAULT_ANNOTATIONS) != 0;
427
}
428
429
private boolean hasTypeAnnotations() {
430
return (getFlags() & HAS_TYPE_ANNOTATIONS) != 0;
431
}
432
433
434
//---------------------------------------------------------------------------
435
// Internals only below this point
436
//
437
438
private boolean isNative() {
439
return getMethod().isNative();
440
}
441
442
// Offset of end of code
443
private long offsetOfCodeEnd() {
444
return bytecodeOffset + getCodeSize();
445
}
446
447
// Offset of start of compressed line number table (see method.hpp)
448
private long offsetOfCompressedLineNumberTable() {
449
return offsetOfCodeEnd() + (isNative() ? 2 * VM.getVM().getAddressSize() : 0);
450
}
451
452
// Offset of last short in Method* before annotations, if present
453
private long offsetOfLastU2Element() {
454
int offset = 0;
455
if (hasMethodAnnotations()) offset++;
456
if (hasParameterAnnotations()) offset++;
457
if (hasTypeAnnotations()) offset++;
458
if (hasDefaultAnnotations()) offset++;
459
long wordSize = VM.getVM().getObjectHeap().getOopSize();
460
return (getSize() * wordSize) - (offset * wordSize) - sizeofShort;
461
}
462
463
// Offset of the generic signature index
464
private long offsetOfGenericSignatureIndex() {
465
return offsetOfLastU2Element();
466
}
467
468
private long offsetOfMethodParametersLength() {
469
if (Assert.ASSERTS_ENABLED) {
470
Assert.that(hasMethodParameters(), "should only be called if table is present");
471
}
472
return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
473
offsetOfLastU2Element();
474
}
475
476
private int getMethodParametersLength() {
477
if (hasMethodParameters())
478
return (int) getAddress().getCIntegerAt(offsetOfMethodParametersLength(), 2, true);
479
else
480
return 0;
481
}
482
483
// Offset of start of checked exceptions
484
private long offsetOfMethodParameters() {
485
long offset = offsetOfMethodParametersLength();
486
long length = getMethodParametersLength();
487
if (Assert.ASSERTS_ENABLED) {
488
Assert.that(length > 0, "should only be called if method parameter information is present");
489
}
490
offset -= length * methodParametersElementSize;
491
return offset;
492
}
493
494
private long offsetOfCheckedExceptionsLength() {
495
if (hasMethodParameters())
496
return offsetOfMethodParameters() - sizeofShort;
497
else {
498
return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
499
offsetOfLastU2Element();
500
}
501
}
502
503
private int getCheckedExceptionsLength() {
504
if (hasCheckedExceptions()) {
505
return (int) getAddress().getCIntegerAt(offsetOfCheckedExceptionsLength(), 2, true);
506
} else {
507
return 0;
508
}
509
}
510
511
// Offset of start of checked exceptions
512
private long offsetOfCheckedExceptions() {
513
long offset = offsetOfCheckedExceptionsLength();
514
long length = getCheckedExceptionsLength();
515
if (Assert.ASSERTS_ENABLED) {
516
Assert.that(length > 0, "should only be called if table is present");
517
}
518
offset -= length * checkedExceptionElementSize;
519
return offset;
520
}
521
522
private int getLineNumberTableLength() {
523
int len = 0;
524
if (hasLineNumberTable()) {
525
CompressedLineNumberReadStream stream =
526
new CompressedLineNumberReadStream(getAddress(), (int) offsetOfCompressedLineNumberTable());
527
while (stream.readPair()) {
528
len += 1;
529
}
530
}
531
return len;
532
}
533
534
private int getLocalVariableTableLength() {
535
if (hasLocalVariableTable()) {
536
return (int) getAddress().getCIntegerAt(offsetOfLocalVariableTableLength(), 2, true);
537
} else {
538
return 0;
539
}
540
}
541
542
// Offset of local variable table length
543
private long offsetOfLocalVariableTableLength() {
544
if (Assert.ASSERTS_ENABLED) {
545
Assert.that(hasLocalVariableTable(), "should only be called if table is present");
546
}
547
548
if (hasExceptionTable()) {
549
return offsetOfExceptionTable() - sizeofShort;
550
} else if (hasCheckedExceptions()) {
551
return offsetOfCheckedExceptions() - sizeofShort;
552
} else if (hasMethodParameters()) {
553
return offsetOfMethodParameters() - sizeofShort;
554
} else {
555
return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
556
offsetOfLastU2Element();
557
}
558
}
559
560
private long offsetOfLocalVariableTable() {
561
long offset = offsetOfLocalVariableTableLength();
562
long length = getLocalVariableTableLength();
563
if (Assert.ASSERTS_ENABLED) {
564
Assert.that(length > 0, "should only be called if table is present");
565
}
566
offset -= length * localVariableTableElementSize;
567
return offset;
568
}
569
570
private int getExceptionTableLength() {
571
if (hasExceptionTable()) {
572
return (int) getAddress().getCIntegerAt(offsetOfExceptionTableLength(), 2, true);
573
} else {
574
return 0;
575
}
576
}
577
578
private long offsetOfExceptionTableLength() {
579
if (Assert.ASSERTS_ENABLED) {
580
Assert.that(hasExceptionTable(), "should only be called if table is present");
581
}
582
if (hasCheckedExceptions()) {
583
return offsetOfCheckedExceptions() - sizeofShort;
584
} else if (hasMethodParameters()) {
585
return offsetOfMethodParameters() - sizeofShort;
586
} else {
587
return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
588
offsetOfLastU2Element();
589
}
590
}
591
592
private long offsetOfExceptionTable() {
593
long offset = offsetOfExceptionTableLength();
594
long length = getExceptionTableLength();
595
if (Assert.ASSERTS_ENABLED) {
596
Assert.that(length > 0, "should only be called if table is present");
597
}
598
offset -= length * exceptionTableElementSize;
599
return offset;
600
}
601
602
}
603
604