--- old/src/hotspot/share/interpreter/linkResolver.hpp 2018-09-28 11:53:21.000000000 -0700 +++ new/src/hotspot/share/interpreter/linkResolver.hpp 2018-09-28 11:53:20.000000000 -0700 @@ -55,7 +55,7 @@ // others inferred), vtable, itable) int _call_index; // vtable or itable index of selected class method (if any) Handle _resolved_appendix; // extra argument in constant pool (if CPCE::has_appendix) - Handle _resolved_method_type; // MethodType (for invokedynamic and invokehandle call sites) + bool _has_local_sig; // use signature from call site, which differs from that of the method itself Handle _resolved_method_name; // Object holding the ResolvedMethodName void set_static(Klass* resolved_klass, const methodHandle& resolved_method, TRAPS); @@ -68,10 +68,10 @@ const methodHandle& selected_method, int vtable_index, TRAPS); void set_handle(const methodHandle& resolved_method, - Handle resolved_appendix, Handle resolved_method_type, TRAPS); + Handle resolved_appendix, bool has_local_sig, TRAPS); void set_handle(Klass* resolved_klass, const methodHandle& resolved_method, - Handle resolved_appendix, Handle resolved_method_type, TRAPS); + Handle resolved_appendix, bool has_local_sig, TRAPS); void set_common(Klass* resolved_klass, Klass* selected_klass, const methodHandle& resolved_method, const methodHandle& selected_method, @@ -79,6 +79,7 @@ int index, TRAPS); friend class LinkResolver; + friend class BootstrapInfo; public: CallInfo() { @@ -98,7 +99,7 @@ methodHandle resolved_method() const { return _resolved_method; } methodHandle selected_method() const { return _selected_method; } Handle resolved_appendix() const { return _resolved_appendix; } - Handle resolved_method_type() const { return _resolved_method_type; } + bool has_local_signature() const { return _has_local_sig; } Handle resolved_method_name() const { return _resolved_method_name; } // Materialize a java.lang.invoke.ResolvedMethodName for this resolved_method void set_resolved_method_name(TRAPS); @@ -131,6 +132,117 @@ void print() PRODUCT_RETURN; }; +// Condensed information from constant pool to use to invoke a bootstrap method. +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 bool _is_method_call; // are we resolving a method (indy) or a value (condy)? + const int _argc; // number of static arguments + Symbol* _name; // extracted from JVM_CONSTANT_NameAndType + Symbol* _signature; + + // pre-bootstrap resolution state: + Handle _bsm; // resolved bootstrap method + Handle _name_arg; // resolved String + Handle _type_arg; // resolved Class or MethodType + typeArrayHandle _arg_indexes; // int[] array of static arguments, as CP indexes + objArrayHandle _arg_values; // Object[] array of static arguments; null for unresolved + + // post-bootstrap resolution state: + bool _is_resolved; // set true when any of the next fields are set + Handle _resolved_value; // bind this as condy constant + methodHandle _resolved_method; // bind this as indy behavior + Handle _resolved_appendix; // extra opaque static argument for _resolved_method + + int nat_ref_index() const { return _pool->bootstrap_name_and_type_ref_index_at(_bss_index); } + + public: + BootstrapInfo(const constantPoolHandle& pool, int bss_index, int indy_index = 0); + + // accessors + 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; } + bool is_method_call() const { return _is_method_call; } + Symbol* name() const { return _name; } + Symbol* signature() const { return _signature; } + + // accessors to lazy state + Handle bsm() const { return _bsm; } + Handle name_arg() const { return _name_arg; } + Handle type_arg() const { return _type_arg; } + typeArrayHandle arg_indexes() const { return _arg_indexes; } + objArrayHandle arg_values() const { return _arg_values; } + bool is_resolved() const { return _is_resolved; } + Handle resolved_value() const { assert(!is_method_call(), ""); return _resolved_value; } + methodHandle resolved_method() const { assert(is_method_call(), ""); return _resolved_method; } + Handle resolved_appendix() const { assert(is_method_call(), ""); return _resolved_appendix; } + + // derived accessors + InstanceKlass* caller() const { return _pool->pool_holder(); } + oop caller_mirror() const { return caller()->java_mirror(); } + int decode_indy_index() const { return ConstantPool::decode_invokedynamic_index(_indy_index); } + int name_index() const { return _pool->name_ref_index_at(nat_ref_index()); } + int signature_index() const { return _pool->signature_ref_index_at(nat_ref_index()); } + 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); } + oop arg_value(int i) const; // pull oop from _arg_values, safely, NULL if not present + + enum BSMMode { _unknown, _metadata, _bsci, _expression }; + BSMMode bsm_mode() const; + + // CP cache entry for call site (indy only) + ConstantPoolCacheEntry* invokedynamic_cp_cache_entry() const { + assert(is_method_call(), ""); + return _pool->invokedynamic_cp_cache_entry_at(_indy_index); + } + + // If there is evidence this call site was already linked, set the + // existing linkage data into result, or throw previouos exception. + // Return true if either action is taken, else false. + bool resolve_previously_linked_invokedynamic(CallInfo& result, TRAPS); + bool save_and_throw_indy_exc(TRAPS); + void resolve_newly_linked_invokedynamic(CallInfo& result, TRAPS); + + // argument location and resolution + // Null returns from these are real, actual null condy constants. + // They never produce Universe::the_null_sentinel. + oop find_arg_oop(int i, Handle if_not_present, TRAPS) { + // Don't pass if_not_present as null unless you are OK with confusing + // "not present" with "present but null". + bool found_it = false; + oop result = _pool->find_cached_constant_at(arg_index(i), found_it, THREAD); + return (found_it ? result : if_not_present()); // OK to execute during exception + } + oop resolve_arg_oop(int i, TRAPS) { + return _pool->resolve_possibly_cached_constant_at(arg_index(i), THREAD); + } + + // pre-bootstrap resolution actions: + Handle resolve_bsm(TRAPS); // lazily compute _bsm and return it + void resolve_metadata(TRAPS); // lazily compute _name/_type + void resolve_args(ConstantPool::BootstrapArgumentReferenceMode resolving, TRAPS); // compute arguments + + // setters for post-bootstrap results: + void set_resolved_value(Handle value) { + assert(!is_resolved() && !is_method_call(), ""); + _is_resolved = true; + _resolved_value = value; + } + void set_resolved_method(methodHandle method, Handle appendix) { + assert(!is_resolved() && is_method_call(), ""); + _is_resolved = true; + _resolved_method = method; + _resolved_appendix = appendix; + } + + void print() { print_msg_on(tty); } + void print_msg_on(outputStream* st, const char* msg = NULL); +}; // Condensed information from constant pool to use to resolve the method or field. // resolved_klass = specified class (i.e., static receiver class) @@ -207,8 +319,7 @@ static Method* lookup_method_in_interfaces(const LinkInfo& link_info); static methodHandle lookup_polymorphic_method(const LinkInfo& link_info, - Handle *appendix_result_or_null, - Handle *method_type_result, TRAPS); + Handle *appendix_result_or_null, TRAPS); JVMCI_ONLY(public:) // Needed for CompilerToVM.resolveMethod() // Not Linktime so doesn't take LinkInfo static methodHandle lookup_instance_method_in_klasses (Klass* klass, Symbol* name, Symbol* signature, @@ -315,9 +426,8 @@ bool check_null_and_abstract, TRAPS); static void resolve_handle_call (CallInfo& result, const LinkInfo& link_info, TRAPS); - static void resolve_dynamic_call (CallInfo& result, int pool_index, Handle bootstrap_specifier, - Symbol* method_name, Symbol* method_signature, - Klass* current_klass, TRAPS); + static void resolve_dynamic_call (CallInfo& result, + BootstrapInfo& bootstrap_specifier, TRAPS); // same as above for compile-time resolution; but returns null handle instead of throwing // an exception on error also, does not initialize klass (i.e., no side effects)