< prev index next >

src/hotspot/share/oops/cpCache.cpp

Print this page

        

@@ -171,21 +171,41 @@
   assert(method->interpreter_entry() != NULL, "should have been set at this point");
   assert(!method->is_obsolete(),  "attempt to write obsolete method to cpCache");
 
   int byte_no = -1;
   bool change_to_virtual = false;
-
+  InstanceKlass* holder = NULL;  // have to declare this outside the switch
   switch (invoke_code) {
     case Bytecodes::_invokeinterface:
+      holder = method->method_holder();
+      // check for private interface method invocations
+      if (vtable_index == Method::nonvirtual_vtable_index && holder->is_interface() ) {
+        assert(method->is_private(), "unexpected non-private method");
+        assert(method->can_be_statically_bound(), "unexpected non-statically-bound method");
+        // set_f2_as_vfinal_method checks if is_vfinal flag is true.
+        set_method_flags(as_TosState(method->result_type()),
+                         (                             1      << is_vfinal_shift) |
+                         ((method->is_final_method() ? 1 : 0) << is_final_shift),
+                         method()->size_of_parameters());
+        set_f2_as_vfinal_method(method());
+        byte_no = 2;
+        set_f1(holder); // interface klass*
+        break;
+      }
+      else {
       // We get here from InterpreterRuntime::resolve_invoke when an invokeinterface
-      // instruction somehow links to a non-interface method (in Object).
+        // instruction links to a non-interface method (in Object). This can happen when
+        // an interface redeclares an Object method (like CharSequence declaring toString())
+        // or when invokeinterface is used explicitly.
       // In that case, the method has no itable index and must be invoked as a virtual.
       // Set a flag to keep track of this corner case.
+        assert(holder->is_interface() || holder == SystemDictionary::Object_klass(), "unexpected holder class");
       assert(method->is_public(), "Calling non-public method in Object with invokeinterface");
       change_to_virtual = true;
 
       // ...and fall through as if we were handling invokevirtual:
+      }
     case Bytecodes::_invokevirtual:
       {
         if (!is_vtable_call) {
           assert(method->can_be_statically_bound(), "");
           // set_f2_as_vfinal_method checks if is_vfinal flag is true.

@@ -254,11 +274,22 @@
       // because the actual selected method may not be public.
       //
       // We set bytecode_2() to _invokevirtual.
       // See also interpreterRuntime.cpp. (8/25/2000)
     } else {
-      assert(invoke_code == Bytecodes::_invokevirtual, "");
+      assert(invoke_code == Bytecodes::_invokevirtual ||
+             (invoke_code == Bytecodes::_invokeinterface &&
+              ((method->is_private() ||
+                (method->is_final() && method->method_holder() == SystemDictionary::Object_klass())))),
+             "unexpected invocation mode");
+      if (invoke_code == Bytecodes::_invokeinterface &&
+          (method->is_private() || method->is_final())) {
+        // We set bytecode_1() to _invokeinterface, because that is the
+        // bytecode # used by the interpreter to see if it is resolved.
+        // We set bytecode_2() to _invokevirtual.
+        set_bytecode_1(invoke_code);
+      }
     }
     // set up for invokevirtual, even if linking for invokeinterface also:
     set_bytecode_2(Bytecodes::_invokevirtual);
   } else {
     ShouldNotReachHere();
< prev index next >