114 } 115 116 public LoopFragment original() { 117 return original; 118 } 119 120 public abstract NodeBitMap nodes(); 121 122 public StructuredGraph graph() { 123 LoopEx l; 124 if (isDuplicate()) { 125 l = original().loop(); 126 } else { 127 l = loop(); 128 } 129 return l.loopBegin().graph(); 130 } 131 132 protected abstract DuplicationReplacement getDuplicationReplacement(); 133 134 protected abstract void finishDuplication(); 135 136 protected void patchNodes(final DuplicationReplacement dataFix) { 137 if (isDuplicate() && !nodesReady) { 138 assert !original.isDuplicate(); 139 final DuplicationReplacement cfgFix = original().getDuplicationReplacement(); 140 DuplicationReplacement dr; 141 if (cfgFix == null && dataFix != null) { 142 dr = dataFix; 143 } else if (cfgFix != null && dataFix == null) { 144 dr = cfgFix; 145 } else if (cfgFix != null && dataFix != null) { 146 dr = new DuplicationReplacement() { 147 148 @Override 149 public Node replacement(Node o) { 150 Node r1 = dataFix.replacement(o); 151 if (r1 != o) { 152 assert cfgFix.replacement(o) == o; 153 return r1; 154 } 155 Node r2 = cfgFix.replacement(o); 156 if (r2 != o) { 157 return r2; 158 } 159 return o; 160 } 161 }; 162 } else { 163 dr = null; 164 } 165 NodeIterable<Node> nodesIterable = original().nodes(); 166 duplicationMap = graph().addDuplicates(nodesIterable, graph(), nodesIterable.count(), dr); 167 finishDuplication(); 168 nodesReady = true; 169 } else { 170 // TODO (gd) apply fix ? 171 } 172 } 173 174 protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks) { 175 return computeNodes(graph, blocks, Collections.emptyList()); 176 } 177 178 protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<LoopExitNode> earlyExits) { 179 final NodeBitMap nodes = graph.createNodeBitMap(); 180 computeNodes(nodes, graph, blocks, earlyExits); 181 return nodes; 182 } 183 184 protected static void computeNodes(NodeBitMap nodes, Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<LoopExitNode> earlyExits) { 185 for (AbstractBeginNode b : blocks) { 186 if (b.isDeleted()) { 187 continue; 188 } 189 190 for (Node n : b.getBlockNodes()) { 191 if (n instanceof Invoke) { 192 nodes.mark(((Invoke) n).callTarget()); 193 } 194 if (n instanceof NodeWithState) { 195 NodeWithState withState = (NodeWithState) n; 196 withState.states().forEach(state -> state.applyToVirtual(node -> nodes.mark(node))); 197 } 198 nodes.mark(n); 199 } 200 } 201 for (LoopExitNode earlyExit : earlyExits) { 202 if (earlyExit.isDeleted()) { 203 continue; 204 } 205 206 FrameState stateAfter = earlyExit.stateAfter(); 207 if (stateAfter != null) { 208 stateAfter.applyToVirtual(node -> nodes.mark(node)); 209 } 210 nodes.mark(earlyExit); 211 for (ProxyNode proxy : earlyExit.proxies()) { 212 nodes.mark(proxy); 213 } 214 } 215 216 final NodeBitMap nonLoopNodes = graph.createNodeBitMap(); 217 for (AbstractBeginNode b : blocks) { 218 if (b.isDeleted()) { 219 continue; 220 } 221 222 for (Node n : b.getBlockNodes()) { 223 if (n instanceof CommitAllocationNode) { 224 for (VirtualObjectNode obj : ((CommitAllocationNode) n).getVirtualObjects()) { 225 markFloating(obj, nodes, nonLoopNodes); 226 } 227 } 228 if (n instanceof MonitorEnterNode) { 229 markFloating(((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes); 230 } 231 for (Node usage : n.usages()) { 232 markFloating(usage, nodes, nonLoopNodes); 233 } 234 } 285 @Override 286 public void remove() { 287 throw new UnsupportedOperationException(); 288 } 289 290 @Override 291 public AbstractBeginNode next() { 292 return it.next().getBeginNode(); 293 } 294 295 @Override 296 public boolean hasNext() { 297 return it.hasNext(); 298 } 299 }; 300 } 301 302 }; 303 } 304 305 public static NodeIterable<LoopExitNode> toHirExits(final Iterable<Block> blocks) { 306 return new NodeIterable<LoopExitNode>() { 307 308 @Override 309 public Iterator<LoopExitNode> iterator() { 310 final Iterator<Block> it = blocks.iterator(); 311 return new Iterator<LoopExitNode>() { 312 313 @Override 314 public void remove() { 315 throw new UnsupportedOperationException(); 316 } 317 318 @Override 319 public LoopExitNode next() { 320 return (LoopExitNode) it.next().getBeginNode(); 321 } 322 323 @Override 324 public boolean hasNext() { 325 return it.hasNext(); 326 } 327 }; 328 } 329 330 }; 331 } 332 333 /** 334 * Merges the early exits (i.e. loop exits) that were duplicated as part of this fragment, with 335 * the original fragment's exits. 336 */ 337 protected void mergeEarlyExits() { 338 assert isDuplicate(); 339 StructuredGraph graph = graph(); 340 for (AbstractBeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().loop().getExits())) { | 114 } 115 116 public LoopFragment original() { 117 return original; 118 } 119 120 public abstract NodeBitMap nodes(); 121 122 public StructuredGraph graph() { 123 LoopEx l; 124 if (isDuplicate()) { 125 l = original().loop(); 126 } else { 127 l = loop(); 128 } 129 return l.loopBegin().graph(); 130 } 131 132 protected abstract DuplicationReplacement getDuplicationReplacement(); 133 134 protected abstract void beforeDuplication(); 135 136 protected abstract void finishDuplication(); 137 138 protected void patchNodes(final DuplicationReplacement dataFix) { 139 if (isDuplicate() && !nodesReady) { 140 assert !original.isDuplicate(); 141 final DuplicationReplacement cfgFix = original().getDuplicationReplacement(); 142 DuplicationReplacement dr; 143 if (cfgFix == null && dataFix != null) { 144 dr = dataFix; 145 } else if (cfgFix != null && dataFix == null) { 146 dr = cfgFix; 147 } else if (cfgFix != null && dataFix != null) { 148 dr = new DuplicationReplacement() { 149 150 @Override 151 public Node replacement(Node o) { 152 Node r1 = dataFix.replacement(o); 153 if (r1 != o) { 154 assert cfgFix.replacement(o) == o; 155 return r1; 156 } 157 Node r2 = cfgFix.replacement(o); 158 if (r2 != o) { 159 return r2; 160 } 161 return o; 162 } 163 }; 164 } else { 165 dr = null; 166 } 167 beforeDuplication(); 168 NodeIterable<Node> nodesIterable = original().nodes(); 169 duplicationMap = graph().addDuplicates(nodesIterable, graph(), nodesIterable.count(), dr); 170 finishDuplication(); 171 nodesReady = true; 172 } else { 173 // TODO (gd) apply fix ? 174 } 175 } 176 177 protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks) { 178 return computeNodes(graph, blocks, Collections.emptyList()); 179 } 180 181 protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) { 182 final NodeBitMap nodes = graph.createNodeBitMap(); 183 computeNodes(nodes, graph, blocks, earlyExits); 184 return nodes; 185 } 186 187 protected static void computeNodes(NodeBitMap nodes, Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) { 188 for (AbstractBeginNode b : blocks) { 189 if (b.isDeleted()) { 190 continue; 191 } 192 193 for (Node n : b.getBlockNodes()) { 194 if (n instanceof Invoke) { 195 nodes.mark(((Invoke) n).callTarget()); 196 } 197 if (n instanceof NodeWithState) { 198 NodeWithState withState = (NodeWithState) n; 199 withState.states().forEach(state -> state.applyToVirtual(node -> nodes.mark(node))); 200 } 201 nodes.mark(n); 202 } 203 } 204 for (AbstractBeginNode earlyExit : earlyExits) { 205 if (earlyExit.isDeleted()) { 206 continue; 207 } 208 209 nodes.mark(earlyExit); 210 211 if (earlyExit instanceof LoopExitNode) { 212 LoopExitNode loopExit = (LoopExitNode) earlyExit; 213 FrameState stateAfter = loopExit.stateAfter(); 214 if (stateAfter != null) { 215 stateAfter.applyToVirtual(node -> nodes.mark(node)); 216 } 217 for (ProxyNode proxy : loopExit.proxies()) { 218 nodes.mark(proxy); 219 } 220 } 221 } 222 223 final NodeBitMap nonLoopNodes = graph.createNodeBitMap(); 224 for (AbstractBeginNode b : blocks) { 225 if (b.isDeleted()) { 226 continue; 227 } 228 229 for (Node n : b.getBlockNodes()) { 230 if (n instanceof CommitAllocationNode) { 231 for (VirtualObjectNode obj : ((CommitAllocationNode) n).getVirtualObjects()) { 232 markFloating(obj, nodes, nonLoopNodes); 233 } 234 } 235 if (n instanceof MonitorEnterNode) { 236 markFloating(((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes); 237 } 238 for (Node usage : n.usages()) { 239 markFloating(usage, nodes, nonLoopNodes); 240 } 241 } 292 @Override 293 public void remove() { 294 throw new UnsupportedOperationException(); 295 } 296 297 @Override 298 public AbstractBeginNode next() { 299 return it.next().getBeginNode(); 300 } 301 302 @Override 303 public boolean hasNext() { 304 return it.hasNext(); 305 } 306 }; 307 } 308 309 }; 310 } 311 312 public static NodeIterable<AbstractBeginNode> toHirExits(final Iterable<Block> blocks) { 313 return new NodeIterable<AbstractBeginNode>() { 314 315 @Override 316 public Iterator<AbstractBeginNode> iterator() { 317 final Iterator<Block> it = blocks.iterator(); 318 return new Iterator<AbstractBeginNode>() { 319 320 @Override 321 public void remove() { 322 throw new UnsupportedOperationException(); 323 } 324 325 /** 326 * Return the true LoopExitNode for this loop or the BeginNode for the block. 327 */ 328 @Override 329 public AbstractBeginNode next() { 330 Block next = it.next(); 331 LoopExitNode exit = next.getLoopExit(); 332 if (exit != null) { 333 return exit; 334 } 335 return next.getBeginNode(); 336 } 337 338 @Override 339 public boolean hasNext() { 340 return it.hasNext(); 341 } 342 }; 343 } 344 345 }; 346 } 347 348 /** 349 * Merges the early exits (i.e. loop exits) that were duplicated as part of this fragment, with 350 * the original fragment's exits. 351 */ 352 protected void mergeEarlyExits() { 353 assert isDuplicate(); 354 StructuredGraph graph = graph(); 355 for (AbstractBeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().loop().getExits())) { |