private static void checkWatchList( ArrayList<FloatingReadNode> watchList, LocationIdentity identity, Block b, ArrayList<Node> result, NodeMap<Block> nodeMap, NodeBitMap unprocessed) { assert identity.isMutable(); if (identity.isAny()) { for (FloatingReadNode r : watchList) { if (unprocessed.isMarked(r)) { sortIntoList(r, b, result, nodeMap, unprocessed, null); } } watchList.clear(); } else { int index = 0; while (index < watchList.size()) { FloatingReadNode r = watchList.get(index); LocationIdentity locationIdentity = r.getLocationIdentity(); assert locationIdentity.isMutable(); if (unprocessed.isMarked(r)) { if (identity.overlaps(locationIdentity)) { sortIntoList(r, b, result, nodeMap, unprocessed, null); } else { ++index; continue; } } int lastIndex = watchList.size() - 1; watchList.set(index, watchList.get(lastIndex)); watchList.remove(lastIndex); } } }
@Override public LocationIdentity getLocationIdentity() { /* * Because of restrictions that the memory graph of snippets matches the original node, * pretend that we kill any. */ return LocationIdentity.any(); }
private void processLocation( Node n, LocationIdentity location, Set<FloatingReadNode> currentState) { assert n != null; if (location.isImmutable()) { return; } for (FloatingReadNode r : cloneState(currentState)) { if (r.getLocationIdentity().overlaps(location)) { // This read is killed by this location. currentState.remove(r); } } }
@Override public LocationIdentity getLocationIdentity() { return LocationIdentity.any(); }
private static void resortEarliestWithinBlock( Block b, BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, NodeBitMap unprocessed) { ArrayList<FloatingReadNode> watchList = new ArrayList<>(); List<Node> oldList = blockToNodes.get(b); AbstractBeginNode beginNode = b.getBeginNode(); for (Node n : oldList) { if (n instanceof FloatingReadNode) { FloatingReadNode floatingReadNode = (FloatingReadNode) n; LocationIdentity locationIdentity = floatingReadNode.getLocationIdentity(); MemoryNode lastLocationAccess = floatingReadNode.getLastLocationAccess(); if (locationIdentity.isMutable() && lastLocationAccess != null) { ValueNode lastAccessLocation = lastLocationAccess.asNode(); if (nodeToBlock.get(lastAccessLocation) == b && lastAccessLocation != beginNode && !(lastAccessLocation instanceof MemoryPhiNode)) { // This node's last access location is within this block. Add to watch // list when processing the last access location. } else { watchList.add(floatingReadNode); } } } } ArrayList<Node> newList = new ArrayList<>(oldList.size()); assert oldList.get(0) == beginNode; unprocessed.clear(beginNode); newList.add(beginNode); for (int i = 1; i < oldList.size(); ++i) { Node n = oldList.get(i); if (unprocessed.isMarked(n)) { if (n instanceof MemoryNode) { if (n instanceof MemoryCheckpoint) { assert n instanceof FixedNode; if (watchList.size() > 0) { // Check whether we need to commit reads from the watch list. checkWatchList(b, nodeToBlock, unprocessed, newList, watchList, n); } } // Add potential dependent reads to the watch list. for (Node usage : n.usages()) { if (usage instanceof FloatingReadNode) { FloatingReadNode floatingReadNode = (FloatingReadNode) usage; if (nodeToBlock.get(floatingReadNode) == b && floatingReadNode.getLastLocationAccess() == n && !(n instanceof MemoryPhiNode)) { watchList.add(floatingReadNode); } } } } assert unprocessed.isMarked(n); unprocessed.clear(n); newList.add(n); } else { // This node was pulled up. assert !(n instanceof FixedNode) : n; } } for (Node n : newList) { unprocessed.mark(n); } assert newList.size() == oldList.size(); blockToNodes.put(b, newList); }
@SuppressFBWarnings( value = "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE", justification = "false positive found by findbugs") private BlockMap<ArrayList<FloatingReadNode>> calcLatestBlocks( SchedulingStrategy strategy, NodeMap<Block> currentNodeMap, BlockMap<List<Node>> earliestBlockToNodesMap, NodeBitMap visited, BlockMap<List<Node>> latestBlockToNodesMap, boolean immutableGraph) { BlockMap<ArrayList<FloatingReadNode>> watchListMap = new BlockMap<>(cfg); Block[] reversePostOrder = cfg.reversePostOrder(); for (int j = reversePostOrder.length - 1; j >= 0; --j) { Block currentBlock = reversePostOrder[j]; List<Node> blockToNodes = earliestBlockToNodesMap.get(currentBlock); LocationSet killed = null; int previousIndex = blockToNodes.size(); for (int i = blockToNodes.size() - 1; i >= 0; --i) { Node currentNode = blockToNodes.get(i); assert currentNodeMap.get(currentNode) == currentBlock; assert !(currentNode instanceof PhiNode) && !(currentNode instanceof ProxyNode); assert visited.isMarked(currentNode); if (currentNode instanceof FixedNode) { // For these nodes, the earliest is at the same time the latest block. } else { Block latestBlock = null; LocationIdentity constrainingLocation = null; if (currentNode instanceof FloatingReadNode) { // We are scheduling a floating read node => check memory // anti-dependencies. FloatingReadNode floatingReadNode = (FloatingReadNode) currentNode; LocationIdentity location = floatingReadNode.getLocationIdentity(); if (location.isMutable()) { // Location can be killed. constrainingLocation = location; if (currentBlock.canKill(location)) { if (killed == null) { killed = new LocationSet(); } fillKillSet(killed, blockToNodes.subList(i + 1, previousIndex)); previousIndex = i; if (killed.contains(location)) { // Earliest block kills location => we need to stay within // earliest block. latestBlock = currentBlock; } } } } if (latestBlock == null) { // We are not constraint within earliest block => calculate optimized // schedule. calcLatestBlock( currentBlock, strategy, currentNode, currentNodeMap, constrainingLocation, watchListMap, latestBlockToNodesMap, visited, immutableGraph); } else { selectLatestBlock( currentNode, currentBlock, latestBlock, currentNodeMap, watchListMap, constrainingLocation, latestBlockToNodesMap); } } } } return watchListMap; }