1 /* 2 * Copyright (c) 2017, 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 org.graalvm.compiler.core.common.GraalOptions; 26 import org.graalvm.compiler.core.test.GraalCompilerTest; 27 import org.graalvm.compiler.nodes.StructuredGraph; 28 import org.graalvm.compiler.nodes.extended.RawLoadNode; 29 import org.graalvm.compiler.nodes.extended.RawStoreNode; 30 import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; 31 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 32 import org.graalvm.compiler.phases.common.inlining.InliningPhase; 33 import org.graalvm.compiler.phases.tiers.HighTierContext; 34 import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; 35 import org.junit.Test; 36 import sun.misc.Unsafe; 37 38 import java.lang.reflect.Field; 39 40 public class TrufflePEATest extends GraalCompilerTest { 41 42 /** 43 * This class mimics the behavior of {@code FrameWithoutBoxing}. 44 */ 45 static class Frame { 46 long[] primitiveLocals; 47 48 Frame(int size) { 49 primitiveLocals = new long[size]; 50 } 51 } 52 53 /** 54 * This class mimics the behavior of {@code DynamicObjectL6I6}. 55 */ 56 static class DynamicObject { 57 int primitiveField0; 58 int primitiveField1; 59 } 60 61 private static final long offsetLong1 = Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * 1; 62 private static final long offsetLong2 = Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * 2; 63 64 private static final long primitiveField0Offset; 65 66 static { 67 try { 68 Field primitiveField0 = DynamicObject.class.getDeclaredField("primitiveField0"); 69 primitiveField0Offset = UNSAFE.objectFieldOffset(primitiveField0); 70 } catch (NoSuchFieldException | SecurityException e) { 71 throw new AssertionError(e); 72 } 73 } 74 75 public static int unsafeAccessToLongArray(int v, Frame frame) { 76 long[] array = frame.primitiveLocals; 77 int s = UNSAFE.getInt(array, offsetLong1); 78 UNSAFE.putInt(array, offsetLong1, v); 79 UNSAFE.putInt(array, offsetLong2, v); 80 return s + UNSAFE.getInt(array, offsetLong1) + UNSAFE.getInt(array, offsetLong2); 81 } 82 83 @Test 84 public void testUnsafeAccessToLongArray() { 85 StructuredGraph graph = processMethod("unsafeAccessToLongArray"); 86 assertDeepEquals(1, graph.getNodes().filter(RawLoadNode.class).count()); 87 } 88 89 /** 90 * The following value should be less than the default value of 91 * {@link GraalOptions#MaximumEscapeAnalysisArrayLength}. 92 */ 93 private static final int FRAME_SIZE = 16; 94 95 public static long newFrame(long v) { 96 Frame frame = new Frame(FRAME_SIZE); 97 // Testing unsafe accesses with other kinds requires special handling of the initialized 98 // entry kind. 99 UNSAFE.putLong(frame.primitiveLocals, offsetLong1, v); 100 return UNSAFE.getLong(frame.primitiveLocals, offsetLong1); 101 } 102 103 @Test 104 public void testNewFrame() { 105 StructuredGraph graph = processMethod("newFrame"); 106 assertDeepEquals(0, graph.getNodes().filter(CommitAllocationNode.class).count()); 107 assertDeepEquals(0, graph.getNodes().filter(RawLoadNode.class).count()); 108 assertDeepEquals(0, graph.getNodes().filter(RawStoreNode.class).count()); 109 } 110 111 protected StructuredGraph processMethod(final String snippet) { 112 StructuredGraph graph = parseEager(snippet, StructuredGraph.AllowAssumptions.NO); 113 HighTierContext context = getDefaultHighTierContext(); 114 new InliningPhase(new CanonicalizerPhase()).apply(graph, context); 115 new PartialEscapePhase(true, true, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); 116 return graph; 117 } 118 119 public static double accessDynamicObject(double v) { 120 DynamicObject obj = new DynamicObject(); 121 UNSAFE.putDouble(obj, primitiveField0Offset, v); 122 return UNSAFE.getDouble(obj, primitiveField0Offset); 123 } 124 125 @Test 126 public void testAccessDynamicObject() { 127 StructuredGraph graph = processMethod("accessDynamicObject"); 128 assertDeepEquals(0, graph.getNodes().filter(CommitAllocationNode.class).count()); 129 assertDeepEquals(0, graph.getNodes().filter(RawLoadNode.class).count()); 130 assertDeepEquals(0, graph.getNodes().filter(RawStoreNode.class).count()); 131 } 132 133 }