# HG changeset patch # User dholmes # Date 1551396503 18000 # Node ID 86ee52ca11e3ce10e809fd3eef450b307d8b96a1 # Parent 393348e562c17fbeafedc6c1b10dcdc5679572d5 8219492: Restore static callsite resolution for the current class Reviewed-by: redestad, lfoltan, vlivanov diff -r 393348e562c1 -r 86ee52ca11e3 src/hotspot/share/interpreter/interpreterRuntime.cpp --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp Thu Feb 28 14:05:58 2019 -0800 +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp Thu Feb 28 18:28:23 2019 -0500 @@ -920,19 +920,23 @@ info.call_kind() == CallInfo::vtable_call, ""); } #endif - // Get sender or sender's unsafe_anonymous_host, and only set cpCache entry to resolved if - // it is not an interface. The receiver for invokespecial calls within interface - // methods must be checked for every call. - InstanceKlass* sender = pool->pool_holder(); - sender = sender->is_unsafe_anonymous() ? sender->unsafe_anonymous_host() : sender; switch (info.call_kind()) { - case CallInfo::direct_call: + case CallInfo::direct_call: { + // Get sender or sender's unsafe_anonymous_host, and only set cpCache entry to resolved if + // it is not an interface. The receiver for invokespecial calls within interface + // methods must be checked for every call. + InstanceKlass* pool_holder = pool->pool_holder(); + InstanceKlass* sender = pool_holder->is_unsafe_anonymous() ? + pool_holder->unsafe_anonymous_host() : pool_holder; + cp_cache_entry->set_direct_call( bytecode, info.resolved_method(), - sender->is_interface()); + sender->is_interface(), + pool_holder); break; + } case CallInfo::vtable_call: cp_cache_entry->set_vtable_call( bytecode, diff -r 393348e562c1 -r 86ee52ca11e3 src/hotspot/share/oops/cpCache.cpp --- a/src/hotspot/share/oops/cpCache.cpp Thu Feb 28 14:05:58 2019 -0800 +++ b/src/hotspot/share/oops/cpCache.cpp Thu Feb 28 18:28:23 2019 -0500 @@ -168,7 +168,8 @@ void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_code, const methodHandle& method, int vtable_index, - bool sender_is_interface) { + bool sender_is_interface, + InstanceKlass* pool_holder) { bool is_vtable_call = (vtable_index >= 0); // FIXME: split this method on this boolean assert(method->interpreter_entry() != NULL, "should have been set at this point"); assert(!method->is_obsolete(), "attempt to write obsolete method to cpCache"); @@ -263,11 +264,17 @@ } // 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()) { + // we resolve it before then that class initialization check is skipped. However if the call + // is from the same class we can resolve as we must be executing with on our call stack. + if (invoke_code == Bytecodes::_invokestatic && + !method->method_holder()->is_initialized() && + method->method_holder() != pool_holder) { do_resolve = false; } if (do_resolve) { + assert(method->method_holder()->is_initialized() || + method->method_holder()->is_reentrant_initialization(Thread::current()), + "invalid class initalization state"); set_bytecode_1(invoke_code); } } else if (byte_no == 2) { @@ -310,17 +317,17 @@ } void ConstantPoolCacheEntry::set_direct_call(Bytecodes::Code invoke_code, const methodHandle& method, - bool sender_is_interface) { + bool sender_is_interface, InstanceKlass* pool_holder) { int index = Method::nonvirtual_vtable_index; // index < 0; FIXME: inline and customize set_direct_or_vtable_call - set_direct_or_vtable_call(invoke_code, method, index, sender_is_interface); + set_direct_or_vtable_call(invoke_code, method, index, sender_is_interface, pool_holder); } void ConstantPoolCacheEntry::set_vtable_call(Bytecodes::Code invoke_code, const methodHandle& method, int index) { // either the method is a miranda or its holder should accept the given index assert(method->method_holder()->is_interface() || method->method_holder()->verify_vtable_index(index), ""); // index >= 0; FIXME: inline and customize set_direct_or_vtable_call - set_direct_or_vtable_call(invoke_code, method, index, false); + set_direct_or_vtable_call(invoke_code, method, index, false, NULL /* not used */); } void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, diff -r 393348e562c1 -r 86ee52ca11e3 src/hotspot/share/oops/cpCache.hpp --- a/src/hotspot/share/oops/cpCache.hpp Thu Feb 28 14:05:58 2019 -0800 +++ b/src/hotspot/share/oops/cpCache.hpp Thu Feb 28 18:28:23 2019 -0500 @@ -230,14 +230,16 @@ Bytecodes::Code invoke_code, // the bytecode used for invoking the method const methodHandle& method, // the method/prototype if any (NULL, otherwise) int vtable_index, // the vtable index if any, else negative - bool sender_is_interface + bool sender_is_interface, // 'logical' sender (may be host of VMAC) + InstanceKlass* pool_holder // class from which the call is made ); public: void set_direct_call( // sets entry to exact concrete method entry Bytecodes::Code invoke_code, // the bytecode used for invoking the method const methodHandle& method, // the method to call - bool sender_is_interface + bool sender_is_interface, // 'logical' sender (may be host of VMAC) + InstanceKlass* pool_holder // class from which the call is made ); void set_vtable_call( // sets entry to vtable index diff -r 393348e562c1 -r 86ee52ca11e3 src/hotspot/share/runtime/sharedRuntime.cpp --- a/src/hotspot/share/runtime/sharedRuntime.cpp Thu Feb 28 14:05:58 2019 -0800 +++ b/src/hotspot/share/runtime/sharedRuntime.cpp Thu Feb 28 18:28:23 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1376,13 +1376,17 @@ } #endif - // Do not patch call site for static call when the class is not - // fully initialized. + // Do not patch call site for static call to another class + // when the class is not fully initialized. if (invoke_code == Bytecodes::_invokestatic && - !callee_method->method_holder()->is_initialized()) { + !callee_method->method_holder()->is_initialized() && + callee_method->method_holder() != caller_nm->method()->method_holder()) { assert(callee_method->method_holder()->is_linked(), "must be"); return callee_method; } + assert(callee_method->method_holder()->is_initialized() || + callee_method->method_holder()->is_reentrant_initialization(thread), + "invalid class initalization state"); // JSR 292 key invariant: // If the resolved method is a MethodHandle invoke target, the call