001/* 002 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.compiler.test.tutorial; 024 025import jdk.internal.jvmci.code.*; 026import jdk.internal.jvmci.meta.*; 027 028import org.junit.*; 029 030import com.oracle.graal.java.*; 031 032/** 033 * Examples for the Graal tutorial. Run them using the unittest harness of the mx script. To look at 034 * the examples in IGV (the graph visualization tool), use the options -G:Dump and -G:MethodFilter. 035 * For example, run the first test case using 036 * 037 * <pre> 038 * mx unittest -G:Dump= -G:MethodFilter=String.hashCode GraalTutorial#testStringHashCode 039 * </pre> 040 */ 041public class GraalTutorial extends InvokeGraal { 042 043 /* 044 * Example for the Graal API: access the Graal API metadata object for a method. 045 */ 046 047 @Test 048 public void testPrintBytecodes() { 049 ResolvedJavaMethod method = findMethod(String.class, "hashCode"); 050 051 byte[] bytecodes = method.getCode(); 052 Assert.assertNotNull(bytecodes); 053 054 System.out.println(new BytecodeDisassembler().disassemble(method)); 055 } 056 057 /* 058 * A simple Graal compilation example: Compile the method String.hashCode() 059 */ 060 061 @Test 062 public void testStringHashCode() throws InvalidInstalledCodeException { 063 int expectedResult = "Hello World".hashCode(); 064 065 InstalledCode installedCode = compileAndInstallMethod(findMethod(String.class, "hashCode")); 066 067 int result = (int) installedCode.executeVarargs("Hello World"); 068 Assert.assertEquals(expectedResult, result); 069 } 070 071 /* 072 * Tutorial example for speculative optimizations. 073 */ 074 075 int f1; 076 int f2; 077 078 public void speculativeOptimization(boolean flag) { 079 f1 = 41; 080 if (flag) { 081 f2 = 42; 082 return; 083 } 084 f2 = 43; 085 } 086 087 @Test 088 public void testSpeculativeOptimization() throws InvalidInstalledCodeException { 089 /* 090 * Collect profiling information by running the method in the interpreter. 091 */ 092 093 for (int i = 0; i < 10000; i++) { 094 /* Execute several times so that enough profiling information gets collected. */ 095 speculativeOptimization(false); 096 } 097 098 /* 099 * Warmup to collect profiling information is done, now we compile the method. Since the 100 * value of "flag" was always false during the warmup, the compiled code speculates that the 101 * value remains false. 102 */ 103 104 InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "speculativeOptimization")); 105 f1 = 0; 106 f2 = 0; 107 compiledMethod.executeVarargs(this, true); 108 Assert.assertEquals(41, f1); 109 Assert.assertEquals(42, f2); 110 111 /* 112 * We executed the compiled method with a "flag" value that triggered deoptimization (since 113 * the warmup always used the different "flag" value). The interpreter updated the profiling 114 * information, so the second compilation does not perform the speculative optimization. 115 */ 116 117 compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "speculativeOptimization")); 118 f1 = 0; 119 f2 = 0; 120 compiledMethod.executeVarargs(this, false); 121 Assert.assertEquals(41, f1); 122 Assert.assertEquals(43, f2); 123 } 124 125 /* 126 * Tutorial example for snippets and lowering. 127 */ 128 129 static class A { 130 } 131 132 static class B extends A { 133 } 134 135 public static int instanceOfUsage(Object obj) { 136 if (obj instanceof A) { 137 return 42; 138 } else { 139 return 0; 140 } 141 } 142 143 @Test 144 public void testInstanceOfUsage() throws InvalidInstalledCodeException { 145 /* 146 * Collect profiling information by running the method in the interpreter. 147 */ 148 149 A a = new A(); 150 /* Allocate an (unused) instance of B so that the class B gets loaded. */ 151 @SuppressWarnings("unused") 152 B b = new B(); 153 int expectedResult = instanceOfUsage(a); 154 for (int i = 0; i < 10000; i++) { 155 /* Execute several times so that enough profiling information gets collected. */ 156 instanceOfUsage(a); 157 } 158 159 /* Warmup to collect profiling information is done, now compile the method. */ 160 161 InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "instanceOfUsage")); 162 163 int result = (int) compiledMethod.executeVarargs(a); 164 Assert.assertEquals(expectedResult, result); 165 } 166 167 /* 168 * Tutorial example for intrinsic methods. 169 */ 170 171 public static double intrinsicUsage(double val) { 172 return Math.sin(val); 173 } 174 175 @Test 176 public void testIntrinsicUsage() throws InvalidInstalledCodeException { 177 double expectedResult = intrinsicUsage(42d); 178 179 InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "intrinsicUsage")); 180 181 double result = (double) compiledMethod.executeVarargs(42d); 182 Assert.assertEquals(expectedResult, result, 0); 183 } 184}