92
92
import org .truffleruby .language .constants .LookupConstantNode ;
93
93
import org .truffleruby .language .control .BreakException ;
94
94
import org .truffleruby .language .control .BreakID ;
95
+ import org .truffleruby .language .control .DynamicReturnException ;
96
+ import org .truffleruby .language .control .LocalReturnException ;
97
+ import org .truffleruby .language .control .NextException ;
98
+ import org .truffleruby .language .control .RedoException ;
99
+ import org .truffleruby .language .control .RetryException ;
95
100
import org .truffleruby .language .control .RaiseException ;
101
+ import org .truffleruby .language .control .ThrowException ;
96
102
import org .truffleruby .language .dispatch .DispatchNode ;
97
103
import org .truffleruby .language .dispatch .LiteralCallNode ;
98
104
import org .truffleruby .language .library .RubyStringLibrary ;
130
136
@ CoreModule ("Truffle::CExt" )
131
137
public class CExtNodes {
132
138
139
+ /* These tag values are derived from MRI source and from the Tk gem and are used to represent different control flow
140
+ * states under which code may exit an `rb_protect` plock. The fatal tag is defined but I could not find a point
141
+ * where it is assigned, and am not sure it maps to anything we would use in TruffleRuby. */
142
+ public static int RUBY_TAG_RETURN = 0x1 ;
143
+ public static int RUBY_TAG_BREAK = 0x2 ;
144
+ public static int RUBY_TAG_NEXT = 0x3 ;
145
+ public static int RUBY_TAG_RETRY = 0x4 ;
146
+ public static int RUBY_TAG_REDO = 0x5 ;
147
+ public static int RUBY_TAG_RAISE = 0x6 ;
148
+ public static int RUBY_TAG_THROW = 0x7 ;
149
+ public static int RUBY_TAG_FATAL = 0x8 ;
150
+
133
151
public static Pointer newNativeStringPointer (int capacity , RubyLanguage language ) {
134
152
// We need up to 4 \0 bytes for UTF-32. Always use 4 for speed rather than checking the encoding min length.
135
153
Pointer pointer = Pointer .mallocAutoRelease (capacity + 4 , language );
@@ -1355,6 +1373,31 @@ protected Object executeWithProtect(RubyProc block,
1355
1373
}
1356
1374
}
1357
1375
1376
+ @ CoreMethod (names = "store_exception" , onSingleton = true , required = 1 )
1377
+ public abstract static class StoreException extends YieldingCoreMethodNode {
1378
+
1379
+ @ Specialization
1380
+ protected Object storeException (CapturedException captured ) {
1381
+ final ExtensionCallStack extensionStack = getLanguage ()
1382
+ .getCurrentThread ()
1383
+ .getCurrentFiber ().extensionCallStack ;
1384
+ extensionStack .setException (captured );
1385
+ return nil ;
1386
+ }
1387
+ }
1388
+
1389
+ @ CoreMethod (names = "retrieve_exception" , onSingleton = true )
1390
+ public abstract static class RetrieveException extends YieldingCoreMethodNode {
1391
+
1392
+ @ Specialization
1393
+ protected Object retrieveException () {
1394
+ final ExtensionCallStack extensionStack = getLanguage ()
1395
+ .getCurrentThread ()
1396
+ .getCurrentFiber ().extensionCallStack ;
1397
+ return extensionStack .getException ();
1398
+ }
1399
+ }
1400
+
1358
1401
@ CoreMethod (names = "extract_ruby_exception" , onSingleton = true , required = 1 )
1359
1402
public abstract static class ExtractRubyException extends CoreMethodArrayArgumentsNode {
1360
1403
@@ -1370,6 +1413,41 @@ protected Object executeThrow(CapturedException captured,
1370
1413
}
1371
1414
}
1372
1415
1416
+ @ CoreMethod (names = "extract_tag" , onSingleton = true , required = 1 )
1417
+ public abstract static class ExtractRubyTag extends CoreMethodArrayArgumentsNode {
1418
+
1419
+ @ Specialization
1420
+ protected int executeThrow (CapturedException captured ,
1421
+ @ Cached ConditionProfile localReturnProfile ,
1422
+ @ Cached ConditionProfile dynamicReturnProfile ,
1423
+ @ Cached ConditionProfile breakProfile ,
1424
+ @ Cached ConditionProfile nextProfile ,
1425
+ @ Cached ConditionProfile retryProfile ,
1426
+ @ Cached ConditionProfile redoProfile ,
1427
+ @ Cached ConditionProfile raiseProfile ,
1428
+ @ Cached ConditionProfile throwProfile ) {
1429
+ final Throwable e = captured .getException ();
1430
+ if (dynamicReturnProfile .profile (e instanceof DynamicReturnException )) {
1431
+ return RUBY_TAG_RETURN ;
1432
+ } else if (localReturnProfile .profile (e instanceof LocalReturnException )) {
1433
+ return RUBY_TAG_RETURN ;
1434
+ } else if (breakProfile .profile (e instanceof BreakException )) {
1435
+ return RUBY_TAG_BREAK ;
1436
+ } else if (nextProfile .profile (e instanceof NextException )) {
1437
+ return RUBY_TAG_NEXT ;
1438
+ } else if (retryProfile .profile (e instanceof RetryException )) {
1439
+ return RUBY_TAG_RETRY ;
1440
+ } else if (redoProfile .profile (e instanceof RedoException )) {
1441
+ return RUBY_TAG_REDO ;
1442
+ } else if (raiseProfile .profile (e instanceof RaiseException )) {
1443
+ return RUBY_TAG_RAISE ;
1444
+ } else if (throwProfile .profile (e instanceof ThrowException )) {
1445
+ return RUBY_TAG_THROW ;
1446
+ }
1447
+ return 0 ;
1448
+ }
1449
+ }
1450
+
1373
1451
@ CoreMethod (names = "raise_exception" , onSingleton = true , required = 1 )
1374
1452
public abstract static class RaiseExceptionNode extends CoreMethodArrayArgumentsNode {
1375
1453
@@ -1382,6 +1460,7 @@ protected Object executeThrow(CapturedException captured,
1382
1460
if (runtimeExceptionProfile .profile (e instanceof RuntimeException )) {
1383
1461
throw (RuntimeException ) e ;
1384
1462
} else if (errorProfile .profile (e instanceof Error )) {
1463
+
1385
1464
throw (Error ) e ;
1386
1465
} else {
1387
1466
throw CompilerDirectives .shouldNotReachHere ("Checked Java Throwable rethrown" , e );
0 commit comments