9
9
*/
10
10
package org .truffleruby .language .exceptions ;
11
11
12
+ import com .oracle .truffle .api .dsl .Cached ;
13
+ import com .oracle .truffle .api .dsl .Specialization ;
12
14
import com .oracle .truffle .api .exception .AbstractTruffleException ;
13
15
import com .oracle .truffle .api .interop .InteropLibrary ;
14
16
import com .oracle .truffle .api .nodes .ControlFlowException ;
15
- import com .oracle .truffle .api .profiles .ConditionProfile ;
17
+ import com .oracle .truffle .api .profiles .InlinedBranchProfile ;
18
+ import com .oracle .truffle .api .profiles .InlinedConditionProfile ;
16
19
import org .truffleruby .core .exception .ExceptionOperations ;
17
20
import org .truffleruby .language .RubyContextSourceNode ;
18
21
import org .truffleruby .language .RubyNode ;
19
22
20
23
import com .oracle .truffle .api .frame .VirtualFrame ;
21
- import com .oracle .truffle .api .profiles .BranchProfile ;
22
24
import org .truffleruby .language .control .KillException ;
23
25
import org .truffleruby .language .threadlocal .ThreadLocalGlobals ;
24
26
25
- public class EnsureNode extends RubyContextSourceNode {
27
+ public abstract class EnsureNode extends RubyContextSourceNode {
26
28
27
29
@ Child private RubyNode tryPart ;
28
30
@ Child private RubyNode ensurePart ;
29
31
30
- private final BranchProfile killExceptionProfile = BranchProfile .create ();
31
- private final BranchProfile guestExceptionProfile = BranchProfile .create ();
32
- private final BranchProfile controlFlowExceptionProfile = BranchProfile .create ();
33
- private final ConditionProfile raiseExceptionProfile = ConditionProfile .create ();
34
-
35
32
public EnsureNode (RubyNode tryPart , RubyNode ensurePart ) {
36
33
this .tryPart = tryPart ;
37
34
this .ensurePart = ensurePart ;
38
35
}
39
36
37
+
40
38
@ Override
41
- public Object execute (VirtualFrame frame ) {
39
+ public final Object execute (VirtualFrame frame ) {
42
40
return executeCommon (frame , false );
43
41
}
44
42
45
43
@ Override
46
- public void doExecuteVoid (VirtualFrame frame ) {
44
+ public final void doExecuteVoid (VirtualFrame frame ) {
47
45
executeCommon (frame , true );
48
46
}
49
47
48
+ protected abstract Object executeCommon (VirtualFrame frame , boolean executeVoid );
49
+
50
+
50
51
/** Based on {@link InteropLibrary#throwException(Object)}'s {@code TryCatchNode}. It only runs code in ensure for
51
52
* guest exceptions (AbstractTruffleException), ControlFlowException or no exception. */
52
- public Object executeCommon (VirtualFrame frame , boolean executeVoid ) {
53
+ @ Specialization
54
+ protected Object ensure (VirtualFrame frame , boolean executeVoid ,
55
+ @ Cached InlinedBranchProfile killExceptionProfile ,
56
+ @ Cached InlinedBranchProfile guestExceptionProfile ,
57
+ @ Cached InlinedBranchProfile controlFlowExceptionProfile ,
58
+ @ Cached InlinedConditionProfile raiseExceptionProfile ) {
53
59
Object value = nil ;
54
60
RuntimeException rethrowException = null ;
55
61
AbstractTruffleException guestException = null ;
@@ -61,22 +67,22 @@ public Object executeCommon(VirtualFrame frame, boolean executeVoid) {
61
67
value = tryPart .execute (frame );
62
68
}
63
69
} catch (KillException e ) { // an AbstractTruffleException but must not set $!
64
- killExceptionProfile .enter ();
70
+ killExceptionProfile .enter (this );
65
71
rethrowException = e ;
66
72
} catch (AbstractTruffleException e ) {
67
- guestExceptionProfile .enter ();
73
+ guestExceptionProfile .enter (this );
68
74
guestException = e ;
69
75
rethrowException = e ;
70
76
} catch (ControlFlowException e ) {
71
- controlFlowExceptionProfile .enter ();
77
+ controlFlowExceptionProfile .enter (this );
72
78
rethrowException = e ;
73
79
}
74
80
75
81
ThreadLocalGlobals threadLocalGlobals = null ;
76
82
Object previousException = null ;
77
83
78
84
if (guestException != null ) {
79
- var exceptionObject = ExceptionOperations .getExceptionObject (guestException , raiseExceptionProfile );
85
+ var exceptionObject = ExceptionOperations .getExceptionObject (this , guestException , raiseExceptionProfile );
80
86
threadLocalGlobals = getLanguage ().getCurrentThread ().threadLocalGlobals ;
81
87
previousException = threadLocalGlobals .getLastException ();
82
88
threadLocalGlobals .setLastException (exceptionObject );
@@ -96,9 +102,10 @@ public Object executeCommon(VirtualFrame frame, boolean executeVoid) {
96
102
}
97
103
}
98
104
105
+
99
106
@ Override
100
107
public RubyNode cloneUninitialized () {
101
- var copy = new EnsureNode (
108
+ var copy = EnsureNodeGen . create (
102
109
tryPart .cloneUninitialized (),
103
110
ensurePart .cloneUninitialized ());
104
111
return copy .copyFlags (this );
0 commit comments