Skip to content

Commit 3a207a2

Browse files
committed
[GR-19220] Split local and non-local returns (#1851).
PullRequest: truffleruby/1178
2 parents df83bc5 + 4cb8337 commit 3a207a2

File tree

11 files changed

+97
-20
lines changed

11 files changed

+97
-20
lines changed

src/launcher/java/org/truffleruby/launcher/RubyLauncher.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ private int runRubyMain(Context.Builder contextBuilder, CommandLineOptions confi
234234
Metrics.printTime("after-run");
235235
return exitCode;
236236
} catch (PolyglotException e) {
237+
System.err.println(
238+
"truffleruby: an exception escaped out of the interpreter - this is an implementation bug");
237239
e.printStackTrace();
238240
return 1;
239241
}

src/main/java/org/truffleruby/core/fiber/FiberManager.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
import org.truffleruby.language.control.BreakException;
2828
import org.truffleruby.language.control.ExitException;
2929
import org.truffleruby.language.control.KillException;
30+
import org.truffleruby.language.control.DynamicReturnException;
3031
import org.truffleruby.language.control.RaiseException;
31-
import org.truffleruby.language.control.ReturnException;
3232
import org.truffleruby.language.control.TerminationException;
3333
import org.truffleruby.language.objects.ObjectIDOperations;
3434

@@ -186,7 +186,7 @@ private void fiberMain(RubyContext context, DynamicObject fiber, DynamicObject b
186186
fiber,
187187
new RaiseException(context, context.getCoreExceptions().breakFromProcClosure(currentNode)),
188188
currentNode);
189-
} catch (ReturnException e) {
189+
} catch (DynamicReturnException e) {
190190
sendExceptionToParentFiber(
191191
fiber,
192192
new RaiseException(context, context.getCoreExceptions().unexpectedReturn(currentNode)),

src/main/java/org/truffleruby/core/thread/ThreadManager.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
import org.truffleruby.language.SafepointManager;
3434
import org.truffleruby.language.control.ExitException;
3535
import org.truffleruby.language.control.KillException;
36+
import org.truffleruby.language.control.DynamicReturnException;
3637
import org.truffleruby.language.control.RaiseException;
37-
import org.truffleruby.language.control.ReturnException;
3838
import org.truffleruby.language.objects.AllocateObjectNode;
3939
import org.truffleruby.language.objects.ObjectIDOperations;
4040
import org.truffleruby.language.objects.ReadObjectFieldNodeGen;
@@ -286,7 +286,7 @@ private void threadMain(DynamicObject thread, Node currentNode, Supplier<Object>
286286
setThreadValue(context, thread, nil());
287287
} catch (RaiseException e) {
288288
setException(context, thread, e.getException(), currentNode);
289-
} catch (ReturnException e) {
289+
} catch (DynamicReturnException e) {
290290
setException(context, thread, context.getCoreExceptions().unexpectedReturn(currentNode), currentNode);
291291
} finally {
292292
assert Layouts.THREAD.getValue(thread) != null || Layouts.THREAD.getException(thread) != null;

src/main/java/org/truffleruby/language/control/ReturnException.java renamed to src/main/java/org/truffleruby/language/control/DynamicReturnException.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111

1212
import com.oracle.truffle.api.nodes.ControlFlowException;
1313

14-
public final class ReturnException extends ControlFlowException {
14+
public final class DynamicReturnException extends ControlFlowException {
1515

1616
private static final long serialVersionUID = -45053969587014940L;
1717

1818
private final ReturnID returnID;
1919
private final Object value;
2020

21-
public ReturnException(ReturnID returnID, Object value) {
21+
public DynamicReturnException(ReturnID returnID, Object value) {
2222
this.returnID = returnID;
2323
this.value = value;
2424
}

src/main/java/org/truffleruby/language/control/ReturnNode.java renamed to src/main/java/org/truffleruby/language/control/DynamicReturnNode.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,20 @@
1313

1414
import com.oracle.truffle.api.frame.VirtualFrame;
1515

16-
public class ReturnNode extends RubyNode {
16+
public class DynamicReturnNode extends RubyNode {
1717

1818
private final ReturnID returnID;
1919

2020
@Child private RubyNode value;
2121

22-
public ReturnNode(ReturnID returnID, RubyNode value) {
22+
public DynamicReturnNode(ReturnID returnID, RubyNode value) {
2323
this.returnID = returnID;
2424
this.value = value;
2525
}
2626

2727
@Override
2828
public Object execute(VirtualFrame frame) {
29-
throw new ReturnException(returnID, value.execute(frame));
29+
throw new DynamicReturnException(returnID, value.execute(frame));
3030
}
3131

3232
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved. This
3+
* code is released under a tri EPL/GPL/LGPL license. You can use it,
4+
* redistribute it and/or modify it under the terms of the:
5+
*
6+
* Eclipse Public License version 2.0, or
7+
* GNU General Public License version 2, or
8+
* GNU Lesser General Public License version 2.1.
9+
*/
10+
package org.truffleruby.language.control;
11+
12+
import com.oracle.truffle.api.nodes.ControlFlowException;
13+
14+
public final class LocalReturnException extends ControlFlowException {
15+
16+
private static final long serialVersionUID = -98757896543565476L;
17+
18+
private final Object value;
19+
20+
public LocalReturnException(Object value) {
21+
this.value = value;
22+
}
23+
24+
public Object getValue() {
25+
return value;
26+
}
27+
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved. This
3+
* code is released under a tri EPL/GPL/LGPL license. You can use it,
4+
* redistribute it and/or modify it under the terms of the:
5+
*
6+
* Eclipse Public License version 2.0, or
7+
* GNU General Public License version 2, or
8+
* GNU Lesser General Public License version 2.1.
9+
*/
10+
package org.truffleruby.language.control;
11+
12+
import com.oracle.truffle.api.frame.VirtualFrame;
13+
import org.truffleruby.language.RubyNode;
14+
15+
public class LocalReturnNode extends RubyNode {
16+
17+
@Child private RubyNode value;
18+
19+
public LocalReturnNode(RubyNode value) {
20+
this.value = value;
21+
}
22+
23+
@Override
24+
public Object execute(VirtualFrame frame) {
25+
throw new LocalReturnException(value.execute(frame));
26+
}
27+
28+
}

src/main/java/org/truffleruby/language/methods/CatchForLambdaNode.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
import org.truffleruby.language.RubyNode;
1313
import org.truffleruby.language.control.BreakException;
1414
import org.truffleruby.language.control.BreakID;
15+
import org.truffleruby.language.control.LocalReturnException;
1516
import org.truffleruby.language.control.NextException;
17+
import org.truffleruby.language.control.DynamicReturnException;
18+
import org.truffleruby.language.control.ReturnID;
1619
import org.truffleruby.language.control.RaiseException;
1720
import org.truffleruby.language.control.RedoException;
1821
import org.truffleruby.language.control.RetryException;
19-
import org.truffleruby.language.control.ReturnException;
20-
import org.truffleruby.language.control.ReturnID;
2122

2223
import com.oracle.truffle.api.frame.VirtualFrame;
2324
import com.oracle.truffle.api.profiles.BranchProfile;
@@ -30,6 +31,7 @@ public class CatchForLambdaNode extends RubyNode {
3031

3132
@Child private RubyNode body;
3233

34+
private final BranchProfile localReturnProfile = BranchProfile.create();
3335
private final ConditionProfile matchingReturnProfile = ConditionProfile.createBinaryProfile();
3436
private final ConditionProfile matchingBreakProfile = ConditionProfile.createBinaryProfile();
3537
private final BranchProfile retryProfile = BranchProfile.create();
@@ -47,7 +49,10 @@ public Object execute(VirtualFrame frame) {
4749
while (true) {
4850
try {
4951
return body.execute(frame);
50-
} catch (ReturnException e) {
52+
} catch (LocalReturnException e) {
53+
localReturnProfile.enter();
54+
return e.getValue();
55+
} catch (DynamicReturnException e) {
5156
if (matchingReturnProfile.profile(e.getReturnID() == returnID)) {
5257
return e.getValue();
5358
} else {

src/main/java/org/truffleruby/language/methods/CatchForMethodNode.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
package org.truffleruby.language.methods;
1111

1212
import org.truffleruby.language.RubyNode;
13+
import org.truffleruby.language.control.LocalReturnException;
14+
import org.truffleruby.language.control.DynamicReturnException;
15+
import org.truffleruby.language.control.ReturnID;
1316
import org.truffleruby.language.control.RaiseException;
1417
import org.truffleruby.language.control.RetryException;
15-
import org.truffleruby.language.control.ReturnException;
16-
import org.truffleruby.language.control.ReturnID;
1718

1819
import com.oracle.truffle.api.frame.VirtualFrame;
1920
import com.oracle.truffle.api.profiles.BranchProfile;
@@ -25,6 +26,7 @@ public class CatchForMethodNode extends RubyNode {
2526

2627
@Child private RubyNode body;
2728

29+
private final BranchProfile localReturnProfile = BranchProfile.create();
2830
private final ConditionProfile matchingReturnProfile = ConditionProfile.createBinaryProfile();
2931
private final BranchProfile retryProfile = BranchProfile.create();
3032

@@ -37,7 +39,10 @@ public CatchForMethodNode(ReturnID returnID, RubyNode body) {
3739
public Object execute(VirtualFrame frame) {
3840
try {
3941
return body.execute(frame);
40-
} catch (ReturnException e) {
42+
} catch (LocalReturnException e) {
43+
localReturnProfile.enter();
44+
return e.getValue();
45+
} catch (DynamicReturnException e) {
4146
if (matchingReturnProfile.profile(e.getReturnID() == returnID)) {
4247
return e.getValue();
4348
} else {

src/main/java/org/truffleruby/language/methods/CatchReturnAsErrorNode.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
package org.truffleruby.language.methods;
1111

1212
import org.truffleruby.language.RubyNode;
13+
import org.truffleruby.language.control.LocalReturnException;
1314
import org.truffleruby.language.control.RaiseException;
14-
import org.truffleruby.language.control.ReturnException;
15+
import org.truffleruby.language.control.DynamicReturnException;
1516

1617
import com.oracle.truffle.api.frame.VirtualFrame;
1718
import com.oracle.truffle.api.profiles.BranchProfile;
@@ -30,7 +31,7 @@ public CatchReturnAsErrorNode(RubyNode body) {
3031
public Object execute(VirtualFrame frame) {
3132
try {
3233
return body.execute(frame);
33-
} catch (ReturnException e) {
34+
} catch (LocalReturnException | DynamicReturnException e) {
3435
retryProfile.enter();
3536
throw new RaiseException(getContext(), coreExceptions().unexpectedReturn(this));
3637
}

0 commit comments

Comments
 (0)