Bug 691898 - Use YARR interpreter instead of PCRE on platforms where YARR JIT is not supported. r=dmandelin

This commit is contained in:
Landry Breuil 2012-03-07 12:06:19 +01:00
parent 255811e424
commit c78af1f2ba
9 changed files with 43 additions and 99 deletions

View File

@ -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

View File

@ -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

View File

@ -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, &regexp, &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)

View File

@ -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);
}

View File

@ -318,12 +318,13 @@ typedef Handle<Value> HandleValue;
} /* namespace js */
#if ENABLE_ASSEMBLER
namespace JSC {
class ExecutableAllocator;
} /* namespace JSC */
#endif
namespace WTF {
class BumpPointerAllocator;

View File

@ -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)

View File

@ -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;
}

View File

@ -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);

View File

@ -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 {