Skip to content

Commit 52f7d8b

Browse files
committed
[GR-18163] Implement Fiber#raise
PullRequest: truffleruby/2620
2 parents 44d81c7 + 86c0050 commit 52f7d8b

File tree

6 files changed

+51
-29
lines changed

6 files changed

+51
-29
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Compatibility:
2121
* Decide the visibility in `Module#define_method` based on `self` and the default definee (#2334).
2222
* Configure `mandir` value in `RbConfig::CONFIG` and `RbConfig::MAKEFILE_CONFIG` (#2315).
2323
* TruffleRuby now supports the Truffle polyglot Hash interop API.
24+
* Implement `Fiber#raise` (#2338).
2425

2526
Performance:
2627

spec/tags/core/fiber/raise_tags.txt

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,2 @@
1-
fails:Fiber#raise aborts execution
2-
fails:Fiber#raise raises RuntimeError if no exception class is given
3-
fails:Fiber#raise raises a given Exception instance
4-
fails:Fiber#raise raises a RuntimeError if string given
5-
fails:Fiber#raise passes no arguments to the constructor when given only an exception class
6-
fails:Fiber#raise raises a TypeError when passed a non-Exception object
7-
fails:Fiber#raise raises a TypeError when passed true
8-
fails:Fiber#raise raises a TypeError when passed false
9-
fails:Fiber#raise raises a TypeError when passed nil
101
fails:Fiber#raise re-raises a previously rescued exception without overwriting the backtrace
11-
fails:Fiber#raise allows Exception, message, and backtrace parameters
12-
fails:Fiber#raise raises RuntimeError by default
132
fails:Fiber#raise raises FiberError if Fiber is not born
14-
fails:Fiber#raise raises FiberError if Fiber is dead
15-
fails:Fiber#raise accepts error class
16-
fails:Fiber#raise accepts error message
17-
fails:Fiber#raise does not accept array of backtrace information only
18-
fails:Fiber#raise does not accept integer
19-
fails:Fiber#raise accepts error class with error message
20-
fails:Fiber#raise accepts error class with with error message and backtrace information
21-
fails:Fiber#raise does not accept only error message and backtrace information
22-
fails:Fiber#raise raises a FiberError if invoked from a different Thread
23-
fails:Fiber#raise kills Fiber
24-
fails:Fiber#raise raises a FiberError if invoked on a transferring Fiber
25-
fails:Fiber#raise accepts an exception that implements to_hash
26-
fails:Fiber#raise allows the message parameter to be a hash

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.truffleruby.core.basicobject.BasicObjectNodes.ObjectIDNode;
2323
import org.truffleruby.core.basicobject.RubyBasicObject;
2424
import org.truffleruby.core.exception.ExceptionOperations;
25+
import org.truffleruby.core.exception.RubyException;
2526
import org.truffleruby.core.klass.RubyClass;
2627
import org.truffleruby.core.proc.ProcOperations;
2728
import org.truffleruby.core.thread.RubyThread;
@@ -266,9 +267,13 @@ private Object[] handleMessage(RubyFiber fiber, FiberMessage message) {
266267
} else if (message instanceof FiberResumeMessage) {
267268
final FiberResumeMessage resumeMessage = (FiberResumeMessage) message;
268269
assert context.getThreadManager().getCurrentThread() == resumeMessage.getSendingFiber().rubyThread;
269-
if (resumeMessage.getOperation() == FiberOperation.RESUME) {
270+
if (resumeMessage.getOperation() == FiberOperation.RESUME ||
271+
resumeMessage.getOperation() == FiberOperation.RAISE) {
270272
fiber.lastResumedByFiber = resumeMessage.getSendingFiber();
271273
}
274+
if (resumeMessage.getOperation() == FiberOperation.RAISE) {
275+
throw new RaiseException(context, (RubyException) resumeMessage.getArgs()[0]);
276+
}
272277
return resumeMessage.getArgs();
273278
} else {
274279
throw CompilerDirectives.shouldNotReachHere();

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

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.truffleruby.core.array.RubyArray;
2121
import org.truffleruby.core.cast.SingleValueCastNode;
2222
import org.truffleruby.core.cast.SingleValueCastNodeGen;
23+
import org.truffleruby.core.exception.RubyException;
2324
import org.truffleruby.core.fiber.FiberNodesFactory.FiberTransferNodeFactory;
2425
import org.truffleruby.core.klass.RubyClass;
2526
import org.truffleruby.core.proc.RubyProc;
@@ -149,13 +150,19 @@ protected Object resume(RubyFiber fiber, Object[] args,
149150

150151
}
151152

152-
@CoreMethod(names = "resume", rest = true)
153-
public abstract static class ResumeNode extends CoreMethodArrayArgumentsNode {
153+
154+
public abstract static class FiberResumeNode extends CoreMethodArrayArgumentsNode {
155+
156+
public static FiberResumeNode create() {
157+
return FiberNodesFactory.FiberResumeNodeFactory.create(null);
158+
}
159+
160+
public abstract Object executeResume(FiberOperation operation, RubyFiber fiber, Object[] args);
154161

155162
@Child private FiberTransferNode fiberTransferNode = FiberTransferNodeFactory.create(null);
156163

157164
@Specialization
158-
protected Object resume(RubyFiber fiber, Object[] args,
165+
protected Object resume(FiberOperation operation, RubyFiber fiber, Object[] args,
159166
@Cached GetCurrentRubyThreadNode getCurrentRubyThreadNode,
160167
@Cached ConditionProfile doubleResumeProfile,
161168
@Cached ConditionProfile transferredProfile) {
@@ -178,7 +185,32 @@ protected Object resume(RubyFiber fiber, Object[] args,
178185
final RubyFiber currentFiber = fiberManager.getCurrentFiber();
179186

180187
return fiberTransferNode
181-
.executeTransferControlTo(currentThread, currentFiber, fiber, FiberOperation.RESUME, args);
188+
.executeTransferControlTo(currentThread, currentFiber, fiber, operation, args);
189+
}
190+
191+
}
192+
193+
194+
@Primitive(name = "fiber_raise")
195+
public abstract static class FiberRaiseNode extends PrimitiveArrayArgumentsNode {
196+
197+
@Child private FiberResumeNode fiberResumeNode = FiberResumeNode.create();
198+
199+
@Specialization
200+
protected Object raise(RubyFiber fiber, RubyException exception) {
201+
return fiberResumeNode.executeResume(FiberOperation.RAISE, fiber, new Object[]{ exception });
202+
}
203+
204+
}
205+
206+
@CoreMethod(names = "resume", rest = true)
207+
public abstract static class ResumeNode extends CoreMethodArrayArgumentsNode {
208+
209+
@Child private FiberResumeNode fiberResumeNode = FiberResumeNode.create();
210+
211+
@Specialization
212+
protected Object resume(RubyFiber fiber, Object[] args) {
213+
return fiberResumeNode.executeResume(FiberOperation.RESUME, fiber, args);
182214
}
183215

184216
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package org.truffleruby.core.fiber;
1111

1212
public enum FiberOperation {
13+
RAISE,
1314
RESUME,
1415
TRANSFER,
1516
YIELD

src/main/ruby/truffleruby/core/fiber.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99
# GNU Lesser General Public License version 2.1.
1010

1111
class Fiber
12+
13+
def raise(*args)
14+
exc = Truffle::ExceptionOperations.make_exception(args)
15+
exc = RuntimeError.new('') unless exc
16+
Primitive.fiber_raise(self, exc)
17+
end
18+
1219
def inspect
1320
loc = Primitive.fiber_source_location(self)
1421
status = Primitive.fiber_status(self)

0 commit comments

Comments
 (0)