changeset 4525:41ed397cc0cd

8006267: InterfaceMethod_ref should allow invokestatic and invokespecial Summary: Lambda changes; spec 0.6.2 - Allow static invokestatic and invokespecial calls to InterfaceMethod_ref Reviewed-by: dholmes, acorn
author bharadwaj
date Thu, 18 Apr 2013 08:05:35 -0700
parents 63e31ce40bdb
children 7815eaceaa8c
files src/share/vm/classfile/classFileParser.cpp src/share/vm/classfile/genericSignatures.cpp src/share/vm/interpreter/linkResolver.cpp src/share/vm/prims/methodHandles.cpp
diffstat 4 files changed, 44 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/classfile/classFileParser.cpp	Wed Apr 17 08:20:02 2013 -0400
+++ b/src/share/vm/classfile/classFileParser.cpp	Thu Apr 18 08:05:35 2013 -0700
@@ -436,14 +436,19 @@
               ref_index, CHECK_(nullHandle));
             break;
           case JVM_REF_invokeVirtual:
-          case JVM_REF_invokeStatic:
-          case JVM_REF_invokeSpecial:
           case JVM_REF_newInvokeSpecial:
             check_property(
               tag.is_method(),
               "Invalid constant pool index %u in class file %s (not a method)",
               ref_index, CHECK_(nullHandle));
             break;
+          case JVM_REF_invokeStatic:
+          case JVM_REF_invokeSpecial:
+            check_property(
+               tag.is_method() || tag.is_interface_method(),
+               "Invalid constant pool index %u in class file %s (not a method)",
+               ref_index, CHECK_(nullHandle));
+             break;
           case JVM_REF_invokeInterface:
             check_property(
               tag.is_interface_method(),
@@ -3837,7 +3842,7 @@
     }
 
     if (TraceClassLoadingPreorder) {
-      tty->print("[Loading %s", name->as_klass_external_name());
+      tty->print("[Loading %s", (name != NULL) ? name->as_klass_external_name() : "NoName");
       if (cfs->source() != NULL) tty->print(" from %s", cfs->source());
       tty->print_cr("]");
     }
--- a/src/share/vm/classfile/genericSignatures.cpp	Wed Apr 17 08:20:02 2013 -0400
+++ b/src/share/vm/classfile/genericSignatures.cpp	Thu Apr 18 08:05:35 2013 -0700
@@ -268,8 +268,15 @@
     Klass* outer = SystemDictionary::find(
         outer_name, class_loader, protection_domain, CHECK_NULL);
     if (outer == NULL && !THREAD->is_Compiler_thread()) {
-      outer = SystemDictionary::resolve_super_or_fail(original_name,
-          outer_name, class_loader, protection_domain, false, CHECK_NULL);
+      if (outer_name == ik->super()->name()) {
+        outer = SystemDictionary::resolve_super_or_fail(original_name, outer_name,
+                                                        class_loader, protection_domain,
+                                                        false, CHECK_NULL);
+      }
+      else {
+        outer = SystemDictionary::resolve_or_fail(outer_name, class_loader,
+                                                  protection_domain, false, CHECK_NULL);
+      }
     }
 
     InstanceKlass* outer_ik;
--- a/src/share/vm/interpreter/linkResolver.cpp	Wed Apr 17 08:20:02 2013 -0400
+++ b/src/share/vm/interpreter/linkResolver.cpp	Thu Apr 18 08:05:35 2013 -0700
@@ -1014,13 +1014,28 @@
                                                       resolved_method->name(),
                                                       resolved_method->signature()));
   }
-  // check if public
-  if (!sel_method->is_public()) {
-    ResourceMark rm(THREAD);
-    THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
-              Method::name_and_sig_as_C_string(recv_klass(),
-                                                      sel_method->name(),
-                                                      sel_method->signature()));
+  // check access
+  if (sel_method->method_holder()->is_interface()) {
+    // Method holder is an interface. Throw Illegal Access Error if sel_method
+    // is neither public nor private.
+    if (!(sel_method->is_public() || sel_method->is_private())) {
+      ResourceMark rm(THREAD);
+      THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
+                Method::name_and_sig_as_C_string(recv_klass(),
+                                                 sel_method->name(),
+                                                 sel_method->signature()));
+    }
+  }
+  else {
+    // Method holder is a class. Throw Illegal Access Error if sel_method
+    // is not public.
+    if (!sel_method->is_public()) {
+      ResourceMark rm(THREAD);
+      THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
+                Method::name_and_sig_as_C_string(recv_klass(),
+                                                 sel_method->name(),
+                                                 sel_method->signature()));
+    }
   }
   // check if abstract
   if (check_null_and_abstract && sel_method->is_abstract()) {
--- a/src/share/vm/prims/methodHandles.cpp	Wed Apr 17 08:20:02 2013 -0400
+++ b/src/share/vm/prims/methodHandles.cpp	Thu Apr 18 08:05:35 2013 -0700
@@ -187,6 +187,11 @@
     flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
   } else if (mods.is_static()) {
     flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT);
+     // Check if this method is a lambda method that is generated as
+     // private static method.
+     if (m->is_private() && 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