10
10
package org .truffleruby .language .control ;
11
11
12
12
import com .oracle .truffle .api .TruffleSafepoint ;
13
+ import com .oracle .truffle .api .dsl .Cached ;
14
+ import com .oracle .truffle .api .dsl .Specialization ;
15
+ import com .oracle .truffle .api .profiles .InlinedBranchProfile ;
13
16
import org .truffleruby .RubyLanguage ;
14
17
import org .truffleruby .core .cast .BooleanCastNode ;
15
- import org .truffleruby .core .cast .BooleanCastNodeGen ;
16
18
import org .truffleruby .language .RubyBaseNode ;
17
19
import org .truffleruby .language .RubyContextSourceNode ;
18
20
import org .truffleruby .language .RubyNode ;
21
23
import com .oracle .truffle .api .frame .VirtualFrame ;
22
24
import com .oracle .truffle .api .nodes .LoopNode ;
23
25
import com .oracle .truffle .api .nodes .RepeatingNode ;
24
- import com .oracle .truffle .api .profiles .BranchProfile ;
25
26
26
27
public final class WhileNode extends RubyContextSourceNode {
27
28
@@ -45,17 +46,30 @@ public RubyNode cloneUninitialized() {
45
46
46
47
private abstract static class WhileRepeatingBaseNode extends RubyBaseNode implements RepeatingNode {
47
48
48
- @ Child protected BooleanCastNode condition ;
49
+ @ Child protected RubyNode condition ;
49
50
@ Child protected RubyNode body ;
50
51
51
- protected final BranchProfile redoUsed = BranchProfile .create ();
52
- protected final BranchProfile nextUsed = BranchProfile .create ();
53
-
54
52
public WhileRepeatingBaseNode (RubyNode condition , RubyNode body ) {
55
- this .condition = BooleanCastNodeGen . create ( condition ) ;
53
+ this .condition = condition ;
56
54
this .body = body ;
57
55
}
58
56
57
+ protected abstract boolean execute (VirtualFrame frame );
58
+
59
+ @ Override
60
+ public final boolean executeRepeating (VirtualFrame frame ) {
61
+ return execute (frame );
62
+ }
63
+
64
+ @ Override
65
+ public final Object executeRepeatingWithValue (VirtualFrame frame ) {
66
+ if (executeRepeating (frame )) {
67
+ return CONTINUE_LOOP_STATUS ;
68
+ } else {
69
+ return BREAK_LOOP_STATUS ;
70
+ }
71
+ }
72
+
59
73
@ Override
60
74
public String toString () {
61
75
return "while loop at " + RubyLanguage .filenameLine (getEncapsulatingSourceSection ());
@@ -64,15 +78,19 @@ public String toString() {
64
78
public abstract WhileRepeatingBaseNode cloneUninitialized ();
65
79
}
66
80
67
- public static class WhileRepeatingNode extends WhileRepeatingBaseNode implements RepeatingNode {
81
+ public abstract static class WhileRepeatingNode extends WhileRepeatingBaseNode {
68
82
69
83
public WhileRepeatingNode (RubyNode condition , RubyNode body ) {
70
84
super (condition , body );
71
85
}
72
86
73
- @ Override
74
- public boolean executeRepeating (VirtualFrame frame ) {
75
- if (!condition .execute (frame )) {
87
+ @ Specialization
88
+ protected boolean doRepeating (VirtualFrame frame ,
89
+ @ Cached BooleanCastNode booleanCastNode ,
90
+ @ Cached InlinedBranchProfile redoUsed ,
91
+ @ Cached InlinedBranchProfile nextUsed ) {
92
+ var conditionAsBoolean = booleanCastNode .execute (condition .execute (frame ));
93
+ if (!conditionAsBoolean ) {
76
94
return false ;
77
95
}
78
96
@@ -81,54 +99,53 @@ public boolean executeRepeating(VirtualFrame frame) {
81
99
body .doExecuteVoid (frame );
82
100
return true ;
83
101
} catch (NextException e ) {
84
- nextUsed .enter ();
102
+ nextUsed .enter (this );
85
103
return true ;
86
104
} catch (RedoException e ) {
87
105
// Just continue in the while(true) loop.
88
- redoUsed .enter ();
106
+ redoUsed .enter (this );
89
107
TruffleSafepoint .poll (this );
90
108
}
91
109
}
92
110
}
93
111
94
112
@ Override
95
113
public WhileRepeatingBaseNode cloneUninitialized () {
96
- return new WhileRepeatingNode (
97
- condition .getValueNode (). cloneUninitialized (),
114
+ return WhileNodeFactory . WhileRepeatingNodeGen . create (
115
+ condition .cloneUninitialized (),
98
116
body .cloneUninitialized ());
99
117
}
100
118
101
119
}
102
120
103
- public static class DoWhileRepeatingNode extends WhileRepeatingBaseNode implements RepeatingNode {
121
+ public abstract static class DoWhileRepeatingNode extends WhileRepeatingBaseNode {
104
122
105
123
public DoWhileRepeatingNode (RubyNode condition , RubyNode body ) {
106
124
super (condition , body );
107
125
}
108
126
109
- @ Override
110
- public boolean executeRepeating (VirtualFrame frame ) {
127
+ @ Specialization
128
+ protected boolean doRepeating (VirtualFrame frame ,
129
+ @ Cached BooleanCastNode booleanCastNode ,
130
+ @ Cached InlinedBranchProfile redoUsed ,
131
+ @ Cached InlinedBranchProfile nextUsed ) {
111
132
try {
112
133
body .doExecuteVoid (frame );
113
134
} catch (NextException e ) {
114
- nextUsed .enter ();
135
+ nextUsed .enter (this );
115
136
} catch (RedoException e ) {
116
137
// Just continue to next iteration without executing the condition.
117
- redoUsed .enter ();
138
+ redoUsed .enter (this );
118
139
return true ;
119
140
}
120
141
121
- return condition .execute (frame );
122
- }
123
-
124
- private RubyNode getConditionBeforeCasting () {
125
- return condition .getValueNode ();
142
+ return booleanCastNode .execute (condition .execute (frame ));
126
143
}
127
144
128
145
@ Override
129
146
public WhileRepeatingBaseNode cloneUninitialized () {
130
- return new DoWhileRepeatingNode (
131
- getConditionBeforeCasting () .cloneUninitialized (),
147
+ return WhileNodeFactory . DoWhileRepeatingNodeGen . create (
148
+ condition .cloneUninitialized (),
132
149
body .cloneUninitialized ());
133
150
}
134
151
0 commit comments