1 /* 2 * Copyright (c) 2018, 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 24 25 package org.graalvm.compiler.replacements.jdk9.test; 26 27 import java.lang.invoke.MethodHandles; 28 import java.lang.invoke.VarHandle; 29 30 import org.graalvm.compiler.core.test.GraalCompilerTest; 31 import org.graalvm.compiler.debug.GraalError; 32 import org.graalvm.compiler.graph.Node; 33 import org.graalvm.compiler.nodes.StartNode; 34 import org.graalvm.compiler.nodes.StructuredGraph; 35 import org.graalvm.compiler.nodes.extended.MembarNode; 36 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; 37 import org.graalvm.compiler.nodes.memory.ReadNode; 38 import org.graalvm.compiler.nodes.memory.WriteNode; 39 import jdk.internal.vm.compiler.word.LocationIdentity; 40 import org.junit.Assert; 41 import org.junit.Test; 42 43 import jdk.vm.ci.meta.ResolvedJavaMethod; 44 45 public class VarHandleTest extends GraalCompilerTest { 46 47 static class Holder { 48 /* Field is declared volatile, but accessed with non-volatile semantics in the tests. */ 49 volatile int volatileField = 42; 50 51 /* Field is declared non-volatile, but accessed with volatile semantics in the tests. */ 52 int field = 2018; 53 54 static final VarHandle VOLATILE_FIELD; 55 static final VarHandle FIELD; 56 57 static { 58 try { 59 VOLATILE_FIELD = MethodHandles.lookup().findVarHandle(Holder.class, "volatileField", int.class); 60 FIELD = MethodHandles.lookup().findVarHandle(Holder.class, "field", int.class); 61 } catch (ReflectiveOperationException ex) { 62 throw GraalError.shouldNotReachHere(ex); 63 } 64 } 65 } 66 67 public static int testRead1Snippet(Holder h) { 68 /* Explicitly access the volatile field with non-volatile access semantics. */ 69 return (int) Holder.VOLATILE_FIELD.get(h); 70 } 71 72 public static int testRead2Snippet(Holder h) { 73 /* Explicitly access the volatile field with volatile access semantics. */ 74 return (int) Holder.VOLATILE_FIELD.getVolatile(h); 75 } 76 77 public static int testRead3Snippet(Holder h) { 78 /* Explicitly access the non-volatile field with non-volatile access semantics. */ 79 return (int) Holder.FIELD.get(h); 80 } 81 82 public static int testRead4Snippet(Holder h) { 83 /* Explicitly access the non-volatile field with volatile access semantics. */ 84 return (int) Holder.FIELD.getVolatile(h); 85 } 86 87 public static void testWrite1Snippet(Holder h) { 88 /* Explicitly access the volatile field with non-volatile access semantics. */ 89 Holder.VOLATILE_FIELD.set(h, 123); 90 } 91 92 public static void testWrite2Snippet(Holder h) { 93 /* Explicitly access the volatile field with volatile access semantics. */ 94 Holder.VOLATILE_FIELD.setVolatile(h, 123); 95 } 96 97 public static void testWrite3Snippet(Holder h) { 98 /* Explicitly access the non-volatile field with non-volatile access semantics. */ 99 Holder.FIELD.set(h, 123); 100 } 101 102 public static void testWrite4Snippet(Holder h) { 103 /* Explicitly access the non-volatile field with volatile access semantics. */ 104 Holder.FIELD.setVolatile(h, 123); 105 } 106 107 void testAccess(String name, int expectedReads, int expectedWrites, int expectedMembars, int expectedAnyKill) { 108 ResolvedJavaMethod method = getResolvedJavaMethod(name); 109 StructuredGraph graph = parseForCompile(method); 110 compile(method, graph); 111 Assert.assertEquals(expectedReads, graph.getNodes().filter(ReadNode.class).count()); 112 Assert.assertEquals(expectedWrites, graph.getNodes().filter(WriteNode.class).count()); 113 Assert.assertEquals(expectedMembars, graph.getNodes().filter(MembarNode.class).count()); 114 Assert.assertEquals(expectedAnyKill, countAnyKill(graph)); 115 } 116 117 @Test 118 public void testRead1() { 119 testAccess("testRead1Snippet", 1, 0, 0, 0); 120 } 121 122 @Test 123 public void testRead2() { 124 testAccess("testRead2Snippet", 1, 0, 2, 2); 125 } 126 127 @Test 128 public void testRead3() { 129 testAccess("testRead3Snippet", 1, 0, 0, 0); 130 } 131 132 @Test 133 public void testRead4() { 134 testAccess("testRead4Snippet", 1, 0, 2, 2); 135 } 136 137 @Test 138 public void testWrite1() { 139 testAccess("testWrite1Snippet", 0, 1, 0, 0); 140 } 141 142 @Test 143 public void testWrite2() { 144 testAccess("testWrite2Snippet", 0, 1, 2, 2); 145 } 146 147 @Test 148 public void testWrite3() { 149 testAccess("testWrite3Snippet", 0, 1, 0, 0); 150 } 151 152 @Test 153 public void testWrite4() { 154 testAccess("testWrite4Snippet", 0, 1, 2, 2); 155 } 156 157 private static int countAnyKill(StructuredGraph graph) { 158 int anyKillCount = 0; 159 int startNodes = 0; 160 for (Node n : graph.getNodes()) { 161 if (n instanceof StartNode) { 162 startNodes++; 163 } else if (n instanceof MemoryCheckpoint.Single) { 164 MemoryCheckpoint.Single single = (MemoryCheckpoint.Single) n; 165 if (single.getLocationIdentity().isAny()) { 166 anyKillCount++; 167 } 168 } else if (n instanceof MemoryCheckpoint.Multi) { 169 MemoryCheckpoint.Multi multi = (MemoryCheckpoint.Multi) n; 170 for (LocationIdentity loc : multi.getLocationIdentities()) { 171 if (loc.isAny()) { 172 anyKillCount++; 173 break; 174 } 175 } 176 } 177 } 178 // Ignore single StartNode. 179 Assert.assertEquals(1, startNodes); 180 return anyKillCount; 181 } 182 }