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.hotspot.test; 24 25 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.config; 26 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.referentOffset; 27 28 import java.lang.ref.WeakReference; 29 30 import org.junit.Assert; 31 import org.junit.Test; 32 33 import org.graalvm.compiler.debug.Debug; 34 import org.graalvm.compiler.debug.Debug.Scope; 35 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 36 import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; 37 import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; 38 import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier; 39 import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; 40 import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; 41 import org.graalvm.compiler.nodes.StructuredGraph; 42 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 43 import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; 44 import org.graalvm.compiler.nodes.memory.ReadNode; 45 import org.graalvm.compiler.nodes.memory.WriteNode; 46 import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; 47 import org.graalvm.compiler.nodes.spi.LoweringTool; 48 import org.graalvm.compiler.phases.OptimisticOptimizations; 49 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 50 import org.graalvm.compiler.phases.common.GuardLoweringPhase; 51 import org.graalvm.compiler.phases.common.LoweringPhase; 52 import org.graalvm.compiler.phases.common.inlining.InliningPhase; 53 import org.graalvm.compiler.phases.common.inlining.policy.InlineEverythingPolicy; 54 import org.graalvm.compiler.phases.tiers.HighTierContext; 55 import org.graalvm.compiler.phases.tiers.MidTierContext; 56 57 import jdk.vm.ci.hotspot.HotSpotInstalledCode; 58 import jdk.vm.ci.meta.JavaConstant; 59 import jdk.vm.ci.meta.ResolvedJavaMethod; 60 import sun.misc.Unsafe; 61 62 /** 63 * The following unit tests assert the presence of write barriers for both Serial and G1 GCs. 64 * Normally, the tests check for compile time inserted barriers. However, there are the cases of 65 * unsafe loads of the java.lang.ref.Reference.referent field where runtime checks have to be 66 * performed also. For those cases, the unit tests check the presence of the compile-time inserted 67 * barriers. Concerning the runtime checks, the results of variable inputs (object types and 68 * offsets) passed as input parameters can be checked against printed output from the G1 write 69 * barrier snippets. The runtime checks have been validated offline. 70 */ 71 public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest { 72 73 private final GraalHotSpotVMConfig config = runtime().getVMConfig(); 74 private static final long referentOffset = referentOffset(); 75 239 public void test11() throws Exception { 240 test2("testArrayCopy", src, dst, dst.length); 241 } 242 243 public static Object testUnsafeLoad(Unsafe theUnsafe, Object a, Object b, Object c) throws Exception { 244 final int offset = (c == null ? 0 : ((Integer) c).intValue()); 245 final long displacement = (b == null ? 0 : ((Long) b).longValue()); 246 return theUnsafe.getObject(a, offset + displacement); 247 } 248 249 private HotSpotInstalledCode getInstalledCode(String name, boolean withUnsafePrefix) throws Exception { 250 final ResolvedJavaMethod javaMethod = withUnsafePrefix ? getResolvedJavaMethod(WriteBarrierAdditionTest.class, name, Unsafe.class, Object.class, Object.class, Object.class) 251 : getResolvedJavaMethod(WriteBarrierAdditionTest.class, name, Object.class, Object.class, Object.class); 252 final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(javaMethod); 253 return installedCode; 254 } 255 256 @SuppressWarnings("try") 257 private void testHelper(final String snippetName, final int expectedBarriers) throws Exception, SecurityException { 258 ResolvedJavaMethod snippet = getResolvedJavaMethod(snippetName); 259 try (Scope s = Debug.scope("WriteBarrierAdditionTest", snippet)) { 260 StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); 261 HighTierContext highContext = getDefaultHighTierContext(); 262 MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); 263 new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase()).apply(graph, highContext); 264 new CanonicalizerPhase().apply(graph, highContext); 265 new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highContext); 266 new GuardLoweringPhase().apply(graph, midContext); 267 new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); 268 new WriteBarrierAdditionPhase(config).apply(graph); 269 Debug.dump(Debug.BASIC_LEVEL, graph, "After Write Barrier Addition"); 270 271 int barriers = 0; 272 if (config.useG1GC) { 273 barriers = graph.getNodes().filter(G1ReferentFieldReadBarrier.class).count() + graph.getNodes().filter(G1PreWriteBarrier.class).count() + 274 graph.getNodes().filter(G1PostWriteBarrier.class).count(); 275 } else { 276 barriers = graph.getNodes().filter(SerialWriteBarrier.class).count(); 277 } 278 if (expectedBarriers != barriers) { 279 Assert.assertEquals(getScheduledGraphString(graph), expectedBarriers, barriers); 280 } 281 for (WriteNode write : graph.getNodes().filter(WriteNode.class)) { 282 if (config.useG1GC) { 283 if (write.getBarrierType() != BarrierType.NONE) { 284 Assert.assertEquals(1, write.successors().count()); 285 Assert.assertTrue(write.next() instanceof G1PostWriteBarrier); 286 Assert.assertTrue(write.predecessor() instanceof G1PreWriteBarrier); 287 } 288 } else { 289 if (write.getBarrierType() != BarrierType.NONE) { 290 Assert.assertEquals(1, write.successors().count()); 291 Assert.assertTrue(write.next() instanceof SerialWriteBarrier); 292 } 293 } 294 } 295 296 for (ReadNode read : graph.getNodes().filter(ReadNode.class)) { 297 if (read.getBarrierType() != BarrierType.NONE) { 298 Assert.assertTrue(read.getAddress() instanceof OffsetAddressNode); 299 JavaConstant constDisp = ((OffsetAddressNode) read.getAddress()).getOffset().asJavaConstant(); 300 Assert.assertNotNull(constDisp); 301 Assert.assertEquals(referentOffset, constDisp.asLong()); 302 Assert.assertTrue(config.useG1GC); 303 Assert.assertEquals(BarrierType.PRECISE, read.getBarrierType()); 304 Assert.assertTrue(read.next() instanceof G1ReferentFieldReadBarrier); 305 } 306 } 307 } catch (Throwable e) { 308 throw Debug.handle(e); 309 } 310 } 311 312 private void test2(final String snippet, Object... args) throws Exception { 313 HotSpotInstalledCode code = getInstalledCode(snippet, args[0] instanceof Unsafe); 314 code.executeVarargs(args); 315 } 316 } | 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.hotspot.test; 24 25 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.config; 26 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.referentOffset; 27 28 import java.lang.ref.WeakReference; 29 30 import org.graalvm.compiler.debug.DebugContext; 31 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 32 import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; 33 import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; 34 import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier; 35 import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; 36 import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; 37 import org.graalvm.compiler.nodes.StructuredGraph; 38 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 39 import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; 40 import org.graalvm.compiler.nodes.memory.ReadNode; 41 import org.graalvm.compiler.nodes.memory.WriteNode; 42 import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; 43 import org.graalvm.compiler.nodes.spi.LoweringTool; 44 import org.graalvm.compiler.phases.OptimisticOptimizations; 45 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 46 import org.graalvm.compiler.phases.common.GuardLoweringPhase; 47 import org.graalvm.compiler.phases.common.LoweringPhase; 48 import org.graalvm.compiler.phases.common.inlining.InliningPhase; 49 import org.graalvm.compiler.phases.common.inlining.policy.InlineEverythingPolicy; 50 import org.graalvm.compiler.phases.tiers.HighTierContext; 51 import org.graalvm.compiler.phases.tiers.MidTierContext; 52 import org.junit.Assert; 53 import org.junit.Test; 54 55 import jdk.vm.ci.hotspot.HotSpotInstalledCode; 56 import jdk.vm.ci.meta.JavaConstant; 57 import jdk.vm.ci.meta.ResolvedJavaMethod; 58 import sun.misc.Unsafe; 59 60 /** 61 * The following unit tests assert the presence of write barriers for both Serial and G1 GCs. 62 * Normally, the tests check for compile time inserted barriers. However, there are the cases of 63 * unsafe loads of the java.lang.ref.Reference.referent field where runtime checks have to be 64 * performed also. For those cases, the unit tests check the presence of the compile-time inserted 65 * barriers. Concerning the runtime checks, the results of variable inputs (object types and 66 * offsets) passed as input parameters can be checked against printed output from the G1 write 67 * barrier snippets. The runtime checks have been validated offline. 68 */ 69 public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest { 70 71 private final GraalHotSpotVMConfig config = runtime().getVMConfig(); 72 private static final long referentOffset = referentOffset(); 73 237 public void test11() throws Exception { 238 test2("testArrayCopy", src, dst, dst.length); 239 } 240 241 public static Object testUnsafeLoad(Unsafe theUnsafe, Object a, Object b, Object c) throws Exception { 242 final int offset = (c == null ? 0 : ((Integer) c).intValue()); 243 final long displacement = (b == null ? 0 : ((Long) b).longValue()); 244 return theUnsafe.getObject(a, offset + displacement); 245 } 246 247 private HotSpotInstalledCode getInstalledCode(String name, boolean withUnsafePrefix) throws Exception { 248 final ResolvedJavaMethod javaMethod = withUnsafePrefix ? getResolvedJavaMethod(WriteBarrierAdditionTest.class, name, Unsafe.class, Object.class, Object.class, Object.class) 249 : getResolvedJavaMethod(WriteBarrierAdditionTest.class, name, Object.class, Object.class, Object.class); 250 final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(javaMethod); 251 return installedCode; 252 } 253 254 @SuppressWarnings("try") 255 private void testHelper(final String snippetName, final int expectedBarriers) throws Exception, SecurityException { 256 ResolvedJavaMethod snippet = getResolvedJavaMethod(snippetName); 257 DebugContext debug = getDebugContext(); 258 try (DebugContext.Scope s = debug.scope("WriteBarrierAdditionTest", snippet)) { 259 StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, debug); 260 HighTierContext highContext = getDefaultHighTierContext(); 261 MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); 262 new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase()).apply(graph, highContext); 263 new CanonicalizerPhase().apply(graph, highContext); 264 new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highContext); 265 new GuardLoweringPhase().apply(graph, midContext); 266 new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); 267 new WriteBarrierAdditionPhase(config).apply(graph); 268 debug.dump(DebugContext.BASIC_LEVEL, graph, "After Write Barrier Addition"); 269 270 int barriers = 0; 271 if (config.useG1GC) { 272 barriers = graph.getNodes().filter(G1ReferentFieldReadBarrier.class).count() + graph.getNodes().filter(G1PreWriteBarrier.class).count() + 273 graph.getNodes().filter(G1PostWriteBarrier.class).count(); 274 } else { 275 barriers = graph.getNodes().filter(SerialWriteBarrier.class).count(); 276 } 277 if (expectedBarriers != barriers) { 278 Assert.assertEquals(getScheduledGraphString(graph), expectedBarriers, barriers); 279 } 280 for (WriteNode write : graph.getNodes().filter(WriteNode.class)) { 281 if (config.useG1GC) { 282 if (write.getBarrierType() != BarrierType.NONE) { 283 Assert.assertEquals(1, write.successors().count()); 284 Assert.assertTrue(write.next() instanceof G1PostWriteBarrier); 285 Assert.assertTrue(write.predecessor() instanceof G1PreWriteBarrier); 286 } 287 } else { 288 if (write.getBarrierType() != BarrierType.NONE) { 289 Assert.assertEquals(1, write.successors().count()); 290 Assert.assertTrue(write.next() instanceof SerialWriteBarrier); 291 } 292 } 293 } 294 295 for (ReadNode read : graph.getNodes().filter(ReadNode.class)) { 296 if (read.getBarrierType() != BarrierType.NONE) { 297 Assert.assertTrue(read.getAddress() instanceof OffsetAddressNode); 298 JavaConstant constDisp = ((OffsetAddressNode) read.getAddress()).getOffset().asJavaConstant(); 299 Assert.assertNotNull(constDisp); 300 Assert.assertEquals(referentOffset, constDisp.asLong()); 301 Assert.assertTrue(config.useG1GC); 302 Assert.assertEquals(BarrierType.PRECISE, read.getBarrierType()); 303 Assert.assertTrue(read.next() instanceof G1ReferentFieldReadBarrier); 304 } 305 } 306 } catch (Throwable e) { 307 throw debug.handle(e); 308 } 309 } 310 311 private void test2(final String snippet, Object... args) throws Exception { 312 HotSpotInstalledCode code = getInstalledCode(snippet, args[0] instanceof Unsafe); 313 code.executeVarargs(args); 314 } 315 } |