--- old/src/hotspot/share/runtime/sharedRuntime.cpp 2019-11-14 15:42:09.443607415 +0100 +++ new/src/hotspot/share/runtime/sharedRuntime.cpp 2019-11-14 15:42:08.963607422 +0100 @@ -1054,6 +1054,21 @@ methodHandle caller(THREAD, vfst.method()); int bci = vfst.bci(); + // Substitutability test implementation piggy backs on static call resolution + Bytecodes::Code code = caller->java_code_at(bci); + if (code == Bytecodes::_if_acmpeq || code == Bytecodes::_if_acmpne) { + bc = Bytecodes::_invokestatic; + methodHandle attached_method = extract_attached_method(vfst); + assert(attached_method.not_null(), "must have attached method"); + LinkResolver::resolve_invoke(callinfo, receiver, attached_method, bc, CHECK_NH); +#ifdef ASSERT + SystemDictionary::ValueBootstrapMethods_klass()->initialize(CHECK_NH); + Method* is_subst = SystemDictionary::ValueBootstrapMethods_klass()->find_method(vmSymbols::isSubstitutable_name(), vmSymbols::object_object_boolean_signature()); + assert(callinfo.selected_method() == is_subst, "must be isSubstitutable method"); +#endif + return receiver; + } + Bytecode_invoke bytecode(caller, bci); int bytecode_index = bytecode.index(); bc = bytecode.invoke_code(); @@ -1357,16 +1372,6 @@ // CLEANUP - with lazy deopt shouldn't need this lock nmethodLocker caller_lock(caller_nm); - if (!is_virtual && !is_optimized) { - SimpleScopeDesc ssd(caller_nm, caller_frame.pc()); - Bytecode bc(ssd.method(), ssd.method()->bcp_from(ssd.bci())); - // Substitutability test implementation piggy backs on static call resolution - if (bc.code() == Bytecodes::_if_acmpeq || bc.code() == Bytecodes::_if_acmpne) { - SystemDictionary::ValueBootstrapMethods_klass()->initialize(CHECK_NULL); - return SystemDictionary::ValueBootstrapMethods_klass()->find_method(vmSymbols::isSubstitutable_name(), vmSymbols::object_object_boolean_signature()); - } - } - // determine call info & receiver // note: a) receiver is NULL for static calls // b) an exception is thrown if receiver is NULL for non-static calls --- /dev/null 2019-11-14 07:49:01.875999967 +0100 +++ new/test/hotspot/jtreg/compiler/valhalla/valuetypes/TestIsSubstitutableReresolution.java 2019-11-14 15:42:09.839607410 +0100 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.valhalla.valuetypes; +import jdk.test.lib.Asserts; + +/** + * @test + * @bug 8234108 + * @library /testlibrary /test/lib + * @summary Verify that call reresolution works for C2 compiled calls to java.lang.invoke.ValueBootstrapMethods::isSubstitutable0. + * @run main/othervm -XX:CompileCommand=dontinline,compiler.valhalla.valuetypes.TestIsSubstitutableReresolution::test + * compiler.valhalla.valuetypes.TestIsSubstitutableReresolution + */ +final inline class MyValue { + final int x; + + public MyValue(int x) { + this.x = x; + } +} + +public class TestIsSubstitutableReresolution { + + static boolean test(Object obj) { + MyValue vt = new MyValue(42); + return vt == obj; + } + + public static void main(String[] args) throws Exception { + MyValue vt1 = new MyValue(42); + MyValue vt2 = new MyValue(43); + for (int i = 0; i < 1_000_000; ++i) { + Asserts.assertEQ(test(vt1), true); + Asserts.assertEQ(test(vt2), false); + } + } +}