From 1c44a2b3427232b822bceb9120a9197ca3caaf45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Sj=C3=B6l=C3=A9n?= Date: Wed, 7 May 2025 14:47:14 +0200 Subject: [PATCH] simplify bootstrap method logic (first cut) --- .../share/cds/aotConstantPoolResolver.cpp | 10 +- src/hotspot/share/cds/classListParser.cpp | 33 +- src/hotspot/share/ci/ciEnv.cpp | 5 +- .../share/classfile/classFileParser.cpp | 95 +++-- src/hotspot/share/classfile/verifier.cpp | 2 +- .../share/interpreter/bootstrapInfo.cpp | 77 ++-- .../share/interpreter/bootstrapInfo.hpp | 15 +- .../share/interpreter/bytecodeTracer.cpp | 9 +- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 2 +- src/hotspot/share/oops/array.hpp | 1 + src/hotspot/share/oops/constMethod.cpp | 7 +- src/hotspot/share/oops/constMethod.hpp | 2 +- src/hotspot/share/oops/constantPool.cpp | 339 +++++++++--------- src/hotspot/share/oops/constantPool.hpp | 208 +++++------ .../share/oops/constantPool.inline.hpp | 4 - src/hotspot/share/oops/cpCache.cpp | 5 +- src/hotspot/share/oops/resolvedIndyEntry.cpp | 21 +- src/hotspot/share/oops/resolvedIndyEntry.hpp | 35 +- .../prims/jvmtiClassFileReconstituter.cpp | 22 +- .../share/prims/jvmtiRedefineClasses.cpp | 298 +++++++-------- .../share/prims/jvmtiRedefineClasses.hpp | 25 +- src/hotspot/share/prims/methodComparator.cpp | 14 +- src/hotspot/share/prims/methodHandles.cpp | 29 +- src/hotspot/share/prims/nativeLookup.cpp | 6 + src/hotspot/share/runtime/vmStructs.cpp | 13 +- 25 files changed, 667 insertions(+), 610 deletions(-) diff --git a/src/hotspot/share/cds/aotConstantPoolResolver.cpp b/src/hotspot/share/cds/aotConstantPoolResolver.cpp index 6787242adbd3a..ad7e3a6900eca 100644 --- a/src/hotspot/share/cds/aotConstantPoolResolver.cpp +++ b/src/hotspot/share/cds/aotConstantPoolResolver.cpp @@ -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; @@ -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; @@ -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); @@ -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; diff --git a/src/hotspot/share/cds/classListParser.cpp b/src/hotspot/share/cds/classListParser.cpp index 10154265becd1..4f13652c3bb22 100644 --- a/src/hotspot/share/cds/classListParser.cpp +++ b/src/hotspot/share/cds/classListParser.cpp @@ -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(); } } } diff --git a/src/hotspot/share/ci/ciEnv.cpp b/src/hotspot/share/ci/ciEnv.cpp index 3991773d86fa3..5ee88f2e0e91f 100644 --- a/src/hotspot/share/ci/ciEnv.cpp +++ b/src/hotspot/share/ci/ciEnv.cpp @@ -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); @@ -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); diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index 757f0e72c8cce..b58e367331472 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -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 @@ -3280,57 +3279,56 @@ 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* const operands = - MetadataFactory::new_array(_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(sizeof(u2)); + assert(attribute_tail_length % sizeof(u2) == 0, ""); + Array* const offsets = + MetadataFactory::new_array(_loader_data, num_bootstrap_methods, CHECK); + Array* const entries = // u2 data holding all the BSM attribute entries + MetadataFactory::new_array(_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) && @@ -3338,12 +3336,37 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(const ClassFil "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, diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp index 98c05909b82ad..be6bb6f3507c9 100644 --- a/src/hotspot/share/classfile/verifier.cpp +++ b/src/hotspot/share/classfile/verifier.cpp @@ -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); diff --git a/src/hotspot/share/interpreter/bootstrapInfo.cpp b/src/hotspot/share/interpreter/bootstrapInfo.cpp index c8553615d0c64..2d7ac0239dcee 100644 --- a/src/hotspot/share/interpreter/bootstrapInfo.cpp +++ b/src/hotspot/share/interpreter/bootstrapInfo.cpp @@ -48,15 +48,22 @@ BootstrapInfo::BootstrapInfo(const constantPoolHandle& pool, int bss_index, int indy_index) : _pool(pool), _bss_index(bss_index), - _indy_index(indy_index), - // derived and eagerly cached: - _argc( pool->bootstrap_argument_count_at(bss_index) ), - _name( pool->uncached_name_ref_at(bss_index) ), - _signature( pool->uncached_signature_ref_at(bss_index) ) + _indy_index(indy_index) { - _is_resolved = false; + assert(bss_index != 0, ""); + _bsm_attr_index = _pool->bootstrap_methods_attribute_index(_bss_index); + _name = pool->uncached_name_ref_at(bss_index); + _signature = pool->uncached_signature_ref_at(bss_index); assert(pool->tag_at(bss_index).has_bootstrap(), ""); assert(indy_index == -1 || pool->resolved_indy_entry_at(indy_index)->constant_pool_index() == bss_index, "invalid bootstrap specifier index"); + _is_resolved = false; +} + +ResolvedIndyEntry* BootstrapInfo::indy_entry() const { + if (_indy_index >= 0) { + return _pool->resolved_indy_entry_at(_indy_index); + } + return nullptr; } // If there is evidence this call site was already linked, set the @@ -130,7 +137,9 @@ void BootstrapInfo::resolve_args(TRAPS) { assert(_bsm.not_null(), "resolve_bsm first"); // if there are no static arguments, return leaving _arg_values as null - if (_argc == 0 && UseBootstrapCallInfo < 2) return; + BSMAttributeEntry& attr = bsm_attr(); + int argc = attr.argument_count(); + if (argc == 0 && UseBootstrapCallInfo < 2) return; bool use_BSCI; switch (UseBootstrapCallInfo) { @@ -156,41 +165,50 @@ void BootstrapInfo::resolve_args(TRAPS) { // potentially cyclic cases from C to Java. if (!use_BSCI && _pool->tag_at(_bss_index).is_dynamic_constant()) { bool found_unresolved_condy = false; - for (int i = 0; i < _argc; i++) { - int arg_index = _pool->bootstrap_argument_index_at(_bss_index, i); + for (int i = 0; i < argc; i++) { + int arg_index = attr.argument_index(i); if (_pool->tag_at(arg_index).is_dynamic_constant()) { // potential recursion point condy -> condy bool found_it = false; _pool->find_cached_constant_at(arg_index, found_it, CHECK); - if (!found_it) { found_unresolved_condy = true; break; } + if (!found_it) { + found_unresolved_condy = true; + break; + } } } - if (found_unresolved_condy) + if (found_unresolved_condy) { use_BSCI = true; + } } const int SMALL_ARITY = 5; - if (use_BSCI && _argc <= SMALL_ARITY && UseBootstrapCallInfo <= 2) { + if (use_BSCI && argc <= SMALL_ARITY && UseBootstrapCallInfo <= 2) { // If there are only a few arguments, and none of them need linking, // push them, instead of asking the JDK runtime to turn around and // pull them, saving a JVM/JDK transition in some simple cases. bool all_resolved = true; - for (int i = 0; i < _argc; i++) { + for (int i = 0; i < argc; i++) { bool found_it = false; - int arg_index = _pool->bootstrap_argument_index_at(_bss_index, i); + int arg_index = attr.argument_index(i); _pool->find_cached_constant_at(arg_index, found_it, CHECK); - if (!found_it) { all_resolved = false; break; } + if (!found_it) { + all_resolved = false; + break; + } } - if (all_resolved) + if (all_resolved) { use_BSCI = false; + } } if (!use_BSCI) { // return {arg...}; resolution of arguments is done immediately, before JDK code is called - objArrayOop args_oop = oopFactory::new_objArray(vmClasses::Object_klass(), _argc, CHECK); + objArrayOop args_oop = oopFactory::new_objArray(vmClasses::Object_klass(), argc, CHECK); objArrayHandle args(THREAD, args_oop); - _pool->copy_bootstrap_arguments_at(_bss_index, 0, _argc, args, 0, true, Handle(), CHECK); - oop arg_oop = ((_argc == 1) ? args->obj_at(0) : (oop)nullptr); + _pool->copy_bootstrap_arguments_at(_bsm_attr_index, + 0, argc, args, 0, true, Handle(), CHECK); + oop arg_oop = ((argc == 1) ? args->obj_at(0) : (oop)nullptr); // try to discard the singleton array if (arg_oop != nullptr && !arg_oop->is_array()) { // JVM treats arrays and nulls specially in this position, @@ -200,10 +218,12 @@ void BootstrapInfo::resolve_args(TRAPS) { _arg_values = args; } } else { - // return {arg_count, pool_index}; JDK code must pull the arguments as needed - typeArrayOop ints_oop = oopFactory::new_typeArray(T_INT, 2, CHECK); - ints_oop->int_at_put(0, _argc); + // return {arg_count, pool_index, indy_index} + // JDK code must pull the arguments as needed + typeArrayOop ints_oop = oopFactory::new_typeArray(T_INT, 3, CHECK); + ints_oop->int_at_put(0, argc); ints_oop->int_at_put(1, _bss_index); + ints_oop->int_at_put(2, _indy_index); _arg_values = Handle(THREAD, ints_oop); } } @@ -236,6 +256,7 @@ void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) { os::snprintf_checked(what, sizeof(what), "condy"); } bool have_msg = (msg != nullptr && strlen(msg) > 0); + int argc = arg_count(); st->print_cr("%s%sBootstrap in %s %s@CP[%d] %s:%s%s BSMS[%d] BSM@CP[%d]%s argc=%d%s", (have_msg ? msg : ""), (have_msg ? " " : ""), caller()->name()->as_C_string(), @@ -244,13 +265,13 @@ void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) { _name->as_C_string(), _signature->as_C_string(), (_type_arg.is_null() ? "" : "(resolved)"), - bsms_attr_index(), + bsm_attr_index(), bsm_index(), (_bsm.is_null() ? "" : "(resolved)"), - _argc, (_arg_values.is_null() ? "" : "(resolved)")); - if (_argc > 0) { + argc, (_arg_values.is_null() ? "" : "(resolved)")); + if (argc > 0) { char argbuf[80]; argbuf[0] = 0; - for (int i = 0; i < _argc; i++) { + for (int i = 0; i < argc; i++) { int pos = (int) strlen(argbuf); if (pos + 20 > (int)sizeof(argbuf)) { os::snprintf_checked(argbuf + pos, sizeof(argbuf) - pos, "..."); @@ -272,11 +293,11 @@ void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) { // Find the static arguments within the first element of _arg_values. objArrayOop static_args = (objArrayOop)_arg_values(); if (!static_args->is_array()) { - assert(_argc == 1, "Invalid BSM _arg_values for non-array"); + assert(argc == 1, "Invalid BSM _arg_values for non-array"); st->print(" resolved arg[0]: "); static_args->print_on(st); } else if (static_args->is_objArray()) { int lines = 0; - for (int i = 0; i < _argc; i++) { + for (int i = 0; i < argc; i++) { oop x = static_args->obj_at(i); if (x != nullptr) { if (++lines > 6) { diff --git a/src/hotspot/share/interpreter/bootstrapInfo.hpp b/src/hotspot/share/interpreter/bootstrapInfo.hpp index 4c479fe845fbe..32bb3dbe34e97 100644 --- a/src/hotspot/share/interpreter/bootstrapInfo.hpp +++ b/src/hotspot/share/interpreter/bootstrapInfo.hpp @@ -34,7 +34,7 @@ class BootstrapInfo : public StackObj { constantPoolHandle _pool; // constant pool containing the bootstrap specifier const int _bss_index; // index of bootstrap specifier in CP (condy or indy) const int _indy_index; // internal index of indy call site, or -1 if a condy call - const int _argc; // number of static arguments + int _bsm_attr_index; // index in the BootstrapMethods attribute Symbol* _name; // extracted from JVM_CONSTANT_NameAndType Symbol* _signature; @@ -43,7 +43,7 @@ class BootstrapInfo : public StackObj { Handle _name_arg; // resolved String Handle _type_arg; // resolved Class or MethodType Handle _arg_values; // array of static arguments; null implies either - // uresolved or zero static arguments are specified + // unresolved or zero static arguments are specified // post-bootstrap resolution state: bool _is_resolved; // set true when any of the next fields are set @@ -58,7 +58,7 @@ class BootstrapInfo : public StackObj { const constantPoolHandle& pool() const{ return _pool; } int bss_index() const { return _bss_index; } int indy_index() const { return _indy_index; } - int argc() const { return _argc; } + int bsm_attr_index() const { return _bsm_attr_index; } bool is_method_call() const { return (_indy_index != -1); } Symbol* name() const { return _name; } Symbol* signature() const { return _signature; } @@ -76,10 +76,11 @@ class BootstrapInfo : public StackObj { // derived accessors InstanceKlass* caller() const { return _pool->pool_holder(); } oop caller_mirror() const { return caller()->java_mirror(); } - int bsms_attr_index() const { return _pool->bootstrap_methods_attribute_index(_bss_index); } - int bsm_index() const { return _pool->bootstrap_method_ref_index_at(_bss_index); } - //int argc() is eagerly cached in _argc - int arg_index(int i) const { return _pool->bootstrap_argument_index_at(_bss_index, i); } + BSMAttributeEntry& bsm_attr() const { return *_pool->bsm_attribute_entry(_bsm_attr_index); } + int bsm_index() const { return bsm_attr().bootstrap_method_index(); } + int arg_count() const { return bsm_attr().argument_count(); } + int arg_index(int j) const { return bsm_attr().argument_index(j); } + ResolvedIndyEntry* indy_entry() const; // If there is evidence this call site was already linked, set the // existing linkage data into result, or throw previous exception. diff --git a/src/hotspot/share/interpreter/bytecodeTracer.cpp b/src/hotspot/share/interpreter/bytecodeTracer.cpp index 798c0bfc7d81c..bef01814a69cd 100644 --- a/src/hotspot/share/interpreter/bytecodeTracer.cpp +++ b/src/hotspot/share/interpreter/bytecodeTracer.cpp @@ -284,7 +284,7 @@ void BytecodePrinter::print_dynamic(int cp_index, outputStream* st) { return; } - int bsm = constants->bootstrap_method_ref_index_at(cp_index); + int bsm = constants->bootstrap_methods_attribute_index(cp_index); st->print(" bsm=%d", bsm); Symbol* name = constants->uncached_name_ref_at(cp_index); @@ -310,7 +310,7 @@ void BytecodePrinter::print_invokedynamic(int indy_index, int cp_index, outputSt // cp_index: must be the cp_index of a JVM_CONSTANT_{Dynamic, DynamicInError, InvokeDynamic} void BytecodePrinter::print_bsm(int cp_index, outputStream* st) { assert(constants()->tag_at(cp_index).has_bootstrap(), "must be"); - int bsm = constants()->bootstrap_method_ref_index_at(cp_index); + int bsm = constants()->bootstrap_methods_attribute_index(cp_index); const char* ref_kind = ""; switch (constants()->method_handle_ref_kind_at(bsm)) { case JVM_REF_getField : ref_kind = "REF_getField"; break; @@ -326,12 +326,13 @@ void BytecodePrinter::print_bsm(int cp_index, outputStream* st) { } st->print(" BSM: %s", ref_kind); print_field_or_method(constants()->method_handle_index_at(bsm), st); - int argc = constants()->bootstrap_argument_count_at(cp_index); + BSMAttributeEntry* bsme = constants()->bootstrap_methods_attribute_entry(cp_index); + int argc = bsme->argument_count(); st->print(" arguments[%d] = {", argc); if (argc > 0) { st->cr(); for (int arg_i = 0; arg_i < argc; arg_i++) { - int arg = constants()->bootstrap_argument_index_at(cp_index, arg_i); + int arg = bsme->argument_index(arg_i); st->print(" "); print_constant(arg, st); } diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index b4b8150917dd5..d30852d6ed5ac 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -890,7 +890,7 @@ C2V_END C2V_VMENTRY_0(jint, bootstrapArgumentIndexAt, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint cpi, jint index)) constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp)); - return cp->bootstrap_argument_index_at(cpi, index); + return cp->bootstrap_methods_attribute_entry(cpi)->argument_index(index); C2V_END C2V_VMENTRY_0(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index, jint opcode)) diff --git a/src/hotspot/share/oops/array.hpp b/src/hotspot/share/oops/array.hpp index 12e23080166ec..8922babd1300d 100644 --- a/src/hotspot/share/oops/array.hpp +++ b/src/hotspot/share/oops/array.hpp @@ -126,6 +126,7 @@ class Array: public MetaspaceObj { T at(int i) const { assert(i >= 0 && i< _length, "oob: 0 <= %d < %d", i, _length); return data()[i]; } void at_put(const int i, const T& x) { assert(i >= 0 && i< _length, "oob: 0 <= %d < %d", i, _length); data()[i] = x; } T* adr_at(const int i) { assert(i >= 0 && i< _length, "oob: 0 <= %d < %d", i, _length); return &data()[i]; } + const T* adr_at(const int i) const { assert(i >= 0 && i< _length, "oob: 0 <= %d < %d", i, _length); return &data()[i]; } int find(const T& x) { return index_of(x); } T at_acquire(const int i) { return Atomic::load_acquire(adr_at(i)); } diff --git a/src/hotspot/share/oops/constMethod.cpp b/src/hotspot/share/oops/constMethod.cpp index 1fed47f7ff226..6b08e96b5fbb8 100644 --- a/src/hotspot/share/oops/constMethod.cpp +++ b/src/hotspot/share/oops/constMethod.cpp @@ -191,13 +191,14 @@ u2* ConstMethod::last_u2_element() const { u2* ConstMethod::generic_signature_index_addr() const { // Located at the end of the constMethod. assert(has_generic_signature(), "called only if generic signature exists"); - return last_u2_element(); + int offset = 0; // this is always the last u2 (before possible pointers) + return last_u2_element() - offset; } u2* ConstMethod::method_parameters_length_addr() const { assert(has_method_parameters(), "called only if table is present"); - return has_generic_signature() ? (last_u2_element() - 1) : - last_u2_element(); + int offset = has_generic_signature() ? 1 : 0; + return last_u2_element() - offset; } u2* ConstMethod::checked_exceptions_length_addr() const { diff --git a/src/hotspot/share/oops/constMethod.hpp b/src/hotspot/share/oops/constMethod.hpp index 47fcb0d5572ee..91a83ed98b180 100644 --- a/src/hotspot/share/oops/constMethod.hpp +++ b/src/hotspot/share/oops/constMethod.hpp @@ -81,7 +81,7 @@ // (access flags bit tells whether table is present) // (indexed from end of ConstMethod*) // [EMBEDDED generic signature index (u2)] -// (indexed from end of constMethodOop) +// (indexed from end of ConstMethod*) // [EMBEDDED annotations arrays - method, parameter, type, default] // pointer to Array if annotation is present // diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index c02fdaf2dc602..9d0ced7fb022d 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -133,8 +133,10 @@ void ConstantPool::deallocate_contents(ClassLoaderData* loader_data) { MetadataFactory::free_array(loader_data, resolved_klasses()); set_resolved_klasses(nullptr); - MetadataFactory::free_array(loader_data, operands()); - set_operands(nullptr); + MetadataFactory::free_array(loader_data, bsm_attribute_offsets()); + MetadataFactory::free_array(loader_data, bsm_attribute_entries()); + set_bsm_attribute_offsets(nullptr); + set_bsm_attribute_entries(nullptr); release_C_heap_structures(); @@ -154,7 +156,8 @@ void ConstantPool::metaspace_pointers_do(MetaspaceClosure* it) { it->push(&_tags, MetaspaceClosure::_writable); it->push(&_cache); it->push(&_pool_holder); - it->push(&_operands); + it->push(&_bsm_attribute_offsets); + it->push(&_bsm_attribute_entries); it->push(&_resolved_klasses, MetaspaceClosure::_writable); for (int i = 0; i < length(); i++) { @@ -293,14 +296,14 @@ void ConstantPool::iterate_archivable_resolved_references(Function function) { if (indy_entries != nullptr) { for (int i = 0; i < indy_entries->length(); i++) { ResolvedIndyEntry *rie = indy_entries->adr_at(i); + BSMAttributeEntry *bsme = rie->bsme(this); if (rie->is_resolved() && AOTConstantPoolResolver::is_resolution_deterministic(this, rie->constant_pool_index())) { int rr_index = rie->resolved_references_index(); assert(resolved_reference_at(rr_index) != nullptr, "must exist"); function(rr_index); // Save the BSM as well (sometimes the JIT looks up the BSM it for replay) - int indy_cp_index = rie->constant_pool_index(); - int bsm_mh_cp_index = bootstrap_method_ref_index_at(indy_cp_index); + int bsm_mh_cp_index = bsme->bootstrap_method_index(); int bsm_rr_index = cp_to_object_index(bsm_mh_cp_index); assert(resolved_reference_at(bsm_rr_index) != nullptr, "must exist"); function(bsm_rr_index); @@ -799,7 +802,12 @@ int ConstantPool::to_cp_index(int index, Bytecodes::Code code) { assert(cache() != nullptr, "'index' is a rewritten index so this class must have been rewritten"); switch(code) { case Bytecodes::_invokedynamic: - return invokedynamic_bootstrap_ref_index_at(index); + { + auto ie = cache()->resolved_indy_entry_at(index); + int cp_index = ie->constant_pool_index(); + assert(tag_at(cp_index).has_bootstrap(), "index contains symbolic ref"); + return cp_index; + } case Bytecodes::_getfield: case Bytecodes::_getstatic: case Bytecodes::_putfield: @@ -1338,20 +1346,24 @@ oop ConstantPool::uncached_string_at(int cp_index, TRAPS) { return str; } -void ConstantPool::copy_bootstrap_arguments_at_impl(const constantPoolHandle& this_cp, int cp_index, +void ConstantPool::copy_bootstrap_arguments_at_impl(const constantPoolHandle& this_cp, + int bsme_index, int start_arg, int end_arg, objArrayHandle info, int pos, bool must_resolve, Handle if_not_available, TRAPS) { int limit = pos + end_arg - start_arg; - // checks: cp_index in range [0..this_cp->length), - // tag at cp_index, start..end in range [0..this_cp->bootstrap_argument_count], + // check explicitly (do not assert) that bsms index is in range + BSMAttributeEntry* bsme = nullptr; + if (0 <= bsme_index && + bsme_index < this_cp->bsm_attribute_count()) { + bsme = this_cp->bsm_attribute_entry(bsme_index); + } + // also check tag at cp_index, start..end in range, // info array non-null, pos..limit in [0..info.length] - if ((0 >= cp_index || cp_index >= this_cp->length()) || - !(this_cp->tag_at(cp_index).is_invoke_dynamic() || - this_cp->tag_at(cp_index).is_dynamic_constant()) || + if (bsme == nullptr || (0 > start_arg || start_arg > end_arg) || - (end_arg > this_cp->bootstrap_argument_count_at(cp_index)) || + (end_arg > bsme->argument_count()) || (0 > pos || pos > limit) || (info.is_null() || limit > info->length())) { // An index or something else went wrong; throw an error. @@ -1362,7 +1374,7 @@ void ConstantPool::copy_bootstrap_arguments_at_impl(const constantPoolHandle& th // now we can loop safely int info_i = pos; for (int i = start_arg; i < end_arg; i++) { - int arg_index = this_cp->bootstrap_argument_index_at(cp_index, i); + int arg_index = bsme->argument_index(i); oop arg_oop; if (must_resolve) { arg_oop = this_cp->resolve_possibly_cached_constant_at(arg_index, CHECK); @@ -1557,22 +1569,22 @@ bool ConstantPool::compare_entry_to(int index1, const constantPoolHandle& cp2, { int k1 = bootstrap_name_and_type_ref_index_at(index1); int k2 = cp2->bootstrap_name_and_type_ref_index_at(index2); - int i1 = bootstrap_methods_attribute_index(index1); - int i2 = cp2->bootstrap_methods_attribute_index(index2); + int e1 = bootstrap_methods_attribute_index(index1); + int e2 = cp2->bootstrap_methods_attribute_index(index2); bool match_entry = compare_entry_to(k1, cp2, k2); - bool match_operand = compare_operand_to(i1, cp2, i2); - return (match_entry && match_operand); + bool match_bsme = compare_bsme_to(e1, cp2, e2); + return (match_entry && match_bsme); } break; case JVM_CONSTANT_InvokeDynamic: { int k1 = bootstrap_name_and_type_ref_index_at(index1); int k2 = cp2->bootstrap_name_and_type_ref_index_at(index2); - int i1 = bootstrap_methods_attribute_index(index1); - int i2 = cp2->bootstrap_methods_attribute_index(index2); + int e1 = bootstrap_methods_attribute_index(index1); + int e2 = cp2->bootstrap_methods_attribute_index(index2); bool match_entry = compare_entry_to(k1, cp2, k2); - bool match_operand = compare_operand_to(i1, cp2, i2); - return (match_entry && match_operand); + bool match_bsme = compare_bsme_to(e1, cp2, e2); + return (match_entry && match_bsme); } break; case JVM_CONSTANT_String: @@ -1607,139 +1619,138 @@ bool ConstantPool::compare_entry_to(int index1, const constantPoolHandle& cp2, } // end compare_entry_to() -// Resize the operands array with delta_len and delta_size. +// Resize the BSM attribute arrays with delta_len and delta_size. // Used in RedefineClasses for CP merge. -void ConstantPool::resize_operands(int delta_len, int delta_size, TRAPS) { - int old_len = operand_array_length(operands()); - int new_len = old_len + delta_len; - int min_len = (delta_len > 0) ? old_len : new_len; +void ConstantPool::resize_bsm_data(int delta_len, int delta_size, TRAPS) { + const Array* old_offs = bsm_attribute_offsets(); + const Array* old_data = bsm_attribute_entries(); + const bool have_old = (bsm_attribute_count() != 0); - int old_size = operands()->length(); - int new_size = old_size + delta_size; - int min_size = (delta_size > 0) ? old_size : new_size; + int old_offs_len = bsm_attribute_count(); + int new_offs_len = old_offs_len + delta_len; + int min_offs_len = (delta_len > 0) ? old_offs_len : new_offs_len; - ClassLoaderData* loader_data = pool_holder()->class_loader_data(); - Array* new_ops = MetadataFactory::new_array(loader_data, new_size, CHECK); + int old_data_len = bsm_entry_count(); + int new_data_len = old_data_len + delta_size; + int min_data_len = (delta_size > 0) ? old_data_len : new_data_len; - // Set index in the resized array for existing elements only - for (int idx = 0; idx < min_len; idx++) { - int offset = operand_offset_at(idx); // offset in original array - operand_offset_at_put(new_ops, idx, offset + 2*delta_len); // offset in resized array - } - // Copy the bootstrap specifiers only - Copy::conjoint_memory_atomic(operands()->adr_at(2*old_len), - new_ops->adr_at(2*new_len), - (min_size - 2*min_len) * sizeof(u2)); - // Explicitly deallocate old operands array. - // Note, it is not needed for 7u backport. - if ( operands() != nullptr) { // the safety check - MetadataFactory::free_array(loader_data, operands()); + ClassLoaderData* loader_data = pool_holder()->class_loader_data(); + Array* new_offs = MetadataFactory::new_array(loader_data, new_offs_len, CHECK); + Array* new_data = MetadataFactory::new_array(loader_data, new_data_len, CHECK); + // Copy the old array data. We do not need to change any offsets. + if (have_old) { + Copy::conjoint_memory_atomic(old_offs->data(), + new_offs->data(), + min_offs_len * sizeof(u4)); + Copy::conjoint_memory_atomic(old_data->data(), + new_data->data(), + min_data_len * sizeof(u2)); } - set_operands(new_ops); -} // end resize_operands() + + // Explicitly deallocate old bsm_data array. + MetadataFactory::free_array(loader_data, bsm_attribute_offsets()); + MetadataFactory::free_array(loader_data, bsm_attribute_entries()); + + set_bsm_attribute_offsets(new_offs); + set_bsm_attribute_entries(new_data); +} // end resize_bsm_data() -// Extend the operands array with the length and size of the ext_cp operands. +// Extend the BSM attribute arrays with the length and size of the ext_cp data. // Used in RedefineClasses for CP merge. -void ConstantPool::extend_operands(const constantPoolHandle& ext_cp, TRAPS) { - int delta_len = operand_array_length(ext_cp->operands()); +void ConstantPool::extend_bsm_data(const constantPoolHandle& ext_cp, TRAPS) { + int delta_len = ext_cp->bsm_attribute_count(); if (delta_len == 0) { return; // nothing to do } - int delta_size = ext_cp->operands()->length(); + int delta_size = ext_cp->bsm_attribute_entries()->length(); - assert(delta_len > 0 && delta_size > 0, "extended operands array must be bigger"); - - if (operand_array_length(operands()) == 0) { - ClassLoaderData* loader_data = pool_holder()->class_loader_data(); - Array* new_ops = MetadataFactory::new_array(loader_data, delta_size, CHECK); - // The first element index defines the offset of second part - operand_offset_at_put(new_ops, 0, 2*delta_len); // offset in new array - set_operands(new_ops); - } else { - resize_operands(delta_len, delta_size, CHECK); - } + assert(delta_len > 0 && delta_size > 0, "extended arrays must be bigger"); -} // end extend_operands() + // Note: resize_bsm_data can handle bsm_attribute_entries()==nullptr + resize_bsm_data(delta_len, delta_size, CHECK); +} // end extend_bsm_data() -// Shrink the operands array to a smaller array with new_len length. +// Shrink the BSM attribute arrays to a smaller number of entries. // Used in RedefineClasses for CP merge. -void ConstantPool::shrink_operands(int new_len, TRAPS) { - int old_len = operand_array_length(operands()); +void ConstantPool::shrink_bsm_data(int new_len, TRAPS) { + int old_len = bsm_attribute_count(); if (new_len == old_len) { return; // nothing to do } - assert(new_len < old_len, "shrunken operands array must be smaller"); - - int free_base = operand_next_offset_at(new_len - 1); - int delta_len = new_len - old_len; - int delta_size = 2*delta_len + free_base - operands()->length(); + assert(new_len < old_len, "shrunken bsm_data array must be smaller"); - resize_operands(delta_len, delta_size, CHECK); + int new_data_len = bsm_attribute_offsets()->at(new_len); //offset + int old_data_len = bsm_attribute_entries()->length(); //length + int delta_len = new_len - old_len; + int delta_size = new_data_len - old_data_len; -} // end shrink_operands() + resize_bsm_data(delta_len, delta_size, CHECK); +} // end shrink_bsm_data() -void ConstantPool::copy_operands(const constantPoolHandle& from_cp, +// Append the BSM attribute entries from one CP to the end of another. +void ConstantPool::copy_bsm_data(const constantPoolHandle& from_cp, const constantPoolHandle& to_cp, TRAPS) { + if (from_cp->bsm_attribute_count() == 0) { + return; // nothing to copy + } - int from_oplen = operand_array_length(from_cp->operands()); - int old_oplen = operand_array_length(to_cp->operands()); - if (from_oplen != 0) { - ClassLoaderData* loader_data = to_cp->pool_holder()->class_loader_data(); - // append my operands to the target's operands array - if (old_oplen == 0) { - // Can't just reuse from_cp's operand list because of deallocation issues - int len = from_cp->operands()->length(); - Array* new_ops = MetadataFactory::new_array(loader_data, len, CHECK); - Copy::conjoint_memory_atomic( - from_cp->operands()->adr_at(0), new_ops->adr_at(0), len * sizeof(u2)); - to_cp->set_operands(new_ops); - } else { - int old_len = to_cp->operands()->length(); - int from_len = from_cp->operands()->length(); - int old_off = old_oplen * sizeof(u2); - int from_off = from_oplen * sizeof(u2); - // Use the metaspace for the destination constant pool - Array* new_operands = MetadataFactory::new_array(loader_data, old_len + from_len, CHECK); - int fillp = 0, len = 0; - // first part of dest - Copy::conjoint_memory_atomic(to_cp->operands()->adr_at(0), - new_operands->adr_at(fillp), - (len = old_off) * sizeof(u2)); - fillp += len; - // first part of src - Copy::conjoint_memory_atomic(from_cp->operands()->adr_at(0), - new_operands->adr_at(fillp), - (len = from_off) * sizeof(u2)); - fillp += len; - // second part of dest - Copy::conjoint_memory_atomic(to_cp->operands()->adr_at(old_off), - new_operands->adr_at(fillp), - (len = old_len - old_off) * sizeof(u2)); - fillp += len; - // second part of src - Copy::conjoint_memory_atomic(from_cp->operands()->adr_at(from_off), - new_operands->adr_at(fillp), - (len = from_len - from_off) * sizeof(u2)); - fillp += len; - assert(fillp == new_operands->length(), ""); - - // Adjust indexes in the first part of the copied operands array. - for (int j = 0; j < from_oplen; j++) { - int offset = operand_offset_at(new_operands, old_oplen + j); - assert(offset == operand_offset_at(from_cp->operands(), j), "correct copy"); - offset += old_len; // every new tuple is preceded by old_len extra u2's - operand_offset_at_put(new_operands, old_oplen + j, offset); - } + const int from_offset_count = from_cp->bsm_attribute_count(); + const int from_entry_count = from_cp->bsm_entry_count(); - // replace target operands array with combined array - to_cp->set_operands(new_operands); - } + const int to_offset_count = to_cp->bsm_attribute_count(); + const int to_entry_count = to_cp->bsm_entry_count(); + + ClassLoaderData* loader_data = to_cp->pool_holder()->class_loader_data(); + + Array* new_offsets = MetadataFactory::new_array(loader_data, from_offset_count + to_offset_count, CHECK); + Array* new_entries = MetadataFactory::new_array(loader_data, from_entry_count + to_entry_count, CHECK); + u2* new_entries_data = new_entries->data(); + u4* new_offsets_data = new_offsets->data(); + + // Copy the original to-data + Array* to_offsets = to_cp->bsm_attribute_offsets(); + Array* to_entries = to_cp->bsm_attribute_entries(); + u4* to_offsets_data = to_offsets == nullptr ? nullptr : to_offsets->data(); + u2* to_entries_data = to_entries == nullptr ? nullptr : to_entries->data(); + + assert(!(to_offsets_data == nullptr) || to_offset_count == 0, "to_offsets_data == nullptr => to_offset_count == 0"); + assert(!(to_entries_data == nullptr) || to_entry_count == 0, "to_entries_data == nullptr => to_entries_count == 0"); + + memcpy(new_entries_data, to_entries_data, to_entry_count * sizeof(u2)); + memcpy(new_offsets_data, to_offsets_data, to_offset_count * sizeof(u4)); + + new_entries_data += to_entry_count; + new_offsets_data += to_offset_count; + + // Append the from-data + Array* from_offsets = from_cp->bsm_attribute_offsets(); + Array* from_entries = from_cp->bsm_attribute_entries(); + u4* from_offsets_data = from_offsets == nullptr ? nullptr : from_offsets->data(); + u2* from_entries_data = from_entries == nullptr ? nullptr : from_entries->data(); + + memcpy(new_entries_data, from_entries_data, from_entry_count * sizeof(u2)); + memcpy(new_offsets_data, from_offsets_data, from_offset_count); + + // Adjust the from-data's offset indices + int entries_base_modifier = to_entry_count; + int offsets_base_modifier = to_offset_count; + for (int i = 0; i < from_offset_count; i++) { + u4 v = new_offsets->at(offsets_base_modifier + i) + entries_base_modifier; + new_offsets->at_put(offsets_base_modifier + i, v); } -} // end copy_operands() + + // Free the old arrays + MetadataFactory::free_array(loader_data, to_cp->bsm_attribute_entries()); + MetadataFactory::free_array(loader_data, to_cp->bsm_attribute_offsets()); + + // replace target bsm_data array with combined array + to_cp->set_bsm_attribute_offsets(new_offsets); + to_cp->set_bsm_attribute_entries(new_entries); +} // end copy_bsm_data() // Copy this constant pool's entries at start_i to end_i (inclusive) @@ -1769,7 +1780,7 @@ void ConstantPool::copy_cp_to_impl(const constantPoolHandle& from_cp, int start_ break; } } - copy_operands(from_cp, to_cp, CHECK); + copy_bsm_data(from_cp, to_cp, CHECK); } // end copy_cp_to_impl() @@ -1893,7 +1904,7 @@ void ConstantPool::copy_entry_to(const constantPoolHandle& from_cp, int from_i, { int k1 = from_cp->bootstrap_methods_attribute_index(from_i); int k2 = from_cp->bootstrap_name_and_type_ref_index_at(from_i); - k1 += operand_array_length(to_cp->operands()); // to_cp might already have operands + k1 += to_cp->bsm_attribute_count(); // to_cp might already have BSMs to_cp->dynamic_constant_at_put(to_i, k1, k2); } break; @@ -1901,7 +1912,7 @@ void ConstantPool::copy_entry_to(const constantPoolHandle& from_cp, int from_i, { int k1 = from_cp->bootstrap_methods_attribute_index(from_i); int k2 = from_cp->bootstrap_name_and_type_ref_index_at(from_i); - k1 += operand_array_length(to_cp->operands()); // to_cp might already have operands + k1 += to_cp->bsm_attribute_count(); // to_cp might already have BSMs to_cp->invoke_dynamic_at_put(to_i, k1, k2); } break; @@ -1935,44 +1946,48 @@ int ConstantPool::find_matching_entry(int pattern_i, } // end find_matching_entry() -// Compare this constant pool's bootstrap specifier at idx1 to the constant pool -// cp2's bootstrap specifier at idx2. -bool ConstantPool::compare_operand_to(int idx1, const constantPoolHandle& cp2, int idx2) { - int k1 = operand_bootstrap_method_ref_index_at(idx1); - int k2 = cp2->operand_bootstrap_method_ref_index_at(idx2); - bool match = compare_entry_to(k1, cp2, k2); +// Compare this constant pool's BSM attribute entry at idx1 to the constant pool +// cp2's BSM attribute entry at idx2. +bool ConstantPool::compare_bsme_to(int idx1, const constantPoolHandle& cp2, int idx2) { + BSMAttributeEntry* e1 = bsm_attribute_entry(idx1); + BSMAttributeEntry* e2 = cp2->bsm_attribute_entry(idx2); + int k1 = e1->bootstrap_method_index(); + int k2 = e2->bootstrap_method_index(); + bool match = compare_entry_to(k1, cp2, k2); if (!match) { return false; } - int argc = operand_argument_count_at(idx1); - if (argc == cp2->operand_argument_count_at(idx2)) { - for (int j = 0; j < argc; j++) { - k1 = operand_argument_index_at(idx1, j); - k2 = cp2->operand_argument_index_at(idx2, j); - match = compare_entry_to(k1, cp2, k2); - if (!match) { - return false; - } + + int argc = e1->argument_count(); + if (argc != e2->argument_count()) { + return false; + } + + for (int j = 0; j < argc; j++) { + k1 = e1->argument_index(j); + k2 = e2->argument_index(j); + match = compare_entry_to(k1, cp2, k2); + if (!match) { + return false; } - return true; // got through loop; all elements equal } - return false; -} // end compare_operand_to() + return true; +} -// Search constant pool search_cp for a bootstrap specifier that matches -// this constant pool's bootstrap specifier data at pattern_i index. -// Return the index of a matching bootstrap attribute record or (-1) if there is no match. -int ConstantPool::find_matching_operand(int pattern_i, +// Search constant pool search_cp for a BSM attribute entry that matches +// this constant pool's BSM attribute entry at pattern_i index. +// Return the index of a entry, or (-1) if there was no match. +int ConstantPool::find_matching_bsme(int pattern_i, const constantPoolHandle& search_cp, int search_len) { for (int i = 0; i < search_len; i++) { - bool found = compare_operand_to(pattern_i, search_cp, i); + bool found = compare_bsme_to(pattern_i, search_cp, i); if (found) { return i; } } return -1; // bootstrap specifier data not found; return unused index (-1) -} // end find_matching_operand() +} #ifndef PRODUCT @@ -2370,12 +2385,13 @@ void ConstantPool::print_entry_on(const int cp_index, outputStream* st) { case JVM_CONSTANT_Dynamic : case JVM_CONSTANT_DynamicInError : { - st->print("bootstrap_method_index=%d", bootstrap_method_ref_index_at(cp_index)); + auto bsme = bootstrap_methods_attribute_entry(cp_index); + st->print("bootstrap_method_index=%d", bsme->bootstrap_method_index()); st->print(" type_index=%d", bootstrap_name_and_type_ref_index_at(cp_index)); - int argc = bootstrap_argument_count_at(cp_index); + int argc = bsme->argument_count(); if (argc > 0) { for (int arg_i = 0; arg_i < argc; arg_i++) { - int arg = bootstrap_argument_index_at(cp_index, arg_i); + int arg = bsme->argument_index(arg_i); st->print((arg_i == 0 ? " arguments={%d" : ", %d"), arg); } st->print("}"); @@ -2384,12 +2400,13 @@ void ConstantPool::print_entry_on(const int cp_index, outputStream* st) { break; case JVM_CONSTANT_InvokeDynamic : { - st->print("bootstrap_method_index=%d", bootstrap_method_ref_index_at(cp_index)); + auto bsme = bootstrap_methods_attribute_entry(cp_index); + st->print("bootstrap_method_index=%d", bsme->bootstrap_method_index()); st->print(" name_and_type_index=%d", bootstrap_name_and_type_ref_index_at(cp_index)); - int argc = bootstrap_argument_count_at(cp_index); + int argc = bsme->argument_count(); if (argc > 0) { for (int arg_i = 0; arg_i < argc; arg_i++) { - int arg = bootstrap_argument_index_at(cp_index, arg_i); + int arg = bsme->argument_index(arg_i); st->print((arg_i == 0 ? " arguments={%d" : ", %d"), arg); } st->print("}"); @@ -2407,7 +2424,7 @@ void ConstantPool::print_value_on(outputStream* st) const { assert(is_constantPool(), "must be constantPool"); st->print("constant pool [%d]", length()); if (has_preresolution()) st->print("/preresolution"); - if (operands() != nullptr) st->print("/operands[%d]", operands()->length()); + st->print("/bsms[%d]", bsm_attribute_count()); print_address_on(st); if (pool_holder() != nullptr) { st->print(" for "); diff --git a/src/hotspot/share/oops/constantPool.hpp b/src/hotspot/share/oops/constantPool.hpp index cc9491d7935db..a94d077945c60 100644 --- a/src/hotspot/share/oops/constantPool.hpp +++ b/src/hotspot/share/oops/constantPool.hpp @@ -77,6 +77,41 @@ class CPKlassSlot { } }; +// A single entry from a BootstrapMethods (BSM) attribute. +// It is an overlaid view of two or more consecutive u2 words within the +// ConstantPool::bsm_attribute_entries array. +class BSMAttributeEntry { + private: + u2 _bootstrap_method_index; + u2 _argument_count; + // C++ does not have a "Flexible Array Member" feature. + //u2 _argument_indexes[_argument_count]; + const u2* argument_indexes() const { return (const u2*)(this+1); } + + // These are overlays on top of Array data. Do not construct. + BSMAttributeEntry() = delete; + + // See also parse_classfile_bootstrap_methods_attribute in the class + // file parser, which builds this layout. + + public: + int bootstrap_method_index() const { return _bootstrap_method_index; } + int argument_count() const { return _argument_count; } + int argument_index(int n) const { assert((uint)n < _argument_count, "oob"); + return argument_indexes()[n]; + } + private: + // how to locate one of these inside a packed u2 data array: + static BSMAttributeEntry* entry_at_offset(Array* entries, int offset) { + assert(0 <= offset && offset+1 < entries->length(), "oob-1"); + // Overlay the struct within the array + BSMAttributeEntry* bsme = reinterpret_cast(entries->adr_at(offset)); + assert(offset+1+bsme->argument_count() < entries->length(), "oob-2"); + return bsme; + } + friend class ConstantPool; // uses entry_at_offset +}; + class ConstantPool : public Metadata { friend class VMStructs; friend class JVMCIVMStructs; @@ -89,12 +124,15 @@ class ConstantPool : public Metadata { Array* _tags; // the tag array describing the constant pool's contents ConstantPoolCache* _cache; // the cache holding interpreter runtime information InstanceKlass* _pool_holder; // the corresponding class - Array* _operands; // for variable-sized (InvokeDynamic) nodes, usually empty // Consider using an array of compressed klass pointers to // save space on 64-bit platforms. Array* _resolved_klasses; + // Support for indy/condy BootstrapMethods attribute, with variable-sized entries + Array* _bsm_attribute_offsets; // offsets to the BSMEs + Array* _bsm_attribute_entries; // BSMAttributeEntry structs (variable-sized) + u2 _major_version; // major version number of class file u2 _minor_version; // minor version number of class file @@ -130,7 +168,8 @@ class ConstantPool : public Metadata { u1* tag_addr_at(int cp_index) const { return tags()->adr_at(cp_index); } - void set_operands(Array* operands) { _operands = operands; } + void set_bsm_attribute_offsets(Array* offs) { _bsm_attribute_offsets = offs; } + void set_bsm_attribute_entries(Array* data) { _bsm_attribute_entries = data; } u2 flags() const { return _flags; } void set_flags(u2 f) { _flags = f; } @@ -171,7 +210,8 @@ class ConstantPool : public Metadata { virtual bool is_constantPool() const { return true; } Array* tags() const { return _tags; } - Array* operands() const { return _operands; } + Array* bsm_attribute_entries() const { return _bsm_attribute_entries; } + Array* bsm_attribute_offsets() const { return _bsm_attribute_offsets; } bool has_preresolution() const { return (_flags & _has_preresolution) != 0; } void set_has_preresolution() { @@ -253,11 +293,6 @@ class ConstantPool : public Metadata { void allocate_resolved_klasses(ClassLoaderData* loader_data, int num_klasses, TRAPS); void initialize_unresolved_klasses(ClassLoaderData* loader_data, TRAPS); - // Given the per-instruction index of an indy instruction, report the - // main constant pool entry for its bootstrap specifier. - // From there, uncached_name/signature_ref_at will get the name/type. - inline u2 invokedynamic_bootstrap_ref_index_at(int indy_index) const; - // Assembly code support static ByteSize tags_offset() { return byte_offset_of(ConstantPool, _tags); } static ByteSize cache_offset() { return byte_offset_of(ConstantPool, _cache); } @@ -294,14 +329,14 @@ class ConstantPool : public Metadata { *int_at_addr(cp_index) = ref_index; } - void dynamic_constant_at_put(int cp_index, int bsms_attribute_index, int name_and_type_index) { + void dynamic_constant_at_put(int cp_index, int bsm_attribute_index, int name_and_type_index) { tag_at_put(cp_index, JVM_CONSTANT_Dynamic); - *int_at_addr(cp_index) = ((jint) name_and_type_index<<16) | bsms_attribute_index; + *int_at_addr(cp_index) = ((jint) name_and_type_index<<16) | bsm_attribute_index; } - void invoke_dynamic_at_put(int cp_index, int bsms_attribute_index, int name_and_type_index) { + void invoke_dynamic_at_put(int cp_index, int bsm_attribute_index, int name_and_type_index) { tag_at_put(cp_index, JVM_CONSTANT_InvokeDynamic); - *int_at_addr(cp_index) = ((jint) name_and_type_index<<16) | bsms_attribute_index; + *int_at_addr(cp_index) = ((jint) name_and_type_index<<16) | bsm_attribute_index; } void unresolved_string_at_put(int cp_index, Symbol* s) { @@ -519,123 +554,38 @@ class ConstantPool : public Metadata { assert(tag_at(cp_index).has_bootstrap(), "Corrupted constant pool"); return extract_low_short_from_int(*int_at_addr(cp_index)); } - int bootstrap_operand_base(int cp_index) { - int bsms_attribute_index = bootstrap_methods_attribute_index(cp_index); - return operand_offset_at(operands(), bsms_attribute_index); - } - // The first part of the operands array consists of an index into the second part. - // Extract a 32-bit index value from the first part. - static int operand_offset_at(Array* operands, int bsms_attribute_index) { - int n = (bsms_attribute_index * 2); - assert(n >= 0 && n+2 <= operands->length(), "oob"); - // The first 32-bit index points to the beginning of the second part - // of the operands array. Make sure this index is in the first part. - DEBUG_ONLY(int second_part = build_int_from_shorts(operands->at(0), - operands->at(1))); - assert(second_part == 0 || n+2 <= second_part, "oob (2)"); - int offset = build_int_from_shorts(operands->at(n+0), - operands->at(n+1)); - // The offset itself must point into the second part of the array. - assert(offset == 0 || (offset >= second_part && offset <= operands->length()), "oob (3)"); - return offset; - } - static void operand_offset_at_put(Array* operands, int bsms_attribute_index, int offset) { - int n = bsms_attribute_index * 2; - assert(n >= 0 && n+2 <= operands->length(), "oob"); - operands->at_put(n+0, extract_low_short_from_int(offset)); - operands->at_put(n+1, extract_high_short_from_int(offset)); - } - static int operand_array_length(Array* operands) { - if (operands == nullptr || operands->length() == 0) return 0; - int second_part = operand_offset_at(operands, 0); - return (second_part / 2); - } - -#ifdef ASSERT - // operand tuples fit together exactly, end to end - static int operand_limit_at(Array* operands, int bsms_attribute_index) { - int nextidx = bsms_attribute_index + 1; - if (nextidx == operand_array_length(operands)) - return operands->length(); - else - return operand_offset_at(operands, nextidx); - } - int bootstrap_operand_limit(int cp_index) { - int bsms_attribute_index = bootstrap_methods_attribute_index(cp_index); - return operand_limit_at(operands(), bsms_attribute_index); - } -#endif //ASSERT - - // Layout of InvokeDynamic and Dynamic bootstrap method specifier - // data in second part of operands array. This encodes one record in - // the BootstrapMethods attribute. The whole specifier also includes - // the name and type information from the main constant pool entry. - enum { - _indy_bsm_offset = 0, // CONSTANT_MethodHandle bsm - _indy_argc_offset = 1, // u2 argc - _indy_argv_offset = 2 // u2 argv[argc] - }; + BSMAttributeEntry* bsm_attribute_entry(int bsm_attribute_index) { + int offset = bsm_attribute_offsets()->at(bsm_attribute_index); + return BSMAttributeEntry::entry_at_offset(bsm_attribute_entries(), offset); + } - // These functions are used in RedefineClasses for CP merge - - int operand_offset_at(int bsms_attribute_index) { - assert(0 <= bsms_attribute_index && - bsms_attribute_index < operand_array_length(operands()), - "Corrupted CP operands"); - return operand_offset_at(operands(), bsms_attribute_index); - } - u2 operand_bootstrap_method_ref_index_at(int bsms_attribute_index) { - int offset = operand_offset_at(bsms_attribute_index); - return operands()->at(offset + _indy_bsm_offset); - } - u2 operand_argument_count_at(int bsms_attribute_index) { - int offset = operand_offset_at(bsms_attribute_index); - u2 argc = operands()->at(offset + _indy_argc_offset); - return argc; - } - u2 operand_argument_index_at(int bsms_attribute_index, int j) { - int offset = operand_offset_at(bsms_attribute_index); - return operands()->at(offset + _indy_argv_offset + j); - } - int operand_next_offset_at(int bsms_attribute_index) { - int offset = operand_offset_at(bsms_attribute_index) + _indy_argv_offset - + operand_argument_count_at(bsms_attribute_index); - return offset; - } - // Compare a bootstrap specifier data in the operands arrays - bool compare_operand_to(int bsms_attribute_index1, const constantPoolHandle& cp2, - int bsms_attribute_index2); - // Find a bootstrap specifier data in the operands array - int find_matching_operand(int bsms_attribute_index, const constantPoolHandle& search_cp, - int operands_cur_len); - // Resize the operands array with delta_len and delta_size - void resize_operands(int delta_len, int delta_size, TRAPS); - // Extend the operands array with the length and size of the ext_cp operands - void extend_operands(const constantPoolHandle& ext_cp, TRAPS); - // Shrink the operands array to a smaller array with new_len length - void shrink_operands(int new_len, TRAPS); - - u2 bootstrap_method_ref_index_at(int cp_index) { - assert(tag_at(cp_index).has_bootstrap(), "Corrupted constant pool"); - int op_base = bootstrap_operand_base(cp_index); - return operands()->at(op_base + _indy_bsm_offset); + int bsm_attribute_count() const { + if (bsm_attribute_offsets() == nullptr) return 0; + return bsm_attribute_offsets()->length(); } - u2 bootstrap_argument_count_at(int cp_index) { - assert(tag_at(cp_index).has_bootstrap(), "Corrupted constant pool"); - int op_base = bootstrap_operand_base(cp_index); - u2 argc = operands()->at(op_base + _indy_argc_offset); - DEBUG_ONLY(int end_offset = op_base + _indy_argv_offset + argc; - int next_offset = bootstrap_operand_limit(cp_index)); - assert(end_offset == next_offset, "matched ending"); - return argc; + int bsm_entry_count() const { + if (bsm_attribute_entries() == nullptr) return 0; + return bsm_attribute_entries()->length(); } - u2 bootstrap_argument_index_at(int cp_index, int j) { - int op_base = bootstrap_operand_base(cp_index); - DEBUG_ONLY(int argc = operands()->at(op_base + _indy_argc_offset)); - assert((uint)j < (uint)argc, "oob"); - return operands()->at(op_base + _indy_argv_offset + j); + + // convenience method, to perform a common extra indirection via CP entry: + BSMAttributeEntry* bootstrap_methods_attribute_entry(int cp_index) { + return bsm_attribute_entry(bootstrap_methods_attribute_index(cp_index)); } + // Compare BSM attribute entries between two CPs + bool compare_bsme_to(int bsme_index1, const constantPoolHandle& cp2, + int bsme_index2); + // Find a matching BSM attribute entries in another CP + int find_matching_bsme(int bsme_index, const constantPoolHandle& search_cp, + int search_len); + // Resize the BSM data arrays with delta_len and delta_size + void resize_bsm_data(int delta_len, int delta_size, TRAPS); + // Extend the BSM data arrays with the length and size of the BSM data in ext_cp + void extend_bsm_data(const constantPoolHandle& ext_cp, TRAPS); + // Shrink the BSM data arrays to a smaller array with new_len length + void shrink_bsm_data(int new_len, TRAPS); + // The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve, // name_and_type_ref_index_at) all expect to be passed indices obtained // directly from the bytecode. @@ -721,12 +671,13 @@ class ConstantPool : public Metadata { return resolve_constant_at_impl(h_this, cp_index, _possible_index_sentinel, &found_it, THREAD); } - void copy_bootstrap_arguments_at(int cp_index, + void copy_bootstrap_arguments_at(int bsme_index, int start_arg, int end_arg, objArrayHandle info, int pos, bool must_resolve, Handle if_not_available, TRAPS) { constantPoolHandle h_this(THREAD, this); - copy_bootstrap_arguments_at_impl(h_this, cp_index, start_arg, end_arg, + copy_bootstrap_arguments_at_impl(h_this, bsme_index, + start_arg, end_arg, info, pos, must_resolve, if_not_available, THREAD); } @@ -820,7 +771,8 @@ class ConstantPool : public Metadata { static oop resolve_constant_at_impl(const constantPoolHandle& this_cp, int cp_index, int cache_index, bool* status_return, TRAPS); - static void copy_bootstrap_arguments_at_impl(const constantPoolHandle& this_cp, int cp_index, + static void copy_bootstrap_arguments_at_impl(const constantPoolHandle& this_cp, + int bsme_index, int start_arg, int end_arg, objArrayHandle info, int pos, bool must_resolve, Handle if_not_available, TRAPS); @@ -840,7 +792,7 @@ class ConstantPool : public Metadata { } static void copy_cp_to_impl(const constantPoolHandle& from_cp, int start_cpi, int end_cpi, const constantPoolHandle& to_cp, int to_cpi, TRAPS); static void copy_entry_to(const constantPoolHandle& from_cp, int from_cpi, const constantPoolHandle& to_cp, int to_cpi); - static void copy_operands(const constantPoolHandle& from_cp, const constantPoolHandle& to_cp, TRAPS); + static void copy_bsm_data(const constantPoolHandle& from_cp, const constantPoolHandle& to_cp, TRAPS); int find_matching_entry(int pattern_i, const constantPoolHandle& search_cp); int version() const { return _saved._version; } void set_version(int version) { _saved._version = version; } diff --git a/src/hotspot/share/oops/constantPool.inline.hpp b/src/hotspot/share/oops/constantPool.inline.hpp index 3aed4408121d1..c4357f51707f0 100644 --- a/src/hotspot/share/oops/constantPool.inline.hpp +++ b/src/hotspot/share/oops/constantPool.inline.hpp @@ -68,10 +68,6 @@ inline oop ConstantPool::appendix_if_resolved(int method_index) const { return resolved_reference_at(ref_index); } -inline u2 ConstantPool::invokedynamic_bootstrap_ref_index_at(int indy_index) const { - return cache()->resolved_indy_entry_at(indy_index)->constant_pool_index(); -} - inline ResolvedIndyEntry* ConstantPool::resolved_indy_entry_at(int index) { return cache()->resolved_indy_entry_at(index); } diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp index a354e0b07a696..634542d5e27be 100644 --- a/src/hotspot/share/oops/cpCache.cpp +++ b/src/hotspot/share/oops/cpCache.cpp @@ -520,7 +520,8 @@ void ConstantPoolCache::remove_resolved_indy_entries_if_non_deterministic() { LogStreamHandle(Trace, cds, resolve) log; if (log.is_enabled()) { ResourceMark rm; - 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); @@ -809,7 +810,7 @@ oop ConstantPoolCache::set_dynamic_call(const CallInfo &call_info, int index) { // Populate entry with resolved information assert(resolved_indy_entries() != nullptr, "Invokedynamic array is empty, cannot fill with resolved information"); - resolved_indy_entry_at(index)->fill_in(adapter, adapter->size_of_parameters(), as_TosState(adapter->result_type()), has_appendix); + resolved_indy_entry_at(index)->fill_in(adapter, has_appendix); if (log_stream != nullptr) { resolved_indy_entry_at(index)->print_on(log_stream); diff --git a/src/hotspot/share/oops/resolvedIndyEntry.cpp b/src/hotspot/share/oops/resolvedIndyEntry.cpp index 09060596caae2..a92d00f385cbf 100644 --- a/src/hotspot/share/oops/resolvedIndyEntry.cpp +++ b/src/hotspot/share/oops/resolvedIndyEntry.cpp @@ -27,6 +27,20 @@ #include "oops/method.hpp" #include "oops/resolvedIndyEntry.hpp" +u2 ResolvedIndyEntry::name_index(ConstantPool* cp) const { + int nti = cp->uncached_name_and_type_ref_index_at(constant_pool_index()); + return cp->name_ref_index_at(nti); +} + +u2 ResolvedIndyEntry::signature_index(ConstantPool* cp) const { + int nti = cp->uncached_name_and_type_ref_index_at(constant_pool_index()); + return cp->signature_ref_index_at(nti); +} + +u2 ResolvedIndyEntry::bsme_index(ConstantPool* cp) const { + return cp->bootstrap_methods_attribute_index(constant_pool_index()); +} + bool ResolvedIndyEntry::check_no_old_or_obsolete_entry() { // return false if m refers to a non-deleted old or obsolete method if (_method != nullptr) { @@ -39,11 +53,8 @@ bool ResolvedIndyEntry::check_no_old_or_obsolete_entry() { #if INCLUDE_CDS void ResolvedIndyEntry::remove_unshareable_info() { - u2 saved_resolved_references_index = _resolved_references_index; - u2 saved_cpool_index = _cpool_index; - memset(this, 0, sizeof(*this)); - _resolved_references_index = saved_resolved_references_index; - _cpool_index = saved_cpool_index; + _method = nullptr; // resolution sets this pointer; the rest is static + _flags &= ~(1 << resolution_failed_shift); } void ResolvedIndyEntry::mark_and_relocate() { diff --git a/src/hotspot/share/oops/resolvedIndyEntry.hpp b/src/hotspot/share/oops/resolvedIndyEntry.hpp index a7782c88f1ee0..bd3ddef18d0f4 100644 --- a/src/hotspot/share/oops/resolvedIndyEntry.hpp +++ b/src/hotspot/share/oops/resolvedIndyEntry.hpp @@ -46,7 +46,7 @@ class ResolvedIndyEntry { Method* _method; // Adapter method for indy call u2 _resolved_references_index; // Index of resolved references array that holds the appendix oop - u2 _cpool_index; // Constant pool index + u2 _cp_index; // Constant pool index u2 _number_of_parameters; // Number of arguments for adapter method u1 _return_type; // Adapter method return type u1 _flags; // Flags: [0000|00|has_appendix|resolution_failed] @@ -55,17 +55,17 @@ class ResolvedIndyEntry { ResolvedIndyEntry() : _method(nullptr), _resolved_references_index(0), - _cpool_index(0), + _cp_index(0), _number_of_parameters(0), _return_type(0), _flags(0) {} - ResolvedIndyEntry(u2 resolved_references_index, u2 cpool_index) : + ResolvedIndyEntry(int resolved_references_index, int cpool_index) : _method(nullptr), - _resolved_references_index(resolved_references_index), - _cpool_index(cpool_index), _number_of_parameters(0), _return_type(0), - _flags(0) {} + _flags(0) { + init(resolved_references_index, cpool_index); + } // Bit shift to get flags enum { @@ -76,7 +76,7 @@ class ResolvedIndyEntry { // Getters Method* method() const { return Atomic::load_acquire(&_method); } u2 resolved_references_index() const { return _resolved_references_index; } - u2 constant_pool_index() const { return _cpool_index; } + u2 constant_pool_index() const { return _cp_index; } u2 num_parameters() const { return _number_of_parameters; } u1 return_type() const { return _return_type; } bool is_resolved() const { return method() != nullptr; } @@ -90,11 +90,20 @@ class ResolvedIndyEntry { void print_on(outputStream* st) const; // Initialize with fields available before resolution - void init(u2 resolved_references_index, u2 cpool_index) { - _resolved_references_index = resolved_references_index; - _cpool_index = cpool_index; + void init(int resolved_references_index, int cpool_index) { + _resolved_references_index = checked_cast(resolved_references_index); + assert(cpool_index != 0, ""); + _cp_index = checked_cast(cpool_index); } + // Symbolic reference queries + u2 name_index(ConstantPool* cp) const; + u2 signature_index(ConstantPool* cp) const; + u2 bsme_index(ConstantPool* cp) const; + Symbol* name(ConstantPool* cp) const { return cp->symbol_at(name_index(cp)); } + Symbol* signature(ConstantPool* cp) const { return cp->symbol_at(signature_index(cp)); } + BSMAttributeEntry* bsme(ConstantPool* cp) const { return cp->bsm_attribute_entry(bsme_index(cp)); } + void set_num_parameters(int value) { assert(_number_of_parameters == 0 || _number_of_parameters == value, "size must not change: parameter_size=%d, value=%d", _number_of_parameters, value); @@ -104,9 +113,9 @@ class ResolvedIndyEntry { } // Populate structure with resolution information - void fill_in(Method* m, u2 num_params, u1 return_type, bool has_appendix) { - set_num_parameters(num_params); - _return_type = return_type; + void fill_in(Method* m, bool has_appendix) { + set_num_parameters(m->size_of_parameters()); + _return_type = as_TosState(m->result_type()); set_has_appendix(has_appendix); // Set the method last since it is read lock free. // Resolution is indicated by whether or not the method is set. diff --git a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp index 731db2e82f1de..f3637043cf952 100644 --- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp +++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp @@ -389,14 +389,17 @@ void JvmtiClassFileReconstituter::write_annotations_attribute(const char* attr_n // } bootstrap_methods[num_bootstrap_methods]; // } void JvmtiClassFileReconstituter::write_bootstrapmethod_attribute() { - Array* operands = cpool()->operands(); write_attribute_name_index("BootstrapMethods"); - int num_bootstrap_methods = ConstantPool::operand_array_length(operands); + + const Array* bsm_offs = cpool()->bsm_attribute_offsets(); + const Array* bsm_data = cpool()->bsm_attribute_entries(); + int num_bootstrap_methods = bsm_offs->length(); // calculate length of attribute u4 length = sizeof(u2); // num_bootstrap_methods for (int n = 0; n < num_bootstrap_methods; n++) { - u2 num_bootstrap_arguments = cpool()->operand_argument_count_at(n); + BSMAttributeEntry* bsme = cpool()->bsm_attribute_entry(n); + u2 num_bootstrap_arguments = bsme->argument_count(); length += sizeof(u2); // bootstrap_method_ref length += sizeof(u2); // num_bootstrap_arguments length += (u4)sizeof(u2) * num_bootstrap_arguments; // bootstrap_arguments[num_bootstrap_arguments] @@ -406,13 +409,12 @@ void JvmtiClassFileReconstituter::write_bootstrapmethod_attribute() { // write attribute write_u2(checked_cast(num_bootstrap_methods)); for (int n = 0; n < num_bootstrap_methods; n++) { - u2 bootstrap_method_ref = cpool()->operand_bootstrap_method_ref_index_at(n); - u2 num_bootstrap_arguments = cpool()->operand_argument_count_at(n); - write_u2(bootstrap_method_ref); + BSMAttributeEntry* bsme = cpool()->bsm_attribute_entry(n); + u2 num_bootstrap_arguments = bsme->argument_count(); + write_u2(bsme->bootstrap_method_index()); write_u2(num_bootstrap_arguments); for (int arg = 0; arg < num_bootstrap_arguments; arg++) { - u2 bootstrap_argument = cpool()->operand_argument_index_at(n, arg); - write_u2(bootstrap_argument); + write_u2(bsme->argument_index(arg)); } } } @@ -798,7 +800,7 @@ void JvmtiClassFileReconstituter::write_class_attributes() { if (type_anno != nullptr) { ++attr_count; // has RuntimeVisibleTypeAnnotations attribute } - if (cpool()->operands() != nullptr) { + if (cpool()->bsm_attribute_count() != 0) { ++attr_count; } if (ik()->nest_host_index() != 0) { @@ -843,7 +845,7 @@ void JvmtiClassFileReconstituter::write_class_attributes() { if (ik()->record_components() != nullptr) { write_record_attribute(); } - if (cpool()->operands() != nullptr) { + if (cpool()->bsm_attribute_count() != 0) { write_bootstrapmethod_attribute(); } if (inner_classes_length > 0) { diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index 33ae15fd80531..076a36884fea5 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -399,7 +399,7 @@ void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp, if (scratch_i != *merge_cp_length_p) { // The new entry in *merge_cp_p is at a different index than // the new entry in scratch_cp so we need to map the index values. - map_index(scratch_cp, scratch_i, *merge_cp_length_p); + map_cp_index(scratch_cp, scratch_i, *merge_cp_length_p); } (*merge_cp_length_p)++; } break; @@ -414,7 +414,7 @@ void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp, if (scratch_i != *merge_cp_length_p) { // The new entry in *merge_cp_p is at a different index than // the new entry in scratch_cp so we need to map the index values. - map_index(scratch_cp, scratch_i, *merge_cp_length_p); + map_cp_index(scratch_cp, scratch_i, *merge_cp_length_p); } (*merge_cp_length_p) += 2; } break; @@ -433,7 +433,7 @@ void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp, if (scratch_i != *merge_cp_length_p) { // The new entry in *merge_cp_p is at a different index than // the new entry in scratch_cp so we need to map the index values. - map_index(scratch_cp, scratch_i, *merge_cp_length_p); + map_cp_index(scratch_cp, scratch_i, *merge_cp_length_p); } (*merge_cp_length_p)++; } break; @@ -468,7 +468,7 @@ void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp, if (scratch_i != *merge_cp_length_p) { // The new entry in *merge_cp_p is at a different index than // the new entry in scratch_cp so we need to map the index values. - map_index(scratch_cp, scratch_i, *merge_cp_length_p); + map_cp_index(scratch_cp, scratch_i, *merge_cp_length_p); } (*merge_cp_length_p)++; } break; @@ -521,7 +521,7 @@ void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp, if (scratch_i != *merge_cp_length_p) { // The new entry in *merge_cp_p is at a different index than // the new entry in scratch_cp so we need to map the index values. - map_index(scratch_cp, scratch_i, *merge_cp_length_p); + map_cp_index(scratch_cp, scratch_i, *merge_cp_length_p); } (*merge_cp_length_p)++; } break; @@ -540,7 +540,7 @@ void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp, if (scratch_i != *merge_cp_length_p) { // The new entry in *merge_cp_p is at a different index than // the new entry in scratch_cp so we need to map the index values. - map_index(scratch_cp, scratch_i, *merge_cp_length_p); + map_cp_index(scratch_cp, scratch_i, *merge_cp_length_p); } (*merge_cp_length_p)++; } break; @@ -560,7 +560,7 @@ void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp, if (scratch_i != *merge_cp_length_p) { // The new entry in *merge_cp_p is at a different index than // the new entry in scratch_cp so we need to map the index values. - map_index(scratch_cp, scratch_i, *merge_cp_length_p); + map_cp_index(scratch_cp, scratch_i, *merge_cp_length_p); } (*merge_cp_length_p)++; } break; @@ -569,18 +569,18 @@ void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp, case JVM_CONSTANT_Dynamic: // fall through case JVM_CONSTANT_InvokeDynamic: { - // Index of the bootstrap specifier in the operands array - int old_bs_i = scratch_cp->bootstrap_methods_attribute_index(scratch_i); - int new_bs_i = find_or_append_operand(scratch_cp, old_bs_i, merge_cp_p, - merge_cp_length_p); + // Index of the bootstrap specifier in the BSM data arrays + int old_bsme_i = scratch_cp->bootstrap_methods_attribute_index(scratch_i); + int new_bsme_i = find_or_append_bsm_data(scratch_cp, old_bsme_i, merge_cp_p, + merge_cp_length_p); // The bootstrap method NameAndType_info index int old_ref_i = scratch_cp->bootstrap_name_and_type_ref_index_at(scratch_i); int new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p, merge_cp_length_p); - if (new_bs_i != old_bs_i) { + if (new_bsme_i != old_bsme_i) { log_trace(redefine, class, constantpool) - ("Dynamic entry@%d bootstrap_method_attr_index change: %d to %d", - *merge_cp_length_p, old_bs_i, new_bs_i); + ("Dynamic entry@%d BootstrapMethods entry change: %d to %d", + *merge_cp_length_p, old_bsme_i, new_bsme_i); } if (new_ref_i != old_ref_i) { log_trace(redefine, class, constantpool) @@ -588,13 +588,13 @@ void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp, } if (scratch_cp->tag_at(scratch_i).is_dynamic_constant()) - (*merge_cp_p)->dynamic_constant_at_put(*merge_cp_length_p, new_bs_i, new_ref_i); + (*merge_cp_p)->dynamic_constant_at_put(*merge_cp_length_p, new_bsme_i, new_ref_i); else - (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, new_bs_i, new_ref_i); + (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, new_bsme_i, new_ref_i); if (scratch_i != *merge_cp_length_p) { // The new entry in *merge_cp_p is at a different index than // the new entry in scratch_cp so we need to map the index values. - map_index(scratch_cp, scratch_i, *merge_cp_length_p); + map_cp_index(scratch_cp, scratch_i, *merge_cp_length_p); } (*merge_cp_length_p)++; } break; @@ -639,7 +639,7 @@ u2 VM_RedefineClasses::find_or_append_indirect_entry(const constantPoolHandle& s guarantee(found_i != ref_i, "compare_entry_to() and find_matching_entry() do not agree"); // Found a matching entry somewhere else in *merge_cp_p so just need a mapping entry. new_ref_i = found_i; - map_index(scratch_cp, ref_i, found_i); + map_cp_index(scratch_cp, ref_i, found_i); } else { // no match found so we have to append this entry to *merge_cp_p append_entry(scratch_cp, ref_i, merge_cp_p, merge_cp_length_p); @@ -656,101 +656,106 @@ u2 VM_RedefineClasses::find_or_append_indirect_entry(const constantPoolHandle& s } // end find_or_append_indirect_entry() -// Append a bootstrap specifier into the merge_cp operands that is semantically equal -// to the scratch_cp operands bootstrap specifier passed by the old_bs_i index. +// Append a BSM attribute entry into merge_cp that is semantically equal +// to the scratch_cp BSM entry passed by the old_bsme_i index. // Recursively append new merge_cp entries referenced by the new bootstrap specifier. -void VM_RedefineClasses::append_operand(const constantPoolHandle& scratch_cp, int old_bs_i, +void VM_RedefineClasses::append_bsm_data(const constantPoolHandle& scratch_cp, int old_bsme_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p) { - u2 old_ref_i = scratch_cp->operand_bootstrap_method_ref_index_at(old_bs_i); + const auto old_bsme = scratch_cp->bsm_attribute_entry(old_bsme_i); + u2 old_ref_i = old_bsme->bootstrap_method_index(); u2 new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p, merge_cp_length_p); if (new_ref_i != old_ref_i) { log_trace(redefine, class, constantpool) - ("operands entry@%d bootstrap method ref_index change: %d to %d", _operands_cur_length, old_ref_i, new_ref_i); + ("bsm_data entry@%d bootstrap method ref_index change: %d to %d", _bsm_data_cur_length, old_ref_i, new_ref_i); } - Array* merge_ops = (*merge_cp_p)->operands(); - int new_bs_i = _operands_cur_length; - // We have _operands_cur_length == 0 when the merge_cp operands is empty yet. - // However, the operand_offset_at(0) was set in the extend_operands() call. - int new_base = (new_bs_i == 0) ? (*merge_cp_p)->operand_offset_at(0) - : (*merge_cp_p)->operand_next_offset_at(new_bs_i - 1); - u2 argc = scratch_cp->operand_argument_count_at(old_bs_i); + const auto merge_offs = (*merge_cp_p)->bsm_attribute_offsets(); + const auto merge_data = (*merge_cp_p)->bsm_attribute_entries(); + + int new_bsme_i = _bsm_data_cur_length; + int new_base = _bsm_data_next_offset; + u2 argc = old_bsme->argument_count(); - ConstantPool::operand_offset_at_put(merge_ops, _operands_cur_length, new_base); - merge_ops->at_put(new_base++, new_ref_i); - merge_ops->at_put(new_base++, argc); + merge_offs->at_put(new_bsme_i, new_base); + merge_data->at_put(new_base++, new_ref_i); + merge_data->at_put(new_base++, argc); for (int i = 0; i < argc; i++) { - u2 old_arg_ref_i = scratch_cp->operand_argument_index_at(old_bs_i, i); + u2 old_arg_ref_i = old_bsme->argument_index(i); u2 new_arg_ref_i = find_or_append_indirect_entry(scratch_cp, old_arg_ref_i, merge_cp_p, merge_cp_length_p); - merge_ops->at_put(new_base++, new_arg_ref_i); + merge_data->at_put(new_base++, new_arg_ref_i); if (new_arg_ref_i != old_arg_ref_i) { log_trace(redefine, class, constantpool) - ("operands entry@%d bootstrap method argument ref_index change: %d to %d", - _operands_cur_length, old_arg_ref_i, new_arg_ref_i); + ("bsm_data entry@%d bootstrap method argument ref_index change: %d to %d", + _bsm_data_cur_length, old_arg_ref_i, new_arg_ref_i); } } - if (old_bs_i != _operands_cur_length) { + if (old_bsme_i != _bsm_data_cur_length) { // The bootstrap specifier in *merge_cp_p is at a different index than // that in scratch_cp so we need to map the index values. - map_operand_index(old_bs_i, new_bs_i); + map_bsm_index(old_bsme_i, new_bsme_i); } - _operands_cur_length++; -} // end append_operand() + _bsm_data_cur_length = new_bsme_i + 1; + _bsm_data_next_offset = new_base; +} // end append_bsm_data() -int VM_RedefineClasses::find_or_append_operand(const constantPoolHandle& scratch_cp, - int old_bs_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p) { +// Try to Find a BSM attribute entry in merge_cp that is semantically equal +// to the scratch_cp BSM entry passed by the old_bsme_i index. +// If none is found, call append_bsm_data to add one into merge_cp. +int VM_RedefineClasses::find_or_append_bsm_data(const constantPoolHandle& scratch_cp, + int old_bsme_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p) { - int new_bs_i = old_bs_i; // bootstrap specifier index - bool match = (old_bs_i < _operands_cur_length) && - scratch_cp->compare_operand_to(old_bs_i, *merge_cp_p, old_bs_i); + int new_bsme_i = old_bsme_i; // bootstrap specifier index + bool match = (old_bsme_i < _bsm_data_cur_length) && + scratch_cp->compare_bsme_to(old_bsme_i, *merge_cp_p, old_bsme_i); if (!match) { // forward reference in *merge_cp_p or not a direct match - int found_i = scratch_cp->find_matching_operand(old_bs_i, *merge_cp_p, - _operands_cur_length); + int found_i = scratch_cp->find_matching_bsme(old_bsme_i, *merge_cp_p, + _bsm_data_cur_length); if (found_i != -1) { - guarantee(found_i != old_bs_i, "compare_operand_to() and find_matching_operand() disagree"); - // found a matching operand somewhere else in *merge_cp_p so just need a mapping - new_bs_i = found_i; - map_operand_index(old_bs_i, found_i); + guarantee(found_i != old_bsme_i, "compare_bsme_to() and find_matching_bsme() disagree"); + // found a matching bsme somewhere else in *merge_cp_p so just need a mapping + new_bsme_i = found_i; + map_bsm_index(old_bsme_i, found_i); } else { // no match found so we have to append this bootstrap specifier to *merge_cp_p - append_operand(scratch_cp, old_bs_i, merge_cp_p, merge_cp_length_p); - new_bs_i = _operands_cur_length - 1; + append_bsm_data(scratch_cp, old_bsme_i, merge_cp_p, merge_cp_length_p); + new_bsme_i = _bsm_data_cur_length - 1; } } - return new_bs_i; -} // end find_or_append_operand() + return new_bsme_i; +} // end find_or_append_bsm_data() -void VM_RedefineClasses::finalize_operands_merge(const constantPoolHandle& merge_cp, TRAPS) { - if (merge_cp->operands() == nullptr) { +void VM_RedefineClasses::finalize_bsm_data_merge(const constantPoolHandle& merge_cp, TRAPS) { + if (merge_cp->bsm_attribute_count() == 0) { return; } - // Shrink the merge_cp operands - merge_cp->shrink_operands(_operands_cur_length, CHECK); + // Shrink the merge_cp bsm_data + merge_cp->shrink_bsm_data(_bsm_data_cur_length, CHECK); if (log_is_enabled(Trace, redefine, class, constantpool)) { // don't want to loop unless we are tracing int count = 0; - for (int i = 1; i < _operands_index_map_p->length(); i++) { - int value = _operands_index_map_p->at(i); + for (int i = 1; i < _bsm_data_index_map_p->length(); i++) { + int value = _bsm_data_index_map_p->at(i); if (value != -1) { - log_trace(redefine, class, constantpool)("operands_index_map[%d]: old=%d new=%d", count, i, value); + log_trace(redefine, class, constantpool)("bsm_data_index_map[%d]: old=%d new=%d", count, i, value); count++; } } } // Clean-up - _operands_index_map_p = nullptr; - _operands_cur_length = 0; - _operands_index_map_count = 0; -} // end finalize_operands_merge() + _bsm_data_index_map_p = nullptr; + _bsm_data_cur_length = 0; + _bsm_data_next_offset = 0; + _bsm_data_index_map_count = 0; +} // end finalize_bsm_data_merge() // Symbol* comparator for qsort // The caller must have an active ResourceMark. @@ -1240,7 +1245,7 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( // Find new constant pool index value for old constant pool index value // by searching the index map. Returns zero (0) if there is no mapped // value for the old constant pool index. -u2 VM_RedefineClasses::find_new_index(int old_index) { +u2 VM_RedefineClasses::find_new_cp_index(int old_index) { if (_index_map_count == 0) { // map is empty so nothing can be found return 0; @@ -1262,32 +1267,32 @@ u2 VM_RedefineClasses::find_new_index(int old_index) { // constant pool indices are u2, unless the merged constant pool overflows which // we don't check for. return checked_cast(value); -} // end find_new_index() +} // end find_new_cp_index() // Find new bootstrap specifier index value for old bootstrap specifier index // value by searching the index map. Returns unused index (-1) if there is // no mapped value for the old bootstrap specifier index. -int VM_RedefineClasses::find_new_operand_index(int old_index) { - if (_operands_index_map_count == 0) { +int VM_RedefineClasses::find_new_bsm_index(int old_index) { + if (_bsm_data_index_map_count == 0) { // map is empty so nothing can be found return -1; } - if (old_index == -1 || old_index >= _operands_index_map_p->length()) { + if (old_index == -1 || old_index >= _bsm_data_index_map_p->length()) { // The old_index is out of range so it is not mapped. // This should not happen in regular constant pool merging use. return -1; } - int value = _operands_index_map_p->at(old_index); + int value = _bsm_data_index_map_p->at(old_index); if (value == -1) { // the old_index is not mapped return -1; } return value; -} // end find_new_operand_index() +} // end find_new_bsm_index() // The bug 6214132 caused the verification to fail. @@ -1532,9 +1537,9 @@ jvmtiError VM_RedefineClasses::load_new_class_versions() { // Map old_index to new_index as needed. scratch_cp is only needed // for log calls. -void VM_RedefineClasses::map_index(const constantPoolHandle& scratch_cp, +void VM_RedefineClasses::map_cp_index(const constantPoolHandle& scratch_cp, int old_index, int new_index) { - if (find_new_index(old_index) != 0) { + if (find_new_cp_index(old_index) != 0) { // old_index is already mapped return; } @@ -1549,12 +1554,12 @@ void VM_RedefineClasses::map_index(const constantPoolHandle& scratch_cp, log_trace(redefine, class, constantpool) ("mapped tag %d at index %d to %d", scratch_cp->tag_at(old_index).value(), old_index, new_index); -} // end map_index() +} // end map_cp_index() // Map old_index to new_index as needed. -void VM_RedefineClasses::map_operand_index(int old_index, int new_index) { - if (find_new_operand_index(old_index) != -1) { +void VM_RedefineClasses::map_bsm_index(int old_index, int new_index) { + if (find_new_bsm_index(old_index) != -1) { // old_index is already mapped return; } @@ -1564,28 +1569,28 @@ void VM_RedefineClasses::map_operand_index(int old_index, int new_index) { return; } - _operands_index_map_p->at_put(old_index, new_index); - _operands_index_map_count++; + _bsm_data_index_map_p->at_put(old_index, new_index); + _bsm_data_index_map_count++; log_trace(redefine, class, constantpool)("mapped bootstrap specifier at index %d to %d", old_index, new_index); -} // end map_index() +} // end map_bsm_index() // Merge old_cp and scratch_cp and return the results of the merge via -// merge_cp_p. The number of entries in merge_cp_p is returned via -// merge_cp_length_p. The entries in old_cp occupy the same locations -// in merge_cp_p. Also creates a map of indices from entries in -// scratch_cp to the corresponding entry in merge_cp_p. Index map +// merge_cp. The number of entries in merge_cp_p is returned via +// merge_cp_length. The entries in old_cp occupy the same locations +// in merge_cp. Also creates a map of indices from entries in +// scratch_cp to the corresponding entry in merge_cp. Index map // entries are only created for entries in scratch_cp that occupy a -// different location in merged_cp_p. +// different location in merged_cp. bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp, - const constantPoolHandle& scratch_cp, constantPoolHandle& merge_cp_p, - int& merge_cp_length_p, TRAPS) { + const constantPoolHandle& scratch_cp, constantPoolHandle& merge_cp, + int& merge_cp_length, TRAPS) { // Worst case we need old_cp->length() + scratch_cp()->length(), // but the caller might be smart so make sure we have at least // the minimum. - if (merge_cp_p->length() < old_cp->length()) { + if (merge_cp->length() < old_cp->length()) { assert(false, "merge area too small"); return false; // robustness } @@ -1594,9 +1599,9 @@ bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp, { // Pass 0: - // The old_cp is copied to *merge_cp_p; this means that any code + // The old_cp is copied to merge_cp; this means that any code // using old_cp does not have to change. This work looks like a - // perfect fit for ConstantPool*::copy_cp_to(), but we need to + // perfect fit for ConstantPool::copy_cp_to(), but we need to // handle one special case: // - revert JVM_CONSTANT_Class to JVM_CONSTANT_UnresolvedClass // This will make verification happy. @@ -1613,7 +1618,7 @@ bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp, // revert the copy to JVM_CONSTANT_UnresolvedClass // May be resolving while calling this so do the same for // JVM_CONSTANT_UnresolvedClass (klass_name_at() deals with transition) - merge_cp_p->temp_unresolved_klass_at_put(old_i, + merge_cp->temp_unresolved_klass_at_put(old_i, old_cp->klass_name_index_at(old_i)); break; @@ -1621,28 +1626,28 @@ bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp, case JVM_CONSTANT_Long: // just copy the entry to merge_cp_p, but double and long take // two constant pool entries - ConstantPool::copy_entry_to(old_cp, old_i, merge_cp_p, old_i); + ConstantPool::copy_entry_to(old_cp, old_i, merge_cp, old_i); old_i++; break; default: // just copy the entry to merge_cp_p - ConstantPool::copy_entry_to(old_cp, old_i, merge_cp_p, old_i); + ConstantPool::copy_entry_to(old_cp, old_i, merge_cp, old_i); break; } } // end for each old_cp entry - ConstantPool::copy_operands(old_cp, merge_cp_p, CHECK_false); - merge_cp_p->extend_operands(scratch_cp, CHECK_false); + ConstantPool::copy_bsm_data(old_cp, merge_cp, CHECK_false); + merge_cp->extend_bsm_data(scratch_cp, CHECK_false); - // We don't need to sanity check that *merge_cp_length_p is within - // *merge_cp_p bounds since we have the minimum on-entry check above. - merge_cp_length_p = old_i; + // We don't need to sanity check that merge_cp_length is within + // merge_cp bounds since we have the minimum on-entry check above. + merge_cp_length = old_i; } // merge_cp_len should be the same as old_cp->length() at this point // so this trace message is really a "warm-and-breathing" message. - log_debug(redefine, class, constantpool)("after pass 0: merge_cp_len=%d", merge_cp_length_p); + log_debug(redefine, class, constantpool)("after pass 0: merge_cp_len=%d", merge_cp_length); int scratch_i; // index into scratch_cp { @@ -1666,32 +1671,32 @@ bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp, break; } - bool match = scratch_cp->compare_entry_to(scratch_i, merge_cp_p, scratch_i); + bool match = scratch_cp->compare_entry_to(scratch_i, merge_cp, scratch_i); if (match) { // found a match at the same index so nothing more to do continue; } - int found_i = scratch_cp->find_matching_entry(scratch_i, merge_cp_p); + int found_i = scratch_cp->find_matching_entry(scratch_i, merge_cp); if (found_i != 0) { guarantee(found_i != scratch_i, "compare_entry_to() and find_matching_entry() do not agree"); // Found a matching entry somewhere else in *merge_cp_p so // just need a mapping entry. - map_index(scratch_cp, scratch_i, found_i); + map_cp_index(scratch_cp, scratch_i, found_i); continue; } // No match found so we have to append this entry and any unique // referenced entries to merge_cp_p. - append_entry(scratch_cp, scratch_i, &merge_cp_p, &merge_cp_length_p); + append_entry(scratch_cp, scratch_i, &merge_cp, &merge_cp_length); } } log_debug(redefine, class, constantpool) ("after pass 1a: merge_cp_len=%d, scratch_i=%d, index_map_len=%d", - merge_cp_length_p, scratch_i, _index_map_count); + merge_cp_length, scratch_i, _index_map_count); if (scratch_i < scratch_cp->length()) { // Pass 1b: @@ -1713,24 +1718,24 @@ bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp, } int found_i = - scratch_cp->find_matching_entry(scratch_i, merge_cp_p); + scratch_cp->find_matching_entry(scratch_i, merge_cp); if (found_i != 0) { // Found a matching entry somewhere else in merge_cp_p so // just need a mapping entry. - map_index(scratch_cp, scratch_i, found_i); + map_cp_index(scratch_cp, scratch_i, found_i); continue; } // No match found so we have to append this entry and any unique // referenced entries to merge_cp_p. - append_entry(scratch_cp, scratch_i, &merge_cp_p, &merge_cp_length_p); + append_entry(scratch_cp, scratch_i, &merge_cp, &merge_cp_length); } log_debug(redefine, class, constantpool) ("after pass 1b: merge_cp_len=%d, scratch_i=%d, index_map_len=%d", - merge_cp_length_p, scratch_i, _index_map_count); + merge_cp_length, scratch_i, _index_map_count); } - finalize_operands_merge(merge_cp_p, CHECK_false); + finalize_bsm_data_merge(merge_cp, CHECK_false); return true; } // end merge_constant_pools() @@ -1800,15 +1805,16 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( _index_map_count = 0; _index_map_p = new intArray(scratch_cp->length(), scratch_cp->length(), -1); - _operands_cur_length = ConstantPool::operand_array_length(old_cp->operands()); - _operands_index_map_count = 0; - int operands_index_map_len = ConstantPool::operand_array_length(scratch_cp->operands()); - _operands_index_map_p = new intArray(operands_index_map_len, operands_index_map_len, -1); + _bsm_data_cur_length = old_cp->bsm_attribute_count(); + _bsm_data_next_offset = old_cp->bsm_entry_count(); + _bsm_data_index_map_count = 0; + int bsm_data_index_map_len = scratch_cp->bsm_attribute_count(); + _bsm_data_index_map_p = new intArray(bsm_data_index_map_len, bsm_data_index_map_len, -1); - // reference to the cp holder is needed for copy_operands() + // reference to the cp holder is needed for copy_bsm_data() merge_cp->set_pool_holder(scratch_class); bool result = merge_constant_pools(old_cp, scratch_cp, merge_cp, - merge_cp_length, THREAD); + merge_cp_length, THREAD); merge_cp->set_pool_holder(nullptr); if (!result) { @@ -1990,7 +1996,7 @@ bool VM_RedefineClasses::rewrite_cp_refs(InstanceKlass* scratch_class) { // rewrite source file name index: u2 source_file_name_idx = scratch_class->source_file_name_index(); if (source_file_name_idx != 0) { - u2 new_source_file_name_idx = find_new_index(source_file_name_idx); + u2 new_source_file_name_idx = find_new_cp_index(source_file_name_idx); if (new_source_file_name_idx != 0) { scratch_class->set_source_file_name_index(new_source_file_name_idx); } @@ -1999,7 +2005,7 @@ bool VM_RedefineClasses::rewrite_cp_refs(InstanceKlass* scratch_class) { // rewrite class generic signature index: u2 generic_signature_index = scratch_class->generic_signature_index(); if (generic_signature_index != 0) { - u2 new_generic_signature_index = find_new_index(generic_signature_index); + u2 new_generic_signature_index = find_new_cp_index(generic_signature_index); if (new_generic_signature_index != 0) { scratch_class->set_generic_signature_index(new_generic_signature_index); } @@ -2014,12 +2020,12 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_nest_attributes( u2 cp_index = scratch_class->nest_host_index(); if (cp_index != 0) { - scratch_class->set_nest_host_index(find_new_index(cp_index)); + scratch_class->set_nest_host_index(find_new_cp_index(cp_index)); } Array* nest_members = scratch_class->nest_members(); for (int i = 0; i < nest_members->length(); i++) { u2 cp_index = nest_members->at(i); - nest_members->at_put(i, find_new_index(cp_index)); + nest_members->at_put(i, find_new_cp_index(cp_index)); } return true; } @@ -2031,12 +2037,12 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_record_attribute(InstanceKlass* scra for (int i = 0; i < components->length(); i++) { RecordComponent* component = components->at(i); u2 cp_index = component->name_index(); - component->set_name_index(find_new_index(cp_index)); + component->set_name_index(find_new_cp_index(cp_index)); cp_index = component->descriptor_index(); - component->set_descriptor_index(find_new_index(cp_index)); + component->set_descriptor_index(find_new_cp_index(cp_index)); cp_index = component->generic_signature_index(); if (cp_index != 0) { - component->set_generic_signature_index(find_new_index(cp_index)); + component->set_generic_signature_index(find_new_cp_index(cp_index)); } AnnotationArray* annotations = component->annotations(); @@ -2071,7 +2077,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_permitted_subclasses_attribute( assert(permitted_subclasses != nullptr, "unexpected null permitted_subclasses"); for (int i = 0; i < permitted_subclasses->length(); i++) { u2 cp_index = permitted_subclasses->at(i); - permitted_subclasses->at_put(i, find_new_index(cp_index)); + permitted_subclasses->at_put(i, find_new_cp_index(cp_index)); } return true; } @@ -2150,7 +2156,7 @@ void VM_RedefineClasses::rewrite_cp_refs_in_method(methodHandle method, case Bytecodes::_ldc: { u1 cp_index = *(bcp + 1); - u2 new_index = find_new_index(cp_index); + u2 new_index = find_new_cp_index(cp_index); if (StressLdcRewrite && new_index == 0) { // If we are stressing ldc -> ldc_w rewriting, then we @@ -2224,7 +2230,7 @@ void VM_RedefineClasses::rewrite_cp_refs_in_method(methodHandle method, { address p = bcp + 1; int cp_index = Bytes::get_Java_u2(p); - u2 new_index = find_new_index(cp_index); + u2 new_index = find_new_cp_index(cp_index); if (new_index != 0) { // the original index is mapped so update w/ new value log_trace(redefine, class, constantpool) @@ -2370,7 +2376,7 @@ u2 VM_RedefineClasses::rewrite_cp_ref_in_annotation_data( address cp_index_addr = (address) annotations_typeArray->adr_at(byte_i_ref); u2 old_cp_index = Bytes::get_Java_u2(cp_index_addr); - u2 new_cp_index = find_new_index(old_cp_index); + u2 new_cp_index = find_new_cp_index(old_cp_index); if (new_cp_index != 0) { log_debug(redefine, class, annotation)("mapped old %s=%d", trace_mesg, old_cp_index); Bytes::put_Java_u2(cp_index_addr, new_cp_index); @@ -3439,7 +3445,7 @@ void VM_RedefineClasses::rewrite_cp_refs_in_verification_type_info( { assert(stackmap_p_ref + 2 <= stackmap_end, "no room for cpool_index"); u2 cpool_index = Bytes::get_Java_u2(stackmap_p_ref); - u2 new_cp_index = find_new_index(cpool_index); + u2 new_cp_index = find_new_cp_index(cpool_index); if (new_cp_index != 0) { log_debug(redefine, class, stackmap)("mapped old cpool_index=%d", cpool_index); Bytes::put_Java_u2(stackmap_p_ref, new_cp_index); @@ -3489,7 +3495,7 @@ void VM_RedefineClasses::set_new_constant_pool( smaller_cp->set_version(version); // attach klass to new constant pool - // reference to the cp holder is needed for copy_operands() + // reference to the cp holder is needed for copy_bsm_data() smaller_cp->set_pool_holder(scratch_class); smaller_cp->copy_fields(scratch_cp()); @@ -3516,28 +3522,28 @@ void VM_RedefineClasses::set_new_constant_pool( for (int i = 0; i < java_fields; i++) { FieldInfo* fi = fields->adr_at(i); jshort cur_index = fi->name_index(); - jshort new_index = find_new_index(cur_index); + jshort new_index = find_new_cp_index(cur_index); if (new_index != 0) { log_trace(redefine, class, constantpool)("field-name_index change: %d to %d", cur_index, new_index); fi->set_name_index(new_index); update_required = true; } cur_index = fi->signature_index(); - new_index = find_new_index(cur_index); + new_index = find_new_cp_index(cur_index); if (new_index != 0) { log_trace(redefine, class, constantpool)("field-signature_index change: %d to %d", cur_index, new_index); fi->set_signature_index(new_index); update_required = true; } cur_index = fi->initializer_index(); - new_index = find_new_index(cur_index); + new_index = find_new_cp_index(cur_index); if (new_index != 0) { log_trace(redefine, class, constantpool)("field-initval_index change: %d to %d", cur_index, new_index); fi->set_initializer_index(new_index); update_required = true; } cur_index = fi->generic_signature_index(); - new_index = find_new_index(cur_index); + new_index = find_new_cp_index(cur_index); if (new_index != 0) { log_trace(redefine, class, constantpool)("field-generic_signature change: %d to %d", cur_index, new_index); fi->set_generic_signature_index(new_index); @@ -3562,19 +3568,19 @@ void VM_RedefineClasses::set_new_constant_pool( if (cur_index == 0) { continue; // JVM spec. allows null inner class refs so skip it } - u2 new_index = find_new_index(cur_index); + u2 new_index = find_new_cp_index(cur_index); if (new_index != 0) { log_trace(redefine, class, constantpool)("inner_class_info change: %d to %d", cur_index, new_index); iter.set_inner_class_info_index(new_index); } cur_index = iter.outer_class_info_index(); - new_index = find_new_index(cur_index); + new_index = find_new_cp_index(cur_index); if (new_index != 0) { log_trace(redefine, class, constantpool)("outer_class_info change: %d to %d", cur_index, new_index); iter.set_outer_class_info_index(new_index); } cur_index = iter.inner_name_index(); - new_index = find_new_index(cur_index); + new_index = find_new_cp_index(cur_index); if (new_index != 0) { log_trace(redefine, class, constantpool)("inner_name change: %d to %d", cur_index, new_index); iter.set_inner_name_index(new_index); @@ -3588,19 +3594,19 @@ void VM_RedefineClasses::set_new_constant_pool( methodHandle method(THREAD, methods->at(i)); method->set_constants(scratch_cp()); - u2 new_index = find_new_index(method->name_index()); + u2 new_index = find_new_cp_index(method->name_index()); if (new_index != 0) { log_trace(redefine, class, constantpool) ("method-name_index change: %d to %d", method->name_index(), new_index); method->set_name_index(new_index); } - new_index = find_new_index(method->signature_index()); + new_index = find_new_cp_index(method->signature_index()); if (new_index != 0) { log_trace(redefine, class, constantpool) ("method-signature_index change: %d to %d", method->signature_index(), new_index); method->set_signature_index(new_index); } - new_index = find_new_index(method->generic_signature_index()); + new_index = find_new_cp_index(method->generic_signature_index()); if (new_index != 0) { log_trace(redefine, class, constantpool) ("method-generic_signature_index change: %d to %d", method->generic_signature_index(), new_index); @@ -3615,7 +3621,7 @@ void VM_RedefineClasses::set_new_constant_pool( method->checked_exceptions_start(); for (int j = 0; j < cext_length; j++) { int cur_index = cext_table[j].class_cp_index; - int new_index = find_new_index(cur_index); + int new_index = find_new_cp_index(cur_index); if (new_index != 0) { log_trace(redefine, class, constantpool)("cext-class_cp_index change: %d to %d", cur_index, new_index); cext_table[j].class_cp_index = (u2)new_index; @@ -3633,7 +3639,7 @@ void VM_RedefineClasses::set_new_constant_pool( for (int j = 0; j < ext_length; j ++) { int cur_index = ex_table.catch_type_index(j); - u2 new_index = find_new_index(cur_index); + u2 new_index = find_new_cp_index(cur_index); if (new_index != 0) { log_trace(redefine, class, constantpool)("ext-klass_index change: %d to %d", cur_index, new_index); ex_table.set_catch_type_index(j, new_index); @@ -3650,19 +3656,19 @@ void VM_RedefineClasses::set_new_constant_pool( method->localvariable_table_start(); for (int j = 0; j < lvt_length; j++) { int cur_index = lv_table[j].name_cp_index; - int new_index = find_new_index(cur_index); + int new_index = find_new_cp_index(cur_index); if (new_index != 0) { log_trace(redefine, class, constantpool)("lvt-name_cp_index change: %d to %d", cur_index, new_index); lv_table[j].name_cp_index = (u2)new_index; } cur_index = lv_table[j].descriptor_cp_index; - new_index = find_new_index(cur_index); + new_index = find_new_cp_index(cur_index); if (new_index != 0) { log_trace(redefine, class, constantpool)("lvt-descriptor_cp_index change: %d to %d", cur_index, new_index); lv_table[j].descriptor_cp_index = (u2)new_index; } cur_index = lv_table[j].signature_cp_index; - new_index = find_new_index(cur_index); + new_index = find_new_cp_index(cur_index); if (new_index != 0) { log_trace(redefine, class, constantpool)("lvt-signature_cp_index change: %d to %d", cur_index, new_index); lv_table[j].signature_cp_index = (u2)new_index; @@ -3676,7 +3682,7 @@ void VM_RedefineClasses::set_new_constant_pool( MethodParametersElement* elem = method->method_parameters_start(); for (int j = 0; j < mp_length; j++) { const int cp_index = elem[j].name_cp_index; - const int new_cp_index = find_new_index(cp_index); + const int new_cp_index = find_new_cp_index(cp_index); if (new_cp_index != 0) { elem[j].name_cp_index = (u2)new_cp_index; } diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiRedefineClasses.hpp index d2eda1f3eede4..4eb1a69877f4e 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.hpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.hpp @@ -363,11 +363,12 @@ class VM_RedefineClasses: public VM_Operation { int _index_map_count; intArray * _index_map_p; - // _operands_index_map_count is just an optimization for knowing if - // _operands_index_map_p contains any entries. - int _operands_cur_length; - int _operands_index_map_count; - intArray * _operands_index_map_p; + // _bsm_data_index_map_count is just an optimization for knowing if + // _bsm_data_index_map_p contains any entries. + int _bsm_data_cur_length; // bsm_attribute_offsets fillp + int _bsm_data_next_offset; // bsm_attribute_entries fillp + int _bsm_data_index_map_count; + intArray* _bsm_data_index_map_p; // ptr to _class_count scratch_classes InstanceKlass** _scratch_classes; @@ -429,17 +430,17 @@ class VM_RedefineClasses: public VM_Operation { // Support for constant pool merging (these routines are in alpha order): void append_entry(const constantPoolHandle& scratch_cp, int scratch_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p); - void append_operand(const constantPoolHandle& scratch_cp, int scratch_bootstrap_spec_index, + void append_bsm_data(const constantPoolHandle& scratch_cp, int scratch_bsm_attr_entry_index, constantPoolHandle *merge_cp_p, int *merge_cp_length_p); - void finalize_operands_merge(const constantPoolHandle& merge_cp, TRAPS); + void finalize_bsm_data_merge(const constantPoolHandle& merge_cp, TRAPS); u2 find_or_append_indirect_entry(const constantPoolHandle& scratch_cp, int scratch_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p); - int find_or_append_operand(const constantPoolHandle& scratch_cp, int scratch_bootstrap_spec_index, + int find_or_append_bsm_data(const constantPoolHandle& scratch_cp, int scratch_bsm_attr_entry_index, constantPoolHandle *merge_cp_p, int *merge_cp_length_p); - u2 find_new_index(int old_index); - int find_new_operand_index(int old_bootstrap_spec_index); - void map_index(const constantPoolHandle& scratch_cp, int old_index, int new_index); - void map_operand_index(int old_bootstrap_spec_index, int new_bootstrap_spec_index); + u2 find_new_cp_index(int old_cp_index); + int find_new_bsm_index(int old_bsme_index); + void map_cp_index(const constantPoolHandle& scratch_cp, int old_index, int new_index); + void map_bsm_index(int old_bsme_index, int new_bsme_index); bool merge_constant_pools(const constantPoolHandle& old_cp, const constantPoolHandle& scratch_cp, constantPoolHandle& merge_cp_p, int& merge_cp_length_p, TRAPS); diff --git a/src/hotspot/share/prims/methodComparator.cpp b/src/hotspot/share/prims/methodComparator.cpp index 9f7740802a438..c54d31b03446a 100644 --- a/src/hotspot/share/prims/methodComparator.cpp +++ b/src/hotspot/share/prims/methodComparator.cpp @@ -133,17 +133,19 @@ bool MethodComparator::args_same(Bytecodes::Code const c_old, Bytecodes::Code c (old_cp->uncached_signature_ref_at(cpi_old) != new_cp->uncached_signature_ref_at(cpi_new))) return false; - int bsm_old = old_cp->bootstrap_method_ref_index_at(cpi_old); - int bsm_new = new_cp->bootstrap_method_ref_index_at(cpi_new); + BSMAttributeEntry* bsme_old = old_cp->bootstrap_methods_attribute_entry(cpi_old); + BSMAttributeEntry* bsme_new = new_cp->bootstrap_methods_attribute_entry(cpi_new); + int bsm_old = bsme_old->bootstrap_method_index(); + int bsm_new = bsme_new->bootstrap_method_index(); if (!pool_constants_same(bsm_old, bsm_new, old_cp, new_cp)) return false; - int cnt_old = old_cp->bootstrap_argument_count_at(cpi_old); - int cnt_new = new_cp->bootstrap_argument_count_at(cpi_new); + int cnt_old = bsme_old->argument_count(); + int cnt_new = bsme_new->argument_count(); if (cnt_old != cnt_new) return false; for (int arg_i = 0; arg_i < cnt_old; arg_i++) { - int idx_old = old_cp->bootstrap_argument_index_at(cpi_old, arg_i); - int idx_new = new_cp->bootstrap_argument_index_at(cpi_new, arg_i); + int idx_old = bsme_old->argument_index(arg_i); + int idx_new = bsme_new->argument_index(arg_i); if (!pool_constants_same(idx_old, idx_new, old_cp, new_cp)) return false; } diff --git a/src/hotspot/share/prims/methodHandles.cpp b/src/hotspot/share/prims/methodHandles.cpp index 1ab5d6ab7f7ba..69fa3c59d15b4 100644 --- a/src/hotspot/share/prims/methodHandles.cpp +++ b/src/hotspot/share/prims/methodHandles.cpp @@ -40,10 +40,12 @@ #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" +#include "oops/constantPool.inline.hpp" #include "oops/klass.inline.hpp" #include "oops/objArrayKlass.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" +#include "oops/resolvedIndyEntry.hpp" #include "oops/typeArrayOop.inline.hpp" #include "prims/methodHandles.hpp" #include "runtime/deoptimization.hpp" @@ -1248,12 +1250,17 @@ JVM_ENTRY(void, MHN_copyOutBootstrapArguments(JNIEnv* env, jobject igcls, THROW_MSG(vmSymbols::java_lang_InternalError(), "bad index info (0)"); } typeArrayHandle index_info(THREAD, index_info_oop); - int bss_index_in_pool = index_info->int_at(1); + int bss_index_in_pool = index_info->length() <= 1 ? -1 : index_info->int_at(1); // While we are here, take a quick look at the index info: - if (bss_index_in_pool <= 0 || - bss_index_in_pool >= caller->constants()->length() || - index_info->int_at(0) - != caller->constants()->bootstrap_argument_count_at(bss_index_in_pool)) { + int bsme_index = -1; + // FIXME: use a BootstrapInfo record to simplify this logic + if (0 < bss_index_in_pool && + bss_index_in_pool < caller->constants()->length() && + caller->constants()->tag_at(bss_index_in_pool).has_bootstrap()) { + bsme_index = caller->constants()->bootstrap_methods_attribute_index(bss_index_in_pool); + } + if (bsme_index < 0 || (caller->constants()->bsm_attribute_entry(bsme_index)->argument_count() + != index_info->int_at(0))) { THROW_MSG(vmSymbols::java_lang_InternalError(), "bad index info (1)"); } objArrayHandle buf(THREAD, (objArrayOop) JNIHandles::resolve(buf_jh)); @@ -1265,12 +1272,15 @@ JVM_ENTRY(void, MHN_copyOutBootstrapArguments(JNIEnv* env, jobject igcls, switch (pseudo_index) { case -4: // bootstrap method { - int bsm_index = caller->constants()->bootstrap_method_ref_index_at(bss_index_in_pool); + // re-derive the bsme at each point + BSMAttributeEntry* bsme = caller->constants()->bsm_attribute_entry(bsme_index); + int bsm_index = bsme->bootstrap_method_index(); pseudo_arg = caller->constants()->resolve_possibly_cached_constant_at(bsm_index, CHECK); break; } case -3: // name { + assert(bss_index_in_pool > 0, ""); Symbol* name = caller->constants()->name_ref_at(bss_index_in_pool, Bytecodes::_invokedynamic); Handle str = java_lang_String::create_from_symbol(name, CHECK); pseudo_arg = str(); @@ -1278,6 +1288,7 @@ JVM_ENTRY(void, MHN_copyOutBootstrapArguments(JNIEnv* env, jobject igcls, } case -2: // type { + assert(bss_index_in_pool > 0, ""); Symbol* type = caller->constants()->signature_ref_at(bss_index_in_pool, Bytecodes::_invokedynamic); Handle th; if (type->char_at(0) == JVM_SIGNATURE_FUNC) { @@ -1290,7 +1301,9 @@ JVM_ENTRY(void, MHN_copyOutBootstrapArguments(JNIEnv* env, jobject igcls, } case -1: // argument count { - int argc = caller->constants()->bootstrap_argument_count_at(bss_index_in_pool); + // re-derive the bsme at each point + BSMAttributeEntry* bsme = caller->constants()->bsm_attribute_entry(bsme_index); + int argc = bsme->argument_count(); jvalue argc_value; argc_value.i = (jint)argc; pseudo_arg = java_lang_boxing_object::create(T_INT, &argc_value, CHECK); break; @@ -1306,7 +1319,7 @@ JVM_ENTRY(void, MHN_copyOutBootstrapArguments(JNIEnv* env, jobject igcls, } Handle ifna(THREAD, JNIHandles::resolve(ifna_jh)); caller->constants()-> - copy_bootstrap_arguments_at(bss_index_in_pool, + copy_bootstrap_arguments_at(bsme_index, start, end, buf, pos, (resolve == JNI_TRUE), ifna, CHECK); } diff --git a/src/hotspot/share/prims/nativeLookup.cpp b/src/hotspot/share/prims/nativeLookup.cpp index 8c8d8510dfca2..c066392ee493f 100644 --- a/src/hotspot/share/prims/nativeLookup.cpp +++ b/src/hotspot/share/prims/nativeLookup.cpp @@ -399,6 +399,12 @@ address NativeLookup::lookup_base(const methodHandle& method, TRAPS) { entry = lookup_entry_prefixed(method, CHECK_NULL); if (entry != nullptr) return entry; + if (log_is_enabled(Trace, jni, resolve)) { + log_trace(jni, resolve)("[Dynamic-linking native method %s.%s ... FAILED]", + method->method_holder()->external_name(), + method->name()->as_C_string()); + } + if (THREAD->has_pending_exception()) { oop exception = THREAD->pending_exception(); if (exception->is_a(vmClasses::IllegalCallerException_klass())) { diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index c47ad7092a8be..7e69acaa58010 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -174,7 +174,8 @@ nonstatic_field(ConstantPool, _tags, Array*) \ nonstatic_field(ConstantPool, _cache, ConstantPoolCache*) \ nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \ - nonstatic_field(ConstantPool, _operands, Array*) \ + nonstatic_field(ConstantPool, _bsm_attribute_offsets, Array*) \ + nonstatic_field(ConstantPool, _bsm_attribute_entries, Array*) \ nonstatic_field(ConstantPool, _resolved_klasses, Array*) \ nonstatic_field(ConstantPool, _length, int) \ nonstatic_field(ConstantPool, _minor_version, u2) \ @@ -189,7 +190,7 @@ nonstatic_field(ConstantPoolCache, _resolved_method_entries, Array*) \ nonstatic_field(ResolvedMethodEntry, _cpool_index, u2) \ nonstatic_field(ConstantPoolCache, _resolved_indy_entries, Array*) \ - nonstatic_field(ResolvedIndyEntry, _cpool_index, u2) \ + nonstatic_field(ResolvedIndyEntry, _cp_index, u2) \ volatile_nonstatic_field(InstanceKlass, _array_klasses, ObjArrayKlass*) \ nonstatic_field(InstanceKlass, _methods, Array*) \ nonstatic_field(InstanceKlass, _default_methods, Array*) \ @@ -1482,14 +1483,6 @@ \ declare_constant(Symbol::max_symbol_length) \ \ - /***********************************************/ \ - /* ConstantPool* layout enum for InvokeDynamic */ \ - /***********************************************/ \ - \ - declare_constant(ConstantPool::_indy_bsm_offset) \ - declare_constant(ConstantPool::_indy_argc_offset) \ - declare_constant(ConstantPool::_indy_argv_offset) \ - \ /***************************************/ \ /* JavaThreadStatus enum */ \ /***************************************/ \