< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java

Print this page




  27 
  28 import java.util.Iterator;
  29 
  30 import org.graalvm.compiler.debug.GraalError;
  31 import org.graalvm.compiler.graph.Node;
  32 import org.graalvm.compiler.graph.NodeFlood;
  33 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  34 import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier;
  35 import org.graalvm.compiler.hotspot.gc.shared.ArrayRangeWriteBarrier;
  36 import org.graalvm.compiler.hotspot.gc.shared.ObjectWriteBarrier;
  37 import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier;
  38 import org.graalvm.compiler.nodeinfo.Verbosity;
  39 import org.graalvm.compiler.nodes.DeoptimizingNode;
  40 import org.graalvm.compiler.nodes.FixedWithNextNode;
  41 import org.graalvm.compiler.nodes.LoopBeginNode;
  42 import org.graalvm.compiler.nodes.StructuredGraph;
  43 import org.graalvm.compiler.nodes.ValueNode;
  44 import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
  45 import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode;
  46 import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode;

  47 import org.graalvm.compiler.nodes.memory.FixedAccessNode;
  48 import org.graalvm.compiler.nodes.memory.HeapAccess;
  49 import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
  50 import org.graalvm.compiler.nodes.memory.ReadNode;
  51 import org.graalvm.compiler.nodes.memory.WriteNode;
  52 import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
  53 import org.graalvm.compiler.nodes.type.StampTool;
  54 import org.graalvm.compiler.nodes.util.GraphUtil;
  55 import org.graalvm.compiler.phases.Phase;
  56 
  57 /**
  58  * Verification phase that checks if, for every write, at least one write barrier is present at all
  59  * paths leading to the previous safepoint. For every write, necessitating a write barrier, a
  60  * bottom-up traversal of the graph is performed up to the previous safepoints via all possible
  61  * paths. If, for a certain path, no write barrier satisfying the processed write is found, an
  62  * assertion is generated.
  63  */
  64 public class WriteBarrierVerificationPhase extends Phase {
  65 
  66     private final GraalHotSpotVMConfig config;


 110                 }
 111             } else {
 112                 if (!(currentNode instanceof SerialWriteBarrier) || (!validateBarrier((FixedAccessNode) write, (ObjectWriteBarrier) currentNode)) ||
 113                                 ((currentNode instanceof SerialWriteBarrier) && !validateBarrier((FixedAccessNode) write, (ObjectWriteBarrier) currentNode))) {
 114                     expandFrontier(frontier, currentNode);
 115                 }
 116             }
 117         }
 118     }
 119 
 120     private boolean useG1GC() {
 121         return config.useG1GC;
 122     }
 123 
 124     private boolean hasAttachedBarrier(FixedWithNextNode node) {
 125         final Node next = node.next();
 126         final Node previous = node.predecessor();
 127         boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWrite) node).isInitialization());
 128         if (node instanceof WriteNode) {
 129             WriteNode writeNode = (WriteNode) node;



 130             if (writeNode.getLocationIdentity().isInit()) {
 131                 validatePreBarrier = false;
 132             }
 133         }
 134         if (isObjectWrite(node)) {
 135             return (isObjectBarrier(node, next) || StampTool.isPointerAlwaysNull(getValueWritten(node))) && (!validatePreBarrier || isObjectBarrier(node, previous));
 136         } else if (isObjectArrayRangeWrite(node)) {
 137             return (isArrayBarrier(node, next) || StampTool.isPointerAlwaysNull(getValueWritten(node))) && (!validatePreBarrier || isArrayBarrier(node, previous));
 138         } else {
 139             return true;
 140         }
 141     }
 142 
 143     private static boolean isObjectBarrier(FixedWithNextNode node, final Node next) {
 144         return next instanceof ObjectWriteBarrier && validateBarrier((FixedAccessNode) node, (ObjectWriteBarrier) next);
 145     }
 146 
 147     private static boolean isArrayBarrier(FixedWithNextNode node, final Node next) {
 148         return (next instanceof ArrayRangeWriteBarrier) && ((ArrayRangeWrite) node).getAddress() == ((ArrayRangeWriteBarrier) next).getAddress();
 149     }


 174          * LoopBegin nodes are also treated as safepoints since a bottom-up analysis is performed
 175          * and loop safepoints are placed before LoopEnd nodes. Possible elimination of write
 176          * barriers inside loops, derived from writes outside loops, can not be permitted.
 177          */
 178         return ((node instanceof DeoptimizingNode) && ((DeoptimizingNode) node).canDeoptimize()) || (node instanceof LoopBeginNode);
 179     }
 180 
 181     private static ValueNode getValueWritten(FixedWithNextNode write) {
 182         if (write instanceof WriteNode) {
 183             return ((WriteNode) write).value();
 184         } else if (write instanceof LogicCompareAndSwapNode) {
 185             return ((LogicCompareAndSwapNode) write).getNewValue();
 186         } else if (write instanceof LoweredAtomicReadAndWriteNode) {
 187             return ((LoweredAtomicReadAndWriteNode) write).getNewValue();
 188         } else {
 189             throw GraalError.shouldNotReachHere(String.format("unexpected write node %s", write));
 190         }
 191     }
 192 
 193     private static boolean validateBarrier(FixedAccessNode write, ObjectWriteBarrier barrier) {
 194         assert write instanceof WriteNode || write instanceof LogicCompareAndSwapNode || write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write;

 195         if (!barrier.usePrecise()) {
 196             if (barrier.getAddress() instanceof OffsetAddressNode && write.getAddress() instanceof OffsetAddressNode) {
 197                 return GraphUtil.unproxify(((OffsetAddressNode) barrier.getAddress()).getBase()) == GraphUtil.unproxify(((OffsetAddressNode) write.getAddress()).getBase());
 198             }
 199         }
 200         return barrier.getAddress() == write.getAddress();
 201     }
 202 }


  27 
  28 import java.util.Iterator;
  29 
  30 import org.graalvm.compiler.debug.GraalError;
  31 import org.graalvm.compiler.graph.Node;
  32 import org.graalvm.compiler.graph.NodeFlood;
  33 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  34 import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier;
  35 import org.graalvm.compiler.hotspot.gc.shared.ArrayRangeWriteBarrier;
  36 import org.graalvm.compiler.hotspot.gc.shared.ObjectWriteBarrier;
  37 import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier;
  38 import org.graalvm.compiler.nodeinfo.Verbosity;
  39 import org.graalvm.compiler.nodes.DeoptimizingNode;
  40 import org.graalvm.compiler.nodes.FixedWithNextNode;
  41 import org.graalvm.compiler.nodes.LoopBeginNode;
  42 import org.graalvm.compiler.nodes.StructuredGraph;
  43 import org.graalvm.compiler.nodes.ValueNode;
  44 import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
  45 import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode;
  46 import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode;
  47 import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode;
  48 import org.graalvm.compiler.nodes.memory.FixedAccessNode;
  49 import org.graalvm.compiler.nodes.memory.HeapAccess;
  50 import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
  51 import org.graalvm.compiler.nodes.memory.ReadNode;
  52 import org.graalvm.compiler.nodes.memory.WriteNode;
  53 import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
  54 import org.graalvm.compiler.nodes.type.StampTool;
  55 import org.graalvm.compiler.nodes.util.GraphUtil;
  56 import org.graalvm.compiler.phases.Phase;
  57 
  58 /**
  59  * Verification phase that checks if, for every write, at least one write barrier is present at all
  60  * paths leading to the previous safepoint. For every write, necessitating a write barrier, a
  61  * bottom-up traversal of the graph is performed up to the previous safepoints via all possible
  62  * paths. If, for a certain path, no write barrier satisfying the processed write is found, an
  63  * assertion is generated.
  64  */
  65 public class WriteBarrierVerificationPhase extends Phase {
  66 
  67     private final GraalHotSpotVMConfig config;


 111                 }
 112             } else {
 113                 if (!(currentNode instanceof SerialWriteBarrier) || (!validateBarrier((FixedAccessNode) write, (ObjectWriteBarrier) currentNode)) ||
 114                                 ((currentNode instanceof SerialWriteBarrier) && !validateBarrier((FixedAccessNode) write, (ObjectWriteBarrier) currentNode))) {
 115                     expandFrontier(frontier, currentNode);
 116                 }
 117             }
 118         }
 119     }
 120 
 121     private boolean useG1GC() {
 122         return config.useG1GC;
 123     }
 124 
 125     private boolean hasAttachedBarrier(FixedWithNextNode node) {
 126         final Node next = node.next();
 127         final Node previous = node.predecessor();
 128         boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWrite) node).isInitialization());
 129         if (node instanceof WriteNode) {
 130             WriteNode writeNode = (WriteNode) node;
 131             if (config.useDeferredInitBarriers && writeNode.getLocationIdentity().isInit()) {
 132                 return true;
 133             }
 134             if (writeNode.getLocationIdentity().isInit()) {
 135                 validatePreBarrier = false;
 136             }
 137         }
 138         if (isObjectWrite(node)) {
 139             return (isObjectBarrier(node, next) || StampTool.isPointerAlwaysNull(getValueWritten(node))) && (!validatePreBarrier || isObjectBarrier(node, previous));
 140         } else if (isObjectArrayRangeWrite(node)) {
 141             return (isArrayBarrier(node, next) || StampTool.isPointerAlwaysNull(getValueWritten(node))) && (!validatePreBarrier || isArrayBarrier(node, previous));
 142         } else {
 143             return true;
 144         }
 145     }
 146 
 147     private static boolean isObjectBarrier(FixedWithNextNode node, final Node next) {
 148         return next instanceof ObjectWriteBarrier && validateBarrier((FixedAccessNode) node, (ObjectWriteBarrier) next);
 149     }
 150 
 151     private static boolean isArrayBarrier(FixedWithNextNode node, final Node next) {
 152         return (next instanceof ArrayRangeWriteBarrier) && ((ArrayRangeWrite) node).getAddress() == ((ArrayRangeWriteBarrier) next).getAddress();
 153     }


 178          * LoopBegin nodes are also treated as safepoints since a bottom-up analysis is performed
 179          * and loop safepoints are placed before LoopEnd nodes. Possible elimination of write
 180          * barriers inside loops, derived from writes outside loops, can not be permitted.
 181          */
 182         return ((node instanceof DeoptimizingNode) && ((DeoptimizingNode) node).canDeoptimize()) || (node instanceof LoopBeginNode);
 183     }
 184 
 185     private static ValueNode getValueWritten(FixedWithNextNode write) {
 186         if (write instanceof WriteNode) {
 187             return ((WriteNode) write).value();
 188         } else if (write instanceof LogicCompareAndSwapNode) {
 189             return ((LogicCompareAndSwapNode) write).getNewValue();
 190         } else if (write instanceof LoweredAtomicReadAndWriteNode) {
 191             return ((LoweredAtomicReadAndWriteNode) write).getNewValue();
 192         } else {
 193             throw GraalError.shouldNotReachHere(String.format("unexpected write node %s", write));
 194         }
 195     }
 196 
 197     private static boolean validateBarrier(FixedAccessNode write, ObjectWriteBarrier barrier) {
 198         assert write instanceof WriteNode || write instanceof LogicCompareAndSwapNode || write instanceof ValueCompareAndSwapNode ||
 199                         write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write;
 200         if (!barrier.usePrecise()) {
 201             if (barrier.getAddress() instanceof OffsetAddressNode && write.getAddress() instanceof OffsetAddressNode) {
 202                 return GraphUtil.unproxify(((OffsetAddressNode) barrier.getAddress()).getBase()) == GraphUtil.unproxify(((OffsetAddressNode) write.getAddress()).getBase());
 203             }
 204         }
 205         return barrier.getAddress() == write.getAddress();
 206     }
 207 }
< prev index next >