mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
(Fixed assert) Bug 551539 - use memcmp for inner loop of StringMatch, sometimes (r=bzbarsky)
This commit is contained in:
parent
b7b64d646f
commit
66fa96ff71
117
js/src/jsstr.cpp
117
js/src/jsstr.cpp
@ -1095,6 +1095,71 @@ js_BoyerMooreHorspool(const jschar *text, jsuint textlen,
|
||||
return -1;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct MemCmp {
|
||||
typedef jsuint Extent;
|
||||
static JS_ALWAYS_INLINE Extent computeExtent(const jschar *, jsuint patlen) {
|
||||
return (patlen - 1) * sizeof(jschar);
|
||||
}
|
||||
static JS_ALWAYS_INLINE bool match(const jschar *p, const jschar *t, Extent extent) {
|
||||
return memcmp(p, t, extent) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct ManualCmp {
|
||||
typedef const jschar *Extent;
|
||||
static JS_ALWAYS_INLINE Extent computeExtent(const jschar *pat, jsuint patlen) {
|
||||
return pat + patlen;
|
||||
}
|
||||
static JS_ALWAYS_INLINE bool match(const jschar *p, const jschar *t, Extent extent) {
|
||||
for (; p != extent; ++p, ++t) {
|
||||
if (*p != *t)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class InnerMatch>
|
||||
static jsint
|
||||
Duff(const jschar *text, jsuint textlen, const jschar *pat, jsuint patlen)
|
||||
{
|
||||
JS_ASSERT(patlen > 0 && textlen > 0);
|
||||
const jschar *textend = text + textlen - (patlen - 1);
|
||||
const jschar p0 = *pat;
|
||||
const jschar *const patNext = pat + 1;
|
||||
const typename InnerMatch::Extent extent = InnerMatch::computeExtent(pat, patlen);
|
||||
uint8 fixup;
|
||||
|
||||
const jschar *t = text;
|
||||
switch ((textend - t) & 7) {
|
||||
do {
|
||||
case 0: if (*t++ == p0) { fixup = 8; goto match; }
|
||||
case 7: if (*t++ == p0) { fixup = 7; goto match; }
|
||||
case 6: if (*t++ == p0) { fixup = 6; goto match; }
|
||||
case 5: if (*t++ == p0) { fixup = 5; goto match; }
|
||||
case 4: if (*t++ == p0) { fixup = 4; goto match; }
|
||||
case 3: if (*t++ == p0) { fixup = 3; goto match; }
|
||||
case 2: if (*t++ == p0) { fixup = 2; goto match; }
|
||||
case 1: if (*t++ == p0) { fixup = 1; goto match; }
|
||||
continue;
|
||||
do {
|
||||
if (*t++ == p0) {
|
||||
match:
|
||||
if (!InnerMatch::match(patNext, t, extent))
|
||||
goto failed_match;
|
||||
return t - text - 1;
|
||||
}
|
||||
failed_match:;
|
||||
} while (--fixup > 0);
|
||||
} while(t != textend);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsint
|
||||
StringMatch(const jschar *text, jsuint textlen,
|
||||
const jschar *pat, jsuint patlen)
|
||||
@ -1104,7 +1169,7 @@ StringMatch(const jschar *text, jsuint textlen,
|
||||
if (textlen < patlen)
|
||||
return -1;
|
||||
|
||||
#if __i386__
|
||||
#if defined(__i386__) || defined(_M_IX86)
|
||||
/*
|
||||
* Given enough registers, the unrolled loop below is faster than the
|
||||
* following loop. 32-bit x86 does not have enough registers.
|
||||
@ -1138,50 +1203,18 @@ StringMatch(const jschar *text, jsuint textlen,
|
||||
return index;
|
||||
}
|
||||
|
||||
const jschar *textend = text + textlen - (patlen - 1);
|
||||
const jschar *patend = pat + patlen;
|
||||
const jschar p0 = *pat;
|
||||
const jschar *patNext = pat + 1;
|
||||
uint8 fixup;
|
||||
|
||||
#if __APPLE__ && __GNUC__ && __i386__
|
||||
/*
|
||||
* It is critical that |t| is kept in a register. The version of gcc we use
|
||||
* to build on 32-bit Mac does not realize this. See bug 526173.
|
||||
* For big patterns with large potential overlap we want the SIMD-optimized
|
||||
* speed of memcmp. For small patterns, a simple loop is faster.
|
||||
*
|
||||
* FIXME: Linux memcmp performance is sad and the manual loop is faster.
|
||||
*/
|
||||
register const jschar *t asm("esi") = text;
|
||||
#else
|
||||
const jschar *t = text;
|
||||
return
|
||||
#if !defined(__linux__)
|
||||
patlen > 128 ? Duff<MemCmp>(text, textlen, pat, patlen)
|
||||
:
|
||||
#endif
|
||||
|
||||
/* Credit: Duff */
|
||||
switch ((textend - text) & 7) {
|
||||
do {
|
||||
case 0: if (*t++ == p0) { fixup = 8; goto match; }
|
||||
case 7: if (*t++ == p0) { fixup = 7; goto match; }
|
||||
case 6: if (*t++ == p0) { fixup = 6; goto match; }
|
||||
case 5: if (*t++ == p0) { fixup = 5; goto match; }
|
||||
case 4: if (*t++ == p0) { fixup = 4; goto match; }
|
||||
case 3: if (*t++ == p0) { fixup = 3; goto match; }
|
||||
case 2: if (*t++ == p0) { fixup = 2; goto match; }
|
||||
case 1: if (*t++ == p0) { fixup = 1; goto match; }
|
||||
continue;
|
||||
do {
|
||||
if (*t++ == p0) {
|
||||
match:
|
||||
for (const jschar *p1 = patNext, *t1 = t;
|
||||
p1 != patend;
|
||||
++p1, ++t1) {
|
||||
if (*p1 != *t1)
|
||||
goto failed_match;
|
||||
}
|
||||
return t - text - 1;
|
||||
}
|
||||
failed_match:;
|
||||
} while (--fixup > 0);
|
||||
} while(t != textend);
|
||||
}
|
||||
return -1;
|
||||
Duff<ManualCmp>(text, textlen, pat, patlen);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
Loading…
Reference in New Issue
Block a user