diff --git a/LEGAL b/LEGAL index 24c8dc670..116a218f6 100644 --- a/LEGAL +++ b/LEGAL @@ -4,10 +4,41 @@ LEGAL NOTICE INFORMATION All the files in this distribution are covered under the MIT license (see the file LICENSE) except some files mentioned below: +- src/string.c: mrb_memsearch_ss() is based on 2 clause BSD license code by Wojciech Muła (@WojciechMula) - src/readfloat.c: public domain by Yasuhiro Matsumoto (@mattn) - src/fmt_fp.c: public domain by Dave Hylands (@dhylands) - mrbgems/mruby-dir/src/Win/dirent.c: MIT-like license by Kevlin Henney +[src/string.c] +The implementation of mrb_memsearch_ss() is taken from +https://github.com/WojciechMula/sse4-strstr.git + +Copyright (c) 2008-2016, Wojciech Muła +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + [src/readfloat.c] strtod implementation. diff --git a/src/string.c b/src/string.c index bbb6c2e15..56a48f3c1 100644 --- a/src/string.c +++ b/src/string.c @@ -263,6 +263,15 @@ mrb_gc_free_str(mrb_state *mrb, struct RString *str) mrb_free(mrb, str->as.heap.ptr); } +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \ + defined(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \ + defined(__mc68020__) +# define ALIGNED_WORD_ACCESS 0 +#else +# define ALIGNED_WORD_ACCESS 1 +#endif + #ifdef MRB_UTF8_STRING #define NOASCII(c) ((c) & 0x80) @@ -327,15 +336,6 @@ search_nonascii(const char *p, const char *e) # define NONASCII_MASK 0x80808080UL #endif -#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \ - defined(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \ - defined(__mc68020__) -# define ALIGNED_WORD_ACCESS 0 -#else -# define ALIGNED_WORD_ACCESS 1 -#endif - static const char* search_nonascii(const char *p, const char *e) { @@ -564,6 +564,70 @@ str_index_str_by_char(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos) #define str_index_str_by_char(mrb, str, sub, pos) str_index_str((mrb), (str), (sub), (pos)) #endif +/* The function is taken from https://github.com/WojciechMula/sse4-strstr.git */ +/* The original source code is under 2 clause BSD license; see LEGAL file. */ +/* The modifications: + + * port from C++ to C + * takes unsigned char* + * returns mrb_int + * alignment adjustment added +*/ +static inline mrb_int +mrb_memsearch_ss(const unsigned char *xs, long m, const unsigned char *ys, long n) +{ +/* maximum pattern length */ +#define MAX_PATLEN 100 + +#ifdef MRB_64BIT +#define bitint uint64_t +#define MASK1 0x0101010101010101llu +#define MASK2 0x7f7f7f7f7f7f7f7fllu +#define MASK3 0x8080808080808080llu +#else +#define bitint uint32_t +#define MASK1 0x01010101lu +#define MASK2 0x7f7f7f7flu +#define MASK3 0x80808080lu +#endif + +#if ALIGNED_WORD_ACCESS + if ((uintptr_t)ys % sizeof(bitint)) { + int l = sizeof(bitint) - (bitint)ys % sizeof(bitint); + const unsigned char *p = (unsigned char*)memchr(ys, *xs, l); + if (p && (p - ys) < m) { + if (memcmp(p, xs, m) == 0) return (mrb_int)(p - ys); + ys = p; + } + } +#endif + + const bitint first = MASK1 * (uint8_t)xs[0]; + const bitint last = MASK1 * (uint8_t)xs[m-1]; + + bitint *s0 = (bitint*)(ys); + bitint *s1 = (bitint*)(ys+m-1); + + for (mrb_int i=0; i < n; i+=sizeof(bitint), s0++, s1++) { + const bitint eq = (*s0 ^ first) | (*s1 ^ last); + bitint zeros = ((~eq & MASK2) + MASK1) & (~eq & MASK3); + size_t j = 0; + + while (zeros) { + if (zeros & 0x80) { + const char* substr = (char*)s0 + j + 1; + if (memcmp(substr, xs + 1, m - 2) == 0) { + return i + j; + } + } + + zeros >>= 8; + j += 1; + } + } + return -1; +} + static inline mrb_int mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n) { @@ -625,6 +689,9 @@ mrb_memsearch(const char *x0, mrb_int m, const char *y0, mrb_int n) } return -1; } + if (m <= MAX_PATLEN) { + return mrb_memsearch_ss((const unsigned char*)x0, m, (const unsigned char*)y0, n); + } return mrb_memsearch_qs((const unsigned char*)x0, m, (const unsigned char*)y0, n); }