Skip to content

Commit c859b6a

Browse files
committed
[GR-18163] Thread#raise should call #exception in the target thread
PullRequest: truffleruby/3349
2 parents 8839057 + 7768269 commit c859b6a

18 files changed

+75
-57
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Compatibility:
2727
* Fix `Float#/` when dividing by `Rational` (@bjfish).
2828
* `Process.euid=` should accept String (#2615, @ngtban).
2929
* Fix `instance_variable_get` and `instance_variable_set` for immutable objects (@bjfish).
30+
* `Thread#raise(exc, message)` now calls `exc.exception` in the target thread like CRuby (@eregon).
3031

3132
Performance:
3233

spec/ruby/core/thread/raise_spec.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,30 @@
102102
raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:")
103103
end
104104
end
105+
106+
it "calls #exception in both the caller and in the target thread" do
107+
cls = Class.new(Exception) do
108+
attr_accessor :log
109+
def initialize(*args)
110+
@log = [] # This is shared because the super #exception uses a shallow clone
111+
super
112+
end
113+
114+
def exception(*args)
115+
@log << [self, Thread.current, args]
116+
super
117+
end
118+
end
119+
exc = cls.new
120+
121+
@thr.raise exc, "Thread#raise #exception spec"
122+
@thr.join
123+
ScratchPad.recorded.should.is_a?(cls)
124+
exc.log.should == [
125+
[exc, Thread.current, ["Thread#raise #exception spec"]],
126+
[ScratchPad.recorded, @thr, []]
127+
]
128+
end
105129
end
106130

107131
describe "Thread#raise on a running thread" do

src/main/java/org/truffleruby/RubyContext.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -436,23 +436,18 @@ private TruffleNFIPlatform createNativePlatform() {
436436
return truffleNFIPlatform;
437437
}
438438

439-
@TruffleBoundary
440-
public static Object send(Object receiver, String methodName, Object... arguments) {
441-
return DispatchNode.getUncached().call(receiver, methodName, arguments);
442-
}
443-
444439
@TruffleBoundary
445440
public static Object send(Node currentNode, Object receiver, String methodName, Object... arguments) {
446441
if (currentNode.isAdoptable()) {
447442
final EncapsulatingNodeReference callNodeRef = EncapsulatingNodeReference.getCurrent();
448443
final Node prev = callNodeRef.set(currentNode);
449444
try {
450-
return send(receiver, methodName, arguments);
445+
return DispatchNode.getUncached().call(receiver, methodName, arguments);
451446
} finally {
452447
callNodeRef.set(prev);
453448
}
454449
} else {
455-
return send(receiver, methodName, arguments);
450+
return DispatchNode.getUncached().call(receiver, methodName, arguments);
456451
}
457452
}
458453

src/main/java/org/truffleruby/core/adapters/InputStreamAdapter.java

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

1212
import org.graalvm.shadowed.org.jline.utils.NonBlockingInputStream;
13-
import org.truffleruby.RubyContext;
1413
import org.truffleruby.core.support.RubyIO;
1514
import org.truffleruby.language.Nil;
15+
import org.truffleruby.language.dispatch.DispatchNode;
1616

1717
/** extends NonBlockingInputStream so JLine does not create an extra thread and calls read() on the same thread as
1818
* calling readLine(). */
@@ -28,7 +28,7 @@ public InputStreamAdapter(RubyIO object) {
2828

2929
@Override
3030
public int read() {
31-
final Object result = RubyContext.send(object, "getbyte");
31+
final Object result = DispatchNode.getUncached().call(object, "getbyte");
3232

3333
if (result == Nil.INSTANCE) {
3434
return EOF;

src/main/java/org/truffleruby/core/adapters/OutputStreamAdapter.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.truffleruby.core.rope.RopeOperations;
1919
import org.truffleruby.core.string.StringOperations;
2020
import org.truffleruby.core.support.RubyIO;
21+
import org.truffleruby.language.dispatch.DispatchNode;
2122

2223
public class OutputStreamAdapter extends OutputStream {
2324

@@ -35,15 +36,8 @@ public OutputStreamAdapter(RubyContext context, RubyLanguage language, RubyIO ob
3536

3637
@Override
3738
public void write(int bite) {
38-
RubyContext.send(
39-
object,
40-
"write",
41-
StringOperations
42-
.createString(
43-
context,
44-
language,
45-
RopeOperations.create((byte) bite, encoding.jcoding, CodeRange.CR_UNKNOWN),
46-
encoding));
39+
DispatchNode.getUncached().call(object, "write", StringOperations.createString(context, language,
40+
RopeOperations.create((byte) bite, encoding.jcoding, CodeRange.CR_UNKNOWN), encoding));
4741
}
4842

4943
}

src/main/java/org/truffleruby/core/exception/CoreExceptions.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import com.oracle.truffle.api.nodes.Node;
5252
import com.oracle.truffle.api.object.DynamicObjectLibrary;
5353
import com.oracle.truffle.api.source.SourceSection;
54+
import org.truffleruby.language.dispatch.DispatchNode;
5455
import org.truffleruby.language.library.RubyStringLibrary;
5556
import org.truffleruby.language.objects.LogicalClassNode;
5657

@@ -80,7 +81,7 @@ public void showExceptionIfDebug(RubyException exception) {
8081
public void showExceptionIfDebug(RubyException rubyException, Backtrace backtrace) {
8182
if (context.getCoreLibrary().getDebug() == Boolean.TRUE) {
8283
final RubyClass rubyClass = rubyException.getLogicalClass();
83-
final Object message = RubyContext.send(rubyException, "to_s");
84+
final Object message = DispatchNode.getUncached().call(rubyException, "to_s");
8485
showExceptionIfDebug(rubyClass, message, backtrace);
8586
}
8687
}
@@ -104,7 +105,7 @@ public void showExceptionIfDebug(RubyClass rubyClass, Object message, Backtrace
104105
language,
105106
StringOperations.encodeRope(output, UTF8Encoding.INSTANCE));
106107
Object stderr = context.getCoreLibrary().getStderr();
107-
RubyContext.send(stderr, "write", outputString);
108+
DispatchNode.getUncached().call(stderr, "write", outputString);
108109
} else {
109110
context.getEnvErrStream().println(output);
110111
}
@@ -113,16 +114,15 @@ public void showExceptionIfDebug(RubyClass rubyClass, Object message, Backtrace
113114

114115
@TruffleBoundary
115116
public String inspect(Object value) {
116-
Object rubyString = RubyContext.send(context.getCoreLibrary().truffleTypeModule, "rb_inspect", value);
117+
Object rubyString = DispatchNode.getUncached().call(
118+
context.getCoreLibrary().truffleTypeModule, "rb_inspect", value);
117119
return RubyStringLibrary.getUncached().getJavaString(rubyString);
118120
}
119121

120122
@TruffleBoundary
121123
public String inspectReceiver(Object receiver) {
122-
Object rubyString = RubyContext.send(
123-
context.getCoreLibrary().truffleExceptionOperationsModule,
124-
"receiver_string",
125-
receiver);
124+
Object rubyString = DispatchNode.getUncached().call(
125+
context.getCoreLibrary().truffleExceptionOperationsModule, "receiver_string", receiver);
126126
return RubyStringLibrary.getUncached().getJavaString(rubyString);
127127
}
128128

@@ -686,7 +686,8 @@ public RubyException typeError(String message, Node currentNode, Throwable javaT
686686
@TruffleBoundary
687687
public RubyException typeErrorUnsupportedTypeException(UnsupportedTypeException exception, Node currentNode) {
688688
RubyArray rubyArray = createArray(context, language, exception.getSuppliedValues());
689-
String formattedValues = RubyStringLibrary.getUncached().getJavaString(RubyContext.send(rubyArray, "inspect"));
689+
String formattedValues = RubyStringLibrary.getUncached()
690+
.getJavaString(DispatchNode.getUncached().call(rubyArray, "inspect"));
690691
return typeError("unsupported type " + formattedValues, currentNode);
691692
}
692693

src/main/java/org/truffleruby/core/exception/ExceptionOperations.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.oracle.truffle.api.nodes.Node;
2929
import com.oracle.truffle.api.object.Shape;
3030
import org.truffleruby.language.control.RaiseException;
31+
import org.truffleruby.language.dispatch.DispatchNode;
3132
import org.truffleruby.language.library.RubyStringLibrary;
3233

3334
public abstract class ExceptionOperations {
@@ -112,7 +113,7 @@ private static String messageFieldToString(RubyException exception) {
112113
public static String messageToString(RubyException exception) {
113114
Object messageObject = null;
114115
try {
115-
messageObject = RubyContext.send(exception, "message");
116+
messageObject = DispatchNode.getUncached().call(exception, "message");
116117
} catch (Throwable e) {
117118
// Fall back to the internal message field
118119
}

src/main/java/org/truffleruby/core/hash/PreInitializationManager.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@
1515
import java.util.Set;
1616
import java.util.WeakHashMap;
1717

18-
import org.truffleruby.RubyContext;
19-
2018
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
19+
import org.truffleruby.language.dispatch.DispatchNode;
2120

2221
public final class PreInitializationManager {
2322

@@ -53,7 +52,7 @@ public void rehash() {
5352
private void rehashRubyHashes() {
5453
for (RubyHash hash : hashesCreatedDuringPreInit) {
5554
if (!HashGuards.isCompareByIdentity(hash)) {
56-
RubyContext.send(hash, "rehash");
55+
DispatchNode.getUncached().call(hash, "rehash");
5756
}
5857
}
5958
hashesCreatedDuringPreInit.clear();

src/main/java/org/truffleruby/core/objectspace/ObjectSpaceNodes.java

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

1212
import com.oracle.truffle.api.object.DynamicObjectLibrary;
1313
import org.truffleruby.Layouts;
14-
import org.truffleruby.RubyContext;
1514
import org.truffleruby.builtins.CoreMethod;
1615
import org.truffleruby.builtins.CoreMethodArrayArgumentsNode;
1716
import org.truffleruby.builtins.CoreModule;
@@ -34,6 +33,7 @@
3433
import org.truffleruby.language.RubyDynamicObject;
3534
import org.truffleruby.language.RubyGuards;
3635
import org.truffleruby.language.control.RaiseException;
36+
import org.truffleruby.language.dispatch.DispatchNode;
3737
import org.truffleruby.language.dispatch.InternalRespondToNode;
3838
import org.truffleruby.language.objects.IsANode;
3939
import org.truffleruby.language.objects.ObjectGraph;
@@ -185,7 +185,7 @@ public CallableFinalizer(Object callable) {
185185
}
186186

187187
public void run() {
188-
RubyContext.send(callable, "call");
188+
DispatchNode.getUncached().call(callable, "call");
189189
}
190190

191191
@Override

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import org.truffleruby.language.control.ExitException;
5757
import org.truffleruby.language.control.KillException;
5858
import org.truffleruby.language.control.RaiseException;
59+
import org.truffleruby.language.dispatch.DispatchNode;
5960
import org.truffleruby.language.objects.shared.SharedObjects;
6061

6162
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
@@ -375,14 +376,10 @@ private void setException(RubyThread thread, RubyException exception, Node curre
375376

376377
if (!isSystemExit && thread.reportOnException) {
377378
final TruffleSafepoint safepoint = TruffleSafepoint.getCurrent();
378-
379379
boolean sideEffects = safepoint.setAllowSideEffects(false);
380380
try {
381-
RubyContext.send(
382-
context.getCoreLibrary().truffleThreadOperationsModule,
383-
"report_exception",
384-
thread,
385-
exception);
381+
DispatchNode.getUncached().call(context.getCoreLibrary().truffleThreadOperationsModule,
382+
"report_exception", thread, exception);
386383
} finally {
387384
safepoint.setAllowSideEffects(sideEffects);
388385
}

0 commit comments

Comments
 (0)