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.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:+WhiteBoxAPI -XX:-BackgroundCompilation -XX:-UseOnStackReplacement 
  33   *                   -server -XX:-TieredCompilation -XX:TypeProfileLevel=020
  34   *                    compiler.profiling.TestTypeProfiling
  35   * @run main/othervm -Xbootclasspath/a:. -XX:+WhiteBoxAPI -XX:-BackgroundCompilation -XX:-UseOnStackReplacement
  36   *                   -server -XX:-TieredCompilation -XX:TypeProfileLevel=200
  37   *                    compiler.profiling.TestTypeProfiling
  38   */
  39 
  40 package compiler.profiling;
  41 
  42 import jdk.test.lib.Platform;
  43 import sun.hotspot.WhiteBox;
  44 import compiler.whitebox.CompilerWhiteBoxTest;
  45 import java.lang.reflect.Method;
  46 
  47 public class TestTypeProfiling {
  48 
  49     public static int[] mParamTypeCheck(Object in) {
  50         try {
  51             return (int[]) in;
  52         } catch (ClassCastException cce) {
  53             return null;
  54         }
  55     }
  56 
  57     static Object x2(Object src) {
  58         return src;
  59     }
  60 
  61     public static int[] mRetTypeCheck(Object in) {
  62         try {
  63             Object out = x2(in); 
  64             return (int[]) out;
  65         } catch (ClassCastException cce) {
  66             return null;
  67         }
  68     }
  69 
  70     private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
  71     private static final int TIERED_STOP_AT_LEVEL = WHITE_BOX.getIntxVMFlag("TieredStopAtLevel").intValue();
  72 
  73     static boolean deoptimize(Method method, Object src_obj) throws Exception {
  74         for (int i = 0; i < 10; i++) {
  75             method.invoke(null, src_obj);
  76             if (!WHITE_BOX.isMethodCompiled(method)) {
  77                 return true;
  78             }
  79         }
  80         return false;
  81     }
  82 
  83     static public void main(String[] args) throws Exception {
  84         if (!Platform.isServer() || Platform.isEmulatedClient()) {
  85             throw new Error("TESTBUG: Not server mode");
  86         }
  87         // Only execute if C2 is available
  88         if (TIERED_STOP_AT_LEVEL != CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION) {
  89             throw new RuntimeException("please enable C2");
  90         }
  91 
  92         Method method;
  93         if (WHITE_BOX.getUintxVMFlag("TypeProfileLevel") == 20) {
  94             method = TestTypeProfiling.class.getMethod("mRetTypeCheck", Object.class);
  95         } else 
  96         if (WHITE_BOX.getUintxVMFlag("TypeProfileLevel") == 200) {
  97             method = TestTypeProfiling.class.getMethod("mParamTypeCheck", Object.class);
  98         } else {
  99             throw new RuntimeException("please setup method return/params type profilation: -XX:TypeProfileLevel=020/200");
 100         }
 101 
 102         int[] src = new int[10];
 103         Object src_obj = new Object();
 104 
 105         // Warm up & make sure we collect type profiling
 106         for (int i = 0; i < 20000; i++) {
 107             mParamTypeCheck(src);
 108             mRetTypeCheck(src);
 109         }
 110 
 111         // And make sure the method is compiled by C2
 112         WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
 113         if (!WHITE_BOX.isMethodCompiled(method)) {
 114             throw new RuntimeException(method.getName() + " is not compiled");
 115         }
 116 
 117         // should deoptimize for speculative type check
 118         if (!deoptimize(method, src_obj)) {
 119             throw new RuntimeException(method.getName() + " is not deoptimized");
 120         }
 121 
 122         // compile again
 123         WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
 124         if (!WHITE_BOX.isMethodCompiled(method)) {
 125             throw new RuntimeException(method.getName() + " is not recompiled");
 126         }
 127 
 128         // should deoptimize for actual type check
 129         if (!deoptimize(method, src_obj)) {
 130             throw new RuntimeException(method.getName() + " is not deoptimized (should deoptimize for actual type check)");
 131         }
 132 
 133         // compile once again
 134         WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
 135         if (!WHITE_BOX.isMethodCompiled(method)) {
 136             throw new RuntimeException(method.getName() + " is not recompiled");
 137         }
 138 
 139         // this time new parameter type should not force deoptimization
 140         if (deoptimize(method, src_obj)) {
 141             throw new RuntimeException(method.getName() + " is deoptimized again");
 142         }
 143     }
 144 }