From: Mike Hommey <mh@glandium.org>
Date: Sat, 24 Dec 2011 09:56:58 +0100
Subject: Bug 691898 - Use YARR interpreter instead of PCRE on platforms where
YARR JIT is not supported
---
js/src/Makefile.in | 21 +++++++++++++--------
js/src/vm/RegExpObject-inl.h | 28 ++++++----------------------
js/src/vm/RegExpObject.cpp | 36 ------------------------------------
js/src/vm/RegExpObject.h | 27 ++++++---------------------
js/src/yarr/wtfbridge.h | 2 --
5 files changed, 25 insertions(+), 89 deletions(-)
diff --git a/js/src/Makefile.in b/js/src/Makefile.in
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -356,25 +356,30 @@ 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,$(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 \
+ Assertions.cpp \
+ OSAllocatorOS2.cpp \
+ OSAllocatorPosix.cpp \
+ OSAllocatorWin.cpp \
+ PageBlock.cpp \
+ YarrInterpreter.cpp \
+ YarrPattern.cpp \
+ YarrSyntaxChecker.cpp \
$(NULL)
else
###############################################
# BEGIN include sources for the Nitro assembler
#
ENABLE_YARR_JIT = 1
@@ -916,20 +921,20 @@ endif
###############################################
# BEGIN kludges for the Nitro assembler
#
# 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
ifdef ENABLE_METHODJIT
# Build a standalone test program that exercises the assembler
# sources a bit.
TESTMAIN_OBJS = \
diff --git a/js/src/vm/RegExpObject-inl.h b/js/src/vm/RegExpObject-inl.h
--- a/js/src/vm/RegExpObject-inl.h
+++ b/js/src/vm/RegExpObject-inl.h
@@ -362,49 +362,50 @@ detail::RegExpPrivate::create(JSContext
return RetType(NULL);
if (!cacheInsert(cx, sourceAtom, RegExpPrivateCache_ExecCapable, priv))
return RetType(NULL);
return RetType(priv);
}
+#if ENABLE_YARR_JIT
/* This function should be deleted once bad Android platforms phase out. See bug 604774. */
inline bool
detail::RegExpPrivateCode::isJITRuntimeEnabled(JSContext *cx)
{
#if defined(ANDROID) && defined(JS_METHODJIT)
return cx->methodJitEnabled;
#else
return true;
#endif
}
+#endif
inline bool
detail::RegExpPrivateCode::compile(JSContext *cx, JSLinearString &pattern, TokenStream *ts,
uintN *parenCount, RegExpFlag flags)
{
-#if ENABLE_YARR_JIT
/* Parse the pattern. */
ErrorCode yarrError;
YarrPattern yarrPattern(pattern, bool(flags & IgnoreCaseFlag), bool(flags & MultilineFlag),
&yarrError);
if (yarrError) {
reportYarrError(cx, ts, yarrError);
return false;
}
*parenCount = yarrPattern.m_numSubpatterns;
/*
* The YARR JIT compiler attempts to compile the parsed pattern. If
* it cannot, it informs us via |codeBlock.isFallBack()|, in which
* 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->threadData()->getOrCreateExecutableAllocator(cx);
if (!execAlloc) {
js_ReportOutOfMemory(cx);
return false;
}
JSGlobalData globalData(execAlloc);
@@ -415,31 +416,21 @@ detail::RegExpPrivateCode::compile(JSCon
#endif
WTF::BumpPointerAllocator *bumpAlloc = cx->threadData()->getOrCreateBumpPointerAllocator(cx);
if (!bumpAlloc) {
js_ReportOutOfMemory(cx);
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
}
inline bool
detail::RegExpPrivate::compile(JSContext *cx, TokenStream *ts)
{
if (!sticky())
return code.compile(cx, *source, ts, &parenCount, getFlags());
@@ -471,29 +462,22 @@ detail::RegExpPrivateCode::execute(JSCon
int result;
#if ENABLE_YARR_JIT
(void) cx; /* Unused. */
if (codeBlock.isFallBack())
result = JSC::Yarr::interpret(byteCode, chars, start, length, output);
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;
}
inline void
detail::RegExpPrivate::incref(JSContext *cx)
{
++refCount;
diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -387,17 +387,16 @@ Class js::RegExpClass = {
NULL, /* checkAccess */
NULL, /* call */
NULL, /* construct */
js_XDRRegExpObject,
NULL, /* hasInstance */
regexp_trace
};
-#if ENABLE_YARR_JIT
void
RegExpPrivateCode::reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error)
{
switch (error) {
case JSC::Yarr::NoError:
JS_NOT_REACHED("Called reportYarrError with value for no error");
return;
#define COMPILE_EMSG(__code, __msg) \
@@ -419,52 +418,16 @@ RegExpPrivateCode::reportYarrError(JSCon
COMPILE_EMSG(QuantifierTooLarge, JSMSG_BAD_QUANTIFIER);
COMPILE_EMSG(EscapeUnterminated, JSMSG_TRAILING_SLASH);
#undef COMPILE_EMSG
default:
JS_NOT_REACHED("Unknown Yarr error code");
}
}
-#else /* !ENABLE_YARR_JIT */
-
-void
-RegExpPrivateCode::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
js::ParseRegExpFlags(JSContext *cx, JSString *flagStr, RegExpFlag *flagsOut)
{
size_t n = flagStr->length();
const jschar *s = flagStr->getChars(cx);
if (!s)
return false;
diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -45,18 +45,16 @@
#include "jsobj.h"
#include "js/TemplateLib.h"
#include "yarr/Yarr.h"
#if ENABLE_YARR_JIT
#include "yarr/YarrJIT.h"
#include "yarr/YarrSyntaxChecker.h"
-#else
-#include "yarr/pcre/pcre.h"
#endif
namespace js {
enum RegExpRunStatus
{
RegExpRunStatus_Error,
RegExpRunStatus_Success,
@@ -235,50 +233,43 @@ class RegExpObjectBuilder
namespace detail {
static const jschar GreedyStarChars[] = {'.', '*'};
/* Abstracts away the gross |RegExpPrivate| backend details. */
class RegExpPrivateCode
{
-#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;
+#endif
BytecodePattern *byteCode;
-#else
- JSRegExp *compiled;
-#endif
public:
RegExpPrivateCode()
:
#if ENABLE_YARR_JIT
codeBlock(),
+#endif
byteCode(NULL)
-#else
- compiled(NULL)
-#endif
{ }
~RegExpPrivateCode() {
#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;
@@ -286,27 +277,21 @@ class RegExpPrivateCode
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
+ 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
}
inline bool compile(JSContext *cx, JSLinearString &pattern, TokenStream *ts, uintN *parenCount,
RegExpFlag flags);
inline RegExpRunStatus execute(JSContext *cx, const jschar *chars, size_t length, size_t start,
int *output, size_t outputCount);
diff --git a/js/src/yarr/wtfbridge.h b/js/src/yarr/wtfbridge.h
--- a/js/src/yarr/wtfbridge.h
+++ b/js/src/yarr/wtfbridge.h
@@ -44,19 +44,17 @@
* WTF compatibility layer. This file provides various type and data
* definitions for use by Yarr.
*/
#include "jsstr.h"
#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 {
/*
* Basic type definitions.
*/
typedef jschar UChar;