1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2019, Red Hat Inc. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 26 package org.graalvm.compiler.hotspot.gc.g1; 27 28 import org.graalvm.compiler.debug.GraalError; 29 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 30 import org.graalvm.compiler.hotspot.gc.shared.BarrierSet; 31 import org.graalvm.compiler.nodes.StructuredGraph; 32 import org.graalvm.compiler.nodes.ValueNode; 33 import org.graalvm.compiler.nodes.extended.ArrayRangeWrite; 34 import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode; 35 import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode; 36 import org.graalvm.compiler.nodes.memory.FixedAccessNode; 37 import org.graalvm.compiler.nodes.memory.HeapAccess; 38 import org.graalvm.compiler.nodes.memory.ReadNode; 39 import org.graalvm.compiler.nodes.memory.WriteNode; 40 import org.graalvm.compiler.nodes.memory.address.AddressNode; 41 import org.graalvm.compiler.nodes.type.StampTool; 42 43 public class G1BarrierSet extends BarrierSet { 44 45 public G1BarrierSet(GraalHotSpotVMConfig vmConfig) { 46 super(vmConfig); 47 } 48 49 @Override 50 public void addReadNodeBarriers(ReadNode node, StructuredGraph graph) { 51 if (node.getBarrierType() == HeapAccess.BarrierType.WEAK_FIELD) { 52 G1ReferentFieldReadBarrier barrier = graph.add(new G1ReferentFieldReadBarrier(node.getAddress(), node, false)); 53 graph.addAfterFixed(node, barrier); 54 } 55 } 56 57 @Override 58 public void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) { 59 HeapAccess.BarrierType barrierType = node.getBarrierType(); 60 switch (barrierType) { 61 case NONE: 62 // nothing to do 63 break; 64 case FIELD: 65 case ARRAY: 66 case UNKNOWN: 67 boolean init = node.getLocationIdentity().isInit(); 68 if (!init || !getVMConfig().useDeferredInitBarriers) { 69 if (!init) { 70 // The pre barrier does nothing if the value being read is null, so it can 71 // be explicitly skipped when this is an initializing store. 72 addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph); 73 } 74 boolean precise = barrierType != HeapAccess.BarrierType.FIELD; 75 addG1PostWriteBarrier(node, node.getAddress(), node.value(), precise, graph); 76 } 77 break; 78 default: 79 throw new GraalError("unexpected barrier type: " + barrierType); 80 } 81 } 82 83 @Override 84 public void addAtomicReadWriteNodeBarriers(LoweredAtomicReadAndWriteNode node, StructuredGraph graph) { 85 HeapAccess.BarrierType barrierType = node.getBarrierType(); 86 switch (barrierType) { 87 case NONE: 88 // nothing to do 89 break; 90 case FIELD: 91 case ARRAY: 92 case UNKNOWN: 93 boolean precise = barrierType != HeapAccess.BarrierType.FIELD; 94 addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph); 95 addG1PostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph); 96 break; 97 default: 98 throw new GraalError("unexpected barrier type: " + barrierType); 99 } 100 } 101 102 @Override 103 public void addCASBarriers(AbstractCompareAndSwapNode node, StructuredGraph graph) { 104 HeapAccess.BarrierType barrierType = node.getBarrierType(); 105 switch (barrierType) { 106 case NONE: 107 // nothing to do 108 break; 109 case FIELD: 110 case ARRAY: 111 case UNKNOWN: 112 boolean precise = barrierType != HeapAccess.BarrierType.FIELD; 113 addG1PreWriteBarrier(node, node.getAddress(), node.getExpectedValue(), false, false, graph); 114 addG1PostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph); 115 break; 116 default: 117 throw new GraalError("unexpected barrier type: " + barrierType); 118 } 119 } 120 121 @Override 122 public void addArrayRangeBarriers(ArrayRangeWrite write, StructuredGraph graph) { 123 if (!write.isInitialization()) { 124 // The pre barrier does nothing if the value being read is null, so it can 125 // be explicitly skipped when this is an initializing store. 126 G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride())); 127 graph.addBeforeFixed(write.asNode(), g1ArrayRangePreWriteBarrier); 128 } 129 G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(new G1ArrayRangePostWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride())); 130 graph.addAfterFixed(write.asNode(), g1ArrayRangePostWriteBarrier); 131 } 132 133 private static void addG1PreWriteBarrier(FixedAccessNode node, AddressNode address, ValueNode value, boolean doLoad, boolean nullCheck, StructuredGraph graph) { 134 G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(address, value, doLoad, nullCheck)); 135 preBarrier.setStateBefore(node.stateBefore()); 136 node.setNullCheck(false); 137 node.setStateBefore(null); 138 graph.addBeforeFixed(node, preBarrier); 139 } 140 141 private static void addG1PostWriteBarrier(FixedAccessNode node, AddressNode address, ValueNode value, boolean precise, StructuredGraph graph) { 142 final boolean alwaysNull = StampTool.isPointerAlwaysNull(value); 143 graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(address, value, precise, alwaysNull))); 144 } 145 }