Skip to content

Commit 41a40f6

Browse files
committed
[GR-18411] Migrate to AbstractTruffleException
PullRequest: truffleruby/2117
2 parents 74ef80f + 6cbb0d7 commit 41a40f6

File tree

10 files changed

+178
-171
lines changed

10 files changed

+178
-171
lines changed

src/main/java/org/truffleruby/core/VMPrimitiveNodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ protected Object vmRaiseException(RubyException exception,
202202
}
203203
}
204204

205-
public static void reRaiseException(RubyContext context, RubyException exception) {
205+
public static RaiseException reRaiseException(RubyContext context, RubyException exception) {
206206
final Backtrace backtrace = exception.backtrace;
207207
if (backtrace != null && backtrace.getRaiseException() != null) {
208208
// We need to rethrow the existing RaiseException, otherwise we would lose the

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import org.truffleruby.language.Nil;
2020
import org.truffleruby.language.RubyGuards;
2121
import org.truffleruby.language.backtrace.Backtrace;
22-
import org.truffleruby.language.control.RaiseException;
2322

2423
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
2524
import com.oracle.truffle.api.nodes.Node;
@@ -94,11 +93,6 @@ public static RubySystemCallError createSystemCallError(RubyContext context, Rub
9493
return new RubySystemCallError(rubyClass, shape, message, backtrace, cause, errno);
9594
}
9695

97-
@TruffleBoundary // Exception#initCause is blacklisted in TruffleFeature
98-
public static void initCause(RaiseException exception, Throwable cause) {
99-
exception.initCause(cause);
100-
}
101-
10296
public static RubyProc getFormatter(String name, RubyContext context) {
10397
return (RubyProc) context.getCoreLibrary().truffleExceptionOperationsModule.fields.getConstant(name).getValue();
10498
}

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

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,39 +9,17 @@
99
*/
1010
package org.truffleruby.core.exception;
1111

12-
import com.oracle.truffle.api.TruffleException;
12+
import com.oracle.truffle.api.exception.AbstractTruffleException;
1313
import com.oracle.truffle.api.nodes.Node;
14-
import org.truffleruby.SuppressFBWarnings;
1514

16-
@SuppressFBWarnings("Se")
17-
public class GetBacktraceException extends RuntimeException implements TruffleException {
15+
public class GetBacktraceException extends AbstractTruffleException {
1816

1917
private static final long serialVersionUID = 2633487517169337464L;
2018

21-
public static final int UNLIMITED = -1;
22-
23-
private final Node location;
24-
private final int limit;
19+
public static final int UNLIMITED = AbstractTruffleException.UNLIMITED_STACK_TRACE;
2520

2621
public GetBacktraceException(Node location, int limit) {
27-
this.location = location;
28-
this.limit = limit;
29-
}
30-
31-
@SuppressWarnings("sync-override")
32-
@Override
33-
public final Throwable fillInStackTrace() {
34-
return null;
35-
}
36-
37-
@Override
38-
public Node getLocation() {
39-
return location;
40-
}
41-
42-
@Override
43-
public int getStackTraceElementLimit() {
44-
return limit;
22+
super("<GetBacktraceException>", null, limit, location);
4523
}
4624

4725
}

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

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,36 @@
1111

1212
import java.util.Set;
1313

14+
import com.oracle.truffle.api.CompilerDirectives;
15+
import com.oracle.truffle.api.dsl.Cached;
16+
import com.oracle.truffle.api.dsl.CachedContext;
17+
import com.oracle.truffle.api.interop.ExceptionType;
18+
import com.oracle.truffle.api.interop.InteropLibrary;
19+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
20+
import com.oracle.truffle.api.library.CachedLibrary;
21+
import com.oracle.truffle.api.library.ExportLibrary;
22+
import com.oracle.truffle.api.library.ExportMessage;
23+
import com.oracle.truffle.api.nodes.Node;
24+
import com.oracle.truffle.api.object.DynamicObjectLibrary;
25+
import com.oracle.truffle.api.source.SourceSection;
26+
import org.truffleruby.RubyContext;
27+
import org.truffleruby.RubyLanguage;
28+
import org.truffleruby.core.VMPrimitiveNodes.VMRaiseExceptionNode;
1429
import org.truffleruby.core.array.RubyArray;
1530
import org.truffleruby.core.klass.RubyClass;
1631
import org.truffleruby.core.proc.RubyProc;
1732
import org.truffleruby.core.string.RubyString;
1833
import org.truffleruby.language.Nil;
1934
import org.truffleruby.language.RubyDynamicObject;
2035
import org.truffleruby.language.backtrace.Backtrace;
36+
import org.truffleruby.language.objects.IsANode;
2137
import org.truffleruby.language.objects.ObjectGraph;
2238
import org.truffleruby.language.objects.ObjectGraphNode;
2339

2440
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
2541
import com.oracle.truffle.api.object.Shape;
2642

43+
@ExportLibrary(InteropLibrary.class)
2744
public class RubyException extends RubyDynamicObject implements ObjectGraphNode {
2845

2946
public Object message;
@@ -53,10 +70,107 @@ public String toString() {
5370
return message.toString();
5471
}
5572

73+
public Node getLocation() {
74+
final Backtrace backtrace = this.backtrace;
75+
if (backtrace == null) {
76+
// The backtrace could be null if for example a user backtrace was passed to Kernel#raise
77+
return null;
78+
} else {
79+
return backtrace.getLocation();
80+
}
81+
}
82+
5683
@Override
5784
public void getAdjacentObjects(Set<Object> reachable) {
5885
ObjectGraph.addProperty(reachable, message);
5986
ObjectGraph.addProperty(reachable, cause);
6087
}
6188

89+
// region Exception interop
90+
@ExportMessage
91+
public boolean isException() {
92+
return true;
93+
}
94+
95+
@ExportMessage
96+
public RuntimeException throwException(
97+
@CachedContext(RubyLanguage.class) RubyContext context) {
98+
throw VMRaiseExceptionNode.reRaiseException(context, this);
99+
}
100+
101+
// TODO (eregon, 01 Nov 2020): these message implementations would be nicer with separate subclasses for SystemExit and SyntaxError.
102+
103+
@ExportMessage
104+
public ExceptionType getExceptionType(
105+
@Cached IsANode isANode) {
106+
// @CachedContext does not work here when running "mx tck"
107+
final RubyContext context = getMetaClass().fields.getContext();
108+
if (isANode.executeIsA(this, context.getCoreLibrary().systemExitClass)) {
109+
return ExceptionType.EXIT;
110+
} else if (isANode.executeIsA(this, context.getCoreLibrary().syntaxErrorClass)) {
111+
return ExceptionType.PARSE_ERROR;
112+
} else {
113+
return ExceptionType.RUNTIME_ERROR;
114+
}
115+
}
116+
117+
@ExportMessage
118+
public int getExceptionExitStatus(
119+
@CachedLibrary("this") InteropLibrary interopLibrary,
120+
@CachedLibrary("this") DynamicObjectLibrary objectLibrary) throws UnsupportedMessageException {
121+
if (interopLibrary.getExceptionType(this) == ExceptionType.EXIT) {
122+
return (int) objectLibrary.getOrDefault(this, "@status", 1);
123+
} else {
124+
throw UnsupportedMessageException.create();
125+
}
126+
}
127+
128+
@ExportMessage
129+
public boolean isExceptionIncompleteSource(
130+
@CachedLibrary("this") InteropLibrary interopLibrary) throws UnsupportedMessageException {
131+
if (interopLibrary.getExceptionType(this) == ExceptionType.PARSE_ERROR) {
132+
return false; // Unknown
133+
} else {
134+
throw UnsupportedMessageException.create();
135+
}
136+
}
137+
138+
@TruffleBoundary
139+
@ExportMessage
140+
public boolean hasSourceLocation(
141+
@CachedLibrary("this") InteropLibrary interopLibrary) {
142+
try {
143+
if (interopLibrary.getExceptionType(this) == ExceptionType.PARSE_ERROR &&
144+
backtrace != null &&
145+
backtrace.getSourceLocation() != null) {
146+
return true;
147+
} else {
148+
final Node location = getLocation();
149+
return location != null && location.getEncapsulatingSourceSection() != null;
150+
}
151+
} catch (UnsupportedMessageException e) {
152+
throw CompilerDirectives.shouldNotReachHere(e);
153+
}
154+
}
155+
156+
@TruffleBoundary
157+
@ExportMessage
158+
public SourceSection getSourceLocation(
159+
@CachedLibrary("this") InteropLibrary interopLibrary) throws UnsupportedMessageException {
160+
if (interopLibrary.getExceptionType(this) == ExceptionType.PARSE_ERROR &&
161+
backtrace != null &&
162+
backtrace.getSourceLocation() != null) {
163+
return backtrace.getSourceLocation();
164+
} else {
165+
final Node location = getLocation();
166+
SourceSection sourceSection = location != null ? location.getEncapsulatingSourceSection() : null;
167+
if (sourceSection != null) {
168+
return sourceSection;
169+
} else {
170+
throw UnsupportedMessageException.create();
171+
}
172+
}
173+
}
174+
// endregion
175+
62176
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545

4646
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
4747
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
48-
import com.oracle.truffle.api.TruffleException;
4948
import com.oracle.truffle.api.TruffleStackTrace;
5049
import com.oracle.truffle.api.nodes.Node;
5150
import com.oracle.truffle.api.object.Shape;
@@ -349,9 +348,9 @@ private static void setException(RubyContext context, RubyThread thread, RubyExc
349348

350349
// We materialize the backtrace eagerly here, as the exception escapes the thread and needs
351350
// to capture the backtrace from this thread.
352-
final TruffleException truffleException = exception.backtrace.getRaiseException();
351+
final RaiseException truffleException = exception.backtrace.getRaiseException();
353352
if (truffleException != null) {
354-
TruffleStackTrace.fillIn((Throwable) truffleException);
353+
TruffleStackTrace.fillIn(truffleException);
355354
}
356355

357356
final RubyThread mainThread = context.getThreadManager().getRootThread();

src/main/java/org/truffleruby/extra/TruffleGraalNodes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ protected Object assertCompilationConstant(Object value) {
205205

206206
@TruffleBoundary
207207
private void notConstantBoundary() {
208-
throw new RaiseException(getContext(), coreExceptions().graalErrorAssertConstantNotConstant(this), true);
208+
throw new RaiseException(getContext(), coreExceptions().graalErrorAssertConstantNotConstant(this));
209209
}
210210
}
211211

@@ -223,7 +223,7 @@ protected Object assertNotCompiled() {
223223

224224
@TruffleBoundary
225225
private void compiledBoundary() {
226-
throw new RaiseException(getContext(), coreExceptions().graalErrorAssertNotCompiledCompiled(this), true);
226+
throw new RaiseException(getContext(), coreExceptions().graalErrorAssertNotCompiledCompiled(this));
227227
}
228228
}
229229

src/main/java/org/truffleruby/interop/TranslateInteropExceptionNode.java

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

1212
import org.truffleruby.RubyContext;
1313
import org.truffleruby.RubyLanguage;
14-
import org.truffleruby.core.exception.ExceptionOperations;
1514
import org.truffleruby.language.RubyBaseNode;
1615
import org.truffleruby.language.control.RaiseException;
1716

@@ -54,11 +53,10 @@ protected RuntimeException handle(
5453
Object receiver,
5554
Object[] args,
5655
@CachedContext(RubyLanguage.class) RubyContext context) {
57-
RaiseException raiseException = new RaiseException(
56+
return new RaiseException(
5857
context,
59-
context.getCoreExceptions().unsupportedMessageError(exception.getMessage(), this));
60-
ExceptionOperations.initCause(raiseException, exception);
61-
return raiseException;
58+
context.getCoreExceptions().unsupportedMessageError(exception.getMessage(), this),
59+
exception);
6260
}
6361

6462
@Specialization
@@ -68,12 +66,10 @@ protected RuntimeException handle(
6866
Object receiver,
6967
Object[] args,
7068
@CachedContext(RubyLanguage.class) RubyContext context) {
71-
72-
RaiseException raiseException = new RaiseException(
69+
return new RaiseException(
7370
context,
74-
context.getCoreExceptions().indexErrorInvalidArrayIndexException(exception, this));
75-
ExceptionOperations.initCause(raiseException, exception);
76-
return raiseException;
71+
context.getCoreExceptions().indexErrorInvalidArrayIndexException(exception, this),
72+
exception);
7773
}
7874

7975
@Specialization
@@ -83,25 +79,22 @@ protected RuntimeException handle(
8379
Object receiver,
8480
Object[] args,
8581
@CachedContext(RubyLanguage.class) RubyContext context) {
86-
87-
final RaiseException raiseException;
8882
if (inInvokeMember) {
89-
raiseException = new RaiseException(
83+
return new RaiseException(
9084
context,
9185
context.getCoreExceptions().noMethodErrorUnknownIdentifier(
9286
receiver,
9387
exception.getUnknownIdentifier(),
9488
args,
9589
exception,
96-
this));
90+
this),
91+
exception);
9792
} else {
98-
raiseException = new RaiseException(
93+
return new RaiseException(
9994
context,
100-
context.getCoreExceptions().nameErrorUnknownIdentifierException(exception, receiver, this));
95+
context.getCoreExceptions().nameErrorUnknownIdentifierException(exception, receiver, this),
96+
exception);
10197
}
102-
103-
ExceptionOperations.initCause(raiseException, exception);
104-
return raiseException;
10598
}
10699

107100
@TruffleBoundary // Throwable#initCause
@@ -112,26 +105,22 @@ protected RuntimeException handle(
112105
Object receiver,
113106
Object[] args,
114107
@CachedContext(RubyLanguage.class) RubyContext context) {
115-
116-
RaiseException raiseException = new RaiseException(
108+
return new RaiseException(
117109
context,
118-
context.getCoreExceptions().typeErrorUnsupportedTypeException(exception, this));
119-
ExceptionOperations.initCause(raiseException, exception);
120-
return raiseException;
110+
context.getCoreExceptions().typeErrorUnsupportedTypeException(exception, this),
111+
exception);
121112
}
122113

123114
@Specialization
124115
protected RuntimeException handle(ArityException exception, boolean inInvokeMember, Object receiver, Object[] args,
125116
@CachedContext(RubyLanguage.class) RubyContext context) {
126-
127-
RaiseException raiseException = new RaiseException(
117+
return new RaiseException(
128118
context,
129119
context.getCoreExceptions().argumentError(
130120
exception.getActualArity(),
131121
exception.getExpectedArity(),
132-
this));
133-
ExceptionOperations.initCause(raiseException, exception);
134-
return raiseException;
122+
this),
123+
exception);
135124
}
136125

137126
}

0 commit comments

Comments
 (0)