mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 691898 - Use YARR interpreter instead of PCRE on platforms where YARR JIT is not supported. r=dmandelin
This commit is contained in:
parent
255811e424
commit
c78af1f2ba
@ -337,20 +337,21 @@ CPPSRCS += checks.cc \
|
||||
# END enclude sources for V8 dtoa
|
||||
#############################################
|
||||
|
||||
# For architectures without YARR JIT, PCRE is faster than the YARR
|
||||
# interpreter (bug 684559).
|
||||
|
||||
ifeq (,$(filter arm% sparc %86 x86_64 mips%,$(TARGET_CPU)))
|
||||
|
||||
VPATH += $(srcdir)/yarr/pcre \
|
||||
VPATH += $(srcdir)/assembler \
|
||||
$(srcdir)/assembler/wtf \
|
||||
$(srcdir)/yarr \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS += \
|
||||
pcre_compile.cpp \
|
||||
pcre_exec.cpp \
|
||||
pcre_tables.cpp \
|
||||
pcre_xclass.cpp \
|
||||
pcre_ucp_searchfuncs.cpp \
|
||||
OSAllocatorOS2.cpp \
|
||||
OSAllocatorPosix.cpp \
|
||||
OSAllocatorWin.cpp \
|
||||
PageBlock.cpp \
|
||||
YarrInterpreter.cpp \
|
||||
YarrPattern.cpp \
|
||||
YarrSyntaxChecker.cpp \
|
||||
$(NULL)
|
||||
else
|
||||
|
||||
@ -885,10 +886,10 @@ endif
|
||||
# Needed to "configure" it correctly. Unfortunately these
|
||||
# flags wind up being applied to all code in js/src, not just
|
||||
# the code in js/src/assembler.
|
||||
CXXFLAGS += -DUSE_SYSTEM_MALLOC=1 -DENABLE_ASSEMBLER=1
|
||||
CXXFLAGS += -DUSE_SYSTEM_MALLOC=1
|
||||
|
||||
ifneq (,$(ENABLE_YARR_JIT)$(ENABLE_METHODJIT))
|
||||
CXXFLAGS += -DENABLE_JIT=1
|
||||
CXXFLAGS += -DENABLE_JIT=1 -DENABLE_ASSEMBLER=1
|
||||
endif
|
||||
|
||||
INCLUDES += -I$(srcdir)/assembler -I$(srcdir)/yarr
|
||||
|
@ -702,7 +702,9 @@ JSRuntime::JSRuntime()
|
||||
ownerThread_(NULL),
|
||||
#endif
|
||||
tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
#if ENABLE_ASSEMBLER
|
||||
execAlloc_(NULL),
|
||||
#endif
|
||||
bumpAlloc_(NULL),
|
||||
nativeStackBase(0),
|
||||
nativeStackQuota(0),
|
||||
@ -864,7 +866,9 @@ JSRuntime::~JSRuntime()
|
||||
{
|
||||
JS_ASSERT(onOwnerThread());
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
delete_<JSC::ExecutableAllocator>(execAlloc_);
|
||||
#endif
|
||||
delete_<WTF::BumpPointerAllocator>(bumpAlloc_);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -105,9 +105,11 @@ JSRuntime::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal, s
|
||||
|
||||
if (regexpCode) {
|
||||
size_t method = 0, regexp = 0, unused = 0;
|
||||
#if ENABLE_ASSEMBLER
|
||||
if (execAlloc_)
|
||||
execAlloc_->sizeOfCode(&method, ®exp, &unused);
|
||||
JS_ASSERT(method == 0); /* this execAlloc is only used for regexp code */
|
||||
#endif
|
||||
*regexpCode = regexp + unused;
|
||||
}
|
||||
|
||||
@ -132,10 +134,13 @@ void
|
||||
JSRuntime::setJitHardening(bool enabled)
|
||||
{
|
||||
jitHardening = enabled;
|
||||
#if ENABLE_ASSEMBLER
|
||||
if (execAlloc_)
|
||||
execAlloc_->setRandomize(enabled);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
JSC::ExecutableAllocator *
|
||||
JSRuntime::createExecutableAllocator(JSContext *cx)
|
||||
{
|
||||
@ -149,6 +154,7 @@ JSRuntime::createExecutableAllocator(JSContext *cx)
|
||||
js_ReportOutOfMemory(cx);
|
||||
return execAlloc_;
|
||||
}
|
||||
#endif
|
||||
|
||||
WTF::BumpPointerAllocator *
|
||||
JSRuntime::createBumpPointerAllocator(JSContext *cx)
|
||||
|
@ -224,16 +224,22 @@ struct JSRuntime : js::RuntimeFriendFields
|
||||
* Both of these allocators are used for regular expression code which is shared at the
|
||||
* thread-data level.
|
||||
*/
|
||||
#if ENABLE_ASSEMBLER
|
||||
JSC::ExecutableAllocator *execAlloc_;
|
||||
#endif
|
||||
WTF::BumpPointerAllocator *bumpAlloc_;
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
JSC::ExecutableAllocator *createExecutableAllocator(JSContext *cx);
|
||||
#endif
|
||||
WTF::BumpPointerAllocator *createBumpPointerAllocator(JSContext *cx);
|
||||
|
||||
public:
|
||||
#if ENABLE_ASSEMBLER
|
||||
JSC::ExecutableAllocator *getExecutableAllocator(JSContext *cx) {
|
||||
return execAlloc_ ? execAlloc_ : createExecutableAllocator(cx);
|
||||
}
|
||||
#endif
|
||||
WTF::BumpPointerAllocator *getBumpPointerAllocator(JSContext *cx) {
|
||||
return bumpAlloc_ ? bumpAlloc_ : createBumpPointerAllocator(cx);
|
||||
}
|
||||
|
@ -318,12 +318,13 @@ typedef Handle<Value> HandleValue;
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#if ENABLE_ASSEMBLER
|
||||
namespace JSC {
|
||||
|
||||
class ExecutableAllocator;
|
||||
|
||||
} /* namespace JSC */
|
||||
|
||||
#endif
|
||||
namespace WTF {
|
||||
|
||||
class BumpPointerAllocator;
|
||||
|
@ -137,6 +137,7 @@ RegExpObject::setSticky(bool enabled)
|
||||
setSlot(STICKY_FLAG_SLOT, BooleanValue(enabled));
|
||||
}
|
||||
|
||||
#if ENABLE_YARR_JIT
|
||||
/* This function should be deleted once bad Android platforms phase out. See bug 604774. */
|
||||
inline bool
|
||||
detail::RegExpCode::isJITRuntimeEnabled(JSContext *cx)
|
||||
@ -147,6 +148,7 @@ detail::RegExpCode::isJITRuntimeEnabled(JSContext *cx)
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
inline bool
|
||||
RegExpToShared(JSContext *cx, JSObject &obj, RegExpGuard *g)
|
||||
|
@ -167,7 +167,6 @@ MatchPairs::checkAgainst(size_t inputLength)
|
||||
|
||||
/* detail::RegExpCode */
|
||||
|
||||
#if ENABLE_YARR_JIT
|
||||
void
|
||||
RegExpCode::reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error)
|
||||
{
|
||||
@ -199,46 +198,9 @@ RegExpCode::reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error)
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !ENABLE_YARR_JIT */
|
||||
|
||||
void
|
||||
RegExpCode::reportPCREError(JSContext *cx, int error)
|
||||
{
|
||||
#define REPORT(msg_) \
|
||||
JS_ReportErrorFlagsAndNumberUC(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL, msg_); \
|
||||
return
|
||||
switch (error) {
|
||||
case -2: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
case 0: JS_NOT_REACHED("Precondition violation: an error must have occurred.");
|
||||
case 1: REPORT(JSMSG_TRAILING_SLASH);
|
||||
case 2: REPORT(JSMSG_TRAILING_SLASH);
|
||||
case 3: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
case 4: REPORT(JSMSG_BAD_QUANTIFIER);
|
||||
case 5: REPORT(JSMSG_BAD_QUANTIFIER);
|
||||
case 6: REPORT(JSMSG_BAD_CLASS_RANGE);
|
||||
case 7: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
case 8: REPORT(JSMSG_BAD_CLASS_RANGE);
|
||||
case 9: REPORT(JSMSG_BAD_QUANTIFIER);
|
||||
case 10: REPORT(JSMSG_UNMATCHED_RIGHT_PAREN);
|
||||
case 11: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
case 12: REPORT(JSMSG_UNMATCHED_RIGHT_PAREN);
|
||||
case 13: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
case 14: REPORT(JSMSG_MISSING_PAREN);
|
||||
case 15: REPORT(JSMSG_BAD_BACKREF);
|
||||
case 16: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
case 17: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
|
||||
default:
|
||||
JS_NOT_REACHED("Precondition violation: unknown PCRE error code.");
|
||||
}
|
||||
#undef REPORT
|
||||
}
|
||||
|
||||
#endif /* ENABLE_YARR_JIT */
|
||||
|
||||
bool
|
||||
RegExpCode::compile(JSContext *cx, JSLinearString &pattern, unsigned *parenCount, RegExpFlag flags)
|
||||
{
|
||||
#if ENABLE_YARR_JIT
|
||||
/* Parse the pattern. */
|
||||
ErrorCode yarrError;
|
||||
YarrPattern yarrPattern(pattern, bool(flags & IgnoreCaseFlag), bool(flags & MultilineFlag),
|
||||
@ -255,7 +217,7 @@ RegExpCode::compile(JSContext *cx, JSLinearString &pattern, unsigned *parenCount
|
||||
* case we have to bytecode compile it.
|
||||
*/
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
#if ENABLE_YARR_JIT && defined(JS_METHODJIT)
|
||||
if (isJITRuntimeEnabled(cx) && !yarrPattern.m_containsBackreferences) {
|
||||
JSC::ExecutableAllocator *execAlloc = cx->runtime->getExecutableAllocator(cx);
|
||||
if (!execAlloc) {
|
||||
@ -276,21 +238,11 @@ RegExpCode::compile(JSContext *cx, JSLinearString &pattern, unsigned *parenCount
|
||||
return false;
|
||||
}
|
||||
|
||||
#if ENABLE_YARR_JIT
|
||||
codeBlock.setFallBack(true);
|
||||
#endif
|
||||
byteCode = byteCompile(yarrPattern, bumpAlloc).get();
|
||||
return true;
|
||||
#else /* !defined(ENABLE_YARR_JIT) */
|
||||
int error = 0;
|
||||
compiled = jsRegExpCompile(pattern.chars(), pattern.length(),
|
||||
ignoreCase() ? JSRegExpIgnoreCase : JSRegExpDoNotIgnoreCase,
|
||||
multiline() ? JSRegExpMultiline : JSRegExpSingleLine,
|
||||
parenCount, &error);
|
||||
if (error) {
|
||||
reportPCREError(cx, error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
RegExpRunStatus
|
||||
@ -305,19 +257,12 @@ RegExpCode::execute(JSContext *cx, const jschar *chars, size_t length, size_t st
|
||||
else
|
||||
result = JSC::Yarr::execute(codeBlock, chars, start, length, output);
|
||||
#else
|
||||
result = jsRegExpExecute(cx, compiled, chars, length, start, output, outputCount);
|
||||
result = JSC::Yarr::interpret(byteCode, chars, start, length, output);
|
||||
#endif
|
||||
|
||||
if (result == -1)
|
||||
return RegExpRunStatus_Success_NotFound;
|
||||
|
||||
#if !ENABLE_YARR_JIT
|
||||
if (result < 0) {
|
||||
reportPCREError(cx, result);
|
||||
return RegExpRunStatus_Error;
|
||||
}
|
||||
#endif
|
||||
|
||||
JS_ASSERT(result >= 0);
|
||||
return RegExpRunStatus_Success;
|
||||
}
|
||||
|
@ -51,10 +51,8 @@
|
||||
#include "yarr/Yarr.h"
|
||||
#if ENABLE_YARR_JIT
|
||||
#include "yarr/YarrJIT.h"
|
||||
#include "yarr/YarrSyntaxChecker.h"
|
||||
#else
|
||||
#include "yarr/pcre/pcre.h"
|
||||
#endif
|
||||
#include "yarr/YarrSyntaxChecker.h"
|
||||
|
||||
/*
|
||||
* JavaScript Regular Expressions
|
||||
@ -112,68 +110,51 @@ namespace detail {
|
||||
|
||||
class RegExpCode
|
||||
{
|
||||
#if ENABLE_YARR_JIT
|
||||
typedef JSC::Yarr::BytecodePattern BytecodePattern;
|
||||
typedef JSC::Yarr::ErrorCode ErrorCode;
|
||||
typedef JSC::Yarr::YarrPattern YarrPattern;
|
||||
#if ENABLE_YARR_JIT
|
||||
typedef JSC::Yarr::JSGlobalData JSGlobalData;
|
||||
typedef JSC::Yarr::YarrCodeBlock YarrCodeBlock;
|
||||
typedef JSC::Yarr::YarrPattern YarrPattern;
|
||||
|
||||
/* Note: Native code is valid only if |codeBlock.isFallBack() == false|. */
|
||||
YarrCodeBlock codeBlock;
|
||||
BytecodePattern *byteCode;
|
||||
#else
|
||||
JSRegExp *compiled;
|
||||
#endif
|
||||
BytecodePattern *byteCode;
|
||||
|
||||
public:
|
||||
RegExpCode()
|
||||
:
|
||||
#if ENABLE_YARR_JIT
|
||||
codeBlock(),
|
||||
byteCode(NULL)
|
||||
#else
|
||||
compiled(NULL)
|
||||
#endif
|
||||
byteCode(NULL)
|
||||
{ }
|
||||
|
||||
~RegExpCode() {
|
||||
#if ENABLE_YARR_JIT
|
||||
codeBlock.release();
|
||||
#endif
|
||||
if (byteCode)
|
||||
Foreground::delete_<BytecodePattern>(byteCode);
|
||||
#else
|
||||
if (compiled)
|
||||
jsRegExpFree(compiled);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool checkSyntax(JSContext *cx, TokenStream *tokenStream, JSLinearString *source) {
|
||||
#if ENABLE_YARR_JIT
|
||||
ErrorCode error = JSC::Yarr::checkSyntax(*source);
|
||||
if (error == JSC::Yarr::NoError)
|
||||
return true;
|
||||
|
||||
reportYarrError(cx, tokenStream, error);
|
||||
return false;
|
||||
#else
|
||||
# error "Syntax checking not implemented for !ENABLE_YARR_JIT"
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_YARR_JIT
|
||||
static inline bool isJITRuntimeEnabled(JSContext *cx);
|
||||
static void reportYarrError(JSContext *cx, TokenStream *ts, JSC::Yarr::ErrorCode error);
|
||||
#else
|
||||
static void reportPCREError(JSContext *cx, int error);
|
||||
#endif
|
||||
static void reportYarrError(JSContext *cx, TokenStream *ts, JSC::Yarr::ErrorCode error);
|
||||
|
||||
static size_t getOutputSize(size_t pairCount) {
|
||||
#if ENABLE_YARR_JIT
|
||||
return pairCount * 2;
|
||||
#else
|
||||
return pairCount * 3; /* Should be x2, but PCRE has... needs. */
|
||||
#endif
|
||||
}
|
||||
|
||||
bool compile(JSContext *cx, JSLinearString &pattern, unsigned *parenCount, RegExpFlag flags);
|
||||
|
@ -49,9 +49,7 @@
|
||||
#include "jsprvtd.h"
|
||||
#include "vm/String.h"
|
||||
#include "assembler/wtf/Platform.h"
|
||||
#if ENABLE_YARR_JIT
|
||||
#include "assembler/jit/ExecutableAllocator.h"
|
||||
#endif
|
||||
|
||||
namespace JSC { namespace Yarr {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user