--- old/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp 2017-11-30 15:39:03.610286042 +0000 +++ new/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp 2017-11-30 15:39:02.830252893 +0000 @@ -1606,6 +1606,7 @@ } void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) { + assert_different_registers(obj, rscratch1); Label update, next, none; verify_oop(obj); @@ -1766,6 +1767,7 @@ } void InterpreterMacroAssembler::profile_parameters_type(Register mdp, Register tmp1, Register tmp2) { + assert_different_registers(rscratch1, rscratch2, mdp, tmp1, tmp2); if (ProfileInterpreter && MethodData::profile_parameters()) { Label profile_continue, done; @@ -1773,8 +1775,8 @@ // Load the offset of the area within the MDO used for // parameters. If it's negative we're not profiling any parameters - ldr(tmp1, Address(mdp, in_bytes(MethodData::parameters_type_data_di_offset()) - in_bytes(MethodData::data_offset()))); - tbnz(tmp1, 63, profile_continue); // i.e. sign bit set + ldrw(tmp1, Address(mdp, in_bytes(MethodData::parameters_type_data_di_offset()) - in_bytes(MethodData::data_offset()))); + tbnz(tmp1, 31, profile_continue); // i.e. sign bit set // Compute a pointer to the area for parameters from the offset // and move the pointer to the slot for the last --- old/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp 2017-11-30 15:39:06.774420507 +0000 +++ new/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp 2017-11-30 15:39:06.038389228 +0000 @@ -998,12 +998,12 @@ void atomic_xchgalw(Register prev, Register newv, Register addr); void orptr(Address adr, RegisterOrConstant src) { - ldr(rscratch2, adr); + ldr(rscratch1, adr); if (src.is_register()) - orr(rscratch2, rscratch2, src.as_register()); + orr(rscratch1, rscratch1, src.as_register()); else - orr(rscratch2, rscratch2, src.as_constant()); - str(rscratch2, adr); + orr(rscratch1, rscratch1, src.as_constant()); + str(rscratch1, adr); } // A generic CAS; success or failure is in the EQ flag. --- old/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp 2017-11-30 15:39:09.854551399 +0000 +++ new/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp 2017-11-30 15:39:09.126520461 +0000 @@ -1662,6 +1662,14 @@ __ mov(rscratch2, true); __ strb(rscratch2, do_not_unlock_if_synchronized); + Label no_mdp; + Register mdp = r3; + __ ldr(mdp, Address(rmethod, Method::method_data_offset())); + __ cbz(mdp, no_mdp); + __ add(mdp, mdp, in_bytes(MethodData::data_offset())); + __ profile_parameters_type(mdp, r1, r2); + __ bind(no_mdp); + // increment invocation count & check for overflow Label invocation_counter_overflow; Label profile_method; --- /dev/null 2017-11-12 17:59:49.826578000 +0000 +++ new/test/hotspot/jtreg/compiler/profiling/TestTypeProfiling.java 2017-11-30 15:39:11.790633673 +0000 @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2018, 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. + */ + + /** + * @test + * @bug 8189439 + * @summary Parameters type profiling is not performed from aarch64 interpreter + * @requires vm.flavor == "server" & !vm.emulatedClient & !vm.graal.enabled + * @library /test/lib / + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+WhiteBoxAPI -XX:-BackgroundCompilation -XX:-UseOnStackReplacement + * -server -XX:-TieredCompilation -XX:TypeProfileLevel=020 + * compiler.profiling.TestTypeProfiling + * @run main/othervm -Xbootclasspath/a:. -XX:+WhiteBoxAPI -XX:-BackgroundCompilation -XX:-UseOnStackReplacement + * -server -XX:-TieredCompilation -XX:TypeProfileLevel=200 + * compiler.profiling.TestTypeProfiling + */ + +package compiler.profiling; + +import jdk.test.lib.Platform; +import sun.hotspot.WhiteBox; +import compiler.whitebox.CompilerWhiteBoxTest; +import java.lang.reflect.Method; + +public class TestTypeProfiling { + + public static int[] mParamTypeCheck(Object in) { + try { + return (int[]) in; + } catch (ClassCastException cce) { + return null; + } + } + + static Object x2(Object src) { + return src; + } + + public static int[] mRetTypeCheck(Object in) { + try { + Object out = x2(in); + return (int[]) out; + } catch (ClassCastException cce) { + return null; + } + } + + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + private static final int TIERED_STOP_AT_LEVEL = WHITE_BOX.getIntxVMFlag("TieredStopAtLevel").intValue(); + + static boolean deoptimize(Method method, Object src_obj) throws Exception { + for (int i = 0; i < 10; i++) { + method.invoke(null, src_obj); + if (!WHITE_BOX.isMethodCompiled(method)) { + return true; + } + } + return false; + } + + static public void main(String[] args) throws Exception { + if (!Platform.isServer() || Platform.isEmulatedClient()) { + throw new Error("TESTBUG: Not server mode"); + } + // Only execute if C2 is available + if (TIERED_STOP_AT_LEVEL != CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION) { + throw new RuntimeException("please enable C2"); + } + + Method method; + if (WHITE_BOX.getUintxVMFlag("TypeProfileLevel") == 20) { + method = TestTypeProfiling.class.getMethod("mRetTypeCheck", Object.class); + } else + if (WHITE_BOX.getUintxVMFlag("TypeProfileLevel") == 200) { + method = TestTypeProfiling.class.getMethod("mParamTypeCheck", Object.class); + } else { + throw new RuntimeException("please setup method return/params type profilation: -XX:TypeProfileLevel=020/200"); + } + + int[] src = new int[10]; + Object src_obj = new Object(); + + // Warm up & make sure we collect type profiling + for (int i = 0; i < 20000; i++) { + mParamTypeCheck(src); + mRetTypeCheck(src); + } + + // And make sure the method is compiled by C2 + WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + if (!WHITE_BOX.isMethodCompiled(method)) { + throw new RuntimeException(method.getName() + " is not compiled"); + } + + // should deoptimize for speculative type check + if (!deoptimize(method, src_obj)) { + throw new RuntimeException(method.getName() + " is not deoptimized"); + } + + // compile again + WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + if (!WHITE_BOX.isMethodCompiled(method)) { + throw new RuntimeException(method.getName() + " is not recompiled"); + } + + // should deoptimize for actual type check + if (!deoptimize(method, src_obj)) { + throw new RuntimeException(method.getName() + " is not deoptimized (should deoptimize for actual type check)"); + } + + // compile once again + WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + if (!WHITE_BOX.isMethodCompiled(method)) { + throw new RuntimeException(method.getName() + " is not recompiled"); + } + + // this time new parameter type should not force deoptimization + if (deoptimize(method, src_obj)) { + throw new RuntimeException(method.getName() + " is deoptimized again"); + } + } +}