1 /* 2 * Copyright (c) 2015, 2015, 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 package org.graalvm.compiler.core.test.tutorial; 24 25 import org.junit.Assert; 26 import org.junit.Test; 27 28 import org.graalvm.compiler.bytecode.Bytecode; 29 import org.graalvm.compiler.bytecode.BytecodeDisassembler; 30 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; 31 32 import jdk.vm.ci.code.InstalledCode; 33 import jdk.vm.ci.code.InvalidInstalledCodeException; 34 import jdk.vm.ci.meta.ResolvedJavaMethod; 35 36 /** 37 * Examples for the Graal tutorial. Run them using the unittest harness of the mx script. To look at 38 * the examples in IGV (the graph visualization tool), use the {@code -Dgraal.Dump} and 39 * {@code -Dgraal.MethodFilter} options. For example, run the first test case using 40 * 41 * <pre> 42 * mx unittest -Dgraal.Dump= -Dgraal.MethodFilter=String.hashCode GraalTutorial#testStringHashCode 43 * </pre> 44 */ 45 public class GraalTutorial extends InvokeGraal { 46 47 /* 48 * Example for the Graal API: access the Graal API metadata object for a method. 49 */ 50 51 @Test 52 public void testPrintBytecodes() { 53 ResolvedJavaMethod method = findMethod(String.class, "hashCode"); 54 Bytecode bytecode = new ResolvedJavaMethodBytecode(method); 55 56 byte[] bytecodes = bytecode.getCode(); 57 Assert.assertNotNull(bytecodes); 58 59 System.out.println(new BytecodeDisassembler().disassemble(bytecode)); 60 } 61 62 /* 63 * A simple Graal compilation example: Compile the method String.hashCode() 64 */ 65 66 @Test 67 public void testStringHashCode() throws InvalidInstalledCodeException { 68 int expectedResult = "Hello World".hashCode(); 69 70 InstalledCode installedCode = compileAndInstallMethod(findMethod(String.class, "hashCode")); 71 72 int result = (int) installedCode.executeVarargs("Hello World"); 73 Assert.assertEquals(expectedResult, result); 74 } 75 76 /* 77 * Tutorial example for speculative optimizations. 78 */ 79 80 int f1; 81 int f2; 82 83 public void speculativeOptimization(boolean flag) { 84 f1 = 41; 85 if (flag) { 86 f2 = 42; 87 return; 88 } 89 f2 = 43; 90 } 91 92 @Test 93 public void testSpeculativeOptimization() throws InvalidInstalledCodeException { 94 /* 95 * Collect profiling information by running the method in the interpreter. 96 */ 97 98 for (int i = 0; i < 10000; i++) { 99 /* Execute several times so that enough profiling information gets collected. */ 100 speculativeOptimization(false); 101 } 102 103 /* 104 * Warmup to collect profiling information is done, now we compile the method. Since the 105 * value of "flag" was always false during the warmup, the compiled code speculates that the 106 * value remains false. 107 */ 108 109 InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "speculativeOptimization")); 110 f1 = 0; 111 f2 = 0; 112 compiledMethod.executeVarargs(this, true); 113 Assert.assertEquals(41, f1); 114 Assert.assertEquals(42, f2); 115 116 /* 117 * We executed the compiled method with a "flag" value that triggered deoptimization (since 118 * the warmup always used the different "flag" value). The interpreter updated the profiling 119 * information, so the second compilation does not perform the speculative optimization. 120 */ 121 122 compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "speculativeOptimization")); 123 f1 = 0; 124 f2 = 0; 125 compiledMethod.executeVarargs(this, false); 126 Assert.assertEquals(41, f1); 127 Assert.assertEquals(43, f2); 128 } 129 130 /* 131 * Tutorial example for snippets and lowering. 132 */ 133 134 static class A { 135 } 136 137 static class B extends A { 138 } 139 140 public static int instanceOfUsage(Object obj) { 141 if (obj instanceof A) { 142 return 42; 143 } else { 144 return 0; 145 } 146 } 147 148 @Test 149 public void testInstanceOfUsage() throws InvalidInstalledCodeException { 150 /* 151 * Collect profiling information by running the method in the interpreter. 152 */ 153 154 A a = new A(); 155 /* Allocate an (unused) instance of B so that the class B gets loaded. */ 156 @SuppressWarnings("unused") 157 B b = new B(); 158 int expectedResult = instanceOfUsage(a); 159 for (int i = 0; i < 10000; i++) { 160 /* Execute several times so that enough profiling information gets collected. */ 161 instanceOfUsage(a); 162 } 163 164 /* Warmup to collect profiling information is done, now compile the method. */ 165 166 InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "instanceOfUsage")); 167 168 int result = (int) compiledMethod.executeVarargs(a); 169 Assert.assertEquals(expectedResult, result); 170 } 171 172 /* 173 * Tutorial example for intrinsic methods. 174 */ 175 176 public static double intrinsicUsage(double val) { 177 return Math.sin(val); 178 } 179 180 @Test 181 public void testIntrinsicUsage() throws InvalidInstalledCodeException { 182 double expectedResult = intrinsicUsage(42d); 183 184 InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "intrinsicUsage")); 185 186 double result = (double) compiledMethod.executeVarargs(42d); 187 Assert.assertEquals(expectedResult, result, 0); 188 } 189 }