8205714: Initial class initialization
authordholmes
Sun, 12 Aug 2018 18:05:16 -0400
changeset 53315 3d4e47348142
parent 53314 827db73f2d6a
child 53316 066d2261108f
8205714: Initial class initialization Summary: ensure class is fully initialized before caching a resolved invokestatic, or patching the callsite Reviewed-by: acorn, coleenp, kvn, vlivanov
src/hotspot/share/oops/cpCache.cpp
src/hotspot/share/runtime/sharedRuntime.cpp
--- a/src/hotspot/share/oops/cpCache.cpp	Tue Jul 31 11:43:24 2018 +0530
+++ b/src/hotspot/share/oops/cpCache.cpp	Sun Aug 12 18:05:16 2018 -0400
@@ -253,11 +253,21 @@
   if (byte_no == 1) {
     assert(invoke_code != Bytecodes::_invokevirtual &&
            invoke_code != Bytecodes::_invokeinterface, "");
+    bool do_resolve = true;
     // Don't mark invokespecial to method as resolved if sender is an interface.  The receiver
     // has to be checked that it is a subclass of the current class every time this bytecode
     // is executed.
-    if (invoke_code != Bytecodes::_invokespecial || !sender_is_interface ||
-        method->name() == vmSymbols::object_initializer_name()) {
+    if (invoke_code == Bytecodes::_invokespecial && sender_is_interface &&
+        method->name() != vmSymbols::object_initializer_name()) {
+      do_resolve = false;
+    }
+    // Don't mark invokestatic to method as resolved if the holder class has not yet completed
+    // initialization. An invokestatic must only proceed if the class is initialized, but if
+    // we resolve it before then that class initialization check is skipped.
+    if (invoke_code == Bytecodes::_invokestatic && !method->method_holder()->is_initialized()) {
+      do_resolve = false;
+    }
+    if (do_resolve) {
       set_bytecode_1(invoke_code);
     }
   } else if (byte_no == 2)  {
--- a/src/hotspot/share/runtime/sharedRuntime.cpp	Tue Jul 31 11:43:24 2018 +0530
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp	Sun Aug 12 18:05:16 2018 -0400
@@ -1376,6 +1376,14 @@
   }
 #endif
 
+  // Do not patch call site for static call when the class is not
+  // fully initialized.
+  if (invoke_code == Bytecodes::_invokestatic &&
+      !callee_method->method_holder()->is_initialized()) {
+    assert(callee_method->method_holder()->is_linked(), "must be");
+    return callee_method;
+  }
+
   // JSR 292 key invariant:
   // If the resolved method is a MethodHandle invoke target, the call
   // site must be a MethodHandle call site, because the lambda form might tail-call