949 REGISTER unsigned byteValue; |
949 REGISTER unsigned byteValue; |
950 int last; |
950 int last; |
951 OBJ cls; |
951 OBJ cls; |
952 |
952 |
953 if (__isSmallInteger(start)) { |
953 if (__isSmallInteger(start)) { |
954 index = __intVal(start); |
954 index = __intVal(start); |
955 if (index > 0) { |
955 if (index > 0) { |
956 if (__isCharacter(aCharacter)) { |
956 if (__isCharacter(aCharacter)) { |
957 byteValue = __intVal(__characterVal(aCharacter)); |
957 byteValue = __intVal(__characterVal(aCharacter)); |
958 if (byteValue <= 0xFF) { |
958 if (byteValue <= 0xFF) { |
959 last = __stringSize(self); |
959 last = __stringSize(self); |
960 cp = __stringVal(self); |
960 cp = __stringVal(self); |
961 if ((cls = __qClass(self)) != String) { |
961 if ((cls = __qClass(self)) != String) { |
962 int numInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars)); |
962 int numInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars)); |
963 |
963 |
964 cp += numInstBytes; |
964 cp += numInstBytes; |
965 last -= numInstBytes; |
965 last -= numInstBytes; |
966 } |
966 } |
967 if (index <= last) { |
967 if (index <= last) { |
968 # ifdef FAST_MEMCHR |
968 # ifdef FAST_MEMCHR |
969 ncp = (unsigned char *) memchr(cp+index-1, byteValue, last+1-index); |
969 ncp = (unsigned char *) memchr(cp+index-1, byteValue, last+1-index); |
970 if (ncp) { |
970 if (ncp) { |
971 RETURN ( __mkSmallInteger(ncp - cp + 1) ); |
971 RETURN ( __mkSmallInteger(ncp - cp + 1) ); |
972 } |
972 } |
973 # else |
973 # else |
974 # ifdef __UNROLL_LOOPS__ |
974 # ifdef __UNROLL_LOOPS__ |
975 { |
975 { |
976 int last3 = last-3; |
976 int last3 = last-3; |
977 |
977 |
978 for (; index <= last3; index += 4) { |
978 for (; index <= last3; index += 4) { |
979 if (cp[index-1] == byteValue) { RETURN ( __mkSmallInteger(index) ); } |
979 if (cp[index-1] == byteValue) { RETURN ( __mkSmallInteger(index) ); } |
980 if (cp[index-1+1] == byteValue) { RETURN ( __mkSmallInteger(index+1) ); } |
980 if (cp[index-1+1] == byteValue) { RETURN ( __mkSmallInteger(index+1) ); } |
981 if (cp[index-1+2] == byteValue) { RETURN ( __mkSmallInteger(index+2) ); } |
981 if (cp[index-1+2] == byteValue) { RETURN ( __mkSmallInteger(index+2) ); } |
982 if (cp[index-1+3] == byteValue) { RETURN ( __mkSmallInteger(index+3) ); } |
982 if (cp[index-1+3] == byteValue) { RETURN ( __mkSmallInteger(index+3) ); } |
983 } |
983 } |
984 } |
984 } |
985 # endif |
985 # endif |
986 # ifdef V1 |
986 # ifdef V1 |
987 for (; index <= last; index++) { |
987 for (; index <= last; index++) { |
988 if (cp[index-1] == byteValue) { |
988 if (cp[index-1] == byteValue) { |
989 RETURN ( __mkSmallInteger(index) ); |
989 RETURN ( __mkSmallInteger(index) ); |
990 } |
990 } |
991 } |
991 } |
992 # endif |
992 # endif |
993 # ifdef V2 |
993 # ifdef V2 |
994 { |
994 { |
995 // see bit twiddling hacks |
995 // see bit twiddling hacks |
996 # define hasZeroByte(v) (((v) - 0x01010101UL) & ~(v) & 0x80808080UL) |
996 # define hasZeroByte(v) (((v) - 0x01010101UL) & ~(v) & 0x80808080UL) |
997 # define hasByteM(v,m) hasZeroByte( (v) ^ m) |
997 # define hasByteM(v,m) hasZeroByte( (v) ^ m) |
998 |
998 # if __POINTER_SIZE__ == 8 |
999 // the following loop checks four bytes at once |
999 # define hasZeroByte8(v) (((v) - 0x0101010101010101ULL) & ~(v) & 0x8080808080808080ULL) |
1000 if (((index-1) & 0x3) == 0) { |
1000 # define hasByteM8(v,m) hasZeroByte8( (v) ^ m) |
1001 int last4 = last-4; |
1001 // the following loop checks eight bytes at once |
1002 int m = (~0UL/255 * (byteValue)); |
1002 if (((index-1) & 0x7) == 0) { |
1003 |
1003 int last8 = last-8; |
1004 while (index <= last4) { |
1004 INT m = (~0UL/255 * (byteValue)); |
1005 unsigned int v = *(unsigned int *)(cp+index-1); |
1005 |
1006 |
1006 while (index <= last8) { |
1007 if (hasByteM(v,m)) break; |
1007 unsigned INT v = *(unsigned INT *)(cp+index-1); |
1008 index += 4; |
1008 |
1009 } |
1009 if (hasByteM8(v,m)) break; |
1010 } |
1010 index += 8; |
1011 while (index <= last) { |
1011 } |
1012 if (cp[index-1] == byteValue) { |
1012 } |
1013 RETURN ( __mkSmallInteger(index) ); |
1013 # endif |
1014 } |
1014 // the following loop checks four bytes at once |
1015 index++; |
1015 if (((index-1) & 0x3) == 0) { |
1016 } |
1016 int last4 = last-4; |
1017 } |
1017 int m = (~0UL/255 * (byteValue)); |
|
1018 |
|
1019 while (index <= last4) { |
|
1020 unsigned int v = *(unsigned int *)(cp+index-1); |
|
1021 |
|
1022 if (hasByteM(v,m)) break; |
|
1023 index += 4; |
|
1024 } |
|
1025 } |
|
1026 while (index <= last) { |
|
1027 if (cp[index-1] == byteValue) { |
|
1028 RETURN ( __mkSmallInteger(index) ); |
|
1029 } |
|
1030 index++; |
|
1031 } |
|
1032 } |
1018 # endif |
1033 # endif |
1019 # endif |
1034 # endif |
1020 } |
1035 } |
1021 } |
1036 } |
1022 } |
1037 } |
1023 RETURN ( __mkSmallInteger(0) ); |
1038 RETURN ( __mkSmallInteger(0) ); |
1024 } |
1039 } |
1025 } |
1040 } |
1026 # undef V2 |
1041 # undef V2 |
1027 #endif /* not SCHTEAM */ |
1042 #endif /* not SCHTEAM */ |
1028 %}. |
1043 %}. |
1029 ^ super indexOf:aCharacter startingAt:start |
1044 ^ super indexOf:aCharacter startingAt:start |