< prev index next >

src/hotspot/share/ci/ciStreams.cpp

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

@@ -363,20 +363,96 @@
   VM_ENTRY_MARK;
   ciEnv* env = CURRENT_ENV;
   constantPoolHandle cpool(THREAD, _method->get_Method()->constants());
   ciMethod* m = env->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder);
   will_link = m->is_loaded();
+  Symbol* local_signature = cpool->symbol_at(get_method_signature_index(cpool));
 
-  // Use the MethodType stored in the CP cache to create a signature
+  // Use the signature stored in the CP cache to create a signature
   // with correct types (in respect to class loaders).
-  if (has_method_type()) {
-    ciSymbol*     sig_sym     = env->get_symbol(cpool->symbol_at(get_method_signature_index(cpool)));
+  //
+  // In classic Java (before Java 7) there is never the slightest
+  // difference between the signature at the call site and that of the
+  // method.  Such a difference would have been a type error in the
+  // JVM.
+  //
+  // Now there are a few circumstances where the signature of a call
+  // site (which controls the outgoing stacked arguments) can differ
+  // from the signature of the method (which controls the receipt of
+  // those arguments at the method entry point).
+  //
+  // A. The signatures can differ if the callee is a static method and
+  // the caller thinks it is calling a non-static method (VH.get).
+  // This requires the method signature to have an explicit leading
+  // argument for the implicit 'this', not present at the call site.
+  //
+  // B. The call site can have less specific parameter types than the
+  // method, allowing loosely-typed code to handle strongly-typed
+  // methods.  This happens with linkToStatic and related linker
+  // commands.  Obviously the loosely-typed code has to ensure that
+  // the strongly typed method's invariants are respected, and this is
+  // done by issuing dynamic casts.
+  //
+  // C. The call site can have more specific parameter types than the
+  // method, allowing loosely-typed methods to handle strongly-typed
+  // requests.
+  //
+  // D. There is are corresponding effects with return values, such as
+  // boolean method returning an int to an int-receiving call site,
+  // even though the method thought it returned just a boolean.
+  //
+  // E. The calling sequence at a particular call site may add an
+  // "appendix" argument not mentioned in the call site signature.  It
+  // is expected by the method signature, though, and this adds to the
+  // method's arity, even after 'this' parameter effects (A) are
+  // discounted.  Appendixes are used by invokehandle and
+  // invokedynamic instructions.
+  //
+  // F. A linker method (linkToStatic, etc.) can also take an extra
+  // argument, a MemberName which routes the call to a concrete
+  // strongly-typed method.  In this case the linker method may also
+  // differ in any of the ways A-D.  The eventual method will ignore
+  // the presence of the extra argument.
+  //
+  // None of these changes to calling sequences requires an argument
+  // to be moved or reformatted in any way.  This works because all
+  // references look alike to the JVM, as do all primitives (except
+  // float/long/double).  Another required property of the JVM is
+  // that, if a trailing argument is added or dropped, the placement
+  // of other arguments does not change.  This allows cases E and F to
+  // work smoothly, against without any moving or reformatting,
+  // despite the arity change.
+  //
+  if (has_local_signature()) {
+    ciSymbol*     sig_sym     = env->get_symbol(local_signature);
     ciKlass*      pool_holder = env->get_klass(cpool->pool_holder());
-    ciMethodType* method_type = get_method_type();
-    ciSignature* declared_signature = new (env->arena()) ciSignature(pool_holder, sig_sym, method_type);
-    (*declared_signature_result) = declared_signature;
+    ciSignature* call_site_sig = new (env->arena()) ciSignature(pool_holder, cpool, sig_sym);
+    // Examples of how the call site signature can differ from the method's own signature:
+    //
+    //  meth = static jboolean java.lang.invoke.VarHandleGuards.guard_LII_Z(jobject, jobject, jint, jint, jobject)
+    //  msig = (Ljava/lang/invoke/VarHandle;Ljava/lang/Object;IILjava/lang/invoke/VarHandle$AccessDescriptor;)Z
+    //  call = (Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;II)Z
+    //
+    //  meth = static jobject java.lang.invoke.LambdaForm$MH/0x0000000800066840.linkToTargetMethod(jobject, jobject)
+    //  msig = (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+    //  call = (Ljava/lang/String;)Ljava/util/function/Predicate;
+    //
+    (*declared_signature_result) = call_site_sig;
+
   } else {
+    // We can just use the method's own signature.  It may differ from the call site, but not by much.
+    //
+    // Examples of how the call site signature can differ from the method's signature:
+    //
+    // meth = static final native jint java.lang.invoke.MethodHandle.linkToStatic(jobject, jobject, jint, jint, jobject)
+    // msig = (Ljava/lang/Object;Ljava/lang/Object;IILjava/lang/invoke/MemberName;)I
+    // call = (Ljava/lang/invoke/VarHandle;Ljava/lang/Object;IILjava/lang/invoke/MemberName;)Z
+    //
+    // meth = final native jint java.lang.invoke.MethodHandle.invokeBasic(jobject, jobject, jint, jint)
+    // msig = (Ljava/lang/Object;Ljava/lang/Object;II)I
+    // call = (Ljava/lang/invoke/VarHandle;Ljava/lang/Object;II)Z
+    //
     (*declared_signature_result) = m->signature();
   }
   return m;
 }
 

@@ -406,27 +482,14 @@
 // ------------------------------------------------------------------
 // ciBytecodeStream::has_method_type
 //
 // Returns true if there is a MethodType argument stored in the
 // constant pool cache at the current bci.
-bool ciBytecodeStream::has_method_type() {
-  GUARDED_VM_ENTRY(
-    constantPoolHandle cpool(_method->get_Method()->constants());
-    return ConstantPool::has_method_type_at_if_loaded(cpool, get_method_index());
-  )
-}
-
-// ------------------------------------------------------------------
-// ciBytecodeStream::get_method_type
-//
-// Return the MethodType stored in the constant pool cache at
-// the current bci.
-ciMethodType* ciBytecodeStream::get_method_type() {
+bool ciBytecodeStream::has_local_signature() {
   GUARDED_VM_ENTRY(
     constantPoolHandle cpool(_method->get_Method()->constants());
-    oop method_type_oop = ConstantPool::method_type_at_if_loaded(cpool, get_method_index());
-    return CURRENT_ENV->get_object(method_type_oop)->as_method_type();
+    return ConstantPool::has_local_signature_at_if_loaded(cpool, get_method_index());
   )
 }
 
 // ------------------------------------------------------------------
 // ciBytecodeStream::get_declared_method_holder
< prev index next >