Skip to content

Bsm refactor #24878

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/hotspot/share/cds/aotConstantPoolResolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ bool AOTConstantPoolResolver::check_lambda_metafactory_signature(ConstantPool* c
}

bool AOTConstantPoolResolver::check_lambda_metafactory_methodtype_arg(ConstantPool* cp, int bsms_attribute_index, int arg_i) {
int mt_index = cp->operand_argument_index_at(bsms_attribute_index, arg_i);
int mt_index = cp->bsm_attribute_entry(bsms_attribute_index)->argument_index(arg_i);
if (!cp->tag_at(mt_index).is_method_type()) {
// malformed class?
return false;
Expand All @@ -408,7 +408,7 @@ bool AOTConstantPoolResolver::check_lambda_metafactory_methodtype_arg(ConstantPo
}

bool AOTConstantPoolResolver::check_lambda_metafactory_methodhandle_arg(ConstantPool* cp, int bsms_attribute_index, int arg_i) {
int mh_index = cp->operand_argument_index_at(bsms_attribute_index, arg_i);
int mh_index = cp->bsm_attribute_entry(bsms_attribute_index)->argument_index(arg_i);
if (!cp->tag_at(mh_index).is_method_handle()) {
// malformed class?
return false;
Expand All @@ -433,7 +433,8 @@ bool AOTConstantPoolResolver::is_indy_resolution_deterministic(ConstantPool* cp,
return false;
}

int bsm = cp->bootstrap_method_ref_index_at(cp_index);
int bsms_attribute_index = cp->bootstrap_methods_attribute_index(cp_index);
int bsm = cp->bsm_attribute_entry(bsms_attribute_index)->bootstrap_method_index();
int bsm_ref = cp->method_handle_index_at(bsm);
Symbol* bsm_name = cp->uncached_name_ref_at(bsm_ref);
Symbol* bsm_signature = cp->uncached_signature_ref_at(bsm_ref);
Expand Down Expand Up @@ -513,8 +514,7 @@ bool AOTConstantPoolResolver::is_indy_resolution_deterministic(ConstantPool* cp,
return false;
}

int bsms_attribute_index = cp->bootstrap_methods_attribute_index(cp_index);
int arg_count = cp->operand_argument_count_at(bsms_attribute_index);
int arg_count = cp->bsm_attribute_entry(bsms_attribute_index)->argument_count();
if (arg_count != 3) {
// Malformed class?
return false;
Expand Down
33 changes: 16 additions & 17 deletions src/hotspot/share/cds/classListParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -570,23 +570,22 @@ void ClassListParser::populate_cds_indy_info(const constantPoolHandle &pool, int
cii->add_item(pool->symbol_at(name_index)->as_C_string());
int sig_index = pool->signature_ref_index_at(type_index);
cii->add_item(pool->symbol_at(sig_index)->as_C_string());
int argc = pool->bootstrap_argument_count_at(cp_index);
if (argc > 0) {
for (int arg_i = 0; arg_i < argc; arg_i++) {
int arg = pool->bootstrap_argument_index_at(cp_index, arg_i);
jbyte tag = pool->tag_at(arg).value();
if (tag == JVM_CONSTANT_MethodType) {
cii->add_item(pool->method_type_signature_at(arg)->as_C_string());
} else if (tag == JVM_CONSTANT_MethodHandle) {
cii->add_ref_kind(pool->method_handle_ref_kind_at(arg));
int callee_index = pool->method_handle_klass_index_at(arg);
Klass* callee = pool->klass_at(callee_index, CHECK);
cii->add_item(callee->name()->as_C_string());
cii->add_item(pool->method_handle_name_ref_at(arg)->as_C_string());
cii->add_item(pool->method_handle_signature_ref_at(arg)->as_C_string());
} else {
ShouldNotReachHere();
}
BSMAttributeEntry* bsme = pool->bootstrap_methods_attribute_entry(cp_index);
int argc = bsme->argument_count();
for (int arg_i = 0; arg_i < argc; arg_i++) {
int arg = bsme->argument_index(arg_i);
jbyte tag = pool->tag_at(arg).value();
if (tag == JVM_CONSTANT_MethodType) {
cii->add_item(pool->method_type_signature_at(arg)->as_C_string());
} else if (tag == JVM_CONSTANT_MethodHandle) {
cii->add_ref_kind(pool->method_handle_ref_kind_at(arg));
int callee_index = pool->method_handle_klass_index_at(arg);
Klass* callee = pool->klass_at(callee_index, CHECK);
cii->add_item(callee->name()->as_C_string());
cii->add_item(pool->method_handle_name_ref_at(arg)->as_C_string());
cii->add_item(pool->method_handle_signature_ref_at(arg)->as_C_string());
} else {
ShouldNotReachHere();
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/hotspot/share/ci/ciEnv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,8 @@ ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
// Patch the call site to the nmethod entry point of the static compiled lambda form.
// As with other two-component call sites, both values must be independently verified.
assert(index < cpool->cache()->resolved_indy_entries_length(), "impossible");
Method* adapter = cpool->resolved_indy_entry_at(index)->method();
ResolvedIndyEntry* rie = cpool->resolved_indy_entry_at(index);
Method* adapter = rie->method();
// Resolved if the adapter is non null.
if (adapter != nullptr) {
return get_method(adapter);
Expand All @@ -830,7 +831,7 @@ ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
// Fake a method that is equivalent to a declared method.
ciInstanceKlass* holder = get_instance_klass(vmClasses::MethodHandle_klass());
ciSymbol* name = ciSymbols::invokeBasic_name();
ciSymbol* signature = get_symbol(cpool->signature_ref_at(index, bc));
ciSymbol* signature = get_symbol(rie->signature(cpool()));
return get_unloaded_method(holder, name, signature, accessor);
} else {
const int holder_index = cpool->klass_ref_index_at(index, bc);
Expand Down
95 changes: 59 additions & 36 deletions src/hotspot/share/classfile/classFileParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2104,7 +2104,6 @@ void ClassFileParser::copy_method_annotations(ConstMethod* cm,
}
}


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

cfs->guarantee_more(attribute_byte_length, CHECK);

const int attribute_array_length = cfs->get_u2_fast();
const u2 num_bootstrap_methods = cfs->get_u2_fast();

guarantee_property(_max_bootstrap_specifier_index < attribute_array_length,
guarantee_property(_max_bootstrap_specifier_index < num_bootstrap_methods,
"Short length on BootstrapMethods in class file %s",
CHECK);


// The attribute contains a counted array of counted tuples of shorts,
// represending bootstrap specifiers:
// length*{bootstrap_method_index, argument_count*{argument_index}}
const unsigned int operand_count = (attribute_byte_length - (unsigned)sizeof(u2)) / (unsigned)sizeof(u2);
// operand_count = number of shorts in attr, except for leading length

// The attribute is copied into a short[] array.
// The array begins with a series of short[2] pairs, one for each tuple.
const int index_size = (attribute_array_length * 2);

Array<u2>* const operands =
MetadataFactory::new_array<u2>(_loader_data, index_size + operand_count, CHECK);

// Eagerly assign operands so they will be deallocated with the constant
// pool if there is an error.
cp->set_operands(operands);

int operand_fill_index = index_size;
// representing bootstrap specifiers:
// length*{bootstrap_method_index, argument_count, argument_count*{argument_index}}
const u4 attribute_tail_length = attribute_byte_length - static_cast<u4>(sizeof(u2));
assert(attribute_tail_length % sizeof(u2) == 0, "");
Array<u4>* const offsets =
MetadataFactory::new_array<u4>(_loader_data, num_bootstrap_methods, CHECK);
Array<u2>* const entries = // u2 data holding all the BSM attribute entries
MetadataFactory::new_array<u2>(_loader_data, attribute_tail_length / sizeof(u2), CHECK);

// Eagerly assign arrays so they will be deallocated with
// the constant pool if there is an error.
cp->set_bsm_attribute_offsets(offsets);
cp->set_bsm_attribute_entries(entries);

int next_entry = 0;
const int cp_size = cp->length();

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

// Read a bootstrap specifier.
// Read a bootstrap method attribute entry.
cfs->guarantee_more(sizeof(u2) * 2, CHECK); // bsm, argc
const u2 bootstrap_method_index = cfs->get_u2_fast();
const u2 argument_count = cfs->get_u2_fast();
const u2 bootstrap_method_ref = cfs->get_u2_fast();
const u2 num_bootstrap_arguments = cfs->get_u2_fast();
guarantee_property(
valid_cp_range(bootstrap_method_index, cp_size) &&
cp->tag_at(bootstrap_method_index).is_method_handle(),
valid_cp_range(bootstrap_method_ref, cp_size) &&
cp->tag_at(bootstrap_method_ref).is_method_handle(),
"bootstrap_method_index %u has bad constant type in class file %s",
bootstrap_method_index,
bootstrap_method_ref,
CHECK);

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

operands->at_put(operand_fill_index++, bootstrap_method_index);
operands->at_put(operand_fill_index++, argument_count);
entries->at_put(next_entry, bootstrap_method_ref);
next_entry++;
entries->at_put(next_entry, num_bootstrap_arguments);
next_entry++;

cfs->guarantee_more(sizeof(u2) * argument_count, CHECK); // argv[argc]
for (int j = 0; j < argument_count; j++) {
cfs->guarantee_more(sizeof(u2) * num_bootstrap_arguments, CHECK); // argv[argc]
for (u2 j = 0; j < num_bootstrap_arguments; j++) {
const u2 argument_index = cfs->get_u2_fast();
guarantee_property(
valid_cp_range(argument_index, cp_size) &&
cp->tag_at(argument_index).is_loadable_constant(),
"argument_index %u has bad constant type in class file %s",
argument_index,
CHECK);
operands->at_put(operand_fill_index++, argument_index);
entries->at_put(next_entry, argument_index);
next_entry++;
}
}
guarantee_property(current_start + attribute_byte_length == cfs->current(),
"Bad length on BootstrapMethods in class file %s",
CHECK);
assert(next_entry == entries->length(), "");

#ifdef ASSERT
if (num_bootstrap_methods > 0) {
BSMAttributeEntry* bsme = cp->bsm_attribute_entry(0);
assert(bsme->bootstrap_method_index() == entries->at(0), "");
assert(bsme->argument_count() == entries->at(1), "");
int nexti = (num_bootstrap_methods == 1) ? entries->length() : offsets->at(1);
assert(nexti == 2 + bsme->argument_count(), "");
if (num_bootstrap_methods > 1) {
bsme = cp->bsm_attribute_entry(1);
assert(bsme->bootstrap_method_index() == entries->at(nexti+0), "");
assert(bsme->argument_count() == entries->at(nexti+1), "");
}
int lasti = offsets->at(offsets->length() - 1);
bsme = cp->bsm_attribute_entry(num_bootstrap_methods - 1);
assert(bsme->bootstrap_method_index() == entries->at(lasti+0), "");
assert(bsme->argument_count() == entries->at(lasti+1), "");
int lastu2 = entries->at(entries->length() - 1);
int lastac = bsme->argument_count();
int expect_lastu2 = (lastac == 0) ? 0 : bsme->argument_index(lastac-1);
assert(lastu2 == expect_lastu2, "");
}
#endif
}

void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cfs,
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/classfile/verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2808,9 +2808,9 @@ void ClassVerifier::verify_invoke_instructions(
default:
types = 1 << JVM_CONSTANT_Methodref;
}
verify_cp_type(bcs->bci(), index, cp, types, CHECK_VERIFY(this));

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

Expand Down
Loading