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