Skip to content

Commit 3aaca4a

Browse files
committed
simplify bootstrap method logic (first cut)
1 parent cc34135 commit 3aaca4a

24 files changed

+602
-554
lines changed

src/hotspot/share/cds/aotConstantPoolResolver.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ bool AOTConstantPoolResolver::check_lambda_metafactory_signature(ConstantPool* c
411411
}
412412

413413
bool AOTConstantPoolResolver::check_lambda_metafactory_methodtype_arg(ConstantPool* cp, int bsms_attribute_index, int arg_i) {
414-
int mt_index = cp->operand_argument_index_at(bsms_attribute_index, arg_i);
414+
int mt_index = cp->bsm_attribute_entry(bsms_attribute_index)->argument_index(arg_i);
415415
if (!cp->tag_at(mt_index).is_method_type()) {
416416
// malformed class?
417417
return false;
@@ -427,7 +427,7 @@ bool AOTConstantPoolResolver::check_lambda_metafactory_methodtype_arg(ConstantPo
427427
}
428428

429429
bool AOTConstantPoolResolver::check_lambda_metafactory_methodhandle_arg(ConstantPool* cp, int bsms_attribute_index, int arg_i) {
430-
int mh_index = cp->operand_argument_index_at(bsms_attribute_index, arg_i);
430+
int mh_index = cp->bsm_attribute_entry(bsms_attribute_index)->argument_index(arg_i);
431431
if (!cp->tag_at(mh_index).is_method_handle()) {
432432
// malformed class?
433433
return false;
@@ -452,7 +452,8 @@ bool AOTConstantPoolResolver::is_indy_resolution_deterministic(ConstantPool* cp,
452452
return false;
453453
}
454454

455-
int bsm = cp->bootstrap_method_ref_index_at(cp_index);
455+
int bsms_attribute_index = cp->bootstrap_methods_attribute_index(cp_index);
456+
int bsm = cp->bsm_attribute_entry(bsms_attribute_index)->bootstrap_method_index();
456457
int bsm_ref = cp->method_handle_index_at(bsm);
457458
Symbol* bsm_name = cp->uncached_name_ref_at(bsm_ref);
458459
Symbol* bsm_signature = cp->uncached_signature_ref_at(bsm_ref);
@@ -532,8 +533,7 @@ bool AOTConstantPoolResolver::is_indy_resolution_deterministic(ConstantPool* cp,
532533
return false;
533534
}
534535

535-
int bsms_attribute_index = cp->bootstrap_methods_attribute_index(cp_index);
536-
int arg_count = cp->operand_argument_count_at(bsms_attribute_index);
536+
int arg_count = cp->bsm_attribute_entry(bsms_attribute_index)->argument_count();
537537
if (arg_count != 3) {
538538
// Malformed class?
539539
return false;

src/hotspot/share/cds/classListParser.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -570,10 +570,11 @@ void ClassListParser::populate_cds_indy_info(const constantPoolHandle &pool, int
570570
cii->add_item(pool->symbol_at(name_index)->as_C_string());
571571
int sig_index = pool->signature_ref_index_at(type_index);
572572
cii->add_item(pool->symbol_at(sig_index)->as_C_string());
573-
int argc = pool->bootstrap_argument_count_at(cp_index);
573+
auto bsme = pool->bootstrap_methods_attribute_entry(cp_index);
574+
int argc = bsme->argument_count();;
574575
if (argc > 0) {
575576
for (int arg_i = 0; arg_i < argc; arg_i++) {
576-
int arg = pool->bootstrap_argument_index_at(cp_index, arg_i);
577+
int arg = bsme->argument_index(arg_i);
577578
jbyte tag = pool->tag_at(arg).value();
578579
if (tag == JVM_CONSTANT_MethodType) {
579580
cii->add_item(pool->method_type_signature_at(arg)->as_C_string());

src/hotspot/share/ci/ciEnv.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,8 @@ ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
821821
// Patch the call site to the nmethod entry point of the static compiled lambda form.
822822
// As with other two-component call sites, both values must be independently verified.
823823
assert(index < cpool->cache()->resolved_indy_entries_length(), "impossible");
824-
Method* adapter = cpool->resolved_indy_entry_at(index)->method();
824+
auto rie = cpool->resolved_indy_entry_at(index);
825+
Method* adapter = rie->method();
825826
// Resolved if the adapter is non null.
826827
if (adapter != nullptr) {
827828
return get_method(adapter);
@@ -830,7 +831,7 @@ ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
830831
// Fake a method that is equivalent to a declared method.
831832
ciInstanceKlass* holder = get_instance_klass(vmClasses::MethodHandle_klass());
832833
ciSymbol* name = ciSymbols::invokeBasic_name();
833-
ciSymbol* signature = get_symbol(cpool->signature_ref_at(index, bc));
834+
ciSymbol* signature = get_symbol(rie->signature(cpool()));
834835
return get_unloaded_method(holder, name, signature, accessor);
835836
} else {
836837
const int holder_index = cpool->klass_ref_index_at(index, bc);

src/hotspot/share/classfile/classFileParser.cpp

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,7 +2104,6 @@ void ClassFileParser::copy_method_annotations(ConstMethod* cm,
21042104
}
21052105
}
21062106

2107-
21082107
// Note: the parse_method below is big and clunky because all parsing of the code and exceptions
21092108
// attribute is inlined. This is cumbersome to avoid since we inline most of the parts in the
21102109
// Method* to save footprint, so we only know the size of the resulting Method* when the
@@ -3280,38 +3279,35 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(const ClassFil
32803279

32813280
cfs->guarantee_more(attribute_byte_length, CHECK);
32823281

3283-
const int attribute_array_length = cfs->get_u2_fast();
3282+
const int attribute_entry_count = cfs->get_u2_fast();
32843283

3285-
guarantee_property(_max_bootstrap_specifier_index < attribute_array_length,
3284+
guarantee_property(_max_bootstrap_specifier_index < attribute_entry_count,
32863285
"Short length on BootstrapMethods in class file %s",
32873286
CHECK);
32883287

3289-
32903288
// The attribute contains a counted array of counted tuples of shorts,
32913289
// represending bootstrap specifiers:
3292-
// length*{bootstrap_method_index, argument_count*{argument_index}}
3293-
const unsigned int operand_count = (attribute_byte_length - (unsigned)sizeof(u2)) / (unsigned)sizeof(u2);
3294-
// operand_count = number of shorts in attr, except for leading length
3295-
3296-
// The attribute is copied into a short[] array.
3297-
// The array begins with a series of short[2] pairs, one for each tuple.
3298-
const int index_size = (attribute_array_length * 2);
3290+
// length*{bootstrap_method_index, argument_count, argument_count*{argument_index}}
3291+
const unsigned int attribute_tail_length = attribute_byte_length - (unsigned)sizeof(u2);
32993292

3300-
Array<u2>* const operands =
3301-
MetadataFactory::new_array<u2>(_loader_data, index_size + operand_count, CHECK);
3293+
Array<u4>* const offsets =
3294+
MetadataFactory::new_array<u4>(_loader_data, attribute_entry_count, CHECK);
3295+
Array<u2>* const entries = // u2 data holding all the BSM attribute entries
3296+
MetadataFactory::new_array<u2>(_loader_data, attribute_tail_length / sizeof(u2), CHECK);
33023297

3303-
// Eagerly assign operands so they will be deallocated with the constant
3298+
// Eagerly assign arrays so they will be deallocated with the constant
33043299
// pool if there is an error.
3305-
cp->set_operands(operands);
3300+
cp->set_bsm_attribute_offsets(offsets);
3301+
cp->set_bsm_attribute_entries(entries);
33063302

3307-
int operand_fill_index = index_size;
3303+
int next_entry = 0;
33083304
const int cp_size = cp->length();
33093305

3310-
for (int n = 0; n < attribute_array_length; n++) {
3311-
// Store a 32-bit offset into the header of the operand array.
3312-
ConstantPool::operand_offset_at_put(operands, n, operand_fill_index);
3306+
for (int n = 0; n < attribute_entry_count; n++) {
3307+
// Store a 32-bit offset into the array of BSM entry offsets.
3308+
offsets->at_put(n, next_entry);
33133309

3314-
// Read a bootstrap specifier.
3310+
// Read a bootstrap method attribute entry.
33153311
cfs->guarantee_more(sizeof(u2) * 2, CHECK); // bsm, argc
33163312
const u2 bootstrap_method_index = cfs->get_u2_fast();
33173313
const u2 argument_count = cfs->get_u2_fast();
@@ -3322,12 +3318,12 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(const ClassFil
33223318
bootstrap_method_index,
33233319
CHECK);
33243320

3325-
guarantee_property((operand_fill_index + 1 + argument_count) < operands->length(),
3321+
guarantee_property((next_entry + 2 + argument_count) <= entries->length(),
33263322
"Invalid BootstrapMethods num_bootstrap_methods or num_bootstrap_arguments value in class file %s",
33273323
CHECK);
33283324

3329-
operands->at_put(operand_fill_index++, bootstrap_method_index);
3330-
operands->at_put(operand_fill_index++, argument_count);
3325+
entries->at_put(next_entry++, bootstrap_method_index);
3326+
entries->at_put(next_entry++, argument_count);
33313327

33323328
cfs->guarantee_more(sizeof(u2) * argument_count, CHECK); // argv[argc]
33333329
for (int j = 0; j < argument_count; j++) {
@@ -3338,12 +3334,35 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(const ClassFil
33383334
"argument_index %u has bad constant type in class file %s",
33393335
argument_index,
33403336
CHECK);
3341-
operands->at_put(operand_fill_index++, argument_index);
3337+
entries->at_put(next_entry++, argument_index);
33423338
}
33433339
}
33443340
guarantee_property(current_start + attribute_byte_length == cfs->current(),
33453341
"Bad length on BootstrapMethods in class file %s",
33463342
CHECK);
3343+
assert(next_entry == entries->length(), "");
3344+
3345+
// check access methods, for extra luck
3346+
if (attribute_entry_count > 0) {
3347+
auto bsme = cp->bsm_attribute_entry(0);
3348+
assert(bsme->bootstrap_method_index() == entries->at(0), "");
3349+
assert(bsme->argument_count() == entries->at(1), "");
3350+
int nexti = (attribute_entry_count == 1) ? entries->length() : offsets->at(1);
3351+
assert(nexti == 2 + bsme->argument_count(), "");
3352+
if (attribute_entry_count > 1) {
3353+
bsme = cp->bsm_attribute_entry(1);
3354+
assert(bsme->bootstrap_method_index() == entries->at(nexti+0), "");
3355+
assert(bsme->argument_count() == entries->at(nexti+1), "");
3356+
}
3357+
int lasti = offsets->at(offsets->length() - 1);
3358+
bsme = cp->bsm_attribute_entry(attribute_entry_count - 1);
3359+
assert(bsme->bootstrap_method_index() == entries->at(lasti+0), "");
3360+
assert(bsme->argument_count() == entries->at(lasti+1), "");
3361+
int lastu2 = entries->at(entries->length() - 1);
3362+
int lastac = bsme->argument_count();
3363+
int expect_lastu2 = (lastac == 0) ? 0 : bsme->argument_index(lastac-1);
3364+
assert(lastu2 == expect_lastu2, "");
3365+
}
33473366
}
33483367

33493368
void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cfs,

src/hotspot/share/classfile/verifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2808,9 +2808,9 @@ void ClassVerifier::verify_invoke_instructions(
28082808
default:
28092809
types = 1 << JVM_CONSTANT_Methodref;
28102810
}
2811-
verify_cp_type(bcs->bci(), index, cp, types, CHECK_VERIFY(this));
28122811

28132812
// Get method name and signature
2813+
verify_cp_type(bcs->bci(), index, cp, types, CHECK_VERIFY(this));
28142814
Symbol* method_name = cp->uncached_name_ref_at(index);
28152815
Symbol* method_sig = cp->uncached_signature_ref_at(index);
28162816

src/hotspot/share/interpreter/bootstrapInfo.cpp

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,22 @@
4848
BootstrapInfo::BootstrapInfo(const constantPoolHandle& pool, int bss_index, int indy_index)
4949
: _pool(pool),
5050
_bss_index(bss_index),
51-
_indy_index(indy_index),
52-
// derived and eagerly cached:
53-
_argc( pool->bootstrap_argument_count_at(bss_index) ),
54-
_name( pool->uncached_name_ref_at(bss_index) ),
55-
_signature( pool->uncached_signature_ref_at(bss_index) )
51+
_indy_index(indy_index)
5652
{
57-
_is_resolved = false;
53+
assert(bss_index != 0, "");
54+
_bsm_attr_index = _pool->bootstrap_methods_attribute_index(_bss_index);
55+
_name = pool->uncached_name_ref_at(bss_index);
56+
_signature = pool->uncached_signature_ref_at(bss_index);
5857
assert(pool->tag_at(bss_index).has_bootstrap(), "");
5958
assert(indy_index == -1 || pool->resolved_indy_entry_at(indy_index)->constant_pool_index() == bss_index, "invalid bootstrap specifier index");
59+
_is_resolved = false;
60+
}
61+
62+
ResolvedIndyEntry* BootstrapInfo::indy_entry() const {
63+
if (_indy_index >= 0) {
64+
return _pool->resolved_indy_entry_at(_indy_index);
65+
}
66+
return nullptr;
6067
}
6168

6269
// If there is evidence this call site was already linked, set the
@@ -130,7 +137,9 @@ void BootstrapInfo::resolve_args(TRAPS) {
130137
assert(_bsm.not_null(), "resolve_bsm first");
131138

132139
// if there are no static arguments, return leaving _arg_values as null
133-
if (_argc == 0 && UseBootstrapCallInfo < 2) return;
140+
BSMAttributeEntry* attr = bsm_attr();
141+
int argc = attr->argument_count();
142+
if (argc == 0 && UseBootstrapCallInfo < 2) return;
134143

135144
bool use_BSCI;
136145
switch (UseBootstrapCallInfo) {
@@ -156,8 +165,8 @@ void BootstrapInfo::resolve_args(TRAPS) {
156165
// potentially cyclic cases from C to Java.
157166
if (!use_BSCI && _pool->tag_at(_bss_index).is_dynamic_constant()) {
158167
bool found_unresolved_condy = false;
159-
for (int i = 0; i < _argc; i++) {
160-
int arg_index = _pool->bootstrap_argument_index_at(_bss_index, i);
168+
for (int i = 0; i < argc; i++) {
169+
int arg_index = attr->argument_index(i);
161170
if (_pool->tag_at(arg_index).is_dynamic_constant()) {
162171
// potential recursion point condy -> condy
163172
bool found_it = false;
@@ -170,14 +179,14 @@ void BootstrapInfo::resolve_args(TRAPS) {
170179
}
171180

172181
const int SMALL_ARITY = 5;
173-
if (use_BSCI && _argc <= SMALL_ARITY && UseBootstrapCallInfo <= 2) {
182+
if (use_BSCI && argc <= SMALL_ARITY && UseBootstrapCallInfo <= 2) {
174183
// If there are only a few arguments, and none of them need linking,
175184
// push them, instead of asking the JDK runtime to turn around and
176185
// pull them, saving a JVM/JDK transition in some simple cases.
177186
bool all_resolved = true;
178-
for (int i = 0; i < _argc; i++) {
187+
for (int i = 0; i < argc; i++) {
179188
bool found_it = false;
180-
int arg_index = _pool->bootstrap_argument_index_at(_bss_index, i);
189+
int arg_index = attr->argument_index(i);
181190
_pool->find_cached_constant_at(arg_index, found_it, CHECK);
182191
if (!found_it) { all_resolved = false; break; }
183192
}
@@ -187,10 +196,11 @@ void BootstrapInfo::resolve_args(TRAPS) {
187196

188197
if (!use_BSCI) {
189198
// return {arg...}; resolution of arguments is done immediately, before JDK code is called
190-
objArrayOop args_oop = oopFactory::new_objArray(vmClasses::Object_klass(), _argc, CHECK);
199+
objArrayOop args_oop = oopFactory::new_objArray(vmClasses::Object_klass(), argc, CHECK);
191200
objArrayHandle args(THREAD, args_oop);
192-
_pool->copy_bootstrap_arguments_at(_bss_index, 0, _argc, args, 0, true, Handle(), CHECK);
193-
oop arg_oop = ((_argc == 1) ? args->obj_at(0) : (oop)nullptr);
201+
_pool->copy_bootstrap_arguments_at(_bsm_attr_index,
202+
0, argc, args, 0, true, Handle(), CHECK);
203+
oop arg_oop = ((argc == 1) ? args->obj_at(0) : (oop)nullptr);
194204
// try to discard the singleton array
195205
if (arg_oop != nullptr && !arg_oop->is_array()) {
196206
// JVM treats arrays and nulls specially in this position,
@@ -200,10 +210,12 @@ void BootstrapInfo::resolve_args(TRAPS) {
200210
_arg_values = args;
201211
}
202212
} else {
203-
// return {arg_count, pool_index}; JDK code must pull the arguments as needed
204-
typeArrayOop ints_oop = oopFactory::new_typeArray(T_INT, 2, CHECK);
205-
ints_oop->int_at_put(0, _argc);
213+
// return {arg_count, pool_index, indy_index}
214+
// JDK code must pull the arguments as needed
215+
typeArrayOop ints_oop = oopFactory::new_typeArray(T_INT, 3, CHECK);
216+
ints_oop->int_at_put(0, argc);
206217
ints_oop->int_at_put(1, _bss_index);
218+
ints_oop->int_at_put(2, _indy_index);
207219
_arg_values = Handle(THREAD, ints_oop);
208220
}
209221
}
@@ -236,6 +248,7 @@ void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) {
236248
os::snprintf_checked(what, sizeof(what), "condy");
237249
}
238250
bool have_msg = (msg != nullptr && strlen(msg) > 0);
251+
int argc = arg_count();
239252
st->print_cr("%s%sBootstrap in %s %s@CP[%d] %s:%s%s BSMS[%d] BSM@CP[%d]%s argc=%d%s",
240253
(have_msg ? msg : ""), (have_msg ? " " : ""),
241254
caller()->name()->as_C_string(),
@@ -244,13 +257,13 @@ void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) {
244257
_name->as_C_string(),
245258
_signature->as_C_string(),
246259
(_type_arg.is_null() ? "" : "(resolved)"),
247-
bsms_attr_index(),
260+
bsm_attr_index(),
248261
bsm_index(), (_bsm.is_null() ? "" : "(resolved)"),
249-
_argc, (_arg_values.is_null() ? "" : "(resolved)"));
250-
if (_argc > 0) {
262+
argc, (_arg_values.is_null() ? "" : "(resolved)"));
263+
if (argc > 0) {
251264
char argbuf[80];
252265
argbuf[0] = 0;
253-
for (int i = 0; i < _argc; i++) {
266+
for (int i = 0; i < argc; i++) {
254267
int pos = (int) strlen(argbuf);
255268
if (pos + 20 > (int)sizeof(argbuf)) {
256269
os::snprintf_checked(argbuf + pos, sizeof(argbuf) - pos, "...");
@@ -272,11 +285,11 @@ void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) {
272285
// Find the static arguments within the first element of _arg_values.
273286
objArrayOop static_args = (objArrayOop)_arg_values();
274287
if (!static_args->is_array()) {
275-
assert(_argc == 1, "Invalid BSM _arg_values for non-array");
288+
assert(argc == 1, "Invalid BSM _arg_values for non-array");
276289
st->print(" resolved arg[0]: "); static_args->print_on(st);
277290
} else if (static_args->is_objArray()) {
278291
int lines = 0;
279-
for (int i = 0; i < _argc; i++) {
292+
for (int i = 0; i < argc; i++) {
280293
oop x = static_args->obj_at(i);
281294
if (x != nullptr) {
282295
if (++lines > 6) {

src/hotspot/share/interpreter/bootstrapInfo.hpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class BootstrapInfo : public StackObj {
3434
constantPoolHandle _pool; // constant pool containing the bootstrap specifier
3535
const int _bss_index; // index of bootstrap specifier in CP (condy or indy)
3636
const int _indy_index; // internal index of indy call site, or -1 if a condy call
37-
const int _argc; // number of static arguments
37+
int _bsm_attr_index; // index in the BootstrapMethods attribute
3838
Symbol* _name; // extracted from JVM_CONSTANT_NameAndType
3939
Symbol* _signature;
4040

@@ -58,7 +58,7 @@ class BootstrapInfo : public StackObj {
5858
const constantPoolHandle& pool() const{ return _pool; }
5959
int bss_index() const { return _bss_index; }
6060
int indy_index() const { return _indy_index; }
61-
int argc() const { return _argc; }
61+
int bsm_attr_index() const { return _bsm_attr_index; }
6262
bool is_method_call() const { return (_indy_index != -1); }
6363
Symbol* name() const { return _name; }
6464
Symbol* signature() const { return _signature; }
@@ -76,10 +76,11 @@ class BootstrapInfo : public StackObj {
7676
// derived accessors
7777
InstanceKlass* caller() const { return _pool->pool_holder(); }
7878
oop caller_mirror() const { return caller()->java_mirror(); }
79-
int bsms_attr_index() const { return _pool->bootstrap_methods_attribute_index(_bss_index); }
80-
int bsm_index() const { return _pool->bootstrap_method_ref_index_at(_bss_index); }
81-
//int argc() is eagerly cached in _argc
82-
int arg_index(int i) const { return _pool->bootstrap_argument_index_at(_bss_index, i); }
79+
BSMAttributeEntry* bsm_attr() const { return _pool->bsm_attribute_entry(_bsm_attr_index); }
80+
int bsm_index() const { return bsm_attr()->bootstrap_method_index(); }
81+
int arg_count() const { return bsm_attr()->argument_count(); }
82+
int arg_index(int j) const { return bsm_attr()->argument_index(j); }
83+
ResolvedIndyEntry* indy_entry() const;
8384

8485
// If there is evidence this call site was already linked, set the
8586
// existing linkage data into result, or throw previous exception.

0 commit comments

Comments
 (0)