1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24  /**
  25   * @test
  26   * @bug 8189439
  27   * @summary Parameters type profiling is not performed from aarch64 interpreter
  28   * @requires vm.flavor == "server" & vm.compMode == "Xmixed" & !vm.emulatedClient & !vm.graal.enabled
  29   * @library /test/lib /
  30   * @build sun.hotspot.WhiteBox
  31   * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
  32   * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  33   *                   -XX:-BackgroundCompilation -XX:-UseOnStackReplacement
  34   *                   -XX:CompileThreshold=10000
  35   *                   -server -XX:-TieredCompilation -XX:TypeProfileLevel=020
  36   *                    compiler.profiling.TestTypeProfiling
  37   * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  38   *                   -XX:-BackgroundCompilation -XX:-UseOnStackReplacement
  39   *                   -XX:CompileThreshold=10000
  40   *                   -server -XX:-TieredCompilation -XX:TypeProfileLevel=200
  41   *                    compiler.profiling.TestTypeProfiling
  42   */
  43 
  44 package compiler.profiling;
  45 
  46 import jdk.test.lib.Platform;
  47 import sun.hotspot.WhiteBox;
  48 import compiler.whitebox.CompilerWhiteBoxTest;
  49 import java.lang.reflect.Method;
  50 
  51 public class TestTypeProfiling {
  52 
  53     public static int[] mParamTypeCheck(Object in) {
  54         try {
  55             return (int[]) in;
  56         } catch (ClassCastException cce) {
  57             return null;
  58         }
  59     }
  60 
  61     static Object x2(Object src) {
  62         return src;
  63     }
  64 
  65     public static int[] mRetTypeCheck(Object in) {
  66         try {
  67             Object out = x2(in);
  68             return (int[]) out;
  69         } catch (ClassCastException cce) {
  70             return null;
  71         }
  72     }
  73 
  74     private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
  75     private static final int TIERED_STOP_AT_LEVEL = WHITE_BOX.getIntxVMFlag("TieredStopAtLevel").intValue();
  76 
  77     static boolean deoptimize(Method method, Object src_obj) throws Exception {
  78         for (int i = 0; i < 10; i++) {
  79             method.invoke(null, src_obj);
  80             if (!WHITE_BOX.isMethodCompiled(method)) {
  81                 return true;
  82             }
  83         }
  84         return false;
  85     }
  86 
  87     static public void main(String[] args) throws Exception {
  88         if (!Platform.isServer() || Platform.isEmulatedClient()) {
  89             throw new Error("TESTBUG: Not server mode");
  90         }
  91         // Only execute if C2 is available
  92         if (TIERED_STOP_AT_LEVEL != CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION) {
  93             throw new RuntimeException("please enable C2");
  94         }
  95 
  96         Method method;
  97         if (WHITE_BOX.getUintxVMFlag("TypeProfileLevel") == 20) {
  98             method = TestTypeProfiling.class.getMethod("mRetTypeCheck", Object.class);
  99         } else
 100         if (WHITE_BOX.getUintxVMFlag("TypeProfileLevel") == 200) {
 101             method = TestTypeProfiling.class.getMethod("mParamTypeCheck", Object.class);
 102         } else {
 103             throw new RuntimeException("please setup method return/params type profilation: -XX:TypeProfileLevel=020/200");
 104         }
 105 
 106         int[] src = new int[10];
 107         Object src_obj = new Object();
 108 
 109         // Warm up & make sure we collect type profiling
 110         for (int i = 0; i < 20000; i++) {
 111             mParamTypeCheck(src);
 112             mRetTypeCheck(src);
 113         }
 114 
 115         // And make sure the method is compiled by C2
 116         WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
 117         if (!WHITE_BOX.isMethodCompiled(method)) {
 118             throw new RuntimeException(method.getName() + " is not compiled");
 119         }
 120 
 121         // should deoptimize for speculative type check
 122         // Intepreter will also add actual type check trap information into MDO
 123         // when it throw ClassCastException
 124         if (!deoptimize(method, src_obj)) {
 125             throw new RuntimeException(method.getName() + " is not deoptimized");
 126         }
 127 
 128         // compile again
 129         // c2 will generate throw instead of uncommon trap because
 130         // actual type check trap information is present in MDO
 131         WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
 132         if (!WHITE_BOX.isMethodCompiled(method)) {
 133             throw new RuntimeException(method.getName() + " is not recompiled");
 134         }
 135 
 136         // this time new parameter type should not force deoptimization
 137         if (deoptimize(method, src_obj)) {
 138             throw new RuntimeException(method.getName() + " is deoptimized again");
 139         }
 140     }
 141 }