From 3d35b408e1e69d7e3953af142c5bf606691fbeb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Sj=C3=B6len?= Date: Mon, 23 Jun 2025 07:05:33 +0000 Subject: [PATCH] 8357220: Introduce a BSMAttributeEntry struct Co-authored-by: John R Rose Reviewed-by: sspitsyn, coleenp, matsaave --- .../share/cds/aotConstantPoolResolver.cpp | 6 +- src/hotspot/share/oops/constantPool.cpp | 14 +-- src/hotspot/share/oops/constantPool.hpp | 98 ++++++++++--------- .../prims/jvmtiClassFileReconstituter.cpp | 10 +- .../share/prims/jvmtiRedefineClasses.cpp | 9 +- src/hotspot/share/runtime/vmStructs.cpp | 12 +-- .../sun/jvm/hotspot/oops/ConstantPool.java | 8 +- 7 files changed, 84 insertions(+), 73 deletions(-) diff --git a/src/hotspot/share/cds/aotConstantPoolResolver.cpp b/src/hotspot/share/cds/aotConstantPoolResolver.cpp index 6ab63418e09..0eb7ddfbbf6 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; @@ -514,7 +514,7 @@ bool AOTConstantPoolResolver::is_indy_resolution_deterministic(ConstantPool* cp, } 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/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 5b0ee298ddc..3223c56628e 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -1937,18 +1937,20 @@ int ConstantPool::find_matching_entry(int pattern_i, // 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); + 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)) { + int argc = e1->argument_count(); + if (argc == e2->argument_count()) { for (int j = 0; j < argc; j++) { - k1 = operand_argument_index_at(idx1, j); - k2 = cp2->operand_argument_index_at(idx2, j); + k1 = e1->argument_index(j); + k2 = e2->argument_index(j); match = compare_entry_to(k1, cp2, k2); if (!match) { return false; diff --git a/src/hotspot/share/oops/constantPool.hpp b/src/hotspot/share/oops/constantPool.hpp index cc9491d7935..be4a7a474d4 100644 --- a/src/hotspot/share/oops/constantPool.hpp +++ b/src/hotspot/share/oops/constantPool.hpp @@ -77,6 +77,43 @@ public: } }; +class BSMAttributeEntry { + friend class ConstantPool; + u2 _bootstrap_method_index; + u2 _argument_count; + + // The argument indexes are stored right after the object, in a contiguous array. + // [ bsmi_0 argc_0 arg_00 arg_01 ... arg_0N bsmi_1 argc_1 arg_10 ... arg_1N ... ] + // So in order to find the argument array, jump over ourselves. + const u2* argument_indexes() const { + return reinterpret_cast(this + 1); + } + u2* argument_indexes() { + return reinterpret_cast(this + 1); + } + // These are overlays on top of the operands array. Do not construct. + BSMAttributeEntry() = delete; + +public: + // Offsets for SA + enum { + _bsmi_offset = 0, + _argc_offset = 1, + _argv_offset = 2 + }; + + int bootstrap_method_index() const { + return _bootstrap_method_index; + } + int argument_count() const { + return _argument_count; + } + int argument_index(int n) const { + assert(checked_cast(n) < _argument_count, "oob"); + return argument_indexes()[n]; + } +}; + class ConstantPool : public Metadata { friend class VMStructs; friend class JVMCIVMStructs; @@ -519,10 +556,6 @@ 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) { @@ -560,47 +593,26 @@ class ConstantPool : public Metadata { 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] - }; - // 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) { + + BSMAttributeEntry* bsm_attribute_entry(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); + return reinterpret_cast(operands()->adr_at(offset)); } + 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; + BSMAttributeEntry* bsme = bsm_attribute_entry(bsms_attribute_index); + u2* argv_start = bsme->argument_indexes(); + int offset = argv_start - operands()->data(); + return offset + bsme->argument_count(); } // Compare a bootstrap specifier data in the operands arrays bool compare_operand_to(int bsms_attribute_index1, const constantPoolHandle& cp2, @@ -617,23 +629,19 @@ class ConstantPool : public Metadata { 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 bsmai = bootstrap_methods_attribute_index(cp_index); + return bsm_attribute_entry(bsmai)->bootstrap_method_index(); } 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 bsmai = bootstrap_methods_attribute_index(cp_index); + return bsm_attribute_entry(bsmai)->argument_count(); } 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); + int bsmai = bootstrap_methods_attribute_index(cp_index); + BSMAttributeEntry* bsme = bsm_attribute_entry(bsmai); + assert((uint)j < (uint)bsme->argument_count(), "oob"); + return bsm_attribute_entry(bsmai)->argument_index(j); } // The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve, diff --git a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp index 731db2e82f1..831f407e7ec 100644 --- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp +++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp @@ -396,7 +396,7 @@ void JvmtiClassFileReconstituter::write_bootstrapmethod_attribute() { // 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); + u2 num_bootstrap_arguments = cpool()->bsm_attribute_entry(n)->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,12 +406,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); + u2 bootstrap_argument = bsme->argument_index(arg); write_u2(bootstrap_argument); } } diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index 305af6df9be..ec4a6cd8c7f 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -659,10 +659,11 @@ u2 VM_RedefineClasses::find_or_append_indirect_entry(const constantPoolHandle& s // 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. // 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_operand(const constantPoolHandle& scratch_cp, const int old_bs_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); + BSMAttributeEntry* old_bsme = scratch_cp->bsm_attribute_entry(old_bs_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) { @@ -676,14 +677,14 @@ void VM_RedefineClasses::append_operand(const constantPoolHandle& scratch_cp, in // 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); + 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); 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); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 4e322c333a9..e248e0f05be 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1483,13 +1483,13 @@ \ declare_constant(Symbol::max_symbol_length) \ \ - /***********************************************/ \ - /* ConstantPool* layout enum for InvokeDynamic */ \ - /***********************************************/ \ + /******************************************************/ \ + /* BSMAttributeEntry* - layout enum for InvokeDynamic */ \ + /******************************************************/ \ \ - declare_constant(ConstantPool::_indy_bsm_offset) \ - declare_constant(ConstantPool::_indy_argc_offset) \ - declare_constant(ConstantPool::_indy_argv_offset) \ + declare_constant(BSMAttributeEntry::_bsmi_offset) \ + declare_constant(BSMAttributeEntry::_argc_offset) \ + declare_constant(BSMAttributeEntry::_argv_offset) \ \ /***************************************/ \ /* JavaThreadStatus enum */ \ diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java index c1df1df9429..563d9d3ac4a 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,9 +100,9 @@ public class ConstantPool extends Metadata implements ClassConstants { headerSize = type.getSize(); elementSize = 0; // fetch constants: - INDY_BSM_OFFSET = db.lookupIntConstant("ConstantPool::_indy_bsm_offset").intValue(); - INDY_ARGC_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argc_offset").intValue(); - INDY_ARGV_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argv_offset").intValue(); + INDY_BSM_OFFSET = db.lookupIntConstant("BSMAttributeEntry::_bsmi_offset").intValue(); + INDY_ARGC_OFFSET = db.lookupIntConstant("BSMAttributeEntry::_argc_offset").intValue(); + INDY_ARGV_OFFSET = db.lookupIntConstant("BSMAttributeEntry::_argv_offset").intValue(); } public ConstantPool(Address addr) {