8013875: Incorrect vtable index being set during methodHandle creation for static
authorbharadwaj
Wed, 08 May 2013 14:18:03 -0700
changeset 17364 cf8b9767e64c
parent 17363 9989d42bbb52
child 17367 64c84d620e5c
8013875: Incorrect vtable index being set during methodHandle creation for static Summary: Set vtable index as appropriate for static interface methods and for interface methods invoked via invokespecial. To be improved in a later enhancement to CallInfo. Reviewed-by: jrose, twisti
hotspot/src/share/vm/prims/methodHandles.cpp
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Wed May 08 10:14:57 2013 -0400
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Wed May 08 14:18:03 2013 -0700
@@ -193,19 +193,15 @@
     flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
   } else if (mods.is_static()) {
     flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT);
-     // Get vindex from itable if method holder is an interface.
-     if (m->method_holder()->is_interface()) {
-       vmindex = klassItable::compute_itable_index(m);
-     }
   } else if (receiver_limit != mklass &&
              !receiver_limit->is_subtype_of(mklass)) {
     return NULL;  // bad receiver limit
-  } else if (receiver_limit->is_interface() &&
+  } else if (do_dispatch && receiver_limit->is_interface() &&
              mklass->is_interface()) {
     flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT);
     receiver_limit = mklass;  // ignore passed-in limit; interfaces are interconvertible
     vmindex = klassItable::compute_itable_index(m);
-  } else if (mklass != receiver_limit && mklass->is_interface()) {
+  } else if (do_dispatch && mklass != receiver_limit && mklass->is_interface()) {
     flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
     // it is a miranda method, so m->vtable_index is not what we want
     ResourceMark rm;
@@ -250,10 +246,25 @@
   }
   methodHandle m = info.resolved_method();
   KlassHandle defc = info.resolved_klass();
-  int vmindex = -1;
+  int vmindex = Method::invalid_vtable_index;
   if (defc->is_interface() && m->method_holder()->is_interface()) {
-    // LinkResolver does not report itable indexes!  (fix this?)
-    vmindex = klassItable::compute_itable_index(m());
+    // static interface methods do not reference vtable or itable
+    if (m->is_static()) {
+      vmindex = Method::nonvirtual_vtable_index;
+    }
+    // interface methods invoked via invokespecial also
+    // do not reference vtable or itable.
+    int ref_kind = ((java_lang_invoke_MemberName::flags(mname()) >>
+                     REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK);
+    if (ref_kind == JVM_REF_invokeSpecial) {
+      vmindex = Method::nonvirtual_vtable_index;
+    }
+    // If neither m is static nor ref_kind is invokespecial,
+    // set it to itable index.
+    if (vmindex == Method::invalid_vtable_index) {
+      // LinkResolver does not report itable indexes!  (fix this?)
+      vmindex = klassItable::compute_itable_index(m());
+    }
   } else if (m->can_be_statically_bound()) {
     // LinkResolver reports vtable index even for final methods!
     vmindex = Method::nonvirtual_vtable_index;
@@ -665,11 +676,9 @@
   case IS_METHOD:
     {
       CallInfo result;
-      bool do_dispatch = true;  // default, neutral setting
       {
         assert(!HAS_PENDING_EXCEPTION, "");
         if (ref_kind == JVM_REF_invokeStatic) {
-          //do_dispatch = false;  // no need, since statics are never dispatched
           LinkResolver::resolve_static_call(result,
                         defc, name, type, KlassHandle(), false, false, THREAD);
         } else if (ref_kind == JVM_REF_invokeInterface) {
@@ -680,7 +689,6 @@
           LinkResolver::resolve_handle_call(result,
                         defc, name, type, KlassHandle(), THREAD);
         } else if (ref_kind == JVM_REF_invokeSpecial) {
-          do_dispatch = false;  // force non-virtual linkage
           LinkResolver::resolve_special_call(result,
                         defc, name, type, KlassHandle(), false, THREAD);
         } else if (ref_kind == JVM_REF_invokeVirtual) {