71
71
import static org .truffleruby .core .string .StringSupport .MBCLEN_INVALID_P ;
72
72
import static org .truffleruby .core .string .StringSupport .MBCLEN_NEEDMORE_P ;
73
73
74
+ import com .oracle .truffle .api .TruffleSafepoint ;
74
75
import com .oracle .truffle .api .dsl .Bind ;
75
76
import com .oracle .truffle .api .dsl .Cached .Exclusive ;
76
77
import com .oracle .truffle .api .dsl .Cached .Shared ;
77
78
import com .oracle .truffle .api .dsl .GenerateNodeFactory ;
79
+ import com .oracle .truffle .api .profiles .LoopConditionProfile ;
78
80
import com .oracle .truffle .api .strings .AbstractTruffleString ;
79
81
import com .oracle .truffle .api .strings .InternalByteArray ;
80
82
import com .oracle .truffle .api .strings .MutableTruffleString ;
@@ -3138,9 +3140,10 @@ public abstract static class StringAwkSplitPrimitiveNode extends PrimitiveArrayA
3138
3140
@ Child GetByteCodeRangeNode codeRangeNode = GetByteCodeRangeNode .create ();
3139
3141
3140
3142
private static final int SUBSTRING_CREATED = -1 ;
3143
+ private static final int DEFAULT_SPLIT_VALUES_SIZE = 10 ;
3141
3144
3142
3145
@ Specialization (guards = "is7Bit(tstring, encoding, codeRangeNode)" )
3143
- protected Object stringAwkSplitSingleByte (Object string , int limit , Object block ,
3146
+ protected Object stringAwkSplitAsciiOnly (Object string , int limit , Object block ,
3144
3147
@ Cached RubyStringLibrary strings ,
3145
3148
@ Cached ConditionProfile executeBlockProfile ,
3146
3149
@ Cached ConditionProfile growArrayProfile ,
@@ -3149,42 +3152,52 @@ protected Object stringAwkSplitSingleByte(Object string, int limit, Object block
3149
3152
@ Cached TruffleString .MaterializeNode materializeNode ,
3150
3153
@ Cached TruffleString .ReadByteNode readByteNode ,
3151
3154
@ Cached TruffleString .SubstringByteIndexNode substringNode ,
3155
+ @ Cached LoopConditionProfile loopProfile ,
3152
3156
@ Bind ("strings.getTString(string)" ) AbstractTruffleString tstring ,
3153
3157
@ Bind ("strings.getEncoding(string)" ) RubyEncoding encoding ) {
3154
- Object [] ret = new Object [10 ];
3158
+ int retSize = limit > 0 && limit < DEFAULT_SPLIT_VALUES_SIZE ? limit : DEFAULT_SPLIT_VALUES_SIZE ;
3159
+ Object [] ret = new Object [retSize ];
3155
3160
int storeIndex = 0 ;
3156
3161
3157
3162
int byteLength = tstring .byteLength (encoding .tencoding );
3158
3163
materializeNode .execute (tstring , encoding .tencoding );
3159
3164
3160
3165
int substringStart = 0 ;
3161
3166
boolean findingSubstringEnd = false ;
3162
- for (int i = 0 ; i < byteLength ; i ++) {
3163
- if (StringSupport .isAsciiSpace (readByteNode .execute (tstring , i , encoding .tencoding ))) {
3164
- if (findingSubstringEnd ) {
3165
- findingSubstringEnd = false ;
3166
-
3167
- final RubyString substring = createSubString (substringNode , tstring , encoding , substringStart ,
3168
- i - substringStart );
3169
- ret = addSubstring (
3170
- ret ,
3171
- storeIndex ++,
3172
- substring ,
3173
- block ,
3174
- executeBlockProfile ,
3175
- growArrayProfile );
3176
- substringStart = SUBSTRING_CREATED ;
3177
- }
3178
- } else {
3179
- if (!findingSubstringEnd ) {
3180
- substringStart = i ;
3181
- findingSubstringEnd = true ;
3182
3167
3183
- if (storeIndex == limit - 1 ) {
3184
- break ;
3168
+ int i = 0 ;
3169
+ try {
3170
+ for (; loopProfile .inject (i < byteLength ); i ++) {
3171
+ if (StringSupport .isAsciiSpace (readByteNode .execute (tstring , i , encoding .tencoding ))) {
3172
+ if (findingSubstringEnd ) {
3173
+ findingSubstringEnd = false ;
3174
+
3175
+ final RubyString substring = createSubString (substringNode , tstring , encoding ,
3176
+ substringStart , i - substringStart );
3177
+ ret = addSubstring (
3178
+ ret ,
3179
+ storeIndex ++,
3180
+ substring ,
3181
+ block ,
3182
+ executeBlockProfile ,
3183
+ growArrayProfile );
3184
+ substringStart = SUBSTRING_CREATED ;
3185
+ }
3186
+ } else {
3187
+ if (!findingSubstringEnd ) {
3188
+ substringStart = i ;
3189
+ findingSubstringEnd = true ;
3190
+
3191
+ if (storeIndex == limit - 1 ) {
3192
+ break ;
3193
+ }
3185
3194
}
3186
3195
}
3196
+
3197
+ TruffleSafepoint .poll (this );
3187
3198
}
3199
+ } finally {
3200
+ profileAndReportLoopCount (loopProfile , i );
3188
3201
}
3189
3202
3190
3203
if (trailingSubstringProfile .profile (findingSubstringEnd )) {
@@ -3193,7 +3206,7 @@ protected Object stringAwkSplitSingleByte(Object string, int limit, Object block
3193
3206
ret = addSubstring (ret , storeIndex ++, substring , block , executeBlockProfile , growArrayProfile );
3194
3207
}
3195
3208
3196
- if (trailingEmptyStringProfile .profile (limit < 0 &&
3209
+ if (trailingEmptyStringProfile .profile (( limit < 0 || storeIndex < limit ) &&
3197
3210
StringSupport .isAsciiSpace (readByteNode .execute (tstring , byteLength - 1 , encoding .tencoding )))) {
3198
3211
final RubyString substring = createSubString (substringNode , tstring , encoding , byteLength - 1 , 0 );
3199
3212
ret = addSubstring (ret , storeIndex ++, substring , block , executeBlockProfile , growArrayProfile );
@@ -3215,9 +3228,11 @@ protected Object stringAwkSplit(Object string, int limit, Object block,
3215
3228
@ Cached CreateCodePointIteratorNode createCodePointIteratorNode ,
3216
3229
@ Cached TruffleStringIterator .NextNode nextNode ,
3217
3230
@ Cached TruffleString .SubstringByteIndexNode substringNode ,
3231
+ @ Cached LoopConditionProfile loopProfile ,
3218
3232
@ Bind ("strings.getTString(string)" ) AbstractTruffleString tstring ,
3219
3233
@ Bind ("strings.getEncoding(string)" ) RubyEncoding encoding ) {
3220
- Object [] ret = new Object [10 ];
3234
+ int retSize = limit > 0 && limit < DEFAULT_SPLIT_VALUES_SIZE ? limit : DEFAULT_SPLIT_VALUES_SIZE ;
3235
+ Object [] ret = new Object [retSize ];
3221
3236
int storeIndex = 0 ;
3222
3237
3223
3238
final boolean limitPositive = limit > 0 ;
@@ -3229,40 +3244,45 @@ protected Object stringAwkSplit(Object string, int limit, Object block,
3229
3244
var iterator = createCodePointIteratorNode .execute (tstring , tencoding , ErrorHandling .RETURN_NEGATIVE );
3230
3245
3231
3246
boolean skip = true ;
3232
- int e = 0 , b = 0 ;
3233
- while (iterator .hasNext ()) {
3234
- int c = nextNode .execute (iterator );
3235
- int p = iterator .getByteIndex ();
3236
-
3237
- if (skip ) {
3238
- if (StringSupport .isAsciiSpace (c )) {
3239
- b = p ;
3240
- } else {
3241
- e = p ;
3242
- skip = false ;
3243
- if (limitPositive && limit <= i ) {
3244
- break ;
3245
- }
3246
- }
3247
- } else {
3248
- if (StringSupport .isAsciiSpace (c )) {
3249
- var substring = createSubString (substringNode , tstring , encoding , b , e - b );
3250
- ret = addSubstring (
3251
- ret ,
3252
- storeIndex ++,
3253
- substring ,
3254
- block ,
3255
- executeBlockProfile ,
3256
- growArrayProfile );
3257
- skip = true ;
3258
- b = p ;
3259
- if (limitPositive ) {
3260
- i ++;
3247
+ int e = 0 , b = 0 , iterations = 0 ;
3248
+ try {
3249
+ while (loopProfile .inject (iterator .hasNext ())) {
3250
+ int c = nextNode .execute (iterator );
3251
+ int p = iterator .getByteIndex ();
3252
+ iterations ++;
3253
+
3254
+ if (skip ) {
3255
+ if (StringSupport .isAsciiSpace (c )) {
3256
+ b = p ;
3257
+ } else {
3258
+ e = p ;
3259
+ skip = false ;
3260
+ if (limitPositive && limit <= i ) {
3261
+ break ;
3262
+ }
3261
3263
}
3262
3264
} else {
3263
- e = p ;
3265
+ if (StringSupport .isAsciiSpace (c )) {
3266
+ var substring = createSubString (substringNode , tstring , encoding , b , e - b );
3267
+ ret = addSubstring (
3268
+ ret ,
3269
+ storeIndex ++,
3270
+ substring ,
3271
+ block ,
3272
+ executeBlockProfile ,
3273
+ growArrayProfile );
3274
+ skip = true ;
3275
+ b = p ;
3276
+ if (limitPositive ) {
3277
+ i ++;
3278
+ }
3279
+ } else {
3280
+ e = p ;
3281
+ }
3264
3282
}
3265
3283
}
3284
+ } finally {
3285
+ profileAndReportLoopCount (loopProfile , iterations );
3266
3286
}
3267
3287
3268
3288
if (trailingSubstringProfile .profile (len > 0 && (limitPositive || len > b || limit < 0 ))) {
0 commit comments