Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/oops/constMethod.cpp
40951 views
1
/*
2
* Copyright (c) 2003, 2021, 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
#include "precompiled.hpp"
26
#include "interpreter/interpreter.hpp"
27
#include "memory/metadataFactory.hpp"
28
#include "memory/metaspaceClosure.hpp"
29
#include "memory/resourceArea.hpp"
30
#include "oops/constMethod.hpp"
31
#include "oops/method.hpp"
32
#include "runtime/safepointVerifiers.hpp"
33
#include "utilities/align.hpp"
34
35
// Static initialization
36
const u2 ConstMethod::MAX_IDNUM = 0xFFFE;
37
const u2 ConstMethod::UNSET_IDNUM = 0xFFFF;
38
39
ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,
40
int byte_code_size,
41
InlineTableSizes* sizes,
42
MethodType method_type,
43
TRAPS) {
44
int size = ConstMethod::size(byte_code_size, sizes);
45
return new (loader_data, size, MetaspaceObj::ConstMethodType, THREAD) ConstMethod(
46
byte_code_size, sizes, method_type, size);
47
}
48
49
ConstMethod::ConstMethod(int byte_code_size,
50
InlineTableSizes* sizes,
51
MethodType method_type,
52
int size) {
53
54
NoSafepointVerifier no_safepoint;
55
init_fingerprint();
56
set_constants(NULL);
57
set_stackmap_data(NULL);
58
set_code_size(byte_code_size);
59
set_constMethod_size(size);
60
set_inlined_tables_length(sizes); // sets _flags
61
set_method_type(method_type);
62
assert(this->size() == size, "wrong size for object");
63
set_name_index(0);
64
set_signature_index(0);
65
set_constants(NULL);
66
set_max_stack(0);
67
set_max_locals(0);
68
set_method_idnum(0);
69
set_size_of_parameters(0);
70
set_result_type((BasicType)0);
71
}
72
73
// Accessor that copies to metadata.
74
void ConstMethod::copy_stackmap_data(ClassLoaderData* loader_data,
75
u1* sd, int length, TRAPS) {
76
_stackmap_data = MetadataFactory::new_array<u1>(loader_data, length, CHECK);
77
memcpy((void*)_stackmap_data->adr_at(0), (void*)sd, length);
78
}
79
80
// Deallocate metadata fields associated with ConstMethod*
81
void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) {
82
if (stackmap_data() != NULL) {
83
MetadataFactory::free_array<u1>(loader_data, stackmap_data());
84
}
85
set_stackmap_data(NULL);
86
87
// deallocate annotation arrays
88
if (has_method_annotations())
89
MetadataFactory::free_array<u1>(loader_data, method_annotations());
90
if (has_parameter_annotations())
91
MetadataFactory::free_array<u1>(loader_data, parameter_annotations());
92
if (has_type_annotations())
93
MetadataFactory::free_array<u1>(loader_data, type_annotations());
94
if (has_default_annotations())
95
MetadataFactory::free_array<u1>(loader_data, default_annotations());
96
}
97
98
// How big must this constMethodObject be?
99
100
int ConstMethod::size(int code_size,
101
InlineTableSizes* sizes) {
102
int extra_bytes = code_size;
103
if (sizes->compressed_linenumber_size() > 0) {
104
extra_bytes += sizes->compressed_linenumber_size();
105
}
106
if (sizes->checked_exceptions_length() > 0) {
107
extra_bytes += sizeof(u2);
108
extra_bytes += sizes->checked_exceptions_length() * sizeof(CheckedExceptionElement);
109
}
110
if (sizes->localvariable_table_length() > 0) {
111
extra_bytes += sizeof(u2);
112
extra_bytes +=
113
sizes->localvariable_table_length() * sizeof(LocalVariableTableElement);
114
}
115
if (sizes->exception_table_length() > 0) {
116
extra_bytes += sizeof(u2);
117
extra_bytes += sizes->exception_table_length() * sizeof(ExceptionTableElement);
118
}
119
if (sizes->generic_signature_index() != 0) {
120
extra_bytes += sizeof(u2);
121
}
122
// This has to be a less-than-or-equal check, because we might be
123
// storing information from a zero-length MethodParameters
124
// attribute. We have to store these, because in some cases, they
125
// cause the reflection API to throw a MalformedParametersException.
126
if (sizes->method_parameters_length() >= 0) {
127
extra_bytes += sizeof(u2);
128
extra_bytes += sizes->method_parameters_length() * sizeof(MethodParametersElement);
129
}
130
131
// Align sizes up to a word.
132
extra_bytes = align_up(extra_bytes, BytesPerWord);
133
134
// One pointer per annotation array
135
if (sizes->method_annotations_length() > 0) {
136
extra_bytes += sizeof(AnnotationArray*);
137
}
138
if (sizes->parameter_annotations_length() > 0) {
139
extra_bytes += sizeof(AnnotationArray*);
140
}
141
if (sizes->type_annotations_length() > 0) {
142
extra_bytes += sizeof(AnnotationArray*);
143
}
144
if (sizes->default_annotations_length() > 0) {
145
extra_bytes += sizeof(AnnotationArray*);
146
}
147
148
int extra_words = align_up(extra_bytes, BytesPerWord) / BytesPerWord;
149
assert(extra_words == extra_bytes/BytesPerWord, "should already be aligned");
150
return align_metadata_size(header_size() + extra_words);
151
}
152
153
Method* ConstMethod::method() const {
154
return _constants->pool_holder()->method_with_idnum(_method_idnum);
155
}
156
157
// linenumber table - note that length is unknown until decompression,
158
// see class CompressedLineNumberReadStream.
159
160
u_char* ConstMethod::compressed_linenumber_table() const {
161
// Located immediately following the bytecodes.
162
assert(has_linenumber_table(), "called only if table is present");
163
return code_end();
164
}
165
166
// Last short in ConstMethod* before annotations
167
u2* ConstMethod::last_u2_element() const {
168
int offset = 0;
169
if (has_method_annotations()) offset++;
170
if (has_parameter_annotations()) offset++;
171
if (has_type_annotations()) offset++;
172
if (has_default_annotations()) offset++;
173
return (u2*)((AnnotationArray**)constMethod_end() - offset) - 1;
174
}
175
176
u2* ConstMethod::generic_signature_index_addr() const {
177
// Located at the end of the constMethod.
178
assert(has_generic_signature(), "called only if generic signature exists");
179
return last_u2_element();
180
}
181
182
u2* ConstMethod::method_parameters_length_addr() const {
183
assert(has_method_parameters(), "called only if table is present");
184
return has_generic_signature() ? (last_u2_element() - 1) :
185
last_u2_element();
186
}
187
188
u2* ConstMethod::checked_exceptions_length_addr() const {
189
// Located immediately before the generic signature index.
190
assert(has_checked_exceptions(), "called only if table is present");
191
if(has_method_parameters()) {
192
// If method parameters present, locate immediately before them.
193
return (u2*)method_parameters_start() - 1;
194
} else {
195
// Else, the exception table is at the end of the constMethod.
196
return has_generic_signature() ? (last_u2_element() - 1) :
197
last_u2_element();
198
}
199
}
200
201
u2* ConstMethod::exception_table_length_addr() const {
202
assert(has_exception_handler(), "called only if table is present");
203
if (has_checked_exceptions()) {
204
// If checked_exception present, locate immediately before them.
205
return (u2*) checked_exceptions_start() - 1;
206
} else {
207
if(has_method_parameters()) {
208
// If method parameters present, locate immediately before them.
209
return (u2*)method_parameters_start() - 1;
210
} else {
211
// Else, the exception table is at the end of the constMethod.
212
return has_generic_signature() ? (last_u2_element() - 1) :
213
last_u2_element();
214
}
215
}
216
}
217
218
u2* ConstMethod::localvariable_table_length_addr() const {
219
assert(has_localvariable_table(), "called only if table is present");
220
if (has_exception_handler()) {
221
// If exception_table present, locate immediately before them.
222
return (u2*) exception_table_start() - 1;
223
} else {
224
if (has_checked_exceptions()) {
225
// If checked_exception present, locate immediately before them.
226
return (u2*) checked_exceptions_start() - 1;
227
} else {
228
if(has_method_parameters()) {
229
// If method parameters present, locate immediately before them.
230
return (u2*)method_parameters_start() - 1;
231
} else {
232
// Else, the exception table is at the end of the constMethod.
233
return has_generic_signature() ? (last_u2_element() - 1) :
234
last_u2_element();
235
}
236
}
237
}
238
}
239
240
// Update the flags to indicate the presence of these optional fields.
241
void ConstMethod::set_inlined_tables_length(InlineTableSizes* sizes) {
242
_flags = 0;
243
if (sizes->compressed_linenumber_size() > 0)
244
_flags |= _has_linenumber_table;
245
if (sizes->generic_signature_index() != 0)
246
_flags |= _has_generic_signature;
247
if (sizes->method_parameters_length() >= 0)
248
_flags |= _has_method_parameters;
249
if (sizes->checked_exceptions_length() > 0)
250
_flags |= _has_checked_exceptions;
251
if (sizes->exception_table_length() > 0)
252
_flags |= _has_exception_table;
253
if (sizes->localvariable_table_length() > 0)
254
_flags |= _has_localvariable_table;
255
256
// annotations, they are all pointer sized embedded objects so don't have
257
// a length embedded also.
258
if (sizes->method_annotations_length() > 0)
259
_flags |= _has_method_annotations;
260
if (sizes->parameter_annotations_length() > 0)
261
_flags |= _has_parameter_annotations;
262
if (sizes->type_annotations_length() > 0)
263
_flags |= _has_type_annotations;
264
if (sizes->default_annotations_length() > 0)
265
_flags |= _has_default_annotations;
266
267
// This code is extremely brittle and should possibly be revised.
268
// The *_length_addr functions walk backwards through the
269
// constMethod data, using each of the length indexes ahead of them,
270
// as well as the flags variable. Therefore, the indexes must be
271
// initialized in reverse order, or else they will compute the wrong
272
// offsets. Moving the initialization of _flags into a separate
273
// block solves *half* of the problem, but the following part will
274
// still break if the order is not exactly right.
275
//
276
// Also, the servicability agent needs to be informed anytime
277
// anything is added here. It might be advisable to have some sort
278
// of indication of this inline.
279
if (sizes->generic_signature_index() != 0)
280
*(generic_signature_index_addr()) = sizes->generic_signature_index();
281
// New data should probably go here.
282
if (sizes->method_parameters_length() >= 0)
283
*(method_parameters_length_addr()) = sizes->method_parameters_length();
284
if (sizes->checked_exceptions_length() > 0)
285
*(checked_exceptions_length_addr()) = sizes->checked_exceptions_length();
286
if (sizes->exception_table_length() > 0)
287
*(exception_table_length_addr()) = sizes->exception_table_length();
288
if (sizes->localvariable_table_length() > 0)
289
*(localvariable_table_length_addr()) = sizes->localvariable_table_length();
290
}
291
292
int ConstMethod::method_parameters_length() const {
293
return has_method_parameters() ? *(method_parameters_length_addr()) : -1;
294
}
295
296
MethodParametersElement* ConstMethod::method_parameters_start() const {
297
u2* addr = method_parameters_length_addr();
298
u2 length = *addr;
299
addr -= length * sizeof(MethodParametersElement) / sizeof(u2);
300
return (MethodParametersElement*) addr;
301
}
302
303
304
int ConstMethod::checked_exceptions_length() const {
305
return has_checked_exceptions() ? *(checked_exceptions_length_addr()) : 0;
306
}
307
308
309
CheckedExceptionElement* ConstMethod::checked_exceptions_start() const {
310
u2* addr = checked_exceptions_length_addr();
311
u2 length = *addr;
312
assert(length > 0, "should only be called if table is present");
313
addr -= length * sizeof(CheckedExceptionElement) / sizeof(u2);
314
return (CheckedExceptionElement*) addr;
315
}
316
317
318
int ConstMethod::localvariable_table_length() const {
319
return has_localvariable_table() ? *(localvariable_table_length_addr()) : 0;
320
}
321
322
323
LocalVariableTableElement* ConstMethod::localvariable_table_start() const {
324
u2* addr = localvariable_table_length_addr();
325
u2 length = *addr;
326
assert(length > 0, "should only be called if table is present");
327
addr -= length * sizeof(LocalVariableTableElement) / sizeof(u2);
328
return (LocalVariableTableElement*) addr;
329
}
330
331
int ConstMethod::exception_table_length() const {
332
return has_exception_handler() ? *(exception_table_length_addr()) : 0;
333
}
334
335
ExceptionTableElement* ConstMethod::exception_table_start() const {
336
u2* addr = exception_table_length_addr();
337
u2 length = *addr;
338
assert(length > 0, "should only be called if table is present");
339
addr -= length * sizeof(ExceptionTableElement) / sizeof(u2);
340
return (ExceptionTableElement*)addr;
341
}
342
343
AnnotationArray** ConstMethod::method_annotations_addr() const {
344
assert(has_method_annotations(), "should only be called if method annotations are present");
345
return (AnnotationArray**)constMethod_end() - 1;
346
}
347
348
AnnotationArray** ConstMethod::parameter_annotations_addr() const {
349
assert(has_parameter_annotations(), "should only be called if method parameter annotations are present");
350
int offset = 1;
351
if (has_method_annotations()) offset++;
352
return (AnnotationArray**)constMethod_end() - offset;
353
}
354
355
AnnotationArray** ConstMethod::type_annotations_addr() const {
356
assert(has_type_annotations(), "should only be called if method type annotations are present");
357
int offset = 1;
358
if (has_method_annotations()) offset++;
359
if (has_parameter_annotations()) offset++;
360
return (AnnotationArray**)constMethod_end() - offset;
361
}
362
363
AnnotationArray** ConstMethod::default_annotations_addr() const {
364
assert(has_default_annotations(), "should only be called if method default annotations are present");
365
int offset = 1;
366
if (has_method_annotations()) offset++;
367
if (has_parameter_annotations()) offset++;
368
if (has_type_annotations()) offset++;
369
return (AnnotationArray**)constMethod_end() - offset;
370
}
371
372
Array<u1>* copy_annotations(ClassLoaderData* loader_data, AnnotationArray* from, TRAPS) {
373
int length = from->length();
374
Array<u1>* a = MetadataFactory::new_array<u1>(loader_data, length, 0, CHECK_NULL);
375
memcpy((void*)a->adr_at(0), (void*)from->adr_at(0), length);
376
return a;
377
}
378
379
// copy annotations from 'cm' to 'this'
380
// Must make copy because these are deallocated with their constMethod, if redefined.
381
void ConstMethod::copy_annotations_from(ClassLoaderData* loader_data, ConstMethod* cm, TRAPS) {
382
Array<u1>* a;
383
if (cm->has_method_annotations()) {
384
assert(has_method_annotations(), "should be allocated already");
385
a = copy_annotations(loader_data, cm->method_annotations(), CHECK);
386
set_method_annotations(a);
387
}
388
if (cm->has_parameter_annotations()) {
389
assert(has_parameter_annotations(), "should be allocated already");
390
a = copy_annotations(loader_data, cm->parameter_annotations(), CHECK);
391
set_parameter_annotations(a);
392
}
393
if (cm->has_type_annotations()) {
394
assert(has_type_annotations(), "should be allocated already");
395
a = copy_annotations(loader_data, cm->type_annotations(), CHECK);
396
set_type_annotations(a);
397
}
398
if (cm->has_default_annotations()) {
399
assert(has_default_annotations(), "should be allocated already");
400
a = copy_annotations(loader_data, cm->default_annotations(), CHECK);
401
set_default_annotations(a);
402
}
403
}
404
405
void ConstMethod::metaspace_pointers_do(MetaspaceClosure* it) {
406
log_trace(cds)("Iter(ConstMethod): %p", this);
407
408
if (!method()->method_holder()->is_rewritten()) {
409
it->push(&_constants, MetaspaceClosure::_writable);
410
} else {
411
it->push(&_constants);
412
}
413
it->push(&_stackmap_data);
414
if (has_method_annotations()) {
415
it->push(method_annotations_addr());
416
}
417
if (has_parameter_annotations()) {
418
it->push(parameter_annotations_addr());
419
}
420
if (has_type_annotations()) {
421
it->push(type_annotations_addr());
422
}
423
if (has_default_annotations()) {
424
it->push(default_annotations_addr());
425
}
426
}
427
428
// Printing
429
430
void ConstMethod::print_on(outputStream* st) const {
431
ResourceMark rm;
432
st->print_cr("%s", internal_name());
433
Method* m = method();
434
st->print(" - method: " INTPTR_FORMAT " ", p2i((address)m));
435
if (m != NULL) {
436
m->print_value_on(st);
437
}
438
st->cr();
439
if (has_stackmap_table()) {
440
st->print(" - stackmap data: ");
441
stackmap_data()->print_value_on(st);
442
st->cr();
443
}
444
}
445
446
// Short version of printing ConstMethod* - just print the name of the
447
// method it belongs to.
448
void ConstMethod::print_value_on(outputStream* st) const {
449
st->print(" const part of method " );
450
Method* m = method();
451
if (m != NULL) {
452
m->print_value_on(st);
453
} else {
454
st->print("NULL");
455
}
456
}
457
458
// Verification
459
460
void ConstMethod::verify_on(outputStream* st) {
461
// Verification can occur during oop construction before the method or
462
// other fields have been initialized.
463
guarantee(method() != NULL && method()->is_method(), "should be method");
464
465
address m_end = (address)((intptr_t) this + size());
466
address compressed_table_start = code_end();
467
guarantee(compressed_table_start <= m_end, "invalid method layout");
468
address compressed_table_end = compressed_table_start;
469
// Verify line number table
470
if (has_linenumber_table()) {
471
CompressedLineNumberReadStream stream(compressed_linenumber_table());
472
while (stream.read_pair()) {
473
guarantee(stream.bci() >= 0 && stream.bci() <= code_size(), "invalid bci in line number table");
474
}
475
compressed_table_end += stream.position();
476
}
477
guarantee(compressed_table_end <= m_end, "invalid method layout");
478
// Verify checked exceptions, exception table and local variable tables
479
if (has_method_parameters()) {
480
u2* addr = method_parameters_length_addr();
481
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
482
}
483
if (has_checked_exceptions()) {
484
u2* addr = checked_exceptions_length_addr();
485
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
486
}
487
if (has_exception_handler()) {
488
u2* addr = exception_table_length_addr();
489
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
490
}
491
if (has_localvariable_table()) {
492
u2* addr = localvariable_table_length_addr();
493
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
494
}
495
// Check compressed_table_end relative to uncompressed_table_start
496
u2* uncompressed_table_start;
497
if (has_localvariable_table()) {
498
uncompressed_table_start = (u2*) localvariable_table_start();
499
} else if (has_exception_handler()) {
500
uncompressed_table_start = (u2*) exception_table_start();
501
} else if (has_checked_exceptions()) {
502
uncompressed_table_start = (u2*) checked_exceptions_start();
503
} else if (has_method_parameters()) {
504
uncompressed_table_start = (u2*) method_parameters_start();
505
} else {
506
uncompressed_table_start = (u2*) m_end;
507
}
508
int gap = (intptr_t) uncompressed_table_start - (intptr_t) compressed_table_end;
509
int max_gap = align_metadata_size(1)*BytesPerWord;
510
guarantee(gap >= 0 && gap < max_gap, "invalid method layout");
511
}
512
513