package org.graalvm.compiler.hotspot.gc.g1;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.gc.shared.BarrierSet;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode;
import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode;
import org.graalvm.compiler.nodes.memory.FixedAccessNode;
import org.graalvm.compiler.nodes.memory.HeapAccess;
import org.graalvm.compiler.nodes.memory.ReadNode;
import org.graalvm.compiler.nodes.memory.WriteNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.type.StampTool;
public class G1BarrierSet extends BarrierSet {
public G1BarrierSet(GraalHotSpotVMConfig vmConfig) {
super(vmConfig);
}
@Override
public void addReadNodeBarriers(ReadNode node, StructuredGraph graph) {
if (node.getBarrierType() == HeapAccess.BarrierType.WEAK_FIELD) {
G1ReferentFieldReadBarrier barrier = graph.add(new G1ReferentFieldReadBarrier(node.getAddress(), node, false));
graph.addAfterFixed(node, barrier);
}
}
@Override
public void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) {
HeapAccess.BarrierType barrierType = node.getBarrierType();
switch (barrierType) {
case NONE:
break;
case FIELD:
case ARRAY:
case UNKNOWN:
boolean init = node.getLocationIdentity().isInit();
if (!init || !getVMConfig().useDeferredInitBarriers) {
if (!init) {
addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph);
}
boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
addG1PostWriteBarrier(node, node.getAddress(), node.value(), precise, graph);
}
break;
default:
throw new GraalError("unexpected barrier type: " + barrierType);
}
}
@Override
public void addAtomicReadWriteNodeBarriers(LoweredAtomicReadAndWriteNode node, StructuredGraph graph) {
HeapAccess.BarrierType barrierType = node.getBarrierType();
switch (barrierType) {
case NONE:
break;
case FIELD:
case ARRAY:
case UNKNOWN:
boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph);
addG1PostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
break;
default:
throw new GraalError("unexpected barrier type: " + barrierType);
}
}
@Override
public void addCASBarriers(AbstractCompareAndSwapNode node, StructuredGraph graph) {
HeapAccess.BarrierType barrierType = node.getBarrierType();
switch (barrierType) {
case NONE:
break;
case FIELD:
case ARRAY:
case UNKNOWN:
boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
addG1PreWriteBarrier(node, node.getAddress(), node.getExpectedValue(), false, false, graph);
addG1PostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
break;
default:
throw new GraalError("unexpected barrier type: " + barrierType);
}
}
@Override
public void addArrayRangeBarriers(ArrayRangeWrite write, StructuredGraph graph) {
if (!write.isInitialization()) {
G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride()));
graph.addBeforeFixed(write.asNode(), g1ArrayRangePreWriteBarrier);
}
G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(new G1ArrayRangePostWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride()));
graph.addAfterFixed(write.asNode(), g1ArrayRangePostWriteBarrier);
}
private static void addG1PreWriteBarrier(FixedAccessNode node, AddressNode address, ValueNode value, boolean doLoad, boolean nullCheck, StructuredGraph graph) {
G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(address, value, doLoad, nullCheck));
preBarrier.setStateBefore(node.stateBefore());
node.setNullCheck(false);
node.setStateBefore(null);
graph.addBeforeFixed(node, preBarrier);
}
private static void addG1PostWriteBarrier(FixedAccessNode node, AddressNode address, ValueNode value, boolean precise, StructuredGraph graph) {
final boolean alwaysNull = StampTool.isPointerAlwaysNull(value);
graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(address, value, precise, alwaysNull)));
}
}