< prev index next >
src/hotspot/share/oops/constantPool.hpp
Print this page
rev 52749 : Bootstrap method consolidation
* clean up and simplify JDK support code for BSM invocation
* simplify JVM bootstrap handshake: use BootstrapCallInfo only
* remove unused JVM paths and data fields
* move bootstrap argument processing from MethodHandleNatives to ConstantPool
* remove ConstantGroup; merge argument access into BootstrapCallInfo
* adjust BSM argument access: remove copyArguments, add argumentRef API
* add metadata-free BSM modes, including symbolic arguments from CP
*** 244,263 ****
// The invokedynamic points at a CP cache entry. This entry points back
// at the original CP entry (CONSTANT_InvokeDynamic) and also (via f2) at an entry
// in the resolved_references array (which provides the appendix argument).
! int invokedynamic_cp_cache_index(int index) const {
! assert (is_invokedynamic_index(index), "should be a invokedynamic index");
! int cache_index = decode_invokedynamic_index(index);
return cache_index;
}
! ConstantPoolCacheEntry* invokedynamic_cp_cache_entry_at(int index) const {
// decode index that invokedynamic points to.
! int cp_cache_index = invokedynamic_cp_cache_index(index);
return cache()->entry_at(cp_cache_index);
}
// Assembly code support
static int tags_offset_in_bytes() { return offset_of(ConstantPool, _tags); }
static int cache_offset_in_bytes() { return offset_of(ConstantPool, _cache); }
static int pool_holder_offset_in_bytes() { return offset_of(ConstantPool, _pool_holder); }
--- 244,269 ----
// The invokedynamic points at a CP cache entry. This entry points back
// at the original CP entry (CONSTANT_InvokeDynamic) and also (via f2) at an entry
// in the resolved_references array (which provides the appendix argument).
! int invokedynamic_cp_cache_index(int indy_index) const {
! assert(is_invokedynamic_index(indy_index), "should be a invokedynamic index");
! int cache_index = decode_invokedynamic_index(indy_index);
return cache_index;
}
! ConstantPoolCacheEntry* invokedynamic_cp_cache_entry_at(int indy_index) const {
// decode index that invokedynamic points to.
! int cp_cache_index = invokedynamic_cp_cache_index(indy_index);
return cache()->entry_at(cp_cache_index);
}
+ // 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.
+ int invokedynamic_bootstrap_ref_index_at(int indy_index) const {
+ return invokedynamic_cp_cache_entry_at(indy_index)->constant_pool_index();
+ }
// Assembly code support
static int tags_offset_in_bytes() { return offset_of(ConstantPool, _tags); }
static int cache_offset_in_bytes() { return offset_of(ConstantPool, _cache); }
static int pool_holder_offset_in_bytes() { return offset_of(ConstantPool, _pool_holder); }
*** 292,309 ****
void method_type_index_at_put(int which, int ref_index) {
tag_at_put(which, JVM_CONSTANT_MethodType);
*int_at_addr(which) = ref_index;
}
! void dynamic_constant_at_put(int which, int bootstrap_specifier_index, int name_and_type_index) {
tag_at_put(which, JVM_CONSTANT_Dynamic);
! *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_specifier_index;
}
! void invoke_dynamic_at_put(int which, int bootstrap_specifier_index, int name_and_type_index) {
tag_at_put(which, JVM_CONSTANT_InvokeDynamic);
! *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_specifier_index;
}
void unresolved_string_at_put(int which, Symbol* s) {
release_tag_at_put(which, JVM_CONSTANT_String);
slot_at_put(which, CPSlot(s));
--- 298,315 ----
void method_type_index_at_put(int which, int ref_index) {
tag_at_put(which, JVM_CONSTANT_MethodType);
*int_at_addr(which) = ref_index;
}
! void dynamic_constant_at_put(int which, int bsms_attribute_index, int name_and_type_index) {
tag_at_put(which, JVM_CONSTANT_Dynamic);
! *int_at_addr(which) = ((jint) name_and_type_index<<16) | bsms_attribute_index;
}
! void invoke_dynamic_at_put(int which, int bsms_attribute_index, int name_and_type_index) {
tag_at_put(which, JVM_CONSTANT_InvokeDynamic);
! *int_at_addr(which) = ((jint) name_and_type_index<<16) | bsms_attribute_index;
}
void unresolved_string_at_put(int which, Symbol* s) {
release_tag_at_put(which, JVM_CONSTANT_String);
slot_at_put(which, CPSlot(s));
*** 532,561 ****
Symbol* method_type_signature_at(int which) {
int sym = method_type_index_at(which);
return symbol_at(sym);
}
! int invoke_dynamic_name_and_type_ref_index_at(int which) {
! assert(tag_at(which).is_invoke_dynamic() ||
! tag_at(which).is_dynamic_constant() ||
! tag_at(which).is_dynamic_constant_in_error(), "Corrupted constant pool");
return extract_high_short_from_int(*int_at_addr(which));
}
! int invoke_dynamic_bootstrap_specifier_index(int which) {
! assert(tag_at(which).is_invoke_dynamic() ||
! tag_at(which).is_dynamic_constant() ||
! tag_at(which).is_dynamic_constant_in_error(), "Corrupted constant pool");
return extract_low_short_from_int(*int_at_addr(which));
}
! int invoke_dynamic_operand_base(int which) {
! int bootstrap_specifier_index = invoke_dynamic_bootstrap_specifier_index(which);
! return operand_offset_at(operands(), bootstrap_specifier_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<u2>* operands, int bootstrap_specifier_index) {
! int n = (bootstrap_specifier_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)));
--- 538,563 ----
Symbol* method_type_signature_at(int which) {
int sym = method_type_index_at(which);
return symbol_at(sym);
}
! int bootstrap_name_and_type_ref_index_at(int which) {
! assert(tag_at(which).has_bootstrap(), "Corrupted constant pool");
return extract_high_short_from_int(*int_at_addr(which));
}
! int bootstrap_methods_attribute_index(int which) {
! assert(tag_at(which).has_bootstrap(), "Corrupted constant pool");
return extract_low_short_from_int(*int_at_addr(which));
}
! int bootstrap_operand_base(int which) {
! int bsms_attribute_index = bootstrap_methods_attribute_index(which);
! 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<u2>* 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)));
*** 564,575 ****
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<u2>* operands, int bootstrap_specifier_index, int offset) {
! int n = bootstrap_specifier_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<u2>* operands) {
--- 566,577 ----
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<u2>* 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<u2>* operands) {
*** 578,666 ****
return (second_part / 2);
}
#ifdef ASSERT
// operand tuples fit together exactly, end to end
! static int operand_limit_at(Array<u2>* operands, int bootstrap_specifier_index) {
! int nextidx = bootstrap_specifier_index + 1;
if (nextidx == operand_array_length(operands))
return operands->length();
else
return operand_offset_at(operands, nextidx);
}
! int invoke_dynamic_operand_limit(int which) {
! int bootstrap_specifier_index = invoke_dynamic_bootstrap_specifier_index(which);
! return operand_limit_at(operands(), bootstrap_specifier_index);
}
#endif //ASSERT
! // layout of InvokeDynamic and Dynamic bootstrap method specifier (in second part of operands array):
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 bootstrap_specifier_index) {
! assert(0 <= bootstrap_specifier_index &&
! bootstrap_specifier_index < operand_array_length(operands()),
"Corrupted CP operands");
! return operand_offset_at(operands(), bootstrap_specifier_index);
}
! int operand_bootstrap_method_ref_index_at(int bootstrap_specifier_index) {
! int offset = operand_offset_at(bootstrap_specifier_index);
return operands()->at(offset + _indy_bsm_offset);
}
! int operand_argument_count_at(int bootstrap_specifier_index) {
! int offset = operand_offset_at(bootstrap_specifier_index);
int argc = operands()->at(offset + _indy_argc_offset);
return argc;
}
! int operand_argument_index_at(int bootstrap_specifier_index, int j) {
! int offset = operand_offset_at(bootstrap_specifier_index);
return operands()->at(offset + _indy_argv_offset + j);
}
! int operand_next_offset_at(int bootstrap_specifier_index) {
! int offset = operand_offset_at(bootstrap_specifier_index) + _indy_argv_offset
! + operand_argument_count_at(bootstrap_specifier_index);
return offset;
}
! // Compare a bootsrap specifier in the operands arrays
! bool compare_operand_to(int bootstrap_specifier_index1, const constantPoolHandle& cp2,
! int bootstrap_specifier_index2, TRAPS);
! // Find a bootsrap specifier in the operands array
! int find_matching_operand(int bootstrap_specifier_index, const constantPoolHandle& search_cp,
int operands_cur_len, TRAPS);
// 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);
! int invoke_dynamic_bootstrap_method_ref_index_at(int which) {
! assert(tag_at(which).is_invoke_dynamic() ||
! tag_at(which).is_dynamic_constant() ||
! tag_at(which).is_dynamic_constant_in_error(), "Corrupted constant pool");
! int op_base = invoke_dynamic_operand_base(which);
return operands()->at(op_base + _indy_bsm_offset);
}
! int invoke_dynamic_argument_count_at(int which) {
! assert(tag_at(which).is_invoke_dynamic() ||
! tag_at(which).is_dynamic_constant() ||
! tag_at(which).is_dynamic_constant_in_error(), "Corrupted constant pool");
! int op_base = invoke_dynamic_operand_base(which);
int argc = operands()->at(op_base + _indy_argc_offset);
DEBUG_ONLY(int end_offset = op_base + _indy_argv_offset + argc;
! int next_offset = invoke_dynamic_operand_limit(which));
assert(end_offset == next_offset, "matched ending");
return argc;
}
! int invoke_dynamic_argument_index_at(int which, int j) {
! int op_base = invoke_dynamic_operand_base(which);
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);
}
--- 580,667 ----
return (second_part / 2);
}
#ifdef ASSERT
// operand tuples fit together exactly, end to end
! static int operand_limit_at(Array<u2>* 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 which) {
! int bsms_attribute_index = bootstrap_methods_attribute_index(which);
! 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);
}
! int 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);
}
! int operand_argument_count_at(int bsms_attribute_index) {
! int offset = operand_offset_at(bsms_attribute_index);
int argc = operands()->at(offset + _indy_argc_offset);
return argc;
}
! int 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, TRAPS);
! // 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, TRAPS);
// 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);
! int bootstrap_method_ref_index_at(int which) {
! assert(tag_at(which).has_bootstrap(), "Corrupted constant pool");
! int op_base = bootstrap_operand_base(which);
return operands()->at(op_base + _indy_bsm_offset);
}
! int bootstrap_argument_count_at(int which) {
! assert(tag_at(which).has_bootstrap(), "Corrupted constant pool");
! int op_base = bootstrap_operand_base(which);
int 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(which));
assert(end_offset == next_offset, "matched ending");
return argc;
}
! int bootstrap_argument_index_at(int which, int j) {
! int op_base = bootstrap_operand_base(which);
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);
}
*** 743,764 ****
oop find_cached_constant_at(int pool_index, bool& found_it, TRAPS) {
constantPoolHandle h_this(THREAD, this);
return resolve_constant_at_impl(h_this, pool_index, _possible_index_sentinel, &found_it, THREAD);
}
! oop resolve_bootstrap_specifier_at(int index, TRAPS) {
! constantPoolHandle h_this(THREAD, this);
! return resolve_bootstrap_specifier_at_impl(h_this, index, THREAD);
! }
void copy_bootstrap_arguments_at(int 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, index, start_arg, end_arg,
! info, pos, must_resolve, if_not_available, THREAD);
}
// Klass name matches name at offset
bool klass_name_at_matches(const InstanceKlass* k, int which);
--- 744,768 ----
oop find_cached_constant_at(int pool_index, bool& found_it, TRAPS) {
constantPoolHandle h_this(THREAD, this);
return resolve_constant_at_impl(h_this, pool_index, _possible_index_sentinel, &found_it, THREAD);
}
! enum BootstrapArgumentReferenceMode { R_IFPRESENT = 0, R_FORCE = 1, R_SYMREF = 2 };
void copy_bootstrap_arguments_at(int index,
int start_arg, int end_arg,
! arrayHandle buf, int pos,
! BootstrapArgumentReferenceMode resolving,
! Handle if_not_available, Handle if_null_constant,
! bool skip_non_null, // don't overwrite previous stuff in buf
! bool skip_recursion, // don't resolve CONSTANT_Dynamic args
! TRAPS) {
constantPoolHandle h_this(THREAD, this);
copy_bootstrap_arguments_at_impl(h_this, index, start_arg, end_arg,
! buf, pos,
! resolving, if_not_available, if_null_constant,
! skip_non_null, skip_recursion, THREAD);
}
// Klass name matches name at offset
bool klass_name_at_matches(const InstanceKlass* k, int which);
*** 794,805 ****
// Used by compiler to prevent classloading.
static Method* method_at_if_loaded (const constantPoolHandle& this_cp, int which);
static bool has_appendix_at_if_loaded (const constantPoolHandle& this_cp, int which);
static oop appendix_at_if_loaded (const constantPoolHandle& this_cp, int which);
! static bool has_method_type_at_if_loaded (const constantPoolHandle& this_cp, int which);
! static oop method_type_at_if_loaded (const constantPoolHandle& this_cp, int which);
static Klass* klass_at_if_loaded (const constantPoolHandle& this_cp, int which);
// Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
// future by other Java code. These take constant pool indices rather than
// constant pool cache indices as do the peer methods above.
--- 798,808 ----
// Used by compiler to prevent classloading.
static Method* method_at_if_loaded (const constantPoolHandle& this_cp, int which);
static bool has_appendix_at_if_loaded (const constantPoolHandle& this_cp, int which);
static oop appendix_at_if_loaded (const constantPoolHandle& this_cp, int which);
! static bool has_local_signature_at_if_loaded (const constantPoolHandle& this_cp, int which);
static Klass* klass_at_if_loaded (const constantPoolHandle& this_cp, int which);
// Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
// future by other Java code. These take constant pool indices rather than
// constant pool cache indices as do the peer methods above.
*** 869,883 ****
// Resolve string constants (to prevent allocation during compilation)
static void resolve_string_constants_impl(const constantPoolHandle& this_cp, TRAPS);
static oop resolve_constant_at_impl(const constantPoolHandle& this_cp, int index, int cache_index,
bool* status_return, TRAPS);
- static oop resolve_bootstrap_specifier_at_impl(const constantPoolHandle& this_cp, int index, TRAPS);
static void copy_bootstrap_arguments_at_impl(const constantPoolHandle& this_cp, int index,
int start_arg, int end_arg,
! objArrayHandle info, int pos,
! bool must_resolve, Handle if_not_available, TRAPS);
// Exception handling
static Symbol* exception_message(const constantPoolHandle& this_cp, int which, constantTag tag, oop pending_exception);
static void save_and_throw_exception(const constantPoolHandle& this_cp, int which, constantTag tag, TRAPS);
--- 872,890 ----
// Resolve string constants (to prevent allocation during compilation)
static void resolve_string_constants_impl(const constantPoolHandle& this_cp, TRAPS);
static oop resolve_constant_at_impl(const constantPoolHandle& this_cp, int index, int cache_index,
bool* status_return, TRAPS);
static void copy_bootstrap_arguments_at_impl(const constantPoolHandle& this_cp, int index,
int start_arg, int end_arg,
! arrayHandle buf, int pos,
! BootstrapArgumentReferenceMode resolving,
! Handle if_not_available,
! Handle if_null_constant,
! bool skip_non_null,
! bool skip_recursion,
! TRAPS);
// Exception handling
static Symbol* exception_message(const constantPoolHandle& this_cp, int which, constantTag tag, oop pending_exception);
static void save_and_throw_exception(const constantPoolHandle& this_cp, int which, constantTag tag, TRAPS);
< prev index next >