/* * Copyright (c) 2019, 2021, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
//------------------------------------------------------------------------------------------------------------------------ // Implementation of BootstrapInfo
// If there is evidence this call site was already linked, set the // existing linkage data into result, or throw previous exception. // Return true if either action is taken, else false. bool BootstrapInfo::resolve_previously_linked_invokedynamic(CallInfo& result, TRAPS) {
assert(_indy_index != -1, "");
ConstantPoolCacheEntry* cpce = invokedynamic_cp_cache_entry(); if (!cpce->is_f1_null()) {
methodHandle method( THREAD, cpce->f1_as_method());
Handle appendix( THREAD, cpce->appendix_if_resolved(_pool));
result.set_handle(vmClasses::MethodHandle_klass(), method, appendix, THREAD);
Exceptions::wrap_dynamic_exception(/* is_indy */ true, CHECK_false); returntrue;
} elseif (cpce->indy_resolution_failed()) { int encoded_index = ResolutionErrorTable::encode_cpcache_index(_indy_index);
ConstantPool::throw_resolution_error(_pool, encoded_index, CHECK_false); returntrue;
} else { returnfalse;
}
}
// Resolve the bootstrap specifier in 3 steps: // - unpack the BSM by resolving the MH constant // - obtain the NameAndType description for the condy/indy // - prepare the BSM's static arguments
Handle BootstrapInfo::resolve_bsm(TRAPS) { if (_bsm.not_null()) { return _bsm;
}
bool is_indy = is_method_call(); // The tag at the bootstrap method index must be a valid method handle or a method handle in error. // If it is a MethodHandleInError, a resolution error will be thrown which will be wrapped if necessary // with a BootstrapMethodError.
assert(_pool->tag_at(bsm_index()).is_method_handle() ||
_pool->tag_at(bsm_index()).is_method_handle_in_error(), "MH not present, classfile structural constraint");
oop bsm_oop = _pool->resolve_possibly_cached_constant_at(bsm_index(), THREAD);
Exceptions::wrap_dynamic_exception(is_indy, CHECK_NH);
guarantee(java_lang_invoke_MethodHandle::is_instance(bsm_oop), "classfile must supply a valid BSM");
_bsm = Handle(THREAD, bsm_oop);
// Obtain NameAndType information
resolve_bss_name_and_type(THREAD);
Exceptions::wrap_dynamic_exception(is_indy, CHECK_NH);
// Resolve metadata from the JVM_Dynamic_info or JVM_InvokeDynamic_info's name and type information. void BootstrapInfo::resolve_bss_name_and_type(TRAPS) {
assert(_bsm.not_null(), "resolve_bsm first");
Symbol* name = this->name();
Symbol* type = this->signature();
_name_arg = java_lang_String::create_from_symbol(name, CHECK); if (type->char_at(0) == '(') {
_type_arg = SystemDictionary::find_method_handle_type(type, caller(), CHECK);
} else {
_type_arg = SystemDictionary::find_java_mirror_for_type(type, caller(), SignatureStream::NCDFError, CHECK);
}
}
// Resolve the bootstrap method's static arguments and store the result in _arg_values. 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;
bool use_BSCI; switch (UseBootstrapCallInfo) { default: use_BSCI = true; break; // stress mode case 0: use_BSCI = false; break; // stress mode case 1: // normal mode // If we were to support an alternative mode of BSM invocation, // we'd convert to pull mode here if the BSM could be a candidate // for that alternative mode. We can't easily test for things // like varargs here, but we can get away with approximate testing, // since the JDK runtime will make up the difference either way. // For now, exercise the pull-mode path if the BSM is of arity 2, // or if there is a potential condy loop (see below).
oop mt_oop = java_lang_invoke_MethodHandle::type(_bsm());
use_BSCI = (java_lang_invoke_MethodType::ptype_count(mt_oop) == 2); break;
}
// Here's a reason to use BSCI even if it wasn't requested: // If a condy uses a condy argument, we want to avoid infinite // recursion (condy loops) in the C code. It's OK in Java, // because Java has stack overflow checking, so we punt // 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); 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_unresolved_condy)
use_BSCI = true;
}
constint SMALL_ARITY = 5; 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++) { bool found_it = false; int arg_index = _pool->bootstrap_argument_index_at(_bss_index, i);
_pool->find_cached_constant_at(arg_index, found_it, CHECK); if (!found_it) { all_resolved = false; break; }
} 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);
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)NULL); // try to discard the singleton array if (arg_oop != NULL && !arg_oop->is_array()) { // JVM treats arrays and nulls specially in this position, // but other things are just single arguments
_arg_values = Handle(THREAD, arg_oop);
} else {
_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);
ints_oop->int_at_put(1, _bss_index);
_arg_values = Handle(THREAD, ints_oop);
}
}
// there must be a LinkageError pending; try to save it and then throw bool BootstrapInfo::save_and_throw_indy_exc(TRAPS) {
assert(HAS_PENDING_EXCEPTION, "");
assert(_indy_index != -1, "");
ConstantPoolCacheEntry* cpce = invokedynamic_cp_cache_entry(); int encoded_index = ResolutionErrorTable::encode_cpcache_index(_indy_index); bool recorded_res_status = cpce->save_and_throw_indy_exc(_pool, _bss_index,
encoded_index,
pool()->tag_at(_bss_index),
CHECK_false); return recorded_res_status;
}
// How the array of resolved arguments is printed depends highly // on how BootstrapInfo::resolve_args structures the array based on // the use_BSCI setting. if (_arg_values.not_null()) { // 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");
st->print(" resolved arg[0]: "); static_args->print_on(st);
} elseif (static_args->is_objArray()) { int lines = 0; for (int i = 0; i < _argc; i++) {
oop x = static_args->obj_at(i); if (x != NULL) { if (++lines > 6) {
st->print_cr(" resolved arg[%d]: ...", i); break;
}
st->print(" resolved arg[%d]: ", i); x->print_on(st);
}
}
} elseif (static_args->is_typeArray()) {
typeArrayOop tmp_array = (typeArrayOop) static_args;
assert(tmp_array->length() == 2, "Invalid BSM _arg_values type array");
st->print_cr(" resolved arg[0]: %d", tmp_array->int_at(0));
st->print_cr(" resolved arg[1]: %d", tmp_array->int_at(1));
}
}
}
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.