8189439: Parameters type profiling is not performed from aarch64 interpreter
authordpochepk
Fri, 01 Dec 2017 18:24:52 +0300
changeset 48183 ee8e37f85775
parent 48182 5fb0f3f24f6b
child 48184 aed61a8ce8f9
8189439: Parameters type profiling is not performed from aarch64 interpreter Reviewed-by: vlivanov Contributed-by: boris.ulasevich@bell-sw.com
src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp
src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp
test/hotspot/jtreg/compiler/profiling/TestTypeProfiling.java
--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp	Fri Dec 01 18:20:00 2017 +0300
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp	Fri Dec 01 18:24:52 2017 +0300
@@ -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
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp	Fri Dec 01 18:20:00 2017 +0300
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp	Fri Dec 01 18:24:52 2017 +0300
@@ -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.
--- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp	Fri Dec 01 18:20:00 2017 +0300
+++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp	Fri Dec 01 18:24:52 2017 +0300
@@ -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	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/profiling/TestTypeProfiling.java	Fri Dec 01 18:24:52 2017 +0300
@@ -0,0 +1,146 @@
+/*
+ * 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.compMode == "Xmixed" & !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:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+  *                   -XX:-BackgroundCompilation -XX:-UseOnStackReplacement
+  *                   -server -XX:-TieredCompilation -XX:TypeProfileLevel=020
+  *                    compiler.profiling.TestTypeProfiling
+  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -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");
+        }
+    }
+}