1 /* 2 * Copyright (c) 2018, 2019, 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 package org.graalvm.compiler.hotspot.lir.test; 26 27 import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine; 28 import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments; 29 30 import java.io.File; 31 import java.io.IOException; 32 import java.util.ArrayList; 33 import java.util.Iterator; 34 import java.util.List; 35 import java.util.regex.Matcher; 36 import java.util.regex.Pattern; 37 38 import org.graalvm.compiler.api.directives.GraalDirectives; 39 import org.graalvm.compiler.core.common.LIRKind; 40 import org.graalvm.compiler.hotspot.HotSpotBackend; 41 import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; 42 import org.graalvm.compiler.lir.ConstantValue; 43 import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 44 import org.graalvm.compiler.lir.jtt.LIRTest; 45 import org.graalvm.compiler.lir.jtt.LIRTestSpecification; 46 import org.graalvm.compiler.test.SubprocessUtil; 47 import org.junit.Assert; 48 import org.junit.Assume; 49 import org.junit.Before; 50 import org.junit.Test; 51 52 import jdk.vm.ci.amd64.AMD64; 53 import jdk.vm.ci.meta.JavaConstant; 54 import jdk.vm.ci.meta.JavaKind; 55 import jdk.vm.ci.meta.ResolvedJavaMethod; 56 57 public class BenchmarkCounterOverflowTest extends LIRTest { 58 private static final String SUBPROCESS_PROPERTY = BenchmarkCounterOverflowTest.class.getSimpleName() + ".subprocess.call"; 59 private static final boolean VERBOSE = Boolean.getBoolean(BenchmarkCounterOverflowTest.class.getSimpleName() + ".verbose"); 60 61 private static LIRKind intKind; 62 63 @Before 64 public void checkAMD64() { 65 Assume.assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64); 66 Assume.assumeTrue("skipping HotSpot specific test", getBackend() instanceof HotSpotBackend); 67 } 68 69 @Before 70 public void setUp() { 71 intKind = LIRKind.fromJavaKind(getBackend().getTarget().arch, JavaKind.Long); 72 } 73 74 private static final LIRTestSpecification constCounterIncrement = new LIRTestSpecification() { 75 @Override 76 public void generate(LIRGeneratorTool gen) { 77 gen.append(gen.createBenchmarkCounter("counter", "test", new ConstantValue(intKind, JavaConstant.forLong(Integer.MAX_VALUE)))); 78 } 79 }; 80 81 @SuppressWarnings("unused") 82 @LIRIntrinsic 83 public static void counterInc(LIRTestSpecification spec) { 84 } 85 86 public static void test(long count) { 87 for (long i = 0; i < count; i++) { 88 counterInc(constCounterIncrement); 89 GraalDirectives.blackhole(i); 90 } 91 } 92 93 @Test 94 public void incrementCounter() { 95 Assume.assumeTrue("not a subprocess -> skip", Boolean.getBoolean(SUBPROCESS_PROPERTY)); 96 BenchmarkCounters.enabled = true; 97 98 Object[] args = new Object[]{Integer.MAX_VALUE * 4L}; 99 ResolvedJavaMethod method = getResolvedJavaMethod("test"); 100 executeActualCheckDeopt(getInitialOptions(), method, EMPTY, null, args); 101 } 102 103 @Test 104 public void spawnSubprocess() throws IOException, InterruptedException { 105 Assume.assumeFalse("subprocess already spawned -> skip", Boolean.getBoolean(SUBPROCESS_PROPERTY)); 106 List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine()); 107 vmArgs.add("-XX:JVMCICounterSize=1"); 108 vmArgs.add("-Dgraal." + BenchmarkCounters.Options.AbortOnBenchmarkCounterOverflow.getName() + "=true"); 109 vmArgs.add("-D" + SUBPROCESS_PROPERTY + "=true"); 110 111 // Disable increment range checks (e.g. HotSpotCounterOp.checkIncrements()) 112 vmArgs.add("-dsa"); 113 vmArgs.add("-da"); 114 115 List<String> mainClassAndArgs = new ArrayList<>(); 116 mainClassAndArgs.add("com.oracle.mxtool.junit.MxJUnitWrapper"); 117 mainClassAndArgs.add(BenchmarkCounterOverflowTest.class.getName()); 118 119 SubprocessUtil.Subprocess proc = SubprocessUtil.java(vmArgs, mainClassAndArgs); 120 121 if (VERBOSE) { 122 System.out.println(proc); 123 } 124 125 Assert.assertNotEquals("Expected non-zero exit status", 0, proc.exitCode); 126 127 Iterator<String> it = proc.output.iterator(); 128 boolean foundProblematicFrame = false; 129 while (it.hasNext()) { 130 String line = it.next(); 131 if (line.contains("Problematic frame:")) { 132 if (!it.hasNext()) { 133 // no more line 134 break; 135 } 136 line = it.next(); 137 if (line.contains(BenchmarkCounterOverflowTest.class.getName() + ".test")) { 138 foundProblematicFrame = true; 139 break; 140 } 141 Assert.fail("Unexpected stack trace: " + line); 142 } 143 } 144 // find and delete hserr file 145 while (it.hasNext()) { 146 String line = it.next(); 147 if (line.contains("An error report file with more information is saved as:")) { 148 if (!it.hasNext()) { 149 // no more line 150 break; 151 } 152 line = it.next(); 153 Pattern pattern = Pattern.compile("^# (.*hs_err_pid.*log)$"); 154 Matcher matcher = pattern.matcher(line); 155 if (matcher.matches()) { 156 File hserrFile = new File(matcher.group(1)); 157 if (hserrFile.exists()) { 158 if (VERBOSE) { 159 System.out.println("Deleting error report file:" + hserrFile.getAbsolutePath()); 160 } 161 hserrFile.delete(); 162 } 163 } 164 } 165 } 166 Assert.assertTrue(String.format("Could not find method in output:%n%s", proc), foundProblematicFrame); 167 } 168 }