1 /*
   2  * Copyright (c) 2011, 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.ea;
  24 
  25 import org.junit.Test;
  26 
  27 import sun.misc.Unsafe;
  28 
  29 import org.graalvm.compiler.nodes.StructuredGraph;
  30 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
  31 import org.graalvm.compiler.nodes.extended.RawLoadNode;
  32 import org.graalvm.compiler.nodes.java.LoadIndexedNode;
  33 import org.graalvm.compiler.nodes.java.StoreIndexedNode;
  34 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
  35 import org.graalvm.compiler.phases.common.inlining.InliningPhase;
  36 import org.graalvm.compiler.phases.tiers.HighTierContext;
  37 import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
  38 
  39 public class PEAReadEliminationTest extends EarlyReadEliminationTest {
  40 
  41     public static int testIndexed1Snippet(int[] array) {
  42         array[1] = 1;
  43         array[2] = 2;
  44         array[3] = 3;
  45         array[4] = 4;
  46         array[5] = 5;
  47         array[6] = 6;
  48         return array[1] + array[2] + array[3] + array[4] + array[5] + array[6];
  49     }
  50 
  51     @Test
  52     public void testIndexed1() {
  53         StructuredGraph graph = processMethod("testIndexed1Snippet", false);
  54         assertDeepEquals(0, graph.getNodes().filter(LoadIndexedNode.class).count());
  55     }
  56 
  57     public static int testIndexed2Snippet(int v, int[] array) {
  58         array[1] = 1;
  59         array[2] = 2;
  60         array[3] = 3;
  61         array[v] = 0;
  62         array[4] = 4;
  63         array[5] = 5;
  64         array[6] = 6;
  65         array[4] = 4;
  66         array[5] = 5;
  67         array[6] = 6;
  68         return array[1] + array[2] + array[3] + array[4] + array[5] + array[6];
  69     }
  70 
  71     @Test
  72     public void testIndexed2() {
  73         StructuredGraph graph = processMethod("testIndexed2Snippet", false);
  74         assertDeepEquals(3, graph.getNodes().filter(LoadIndexedNode.class).count());
  75         assertDeepEquals(7, graph.getNodes().filter(StoreIndexedNode.class).count());
  76     }
  77 
  78     public static int testIndexed3Snippet(int v, int[] array, short[] array2) {
  79         array[1] = 1;
  80         array2[1] = 1;
  81         array[2] = 2;
  82         array2[2] = 2;
  83         array[3] = 3;
  84         array2[3] = 3;
  85         array[v] = 0;
  86         array[4] = 4;
  87         array2[4] = 4;
  88         array[5] = 5;
  89         array2[5] = 5;
  90         array[6] = 6;
  91         array2[6] = 6;
  92         return array[1] + array[2] + array[3] + array[4] + array[5] + array[6] + array2[1] + array2[2] + array2[3] + array2[4] + array2[5] + array2[6];
  93     }
  94 
  95     @Test
  96     public void testIndexed3() {
  97         StructuredGraph graph = processMethod("testIndexed3Snippet", false);
  98         assertDeepEquals(3, graph.getNodes().filter(LoadIndexedNode.class).count());
  99     }
 100 
 101     private static native void nonInlineable();
 102 
 103     public static int testIndexed4Snippet(int[] array) {
 104         array[1] = 1;
 105         array[2] = 2;
 106         array[3] = 3;
 107         nonInlineable();
 108         array[4] = 4;
 109         array[5] = 5;
 110         array[6] = 6;
 111         return array[1] + array[2] + array[3] + array[4] + array[5] + array[6];
 112     }
 113 
 114     @Test
 115     public void testIndexed4() {
 116         StructuredGraph graph = processMethod("testIndexed4Snippet", false);
 117         assertDeepEquals(3, graph.getNodes().filter(LoadIndexedNode.class).count());
 118     }
 119 
 120     private static final long offsetInt1 = Unsafe.ARRAY_INT_BASE_OFFSET + Unsafe.ARRAY_INT_INDEX_SCALE * 1;
 121     private static final long offsetInt2 = Unsafe.ARRAY_INT_BASE_OFFSET + Unsafe.ARRAY_INT_INDEX_SCALE * 2;
 122 
 123     public static int testUnsafe1Snippet(int v, int[] array) {
 124         int s = UNSAFE.getInt(array, offsetInt1);
 125         UNSAFE.putInt(array, offsetInt1, v);
 126         UNSAFE.putInt(array, offsetInt2, v);
 127         return s + UNSAFE.getInt(array, offsetInt1) + UNSAFE.getInt(array, offsetInt2);
 128     }
 129 
 130     @Test
 131     public void testUnsafe1() {
 132         StructuredGraph graph = processMethod("testUnsafe1Snippet", false);
 133         assertDeepEquals(1, graph.getNodes().filter(RawLoadNode.class).count());
 134     }
 135 
 136     public static int testUnsafe2Snippet(int v, Object array) {
 137         int s = UNSAFE.getInt(array, offsetInt1);
 138         UNSAFE.putInt(array, offsetInt1, v);
 139         UNSAFE.putInt(array, offsetInt2, v);
 140         return s + UNSAFE.getInt(array, offsetInt1) + UNSAFE.getInt(array, offsetInt2);
 141     }
 142 
 143     @Test
 144     public void testUnsafe2() {
 145         StructuredGraph graph = processMethod("testUnsafe2Snippet", false);
 146         assertDeepEquals(3, graph.getNodes().filter(RawLoadNode.class).count());
 147     }
 148 
 149     private static final long offsetObject1 = Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * 1;
 150     private static final long offsetObject2 = Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * 2;
 151 
 152     public static int testUnsafe3Snippet(int v, Object[] array) {
 153         int s = (Integer) UNSAFE.getObject(array, offsetObject1);
 154         UNSAFE.putObject(array, offsetObject1, v);
 155         UNSAFE.putObject(array, offsetObject2, v);
 156         return s + (Integer) UNSAFE.getObject(array, offsetObject1) + (Integer) UNSAFE.getObject(array, offsetObject2);
 157     }
 158 
 159     @Test
 160     public void testUnsafe3() {
 161         StructuredGraph graph = processMethod("testUnsafe3Snippet", false);
 162         assertDeepEquals(1, graph.getNodes().filter(RawLoadNode.class).count());
 163     }
 164 
 165     public static int testUnsafe4Snippet(int v, Object[] array) {
 166         int s = (Integer) UNSAFE.getObject(array, offsetObject1);
 167         UNSAFE.putObject(array, offsetObject1, v);
 168         UNSAFE.putObject(array, offsetObject2, v);
 169         array[v] = null;
 170         return s + (Integer) UNSAFE.getObject(array, offsetObject1) + (Integer) UNSAFE.getObject(array, offsetObject2);
 171     }
 172 
 173     @Test
 174     public void testUnsafe4() {
 175         StructuredGraph graph = processMethod("testUnsafe4Snippet", false);
 176         assertDeepEquals(3, graph.getNodes().filter(RawLoadNode.class).count());
 177     }
 178 
 179     private static final long offsetLong1 = Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * 1;
 180     private static final long offsetLong2 = Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * 2;
 181 
 182     public static int testUnsafe5Snippet(int v, long[] array) {
 183         int s = UNSAFE.getInt(array, offsetLong1);
 184         UNSAFE.putInt(array, offsetLong1, v);
 185         UNSAFE.putInt(array, offsetLong2, v);
 186         return s + UNSAFE.getInt(array, offsetLong1) + UNSAFE.getInt(array, offsetLong2);
 187     }
 188 
 189     @Test
 190     public void testUnsafe5() {
 191         StructuredGraph graph = processMethod("testUnsafe5Snippet", false);
 192         assertDeepEquals(1, graph.getNodes().filter(RawLoadNode.class).count());
 193     }
 194 
 195     @Override
 196     protected StructuredGraph processMethod(final String snippet, boolean doLowering) {
 197         StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
 198         HighTierContext context = getDefaultHighTierContext();
 199         new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
 200         new PartialEscapePhase(false, true, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context);
 201         return graph;
 202     }
 203 }