@@ -561,110 +561,19 @@ public StringRuneEnumerator EnumerateRunes()
561561 return new StringRuneEnumerator ( this ) ;
562562 }
563563
564+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
564565 internal static unsafe int wcslen ( char * ptr )
565566 {
566- char * end = ptr ;
567-
568- // First make sure our pointer is aligned on a word boundary
569- int alignment = IntPtr . Size - 1 ;
570-
571- // If ptr is at an odd address (e.g. 0x5), this loop will simply iterate all the way
572- while ( ( ( uint ) end & ( uint ) alignment ) != 0 )
573- {
574- if ( * end == 0 ) goto FoundZero ;
575- end ++ ;
576- }
577-
578- #if ! BIT64
579- // The following code is (somewhat surprisingly!) significantly faster than a naive loop,
580- // at least on x86 and the current jit.
581-
582- // The loop condition below works because if "end[0] & end[1]" is non-zero, that means
583- // neither operand can have been zero. If is zero, we have to look at the operands individually,
584- // but we hope this going to fairly rare.
585-
586- // In general, it would be incorrect to access end[1] if we haven't made sure
587- // end[0] is non-zero. However, we know the ptr has been aligned by the loop above
588- // so end[0] and end[1] must be in the same word (and therefore page), so they're either both accessible, or both not.
589-
590- while ( ( end [ 0 ] & end [ 1 ] ) != 0 || ( end [ 0 ] != 0 && end [ 1 ] != 0 ) )
591- {
592- end += 2 ;
593- }
594-
595- Debug . Assert ( end [ 0 ] == 0 || end [ 1 ] == 0 ) ;
596- if ( end [ 0 ] != 0 ) end ++ ;
597- #else // !BIT64
598- // Based on https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
599-
600- // 64-bit implementation: process 1 ulong (word) at a time
601-
602- // What we do here is add 0x7fff from each of the
603- // 4 individual chars within the ulong, using MagicMask.
604- // If the char > 0 and < 0x8001, it will have its high bit set.
605- // We then OR with MagicMask, to set all the other bits.
606- // This will result in all bits set (ulong.MaxValue) for any
607- // char that fits the above criteria, and something else otherwise.
608-
609- // Note that for any char > 0x8000, this will be a false
610- // positive and we will fallback to the slow path and
611- // check each char individually. This is OK though, since
612- // we optimize for the common case (ASCII chars, which are < 0x80).
613-
614- // NOTE: We can access a ulong a time since the ptr is aligned,
615- // and therefore we're only accessing the same word/page. (See notes
616- // for the 32-bit version above.)
617-
618- const ulong MagicMask = 0x7fff7fff7fff7fff ;
619-
620- while ( true )
567+ // IndexOf processes memory in aligned chunks, and thus it won't crash even if it accesses memory beyond the null terminator.
568+ int length = SpanHelpers . IndexOf ( ref * ptr , '\0 ' , int . MaxValue ) ;
569+ if ( length < 0 )
621570 {
622- ulong word = * ( ulong * ) end ;
623- word += MagicMask ; // cause high bit to be set if not zero, and <= 0x8000
624- word |= MagicMask ; // set everything besides the high bits
625-
626- if ( word == ulong . MaxValue ) // 0xffff...
627- {
628- // all of the chars have their bits set (and therefore none can be 0)
629- end += 4 ;
630- continue ;
631- }
632-
633- // at least one of them didn't have their high bit set!
634- // go through each char and check for 0.
635-
636- if ( end [ 0 ] == 0 ) goto EndAt0 ;
637- if ( end [ 1 ] == 0 ) goto EndAt1 ;
638- if ( end [ 2 ] == 0 ) goto EndAt2 ;
639- if ( end [ 3 ] == 0 ) goto EndAt3 ;
640-
641- // if we reached here, it was a false positive-- just continue
642- end += 4 ;
571+ ThrowMustBeNullTerminatedString ( ) ;
643572 }
644573
645- EndAt3 : end ++ ;
646- EndAt2 : end ++ ;
647- EndAt1 : end ++ ;
648- EndAt0 :
649- #endif // !BIT64
650-
651- FoundZero :
652- Debug . Assert ( * end == 0 ) ;
653-
654- int count = ( int ) ( end - ptr ) ;
655-
656- #if BIT64
657- // Check for overflow
658- if ( ptr + count != end )
659- throw new ArgumentException ( SR . Arg_MustBeNullTerminatedString ) ;
660- #else
661- Debug . Assert ( ptr + count == end ) ;
662- #endif
663-
664- return count ;
574+ return length ;
665575 }
666576
667-
668577 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
669578 internal static unsafe int strlen ( byte * ptr )
670579 {
0 commit comments