33
33
import org .truffleruby .core .array .RubyArray ;
34
34
import org .truffleruby .core .cast .ToRubyEncodingNode ;
35
35
import org .truffleruby .core .encoding .EncodingNodesFactory .NegotiateCompatibleEncodingNodeGen ;
36
- import org .truffleruby .core .encoding .EncodingNodesFactory .NegotiateCompatibleStringEncodingNodeGen ;
37
36
import org .truffleruby .core .klass .RubyClass ;
38
37
import org .truffleruby .core .proc .RubyProc ;
39
38
import org .truffleruby .core .string .RubyString ;
@@ -69,23 +68,18 @@ protected boolean isAsciiCompatible(RubyEncoding encoding) {
69
68
70
69
// MRI: enc_compatible_str and enc_compatible_latter
71
70
@ ImportStatic (TruffleString .CodeRange .class )
71
+ @ GenerateCached (false )
72
+ @ GenerateInline
72
73
public abstract static class NegotiateCompatibleStringEncodingNode extends RubyBaseNode {
73
74
74
- @ Child TruffleString .GetByteCodeRangeNode codeRangeNode ;
75
-
76
- @ NeverDefault
77
- public static NegotiateCompatibleStringEncodingNode create () {
78
- return NegotiateCompatibleStringEncodingNodeGen .create ();
79
- }
80
-
81
- public abstract RubyEncoding execute (AbstractTruffleString first , RubyEncoding firstEncoding ,
75
+ public abstract RubyEncoding execute (Node node , AbstractTruffleString first , RubyEncoding firstEncoding ,
82
76
AbstractTruffleString second , RubyEncoding secondEncoding );
83
77
84
78
@ Specialization (guards = {
85
79
"firstEncoding == cachedEncoding" ,
86
80
"secondEncoding == cachedEncoding" ,
87
81
}, limit = "getCacheLimit()" )
88
- protected RubyEncoding negotiateSameEncodingCached (
82
+ protected static RubyEncoding negotiateSameEncodingCached (
89
83
AbstractTruffleString first ,
90
84
RubyEncoding firstEncoding ,
91
85
AbstractTruffleString second ,
@@ -98,7 +92,7 @@ protected RubyEncoding negotiateSameEncodingCached(
98
92
99
93
100
94
@ Specialization (guards = "firstEncoding == secondEncoding" , replaces = "negotiateSameEncodingCached" )
101
- protected RubyEncoding negotiateSameEncodingUncached (
95
+ protected static RubyEncoding negotiateSameEncodingUncached (
102
96
AbstractTruffleString first ,
103
97
RubyEncoding firstEncoding ,
104
98
AbstractTruffleString second ,
@@ -112,13 +106,14 @@ protected RubyEncoding negotiateSameEncodingUncached(
112
106
"firstEncoding != secondEncoding" ,
113
107
"firstEncoding == cachedEncoding" ,
114
108
"isStandardEncoding(cachedEncoding)" ,
115
- "getCodeRange (second, secondEncoding) == ASCII"
109
+ "codeRangeNode.execute (second, secondEncoding.tencoding ) == ASCII"
116
110
}, limit = "NUMBER_OF_STANDARD_ENCODINGS" )
117
- protected RubyEncoding negotiateStandardEncodingAndCr7Bit (
111
+ protected static RubyEncoding negotiateStandardEncodingAndCr7Bit (
118
112
AbstractTruffleString first ,
119
113
RubyEncoding firstEncoding ,
120
114
AbstractTruffleString second ,
121
115
RubyEncoding secondEncoding ,
116
+ @ Cached (inline = false ) @ Shared TruffleString .GetByteCodeRangeNode codeRangeNode ,
122
117
@ Cached ("firstEncoding" ) RubyEncoding cachedEncoding ) {
123
118
// Encoding negotiation of two strings is most often between strings with the same encoding. The next most
124
119
// frequent case is two strings with different encodings, but each being one of the standard/default runtime
@@ -135,35 +130,39 @@ protected RubyEncoding negotiateStandardEncodingAndCr7Bit(
135
130
"second.isEmpty() == isSecondEmpty" ,
136
131
"cachedFirstEncoding == firstEncoding" ,
137
132
"cachedSecondEncoding == secondEncoding" ,
138
- "getCodeRange(first, firstEncoding) == firstCodeRange " ,
139
- "getCodeRange(second, secondEncoding) == secondCodeRange " },
133
+ "firstCodeRange == firstCodeRangeCached " ,
134
+ "secondCodeRange == secondCodeRangeCached " },
140
135
limit = "getCacheLimit()" )
141
- protected RubyEncoding negotiateEncodingCached (
136
+ protected static RubyEncoding negotiateEncodingCached (
142
137
AbstractTruffleString first ,
143
138
RubyEncoding firstEncoding ,
144
139
AbstractTruffleString second ,
145
140
RubyEncoding secondEncoding ,
146
141
@ Cached ("first.isEmpty()" ) boolean isFirstEmpty ,
147
142
@ Cached ("second.isEmpty()" ) boolean isSecondEmpty ,
148
- @ Cached ("getCodeRange(first, firstEncoding)" ) TruffleString .CodeRange firstCodeRange ,
149
- @ Cached ("getCodeRange(second, secondEncoding)" ) TruffleString .CodeRange secondCodeRange ,
143
+ @ Cached (inline = false ) @ Shared TruffleString .GetByteCodeRangeNode codeRangeNode ,
144
+ @ Bind ("codeRangeNode.execute(first, firstEncoding.tencoding)" ) TruffleString .CodeRange firstCodeRange ,
145
+ @ Bind ("codeRangeNode.execute(second, secondEncoding.tencoding)" ) TruffleString .CodeRange secondCodeRange ,
146
+ @ Cached ("firstCodeRange" ) TruffleString .CodeRange firstCodeRangeCached ,
147
+ @ Cached ("secondCodeRange" ) TruffleString .CodeRange secondCodeRangeCached ,
150
148
@ Cached ("firstEncoding" ) RubyEncoding cachedFirstEncoding ,
151
149
@ Cached ("secondEncoding" ) RubyEncoding cachedSecondEncoding ,
152
- @ Cached ("compatibleEncodingForStrings(first, firstEncoding, second, secondEncoding)" ) RubyEncoding negotiatedEncoding ) {
150
+ @ Cached ("compatibleEncodingForStrings(first, firstEncoding, second, secondEncoding, codeRangeNode )" ) RubyEncoding negotiatedEncoding ) {
153
151
assert first .isCompatibleToUncached (firstEncoding .tencoding ) &&
154
152
second .isCompatibleToUncached (secondEncoding .tencoding );
155
153
return negotiatedEncoding ;
156
154
}
157
155
158
156
@ Specialization (guards = "firstEncoding != secondEncoding" , replaces = "negotiateEncodingCached" )
159
- protected RubyEncoding negotiateEncodingUncached (
157
+ protected static RubyEncoding negotiateEncodingUncached (
160
158
AbstractTruffleString first ,
161
159
RubyEncoding firstEncoding ,
162
160
AbstractTruffleString second ,
163
- RubyEncoding secondEncoding ) {
161
+ RubyEncoding secondEncoding ,
162
+ @ Cached (inline = false ) @ Shared TruffleString .GetByteCodeRangeNode codeRangeNode ) {
164
163
assert first .isCompatibleToUncached (firstEncoding .tencoding ) &&
165
164
second .isCompatibleToUncached (secondEncoding .tencoding );
166
- return compatibleEncodingForStrings (first , firstEncoding , second , secondEncoding );
165
+ return compatibleEncodingForStrings (first , firstEncoding , second , secondEncoding , codeRangeNode );
167
166
}
168
167
169
168
/** This method returns non-null if either:
@@ -173,8 +172,10 @@ protected RubyEncoding negotiateEncodingUncached(
173
172
* </ul>
174
173
*/
175
174
@ TruffleBoundary
176
- protected RubyEncoding compatibleEncodingForStrings (AbstractTruffleString first , RubyEncoding firstEncoding ,
177
- AbstractTruffleString second , RubyEncoding secondEncoding ) {
175
+ protected static RubyEncoding compatibleEncodingForStrings (AbstractTruffleString first ,
176
+ RubyEncoding firstEncoding ,
177
+ AbstractTruffleString second , RubyEncoding secondEncoding ,
178
+ TruffleString .GetByteCodeRangeNode codeRangeNode ) {
178
179
// MRI: enc_compatible_latter
179
180
assert firstEncoding != secondEncoding : "this method assumes the encodings are different" ;
180
181
@@ -183,7 +184,7 @@ protected RubyEncoding compatibleEncodingForStrings(AbstractTruffleString first,
183
184
}
184
185
if (first .isEmpty ()) {
185
186
return (firstEncoding .isAsciiCompatible &&
186
- StringGuards .is7Bit (second , secondEncoding , getCodeRangeNode () ))
187
+ StringGuards .is7Bit (second , secondEncoding , codeRangeNode ))
187
188
? firstEncoding
188
189
: secondEncoding ;
189
190
}
@@ -192,10 +193,10 @@ protected RubyEncoding compatibleEncodingForStrings(AbstractTruffleString first,
192
193
return null ;
193
194
}
194
195
195
- if (StringGuards .is7Bit (second , secondEncoding , getCodeRangeNode () )) {
196
+ if (StringGuards .is7Bit (second , secondEncoding , codeRangeNode )) {
196
197
return firstEncoding ;
197
198
}
198
- if (StringGuards .is7Bit (first , firstEncoding , getCodeRangeNode () )) {
199
+ if (StringGuards .is7Bit (first , firstEncoding , codeRangeNode )) {
199
200
return secondEncoding ;
200
201
}
201
202
@@ -206,19 +207,6 @@ protected int getCacheLimit() {
206
207
return getLanguage ().options .ENCODING_COMPATIBLE_QUERY_CACHE ;
207
208
}
208
209
209
- protected TruffleString .CodeRange getCodeRange (AbstractTruffleString string , RubyEncoding encoding ) {
210
- return getCodeRangeNode ().execute (string , encoding .tencoding );
211
- }
212
-
213
- private TruffleString .GetByteCodeRangeNode getCodeRangeNode () {
214
- if (codeRangeNode == null ) {
215
- CompilerDirectives .transferToInterpreterAndInvalidate ();
216
- codeRangeNode = insert (TruffleString .GetByteCodeRangeNode .create ());
217
- }
218
-
219
- return codeRangeNode ;
220
- }
221
-
222
210
protected static final int NUMBER_OF_STANDARD_ENCODINGS = 3 ;
223
211
224
212
/** Indicates whether the encoding is one of the runtime-default encodings. Many (most?) applications do not
@@ -267,13 +255,15 @@ protected RubyEncoding negotiateSameEncodingUncached(Object first, Object second
267
255
}
268
256
269
257
@ Specialization (guards = { "libFirst.isRubyString(first)" , "libSecond.isRubyString(second)" }, limit = "1" )
270
- protected RubyEncoding negotiateStringStringEncoding (Object first , Object second ,
258
+ protected static RubyEncoding negotiateStringStringEncoding (Object first , Object second ,
271
259
@ Cached @ Shared RubyStringLibrary libFirst ,
272
260
@ Cached @ Shared RubyStringLibrary libSecond ,
273
- @ Cached NegotiateCompatibleStringEncodingNode negotiateNode ) {
261
+ @ Cached NegotiateCompatibleStringEncodingNode negotiateNode ,
262
+ @ Bind ("this" ) Node node ) {
274
263
final RubyEncoding firstEncoding = libFirst .getEncoding (first );
275
264
final RubyEncoding secondEncoding = libSecond .getEncoding (second );
276
265
return negotiateNode .execute (
266
+ node ,
277
267
libFirst .getTString (first ),
278
268
firstEncoding ,
279
269
libSecond .getTString (second ),
@@ -454,7 +444,7 @@ protected Object areCompatible(Object first, Object second,
454
444
@ Cached RubyStringLibrary libSecond ,
455
445
@ Cached NegotiateCompatibleStringEncodingNode negotiateCompatibleStringEncodingNode ,
456
446
@ Cached InlinedConditionProfile noNegotiatedEncodingProfile ) {
457
- final RubyEncoding negotiatedEncoding = negotiateCompatibleStringEncodingNode .execute (
447
+ final RubyEncoding negotiatedEncoding = negotiateCompatibleStringEncodingNode .execute (this ,
458
448
libFirst .getTString (first ), libFirst .getEncoding (first ),
459
449
libSecond .getTString (second ), libSecond .getEncoding (second ));
460
450
@@ -783,7 +773,8 @@ protected static RubyEncoding checkEncodingStringString(Object first, Object sec
783
773
final RubyEncoding secondEncoding = libSecond .getEncoding (second );
784
774
785
775
final RubyEncoding negotiatedEncoding = negotiateCompatibleStringEncodingNode
786
- .execute (libFirst .getTString (first ), firstEncoding , libSecond .getTString (second ), secondEncoding );
776
+ .execute (node , libFirst .getTString (first ), firstEncoding , libSecond .getTString (second ),
777
+ secondEncoding );
787
778
788
779
if (negotiatedEncoding == null ) {
789
780
errorProfile .enter (node );
@@ -813,7 +804,7 @@ protected static RubyEncoding checkEncoding(
813
804
RubyEncoding secondEncoding ,
814
805
@ Cached InlinedBranchProfile errorProfile ,
815
806
@ Cached NegotiateCompatibleStringEncodingNode negotiateCompatibleEncodingNode ) {
816
- var negotiatedEncoding = negotiateCompatibleEncodingNode .execute (first , firstEncoding , second ,
807
+ var negotiatedEncoding = negotiateCompatibleEncodingNode .execute (node , first , firstEncoding , second ,
817
808
secondEncoding );
818
809
819
810
if (negotiatedEncoding == null ) {
0 commit comments