src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java

Print this page


   1 /*
   2  * Copyright (c) 2011, 2014, 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 jdk.vm.ci.meta.JavaConstant;
  26 
  27 import org.junit.Assert;
  28 import org.junit.Test;
  29 
  30 import org.graalvm.compiler.graph.Node;
  31 import org.graalvm.compiler.loop.DefaultLoopPolicies;
  32 import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase;
  33 import org.graalvm.compiler.loop.phases.LoopPeelingPhase;



  34 import org.graalvm.compiler.nodes.extended.ValueAnchorNode;

  35 import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode;
  36 import org.graalvm.compiler.nodes.virtual.CommitAllocationNode;
  37 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
  38 import org.graalvm.compiler.phases.schedule.SchedulePhase;
  39 import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;




  40 
  41 /**
  42  * The PartialEscapeAnalysisPhase is expected to remove all allocations and return the correct
  43  * values.
  44  */
  45 public class EscapeAnalysisTest extends EATestBase {
  46 
  47     @Test
  48     public void test1() {
  49         testEscapeAnalysis("test1Snippet", JavaConstant.forInt(101), false);
  50     }
  51 
  52     public static int test1Snippet() {
  53         Integer x = new Integer(101);
  54         return x.intValue();
  55     }
  56 
  57     @Test
  58     public void test2() {
  59         testEscapeAnalysis("test2Snippet", JavaConstant.forInt(0), false);


 163     }
 164 
 165     @Test
 166     public void testMergeAllocationsInt() {
 167         testEscapeAnalysis("testMergeAllocationsIntSnippet", JavaConstant.forInt(1), false);
 168     }
 169 
 170     public int testMergeAllocationsIntSnippet(int a) {
 171         TestClassInt obj;
 172         if (a < 0) {
 173             obj = new TestClassInt(1, 2);
 174             notInlineable();
 175         } else {
 176             obj = new TestClassInt(1, 2);
 177             notInlineable();
 178         }
 179         return obj.x <= 3 ? 1 : 0;
 180     }
 181 
 182     @Test












































 183     public void testMergeAllocationsObj() {
 184         testEscapeAnalysis("testMergeAllocationsObjSnippet", JavaConstant.forInt(1), false);
 185     }
 186 
 187     public int testMergeAllocationsObjSnippet(int a) {
 188         TestClassObject obj;
 189         Integer one = 1;
 190         Integer two = 2;
 191         Integer three = 3;
 192         if (a < 0) {
 193             obj = new TestClassObject(one, two);
 194             notInlineable();
 195         } else {
 196             obj = new TestClassObject(one, three);
 197             notInlineable();
 198         }
 199         return ((Integer) obj.x).intValue() <= 3 ? 1 : 0;
 200     }
 201 
 202     @Test


 242     }
 243 
 244     @Test
 245     public void testMergeAllocationsException() {
 246         testEscapeAnalysis("testMergeAllocationsExceptionSnippet", JavaConstant.forInt(1), false);
 247     }
 248 
 249     public int testMergeAllocationsExceptionSnippet(int a) {
 250         MyException obj;
 251         Integer one = 1;
 252         if (a < 0) {
 253             obj = new MyException(one);
 254             notInlineable();
 255         } else {
 256             obj = new MyException(one);
 257             notInlineable();
 258         }
 259         return obj.value <= 3 ? 1 : 0;
 260     }
 261 
































































 262     @Test
 263     public void testCheckCast() {
 264         testEscapeAnalysis("testCheckCastSnippet", getSnippetReflection().forObject(TestClassObject.class), false);
 265     }
 266 
 267     public Object testCheckCastSnippet() {
 268         TestClassObject obj = new TestClassObject(TestClassObject.class);
 269         TestClassObject obj2 = new TestClassObject(obj);
 270         return ((TestClassObject) obj2.x).x;
 271     }
 272 
 273     @Test
 274     public void testInstanceOf() {
 275         testEscapeAnalysis("testInstanceOfSnippet", JavaConstant.forInt(1), false);
 276     }
 277 
 278     public boolean testInstanceOfSnippet() {
 279         TestClassObject obj = new TestClassObject(TestClassObject.class);
 280         TestClassObject obj2 = new TestClassObject(obj);
 281         return obj2.x instanceof TestClassObject;
 282     }
 283 
 284     @SuppressWarnings("unused")


 297 
 298     private static final TestClassObject staticObj = new TestClassObject();
 299 
 300     public static Object testFullyUnrolledLoopSnippet() {
 301         /*
 302          * This tests a case that can appear if PEA is performed both before and after loop
 303          * unrolling/peeling: If the VirtualInstanceNode is not duplicated correctly with the loop,
 304          * the resulting object will reference itself, and not a second (different) object.
 305          */
 306         TestClassObject obj = staticObj;
 307         for (int i = 0; i < 2; i++) {
 308             obj = new TestClassObject(obj);
 309         }
 310         return obj.x;
 311     }
 312 
 313     @Test
 314     public void testFullyUnrolledLoop() {
 315         prepareGraph("testFullyUnrolledLoopSnippet", false);
 316         new LoopFullUnrollPhase(new CanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context);
 317         new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context);
 318         Assert.assertEquals(1, returnNodes.size());
 319         Assert.assertTrue(returnNodes.get(0).result() instanceof AllocatedObjectNode);
 320         CommitAllocationNode commit = ((AllocatedObjectNode) returnNodes.get(0).result()).getCommit();
 321         Assert.assertEquals(2, commit.getValues().size());
 322         Assert.assertEquals(1, commit.getVirtualObjects().size());
 323         Assert.assertTrue("non-cyclic data structure expected", commit.getVirtualObjects().get(0) != commit.getValues().get(0));
 324     }
 325 
 326     @SuppressWarnings("unused") private static Object staticField;
 327 
 328     private static TestClassObject inlinedPart(TestClassObject obj) {
 329         TestClassObject ret = new TestClassObject(obj);
 330         staticField = null;
 331         return ret;
 332     }
 333 
 334     public static Object testPeeledLoopSnippet() {
 335         TestClassObject obj = staticObj;
 336         int i = 0;
 337         do {
 338             obj = inlinedPart(obj);
 339         } while (i++ < 10);
 340         staticField = obj;
 341         return obj.x;
 342     }
 343 
 344     @Test
 345     public void testPeeledLoop() {
 346         prepareGraph("testPeeledLoopSnippet", false);
 347         new LoopPeelingPhase(new DefaultLoopPolicies()).apply(graph, getDefaultHighTierContext());
 348         new SchedulePhase().apply(graph);
 349     }
 350 
 351     public static void testDeoptMonitorSnippetInner(Object o2, Object t, int i) {
 352         staticField = null;
 353         if (i == 0) {
 354             staticField = o2;
 355             Number n = (Number) t;
 356             n.toString();
 357         }
 358     }
 359 
 360     public static void testDeoptMonitorSnippet(Object t, int i) {
 361         TestClassObject o = new TestClassObject();
 362         TestClassObject o2 = new TestClassObject(o);
 363 
 364         synchronized (o) {
 365             testDeoptMonitorSnippetInner(o2, t, i);
 366         }
 367     }
 368 
   1 /*
   2  * Copyright (c) 2011, 2017, 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 java.util.List;



  26 
  27 import org.graalvm.compiler.graph.Node;
  28 import org.graalvm.compiler.loop.DefaultLoopPolicies;
  29 import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase;
  30 import org.graalvm.compiler.loop.phases.LoopPeelingPhase;
  31 import org.graalvm.compiler.nodes.ConstantNode;
  32 import org.graalvm.compiler.nodes.ReturnNode;
  33 import org.graalvm.compiler.nodes.extended.BoxNode;
  34 import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
  35 import org.graalvm.compiler.nodes.java.LoadFieldNode;
  36 import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode;
  37 import org.graalvm.compiler.nodes.virtual.CommitAllocationNode;
  38 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
  39 import org.graalvm.compiler.phases.schedule.SchedulePhase;
  40 import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
  41 import org.junit.Assert;
  42 import org.junit.Test;
  43 
  44 import jdk.vm.ci.meta.JavaConstant;
  45 
  46 /**
  47  * The PartialEscapeAnalysisPhase is expected to remove all allocations and return the correct
  48  * values.
  49  */
  50 public class EscapeAnalysisTest extends EATestBase {
  51 
  52     @Test
  53     public void test1() {
  54         testEscapeAnalysis("test1Snippet", JavaConstant.forInt(101), false);
  55     }
  56 
  57     public static int test1Snippet() {
  58         Integer x = new Integer(101);
  59         return x.intValue();
  60     }
  61 
  62     @Test
  63     public void test2() {
  64         testEscapeAnalysis("test2Snippet", JavaConstant.forInt(0), false);


 168     }
 169 
 170     @Test
 171     public void testMergeAllocationsInt() {
 172         testEscapeAnalysis("testMergeAllocationsIntSnippet", JavaConstant.forInt(1), false);
 173     }
 174 
 175     public int testMergeAllocationsIntSnippet(int a) {
 176         TestClassInt obj;
 177         if (a < 0) {
 178             obj = new TestClassInt(1, 2);
 179             notInlineable();
 180         } else {
 181             obj = new TestClassInt(1, 2);
 182             notInlineable();
 183         }
 184         return obj.x <= 3 ? 1 : 0;
 185     }
 186 
 187     @Test
 188     public void testMergeAllocationsInt2() {
 189         testEscapeAnalysis("testMergeAllocationsInt2Snippet", JavaConstant.forInt(1), true);
 190     }
 191 
 192     public int testMergeAllocationsInt2Snippet(int a) {
 193         /*
 194          * The initial object in obj exists until the end of the function, but it can still be
 195          * merged with the one allocated in the else block because noone can observe the identity.
 196          */
 197         TestClassInt obj = new TestClassInt(1, 2);
 198         if (a < 0) {
 199             notInlineable();
 200         } else {
 201             obj = new TestClassInt(1, 2);
 202             notInlineable();
 203         }
 204         return obj.x <= 3 ? 1 : 0;
 205     }
 206 
 207     @Test
 208     public void testMergeAllocationsInt3() {
 209         // ensure that the result is not constant:
 210         assertTrue(testMergeAllocationsInt3Snippet(true));
 211         assertFalse(testMergeAllocationsInt3Snippet(false));
 212 
 213         prepareGraph("testMergeAllocationsInt3Snippet", true);
 214         assertFalse(graph.getNodes().filter(ReturnNode.class).first().result().isConstant());
 215     }
 216 
 217     public boolean testMergeAllocationsInt3Snippet(boolean a) {
 218         TestClassInt phi1;
 219         TestClassInt phi2;
 220         if (a) {
 221             field = new TestClassObject();
 222             field = new TestClassObject();
 223             phi1 = phi2 = new TestClassInt(1, 2);
 224         } else {
 225             phi1 = new TestClassInt(2, 3);
 226             phi2 = new TestClassInt(3, 4);
 227         }
 228         return phi1 == phi2;
 229     }
 230 
 231     @Test
 232     public void testMergeAllocationsObj() {
 233         testEscapeAnalysis("testMergeAllocationsObjSnippet", JavaConstant.forInt(1), false);
 234     }
 235 
 236     public int testMergeAllocationsObjSnippet(int a) {
 237         TestClassObject obj;
 238         Integer one = 1;
 239         Integer two = 2;
 240         Integer three = 3;
 241         if (a < 0) {
 242             obj = new TestClassObject(one, two);
 243             notInlineable();
 244         } else {
 245             obj = new TestClassObject(one, three);
 246             notInlineable();
 247         }
 248         return ((Integer) obj.x).intValue() <= 3 ? 1 : 0;
 249     }
 250 
 251     @Test


 291     }
 292 
 293     @Test
 294     public void testMergeAllocationsException() {
 295         testEscapeAnalysis("testMergeAllocationsExceptionSnippet", JavaConstant.forInt(1), false);
 296     }
 297 
 298     public int testMergeAllocationsExceptionSnippet(int a) {
 299         MyException obj;
 300         Integer one = 1;
 301         if (a < 0) {
 302             obj = new MyException(one);
 303             notInlineable();
 304         } else {
 305             obj = new MyException(one);
 306             notInlineable();
 307         }
 308         return obj.value <= 3 ? 1 : 0;
 309     }
 310 
 311     /**
 312      * Tests that a graph with allocations that does not make progress during PEA will not be
 313      * changed.
 314      */
 315     @Test
 316     public void testChangeHandling() {
 317         prepareGraph("testChangeHandlingSnippet", false);
 318         Assert.assertEquals(2, graph.getNodes().filter(CommitAllocationNode.class).count());
 319         Assert.assertEquals(1, graph.getNodes().filter(BoxNode.class).count());
 320         List<Node> nodes = graph.getNodes().snapshot();
 321         // verify that an additional run doesn't add or remove nodes
 322         new PartialEscapePhase(false, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context);
 323         Assert.assertEquals(nodes.size(), graph.getNodeCount());
 324         for (Node node : nodes) {
 325             Assert.assertTrue(node.isAlive());
 326         }
 327     }
 328 
 329     public volatile Object field;
 330 
 331     public int testChangeHandlingSnippet(int a) {
 332         Object obj;
 333         Integer one = 1;
 334         obj = new MyException(one);
 335         if (a < 0) {
 336             notInlineable();
 337         } else {
 338             obj = new Integer(1);
 339             notInlineable();
 340         }
 341         field = obj;
 342         return 1;
 343     }
 344 
 345     /**
 346      * Test the case where allocations before and during a loop that have no usages other than their
 347      * phi need to be recognized as an important change. This needs a loop so that the allocation is
 348      * not trivially removed by dead code elimination.
 349      */
 350     @Test
 351     public void testRemovalSpecialCase() {
 352         prepareGraph("testRemovalSpecialCaseSnippet", false);
 353         Assert.assertEquals(2, graph.getNodes().filter(CommitAllocationNode.class).count());
 354         // create the situation by removing the if
 355         graph.replaceFixedWithFloating(graph.getNodes().filter(LoadFieldNode.class).first(), graph.unique(ConstantNode.forInt(0)));
 356         new CanonicalizerPhase().apply(graph, context);
 357         // verify that an additional run removes all allocations
 358         new PartialEscapePhase(false, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context);
 359         Assert.assertEquals(0, graph.getNodes().filter(CommitAllocationNode.class).count());
 360     }
 361 
 362     public volatile int field2;
 363 
 364     public int testRemovalSpecialCaseSnippet(int a) {
 365         Object phi = new Object();
 366         for (int i = 0; i < a; i++) {
 367             field = null;
 368             if (field2 == 1) {
 369                 phi = new Object();
 370             }
 371         }
 372         return phi == null ? 1 : 0;
 373     }
 374 
 375     @Test
 376     public void testCheckCast() {
 377         testEscapeAnalysis("testCheckCastSnippet", getSnippetReflection().forObject(TestClassObject.class), true);
 378     }
 379 
 380     public Object testCheckCastSnippet() {
 381         TestClassObject obj = new TestClassObject(TestClassObject.class);
 382         TestClassObject obj2 = new TestClassObject(obj);
 383         return ((TestClassObject) obj2.x).x;
 384     }
 385 
 386     @Test
 387     public void testInstanceOf() {
 388         testEscapeAnalysis("testInstanceOfSnippet", JavaConstant.forInt(1), false);
 389     }
 390 
 391     public boolean testInstanceOfSnippet() {
 392         TestClassObject obj = new TestClassObject(TestClassObject.class);
 393         TestClassObject obj2 = new TestClassObject(obj);
 394         return obj2.x instanceof TestClassObject;
 395     }
 396 
 397     @SuppressWarnings("unused")


 410 
 411     private static final TestClassObject staticObj = new TestClassObject();
 412 
 413     public static Object testFullyUnrolledLoopSnippet() {
 414         /*
 415          * This tests a case that can appear if PEA is performed both before and after loop
 416          * unrolling/peeling: If the VirtualInstanceNode is not duplicated correctly with the loop,
 417          * the resulting object will reference itself, and not a second (different) object.
 418          */
 419         TestClassObject obj = staticObj;
 420         for (int i = 0; i < 2; i++) {
 421             obj = new TestClassObject(obj);
 422         }
 423         return obj.x;
 424     }
 425 
 426     @Test
 427     public void testFullyUnrolledLoop() {
 428         prepareGraph("testFullyUnrolledLoopSnippet", false);
 429         new LoopFullUnrollPhase(new CanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context);
 430         new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context);
 431         Assert.assertEquals(1, returnNodes.size());
 432         Assert.assertTrue(returnNodes.get(0).result() instanceof AllocatedObjectNode);
 433         CommitAllocationNode commit = ((AllocatedObjectNode) returnNodes.get(0).result()).getCommit();
 434         Assert.assertEquals(2, commit.getValues().size());
 435         Assert.assertEquals(1, commit.getVirtualObjects().size());
 436         Assert.assertTrue("non-cyclic data structure expected", commit.getVirtualObjects().get(0) != commit.getValues().get(0));
 437     }
 438 
 439     @SuppressWarnings("unused") private static Object staticField;
 440 
 441     private static TestClassObject inlinedPart(TestClassObject obj) {
 442         TestClassObject ret = new TestClassObject(obj);
 443         staticField = null;
 444         return ret;
 445     }
 446 
 447     public static Object testPeeledLoopSnippet() {
 448         TestClassObject obj = staticObj;
 449         int i = 0;
 450         do {
 451             obj = inlinedPart(obj);
 452         } while (i++ < 10);
 453         staticField = obj;
 454         return obj.x;
 455     }
 456 
 457     @Test
 458     public void testPeeledLoop() {
 459         prepareGraph("testPeeledLoopSnippet", false);
 460         new LoopPeelingPhase(new DefaultLoopPolicies()).apply(graph, getDefaultHighTierContext());
 461         new SchedulePhase(graph.getOptions()).apply(graph);
 462     }
 463 
 464     public static void testDeoptMonitorSnippetInner(Object o2, Object t, int i) {
 465         staticField = null;
 466         if (i == 0) {
 467             staticField = o2;
 468             Number n = (Number) t;
 469             n.toString();
 470         }
 471     }
 472 
 473     public static void testDeoptMonitorSnippet(Object t, int i) {
 474         TestClassObject o = new TestClassObject();
 475         TestClassObject o2 = new TestClassObject(o);
 476 
 477         synchronized (o) {
 478             testDeoptMonitorSnippetInner(o2, t, i);
 479         }
 480     }
 481 
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File