< prev index next >

src/hotspot/share/interpreter/linkResolver.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

@@ -53,11 +53,11 @@
   methodHandle _selected_method;        // dynamic (actual) target method
   CallKind     _call_kind;              // kind of call (static(=bytecode static/special +
                                         //               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);
   void set_interface(Klass* resolved_klass, Klass* selected_klass,
                      const methodHandle& resolved_method,

@@ -66,21 +66,22 @@
   void set_virtual(Klass* resolved_klass, Klass* selected_klass,
                    const methodHandle& resolved_method,
                    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,
                   CallKind kind,
                   int index, TRAPS);
 
   friend class LinkResolver;
+  friend class BootstrapInfo;
 
  public:
   CallInfo() {
 #ifndef PRODUCT
     _call_kind  = CallInfo::unknown_kind;

@@ -96,11 +97,11 @@
   Klass*  resolved_klass() const                 { return _resolved_klass; }
   Klass*  selected_klass() const                 { return _selected_klass; }
   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);
 
   BasicType    result_type() const               { return selected_method()->result_type(); }

@@ -129,10 +130,121 @@
 #endif //ASSERT
   void         verify() PRODUCT_RETURN;
   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)
 //   current_klass  = sending method holder (i.e., class containing the method
 //                    containing the call being resolved)

@@ -205,12 +317,11 @@
                                           bool checkpolymorphism,
                                           bool in_imethod_resolve);
   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,
                                                          Klass::PrivateLookupMode private_mode, TRAPS);
  JVMCI_ONLY(private:)

@@ -313,13 +424,12 @@
   static void resolve_interface_call(CallInfo& result, Handle recv, Klass* recv_klass,
                                      const LinkInfo& link_info,
                                      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)
   static methodHandle resolve_virtual_call_or_null  (Klass* receiver_klass,
                                                      const LinkInfo& link_info);
< prev index next >