aboutsummaryrefslogtreecommitdiffstats
path: root/string.c
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-04-30 15:39:02 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-04-30 15:39:02 +0000
commitc24912aa0f7d618307a431e53fd1f551497307f1 (patch)
treeda5b3754ad1910426086dc4a7f4dd7cca7b65b92 /string.c
parent9689b1cd75b453b7342a2160e364f667cb41158a (diff)
downloadruby-c24912aa0f7d618307a431e53fd1f551497307f1.tar.gz
* string.c (search_nonascii): unroll and use ntz
* configure.in (__builtin_ctz): check. * configure.in (__builtin_ctzll): check. * internal.h (rb_popcount32): defined for ntz_int32. it can use __builtin_popcount but this function is not used on GCC environment because it uses __builtin_ctz. When another function uses this, using __builtin_popcount should be re-considered. * internal.h (rb_popcount64): ditto. * internal.h (ntz_int32): defined for ntz_intptr. * internal.h (ntz_int64): defined for ntz_intptr. * internal.h (ntz_intptr): defined as ntz for uintptr_t. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54854 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r--string.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/string.c b/string.c
index 4ee59b2bd9..e2cb68aac2 100644
--- a/string.c
+++ b/string.c
@@ -427,32 +427,46 @@ search_nonascii(const char *p, const char *e)
#elif SIZEOF_VOIDP == 4
# define NONASCII_MASK 0x80808080UL
#endif
-#ifdef NONASCII_MASK
- if ((int)SIZEOF_VOIDP * 2 < e - p) {
- const uintptr_t *s, *t;
- const uintptr_t lowbits = SIZEOF_VOIDP - 1;
- s = (const uintptr_t*)(~lowbits & ((uintptr_t)p + lowbits));
- while (p < (const char *)s) {
- if (!ISASCII(*p))
- return p;
- p++;
- }
- t = (const uintptr_t*)(~lowbits & (uintptr_t)e);
- while (s < t) {
- if (*s & NONASCII_MASK) {
- t = s;
- break;
- }
- s++;
- }
- p = (const char *)t;
+
+#if !UNALIGNED_WORD_ACCESS
+ if (e - p > SIZEOF_VOIDP) {
+ switch (8 - (uintptr_t)p % 8) {
+#if SIZEOF_VOIDP > 4
+ case 7: if (*p&0x80) return p; p++;
+ case 6: if (*p&0x80) return p; p++;
+ case 5: if (*p&0x80) return p; p++;
+ case 4: if (*p&0x80) return p; p++;
+#endif
+ case 3: if (*p&0x80) return p; p++;
+ case 2: if (*p&0x80) return p; p++;
+ case 1: if (*p&0x80) return p; p++;
+ }
}
#endif
- while (p < e) {
- if (!ISASCII(*p))
- return p;
- p++;
+
+ {
+ const uintptr_t *s = (const uintptr_t *)p;
+ const uintptr_t *t = (const uintptr_t *)(e - (SIZEOF_VOIDP-1));
+ for (;s < t; s++) {
+ if (*s & NONASCII_MASK) {
+ return (const char *)s + (ntz_intptr(*s&NONASCII_MASK)>>3);
+ }
+ }
+ p = (const char *)s;
}
+
+ switch ((e - p) % SIZEOF_VOIDP) {
+#if SIZEOF_VOIDP > 4
+ case 7: if (*p&0x80) return p; p++;
+ case 6: if (*p&0x80) return p; p++;
+ case 5: if (*p&0x80) return p; p++;
+ case 4: if (*p&0x80) return p; p++;
+#endif
+ case 3: if (*p&0x80) return p; p++;
+ case 2: if (*p&0x80) return p; p++;
+ case 1: if (*p&0x80) return p;
+ }
+
return NULL;
}