diff -r 6a1811ef3174 -r aafdccaf5ded mozilla-yarr-pcre.patch --- a/mozilla-yarr-pcre.patch Thu Feb 23 11:18:26 2012 +0100 +++ b/mozilla-yarr-pcre.patch Thu Mar 01 22:24:19 2012 +0100 @@ -1,5 +1,5 @@ # HG changeset patch -# Parent a45e9e6825a2d7e7f4f64df34ccf9fa74fcac6cb +# Parent 58dd942011a81f3149d9bc34e808806bda099056 # User Landry Breuil Use YARR interpreter instead of PCRE on platforms where YARR JIT is not supported @@ -7,19 +7,19 @@ 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 \ +@@ -335,25 +335,29 @@ 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))) + ifeq (,$(filter arm% sparc %86 x86_64 mips%,$(TARGET_CPU))) -VPATH += $(srcdir)/yarr/pcre \ +VPATH += $(srcdir)/assembler \ -+ $(srcdir)/assembler/wtf \ -+ $(srcdir)/yarr \ ++ $(srcdir)/assembler/wtf \ ++ $(srcdir)/yarr \ $(NULL) CPPSRCS += \ @@ -28,14 +28,13 @@ - 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 \ ++ OSAllocatorOS2.cpp \ ++ OSAllocatorPosix.cpp \ ++ OSAllocatorWin.cpp \ ++ PageBlock.cpp \ ++ YarrInterpreter.cpp \ ++ YarrPattern.cpp \ ++ YarrSyntaxChecker.cpp \ $(NULL) else @@ -44,7 +43,7 @@ # ENABLE_YARR_JIT = 1 -@@ -916,20 +921,20 @@ endif +@@ -878,20 +882,20 @@ endif ############################################### # BEGIN kludges for the Nitro assembler @@ -67,6 +66,476 @@ # Build a standalone test program that exercises the assembler # sources a bit. TESTMAIN_OBJS = \ +diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp +--- a/js/src/jsapi.cpp ++++ b/js/src/jsapi.cpp +@@ -696,17 +696,19 @@ JS_IsBuiltinFunctionConstructor(JSFuncti + static JSBool js_NewRuntimeWasCalled = JS_FALSE; + + JSRuntime::JSRuntime() + : atomsCompartment(NULL), + #ifdef JS_THREADSAFE + ownerThread_(NULL), + #endif + tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), ++#if ENABLE_ASSEMBLER + execAlloc_(NULL), ++#endif + bumpAlloc_(NULL), + nativeStackBase(0), + nativeStackQuota(0), + interpreterFrames(NULL), + cxCallback(NULL), + compartmentCallback(NULL), + activityCallback(NULL), + activityCallbackArg(NULL), +@@ -851,17 +853,19 @@ JSRuntime::init(uint32_t maxbytes) + nativeStackBase = GetNativeStackBase(); + return true; + } + + JSRuntime::~JSRuntime() + { + JS_ASSERT(onOwnerThread()); + ++#if ENABLE_ASSEMBLER + delete_(execAlloc_); ++#endif + delete_(bumpAlloc_); + + #ifdef DEBUG + /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */ + if (!JS_CLIST_IS_EMPTY(&contextList)) { + JSContext *cx, *iter = NULL; + uintN cxcount = 0; + while ((cx = js_ContextIterator(this, JS_TRUE, &iter)) != NULL) { +diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp +--- a/js/src/jscntxt.cpp ++++ b/js/src/jscntxt.cpp +@@ -100,19 +100,21 @@ JSRuntime::sizeOfExcludingThis(JSMallocS + if (normal) + *normal = mallocSizeOf(dtoaState); + + if (temporary) + *temporary = tempLifoAlloc.sizeOfExcludingThis(mallocSizeOf); + + 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; + } + + if (stackCommitted) + *stackCommitted = stackSpace.sizeOfCommitted(); + } + + JS_FRIEND_API(void) +@@ -124,33 +126,37 @@ JSRuntime::triggerOperationCallback() + */ + JS_ATOMIC_SET(&interrupt, 1); + } + + 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) + { + JS_ASSERT(!execAlloc_); + JS_ASSERT(cx->runtime == this); + + JSC::AllocationBehavior randomize = + jitHardening ? JSC::AllocationCanRandomize : JSC::AllocationDeterministic; + execAlloc_ = new_(randomize); + if (!execAlloc_) + js_ReportOutOfMemory(cx); + return execAlloc_; + } ++#endif + + WTF::BumpPointerAllocator * + JSRuntime::createBumpPointerAllocator(JSContext *cx) + { + JS_ASSERT(!bumpAlloc_); + JS_ASSERT(cx->runtime == this); + + bumpAlloc_ = new_(); +diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h +--- a/js/src/jscntxt.h ++++ b/js/src/jscntxt.h +@@ -219,26 +219,32 @@ struct JSRuntime : js::RuntimeFriendFiel + static const size_t TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 1 << 12; + js::LifoAlloc tempLifoAlloc; + + private: + /* + * 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); + } + + /* Base address of the native stack for the current thread. */ + uintptr_t nativeStackBase; + + /* The native stack size limit that runtime should not exceed. */ +diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h +--- a/js/src/jsprvtd.h ++++ b/js/src/jsprvtd.h +@@ -313,22 +313,23 @@ typedef Handle Handl + typedef Handle HandleTypeObject; + typedef Handle HandleString; + typedef Handle HandleAtom; + typedef Handle HandleId; + typedef Handle HandleValue; + + } /* namespace js */ + ++#if ENABLE_ASSEMBLER + namespace JSC { + + class ExecutableAllocator; + + } /* namespace JSC */ +- ++#endif + namespace WTF { + + class BumpPointerAllocator; + + } /* namespace WTF */ + + } /* export "C++" */ + +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 +@@ -132,26 +132,28 @@ RegExpObject::setMultiline(bool enabled) + } + + inline void + 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) + { + #if defined(ANDROID) && defined(JS_METHODJIT) + return cx->methodJitEnabled; + #else + return true; + #endif + } ++#endif + + inline bool + RegExpToShared(JSContext *cx, JSObject &obj, RegExpGuard *g) + { + JS_ASSERT(ObjectClassIs(obj, ESClass_RegExp, cx)); + if (obj.isRegExp()) + return obj.asRegExp().getShared(cx, g); + return Proxy::regexp_toShared(cx, &obj, g); +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 +@@ -162,17 +162,16 @@ MatchPairs::checkAgainst(size_t inputLen + continue; + JS_ASSERT(size_t(p.limit) <= inputLength); + } + #endif + } + + /* detail::RegExpCode */ + +-#if ENABLE_YARR_JIT + void + RegExpCode::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) \ +@@ -194,73 +193,36 @@ RegExpCode::reportYarrError(JSContext *c + 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 +-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, 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, NULL, 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->runtime->getExecutableAllocator(cx); + if (!execAlloc) { + js_ReportOutOfMemory(cx); + return false; + } + + JSGlobalData globalData(execAlloc); +@@ -271,58 +233,41 @@ RegExpCode::compile(JSContext *cx, JSLin + #endif + + WTF::BumpPointerAllocator *bumpAlloc = cx->runtime->getBumpPointerAllocator(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 + } + + RegExpRunStatus + RegExpCode::execute(JSContext *cx, const jschar *chars, size_t length, size_t start, + int *output, size_t outputCount) + { + 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; + } + + /* RegExpObject */ + + static void + regexp_trace(JSTracer *trc, JSObject *obj) +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 +@@ -46,20 +46,18 @@ + #include + #include "jsobj.h" + + #include "js/TemplateLib.h" + + #include "yarr/Yarr.h" + #if ENABLE_YARR_JIT + #include "yarr/YarrJIT.h" ++#endif + #include "yarr/YarrSyntaxChecker.h" +-#else +-#include "yarr/pcre/pcre.h" +-#endif + + /* + * JavaScript Regular Expressions + * + * There are several engine concepts associated with a single logical regexp: + * + * RegExpObject - The JS-visible object whose .[[Class]] equals "RegExp" + * +@@ -107,78 +105,61 @@ class RegExpObjectBuilder + + JSObject * + CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *proto); + + 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; ++#endif + BytecodePattern *byteCode; +-#else +- JSRegExp *compiled; +-#endif + + public: + RegExpCode() + : + #if ENABLE_YARR_JIT + codeBlock(), ++#endif + byteCode(NULL) +-#else +- compiled(NULL) +-#endif + { } + + ~RegExpCode() { + #if ENABLE_YARR_JIT + codeBlock.release(); ++#endif + if (byteCode) + Foreground::delete_(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); ++#endif + static void reportYarrError(JSContext *cx, TokenStream *ts, JSC::Yarr::ErrorCode error); +-#else +- static void reportPCREError(JSContext *cx, int error); +-#endif + + 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, uintN *parenCount, RegExpFlag flags); + + + 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