8026022: Verifier: allow anon classes to invokespecial host class/intf methods.
authoracorn
Tue, 08 Oct 2013 16:58:23 -0400
changeset 20395 55915f609319
parent 20394 2868e32b6fd0
child 20396 0ed0e7aa1ed8
8026022: Verifier: allow anon classes to invokespecial host class/intf methods. Reviewed-by: coleenp, bharadwaj
hotspot/src/share/vm/classfile/verifier.cpp
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Tue Oct 08 11:37:54 2013 +0200
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Tue Oct 08 16:58:23 2013 -0400
@@ -2442,10 +2442,16 @@
     bool subtype = ref_class_type.is_assignable_from(
       current_type(), this, CHECK_VERIFY(this));
     if (!subtype) {
-      verify_error(ErrorContext::bad_code(bci),
-          "Bad invokespecial instruction: "
-          "current class isn't assignable to reference class.");
-       return;
+      if (current_class()->is_anonymous()) {
+        subtype = ref_class_type.is_assignable_from(VerificationType::reference_type(
+                   current_class()->host_klass()->name()), this, CHECK_VERIFY(this));
+      }
+      if (!subtype) {
+        verify_error(ErrorContext::bad_code(bci),
+            "Bad invokespecial instruction: "
+            "current class isn't assignable to reference class.");
+         return;
+      }
     }
   }
   // Match method descriptor with operand stack
@@ -2461,7 +2467,28 @@
     } else {   // other methods
       // Ensures that target class is assignable to method class.
       if (opcode == Bytecodes::_invokespecial) {
-        current_frame->pop_stack(current_type(), CHECK_VERIFY(this));
+        if (!current_class()->is_anonymous()) {
+          current_frame->pop_stack(current_type(), CHECK_VERIFY(this));
+        } else {
+          // anonymous class invokespecial calls: either the
+          // operand stack/objectref  is a subtype of the current class OR
+          // the objectref is a subtype of the host_klass of the current class
+          // to allow an anonymous class to reference methods in the host_klass
+          VerificationType top = current_frame->pop_stack(CHECK_VERIFY(this));
+          bool subtype = current_type().is_assignable_from(top, this, CHECK_VERIFY(this));
+          if (!subtype) {
+            VerificationType hosttype =
+              VerificationType::reference_type(current_class()->host_klass()->name());
+            subtype = hosttype.is_assignable_from(top, this, CHECK_VERIFY(this));
+          }
+          if (!subtype) {
+            verify_error( ErrorContext::bad_type(current_frame->offset(),
+              current_frame->stack_top_ctx(),
+              TypeOrigin::implicit(top)),
+              "Bad type on operand stack");
+            return;
+          }
+        }
       } else if (opcode == Bytecodes::_invokevirtual) {
         VerificationType stack_object_type =
           current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this));