Skip to content

Commit 15144ac

Browse files
committed
[GR-35928] Effects closure: properly mark exception edges known to be dead.
PullRequest: graal/10654
2 parents b3de396 + 0154083 commit 15144ac

File tree

4 files changed

+116
-2
lines changed

4 files changed

+116
-2
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package org.graalvm.compiler.core.test.ea;
26+
27+
import org.graalvm.compiler.api.directives.GraalDirectives;
28+
import org.graalvm.compiler.core.common.GraalOptions;
29+
import org.graalvm.compiler.core.test.GraalCompilerTest;
30+
import org.graalvm.compiler.options.OptionValues;
31+
import org.junit.Test;
32+
33+
public class PartialEscapeWithExceptionTest extends GraalCompilerTest {
34+
35+
public static int snippet(int length) {
36+
int[] a = new int[8];
37+
int[] b = new int[8];
38+
for (int i = 0; i < length; i++) {
39+
System.arraycopy(a, 0, b, 0, a.length);
40+
GraalDirectives.blackhole(a);
41+
}
42+
return 0;
43+
}
44+
45+
@Test
46+
public void test01() {
47+
OptionValues opt = new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false);
48+
test(opt, "snippet", 10);
49+
}
50+
51+
}

compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.graalvm.compiler.nodes.LoopBeginNode;
4343
import org.graalvm.compiler.nodes.StructuredGraph;
4444
import org.graalvm.compiler.nodes.cfg.Block;
45+
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
4546

4647
public final class ReentrantBlockIterator {
4748

@@ -56,16 +57,42 @@ public LoopInfo(int endCount, int exitCount) {
5657
}
5758
}
5859

60+
/**
61+
* Abstract base class for reverse post order iteration over the {@link ControlFlowGraph}.
62+
*/
5963
public abstract static class BlockIteratorClosure<StateT> {
6064

65+
/**
66+
* Create the initial state for the reverse post order iteration over the
67+
* {@link ControlFlowGraph}.
68+
*/
6169
protected abstract StateT getInitialState();
6270

71+
/**
72+
* Process the current block with the current state during reverse post order iteration.
73+
*/
6374
protected abstract StateT processBlock(Block block, StateT currentState);
6475

76+
/**
77+
* Merge multiple states when processing {@link Block} starting with a
78+
* {@link AbstractMergeNode}.
79+
*/
6580
protected abstract StateT merge(Block merge, List<StateT> states);
6681

82+
/**
83+
* Clone a state for a successor invocation of
84+
* {@link BlockIteratorClosure#processBlock(Block, Object)}.
85+
*/
6786
protected abstract StateT cloneState(StateT oldState);
6887

88+
/**
89+
* Hook for subclasses to apply additional operations after
90+
* {@link BlockIteratorClosure#cloneState(Object)} for successor blocks.
91+
*/
92+
protected StateT afterSplit(@SuppressWarnings("unused") Block successor, StateT oldState) {
93+
return oldState;
94+
}
95+
6996
protected abstract List<StateT> processLoop(Loop<Block> loop, StateT initialState);
7097
}
7198

@@ -186,7 +213,7 @@ private static <StateT> Block processMultipleSuccessors(BlockIteratorClosure<Sta
186213
for (int i = 1; i < successors.length; i++) {
187214
Block successor = successors[i];
188215
blockQueue.addFirst(successor);
189-
states.put(successor.getBeginNode(), closure.cloneState(state));
216+
states.put(successor.getBeginNode(), closure.afterSplit(successor, closure.cloneState(state)));
190217
}
191218
return successors[0];
192219
}

compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
import java.util.Map;
2929

3030
import org.graalvm.collections.EconomicMap;
31+
import org.graalvm.collections.EconomicSet;
3132
import org.graalvm.collections.UnmodifiableMapCursor;
33+
import org.graalvm.compiler.nodes.WithExceptionNode;
34+
import org.graalvm.compiler.nodes.cfg.Block;
3235

3336
public abstract class EffectsBlockState<T extends EffectsBlockState<T>> {
3437

@@ -38,12 +41,22 @@ public abstract class EffectsBlockState<T extends EffectsBlockState<T>> {
3841
*/
3942
private boolean dead;
4043

44+
/**
45+
* Exception edges marked dead for this state by dominating {@link WithExceptionNode} control
46+
* flow split nodes.
47+
*/
48+
protected EconomicSet<Block> exceptionEdgesToKill;
49+
4150
public EffectsBlockState() {
4251
// emtpy
4352
}
4453

4554
public EffectsBlockState(EffectsBlockState<T> other) {
4655
this.dead = other.dead;
56+
EconomicSet<Block> otherExceptionEdgesToKill = other.exceptionEdgesToKill;
57+
if (otherExceptionEdgesToKill != null) {
58+
this.exceptionEdgesToKill = EconomicSet.create(otherExceptionEdgesToKill);
59+
}
4760
}
4861

4962
@Override

compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
5656
import org.graalvm.compiler.nodes.ValueNode;
5757
import org.graalvm.compiler.nodes.ValuePhiNode;
58+
import org.graalvm.compiler.nodes.WithExceptionNode;
5859
import org.graalvm.compiler.nodes.cfg.Block;
5960
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
6061
import org.graalvm.compiler.nodes.extended.BoxNode;
@@ -191,6 +192,7 @@ protected List<Void> processLoop(Loop<Block> loop, Void initialState) {
191192
apply(loopMergeEffects.get(loop));
192193
return info.exitStates;
193194
}
195+
194196
};
195197
ReentrantBlockIterator.apply(closure, cfg.getStartBlock());
196198
for (GraphEffectList effects : effectList) {
@@ -259,7 +261,19 @@ protected BlockT processBlock(Block block, BlockT state) {
259261
}
260262
processLoopExit(loopExit, loopEntryStates.get(loopExit.loopBegin()), state, blockEffects.get(block));
261263
}
262-
changed |= processNode(node, state, effects, lastFixedNode) && isSignificantNode(node);
264+
Block exceptionEdgeToKill = node instanceof WithExceptionNode ? cfg.blockFor(((WithExceptionNode) node).exceptionEdge()) : null;
265+
boolean lastNodeChanged = processNode(node, state, effects, lastFixedNode) && isSignificantNode(node);
266+
changed |= lastNodeChanged;
267+
if (lastNodeChanged && exceptionEdgeToKill != null) {
268+
/*
269+
* We deleted a exception node, per definition the exception edge died in that
270+
* process, no need to process the exception edge
271+
*/
272+
if (state.exceptionEdgesToKill == null) {
273+
state.exceptionEdgesToKill = EconomicSet.create();
274+
}
275+
state.exceptionEdgesToKill.add(exceptionEdgeToKill);
276+
}
263277
if (node instanceof FixedWithNextNode) {
264278
lastFixedNode = (FixedWithNextNode) node;
265279
}
@@ -272,6 +286,15 @@ protected BlockT processBlock(Block block, BlockT state) {
272286
return state;
273287
}
274288

289+
@Override
290+
protected BlockT afterSplit(Block successor, BlockT oldState) {
291+
BlockT state = oldState;
292+
if (oldState.exceptionEdgesToKill != null && oldState.exceptionEdgesToKill.contains(successor)) {
293+
state.markAsDead();
294+
}
295+
return state;
296+
}
297+
275298
/**
276299
* Changes to {@link CommitAllocationNode}s, {@link AllocatedObjectNode}s and {@link BoxNode}s
277300
* are not considered to be "important". If only changes to those nodes are discovered during

0 commit comments

Comments
 (0)