@@ -4399,48 +4399,94 @@ protected int notValidUtf8(Object string, int byteIndex,
4399
4399
}
4400
4400
4401
4401
@ Primitive (name = "string_character_index" , lowerFixnum = 2 )
4402
- public abstract static class StringCharacterIndexPrimitiveNode extends PrimitiveArrayArgumentsNode {
4402
+ @ NodeChild (value = "string" , type = RubyNode .class )
4403
+ @ NodeChild (value = "pattern" , type = RubyNode .class )
4404
+ @ NodeChild (value = "offset" , type = RubyNode .class )
4405
+ public abstract static class StringCharacterIndexPrimitiveNode extends PrimitiveNode {
4403
4406
4404
- @ TruffleBoundary
4405
- @ Specialization
4406
- protected Object stringCharacterIndex (Object string , Object pattern , int offset ,
4407
- @ CachedLibrary (limit = "2" ) RubyStringLibrary stringLibrary ,
4408
- @ CachedLibrary (limit = "2" ) RubyStringLibrary patternLibrary ,
4409
- @ Cached RopeNodes .CalculateCharacterLengthNode calculateCharacterLengthNode ) {
4410
- if (offset < 0 ) {
4411
- return nil ;
4412
- }
4407
+ @ Child SingleByteOptimizableNode singleByteOptimizableNode = SingleByteOptimizableNode .create ();
4413
4408
4414
- final Rope stringRope = stringLibrary .getRope (string );
4415
- final Rope patternRope = patternLibrary .getRope (pattern );
4409
+ @ CreateCast ("string" )
4410
+ protected RubyNode coerceStringToRope (RubyNode string ) {
4411
+ return ToRopeNodeGen .create (string );
4412
+ }
4416
4413
4417
- final int total = stringRope .byteLength ();
4418
- int p = 0 ;
4419
- final int e = p + total ;
4414
+ @ CreateCast ("pattern" )
4415
+ protected RubyNode coercePatternToRope (RubyNode pattern ) {
4416
+ return ToRopeNodeGen .create (pattern );
4417
+ }
4418
+
4419
+ @ Specialization (guards = "offset < 0" )
4420
+ protected Object stringCharacterIndexNegativeOffset (Rope stringRope , Rope patternRope , int offset ) {
4421
+ return nil ;
4422
+ }
4423
+
4424
+ @ Specialization (
4425
+ guards = {
4426
+ "offset >= 0" ,
4427
+ "singleByteOptimizableNode.execute(stringRope)" ,
4428
+ "patternRope.byteLength() > stringRope.byteLength()" })
4429
+ protected Object stringCharacterIndexPatternTooLarge (Rope stringRope , Rope patternRope , int offset ) {
4430
+ return nil ;
4431
+ }
4432
+
4433
+ @ Specialization (
4434
+ guards = {
4435
+ "offset >= 0" ,
4436
+ "singleByteOptimizableNode.execute(stringRope)" ,
4437
+ "patternRope.byteLength() <= stringRope.byteLength()" })
4438
+ protected Object stringCharacterIndexSingleByteOptimizable (Rope stringRope , Rope patternRope , int offset ,
4439
+ @ Cached RopeNodes .BytesNode stringBytesNode ,
4440
+ @ Cached RopeNodes .BytesNode patternBytesNode ,
4441
+ @ Cached LoopConditionProfile loopProfile ,
4442
+ @ Cached ("createCountingProfile()" ) ConditionProfile matchProfile ) {
4443
+
4444
+ int p = offset ;
4445
+ final int e = stringRope .byteLength ();
4420
4446
final int pe = patternRope .byteLength ();
4421
4447
final int l = e - pe + 1 ;
4422
4448
4423
- final byte [] stringBytes = stringRope . getBytes ( );
4424
- final byte [] patternBytes = patternRope . getBytes ( );
4449
+ final byte [] stringBytes = stringBytesNode . execute ( stringRope );
4450
+ final byte [] patternBytes = patternBytesNode . execute ( patternRope );
4425
4451
4426
- if ( stringRope . isSingleByteOptimizable ()) {
4427
- for (p += offset ; p < l ; p ++) {
4428
- if (ArrayUtils .memcmp (stringBytes , p , patternBytes , 0 , pe ) == 0 ) {
4452
+ try {
4453
+ for (; loopProfile . profile ( p < l ) ; p ++) {
4454
+ if (matchProfile . profile ( ArrayUtils .memcmp (stringBytes , p , patternBytes , 0 , pe ) == 0 ) ) {
4429
4455
return p ;
4430
4456
}
4431
4457
}
4432
-
4433
- return nil ;
4458
+ } finally {
4459
+ LoopNode . reportLoopCount ( this , p - offset ) ;
4434
4460
}
4435
4461
4462
+ return nil ;
4463
+ }
4464
+
4465
+ @ TruffleBoundary
4466
+ @ Specialization (
4467
+ guards = {
4468
+ "offset >= 0" ,
4469
+ "!singleByteOptimizableNode.execute(stringRope)" })
4470
+ protected Object stringCharacterIndex (Rope stringRope , Rope patternRope , int offset ,
4471
+ @ Cached RopeNodes .CalculateCharacterLengthNode calculateCharacterLengthNode ,
4472
+ @ Cached RopeNodes .BytesNode stringBytesNode ,
4473
+ @ Cached RopeNodes .BytesNode patternBytesNode ) {
4474
+
4475
+ int p = offset ;
4476
+ final int e = stringRope .byteLength ();
4477
+ final int pe = patternRope .byteLength ();
4478
+ final int l = e - pe + 1 ;
4479
+
4480
+ final byte [] stringBytes = stringBytesNode .execute (stringRope );
4481
+ final byte [] patternBytes = patternBytesNode .execute (patternRope );
4482
+
4436
4483
final Encoding enc = stringRope .getEncoding ();
4437
4484
final CodeRange cr = stringRope .getCodeRange ();
4438
- int index = 0 ;
4439
4485
int c = 0 ;
4486
+ int index = 0 ;
4440
4487
4441
4488
while (p < e && index < offset ) {
4442
4489
c = calculateCharacterLengthNode .characterLength (enc , cr , Bytes .fromRange (stringBytes , p , e ));
4443
-
4444
4490
if (StringSupport .MBCLEN_CHARFOUND_P (c )) {
4445
4491
p += c ;
4446
4492
index ++;
0 commit comments