GraalTutorial.java revision 13175:3df8ef613001
111562Smlarsson/* 213184Skbarrett * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. 311562Smlarsson * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 411562Smlarsson * 511562Smlarsson * This code is free software; you can redistribute it and/or modify it 611562Smlarsson * under the terms of the GNU General Public License version 2 only, as 711562Smlarsson * published by the Free Software Foundation. 811562Smlarsson * 911562Smlarsson * This code is distributed in the hope that it will be useful, but WITHOUT 1011562Smlarsson * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1111562Smlarsson * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1211562Smlarsson * version 2 for more details (a copy is included in the LICENSE file that 1311562Smlarsson * accompanied this code). 1411562Smlarsson * 1511562Smlarsson * You should have received a copy of the GNU General Public License version 1611562Smlarsson * 2 along with this work; if not, write to the Free Software Foundation, 1711562Smlarsson * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1811562Smlarsson * 1911562Smlarsson * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2011562Smlarsson * or visit www.oracle.com if you need additional information or have any 2111562Smlarsson * questions. 2211562Smlarsson */ 2312158Sstsmirnopackage org.graalvm.compiler.core.test.tutorial; 2411562Smlarsson 2513184Skbarrettimport java.lang.reflect.Method; 2611562Smlarssonimport java.util.regex.Pattern; 2711562Smlarsson 2813249Sstefankimport org.graalvm.compiler.bytecode.BytecodeDisassembler; 2911562Smlarssonimport org.junit.Assert; 3011562Smlarssonimport org.junit.Test; 3113240Sstefank 3213240Sstefankimport jdk.vm.ci.code.InstalledCode; 3313240Sstefankimport jdk.vm.ci.code.InvalidInstalledCodeException; 3413240Sstefankimport jdk.vm.ci.meta.ResolvedJavaMethod; 3513240Sstefank 3613240Sstefank/** 3713240Sstefank * Examples for the Graal tutorial. Run them using the unittest harness of the mx script. To look at 3813240Sstefank * the examples in IGV (the graph visualization tool), use the {@code -Dgraal.Dump} and 3913240Sstefank * {@code -Dgraal.MethodFilter} options. For example, run the first test case using 4013240Sstefank * 4113240Sstefank * <pre> 4213240Sstefank * mx unittest -Dgraal.Dump= -Dgraal.MethodFilter=String.hashCode GraalTutorial#testStringHashCode 4313240Sstefank * </pre> 4413240Sstefank */ 4513240Sstefankpublic class GraalTutorial extends InvokeGraal { 4613240Sstefank 4711562Smlarsson /* 4811562Smlarsson * Example for the Graal API: access the Graal API metadata object for a method. 4911562Smlarsson */ 5011562Smlarsson 5111562Smlarsson @Test 5211562Smlarsson public void testGetBytecodes() throws NoSuchMethodException { 5311562Smlarsson Method reflectionMethod = String.class.getDeclaredMethod("hashCode"); 5411562Smlarsson ResolvedJavaMethod method = metaAccess.lookupJavaMethod(reflectionMethod); 5511562Smlarsson 5611562Smlarsson /* 5711562Smlarsson * ResolvedJavaMethod provides all information that you want about a method, for example, 5811562Smlarsson * the bytecodes. 5911562Smlarsson */ 6011562Smlarsson byte[] bytecodes = method.getCode(); 6111562Smlarsson 6211562Smlarsson /* 6311562Smlarsson * BytecodeDisassembler shows you how to iterate bytecodes, how to access type information, 6411562Smlarsson * and more. 6511562Smlarsson */ 6611562Smlarsson String disassembly = new BytecodeDisassembler().disassemble(method); 6711562Smlarsson 6811562Smlarsson /* 6911562Smlarsson * We don't want test cases to print any output, so we check the validity of the output 7011562Smlarsson * instead. 7111562Smlarsson */ 7211562Smlarsson Pattern disassemblyLineRE = Pattern.compile(" *\\d+: [a-z][\\w_]+"); 7311562Smlarsson for (String line : disassembly.split("\\n")) { 7411562Smlarsson Assert.assertTrue(line, disassemblyLineRE.matcher(line).find()); 7511562Smlarsson } 7611562Smlarsson Assert.assertTrue(bytecodes.length > 0); 7711562Smlarsson } 7811562Smlarsson 7911562Smlarsson /* 8011562Smlarsson * A simple Graal compilation example: Compile the method String.hashCode() 8111562Smlarsson */ 8211562Smlarsson 8311562Smlarsson @Test 8411562Smlarsson public void testStringHashCode() throws InvalidInstalledCodeException { 8511562Smlarsson int expectedResult = "Hello World".hashCode(); 8611562Smlarsson 8711562Smlarsson InstalledCode installedCode = compileAndInstallMethod(findMethod(String.class, "hashCode")); 8811562Smlarsson 8913240Sstefank int result = (int) installedCode.executeVarargs("Hello World"); 9013240Sstefank Assert.assertEquals(expectedResult, result); 9113240Sstefank } 9213240Sstefank 9313240Sstefank /* 9413240Sstefank * Tutorial example for speculative optimizations. 9513240Sstefank */ 9613240Sstefank 9713240Sstefank int f1; 9813240Sstefank int f2; 9913240Sstefank 10013240Sstefank public void speculativeOptimization(boolean flag) { 10113240Sstefank f1 = 41; 10213240Sstefank if (flag) { 10313240Sstefank f2 = 42; 10413240Sstefank return; 10513240Sstefank } 10613240Sstefank f2 = 43; 10713240Sstefank } 10813240Sstefank 10913240Sstefank @Test 11013240Sstefank public void testSpeculativeOptimization() throws InvalidInstalledCodeException { 11113240Sstefank /* 11213240Sstefank * Collect profiling information by running the method in the interpreter. 11313240Sstefank */ 11413240Sstefank 11513240Sstefank for (int i = 0; i < 10000; i++) { 11613240Sstefank /* Execute several times so that enough profiling information gets collected. */ 11713240Sstefank speculativeOptimization(false); 11813240Sstefank } 11913240Sstefank 12013240Sstefank /* 12113240Sstefank * Warmup to collect profiling information is done, now we compile the method. Since the 12213240Sstefank * value of "flag" was always false during the warmup, the compiled code speculates that the 12313240Sstefank * value remains false. 12413240Sstefank */ 12513240Sstefank 12613240Sstefank InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "speculativeOptimization")); 12713240Sstefank f1 = 0; 12813240Sstefank f2 = 0; 12913240Sstefank compiledMethod.executeVarargs(this, true); 13013240Sstefank Assert.assertEquals(41, f1); 13113240Sstefank Assert.assertEquals(42, f2); 13213240Sstefank 13313240Sstefank /* 13413240Sstefank * We executed the compiled method with a "flag" value that triggered deoptimization (since 13513240Sstefank * the warmup always used the different "flag" value). The interpreter updated the profiling 13613240Sstefank * information, so the second compilation does not perform the speculative optimization. 13713240Sstefank */ 13813240Sstefank 13913240Sstefank compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "speculativeOptimization")); 14013240Sstefank f1 = 0; 14113240Sstefank f2 = 0; 14213240Sstefank compiledMethod.executeVarargs(this, false); 14313240Sstefank Assert.assertEquals(41, f1); 14413240Sstefank Assert.assertEquals(43, f2); 14513240Sstefank } 14613240Sstefank 14713240Sstefank /* 14813240Sstefank * Tutorial example for snippets and lowering. 14913240Sstefank */ 15013240Sstefank 15113240Sstefank public static int identityHashCodeUsage(Object obj) { 15213240Sstefank return System.identityHashCode(obj); 15313240Sstefank } 15413240Sstefank 15513240Sstefank @Test 15613243Sstefank public void testIdentityHashCodeUsage() throws InvalidInstalledCodeException { 15713240Sstefank Object a = new Object(); 15813240Sstefank int expectedResult = identityHashCodeUsage(a); 15913240Sstefank 16013240Sstefank InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "identityHashCodeUsage")); 16113240Sstefank 16213240Sstefank int result = (int) compiledMethod.executeVarargs(a); 16313240Sstefank Assert.assertEquals(expectedResult, result); 16413240Sstefank } 16513240Sstefank 16613240Sstefank static class A { 16713240Sstefank } 16813240Sstefank 16913240Sstefank static class B extends A { 17013240Sstefank } 17113240Sstefank 17213240Sstefank public static int instanceOfUsage(Object obj) { 17313240Sstefank if (obj instanceof A) { 17413240Sstefank return 42; 17513240Sstefank } else { 17613240Sstefank return 0; 17713240Sstefank } 17813240Sstefank } 17913240Sstefank 18013240Sstefank @Test 18113240Sstefank public void testInstanceOfUsage() throws InvalidInstalledCodeException { 18213240Sstefank /* 18313240Sstefank * Collect profiling information by running the method in the interpreter. 18413240Sstefank */ 18513240Sstefank 18613240Sstefank A a = new A(); 18713240Sstefank /* Allocate an (unused) instance of B so that the class B gets loaded. */ 18813240Sstefank @SuppressWarnings("unused") 18913240Sstefank B b = new B(); 19013243Sstefank int expectedResult = instanceOfUsage(a); 19113243Sstefank for (int i = 0; i < 10000; i++) { 19213240Sstefank /* Execute several times so that enough profiling information gets collected. */ 19313240Sstefank instanceOfUsage(a); 19413240Sstefank } 19513240Sstefank 19613240Sstefank /* Warmup to collect profiling information is done, now compile the method. */ 19713240Sstefank 19813240Sstefank InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "instanceOfUsage")); 19913240Sstefank 20013240Sstefank int result = (int) compiledMethod.executeVarargs(a); 20113240Sstefank Assert.assertEquals(expectedResult, result); 20213240Sstefank } 20313240Sstefank 204 /* 205 * Tutorial example for intrinsic methods. 206 */ 207 208 public static int intrinsicIntegerReverseBytes(int val) { 209 return Integer.reverseBytes(val); 210 } 211 212 @Test 213 public void testIntrinsicIntegerReverseBytes() throws InvalidInstalledCodeException { 214 int input = 0x12345678; 215 int expected = intrinsicIntegerReverseBytes(input); 216 217 InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "intrinsicIntegerReverseBytes")); 218 219 int actual = (int) compiledMethod.executeVarargs(input); 220 Assert.assertEquals(expected, actual); 221 } 222} 223