Backout d68420c97e0e (bug 691898) as suspected of the jit tests failures
authorMarco Bonardo <mbonardo@mozilla.com>
Wed, 07 Mar 2012 14:06:03 +0100
changeset 88442 44026e95ae904a3e7b59b23968b16a587497c521
parent 88441 1ee8b185cbdb0d491452d7041661f3626c200e2b
child 88443 5d43b850791530388064dee8cfe82b8d0edf753b
push id22199
push userbmo@edmorley.co.uk
push dateThu, 08 Mar 2012 13:15:53 +0000
treeherdermozilla-central@09a8a48476e5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs691898
milestone13.0a1
backs outd68420c97e0e8edb8bca539ce706b300451f119a
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backout d68420c97e0e (bug 691898) as suspected of the jit tests failures
js/src/Makefile.in
js/src/jsapi.cpp
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jsprvtd.h
js/src/vm/RegExpObject-inl.h
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpObject.h
js/src/yarr/wtfbridge.h
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -332,31 +332,30 @@ CPPSRCS += 	checks.cc \
 		platform.cc \
 		utils.cc \
 		$(NONE)
 
 #
 # 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)/assembler \
-                $(srcdir)/assembler/wtf \
-                $(srcdir)/yarr \
+VPATH +=        $(srcdir)/yarr/pcre \
 		$(NULL)
 
 CPPSRCS += \
-                OSAllocatorOS2.cpp \
-                OSAllocatorPosix.cpp \
-                OSAllocatorWin.cpp \
-                PageBlock.cpp \
-                YarrInterpreter.cpp \
-                YarrPattern.cpp \
-                YarrSyntaxChecker.cpp \
+                pcre_compile.cpp \
+                pcre_exec.cpp \
+                pcre_tables.cpp \
+                pcre_xclass.cpp \
+                pcre_ucp_searchfuncs.cpp \
 		$(NULL)
 else
 
 ###############################################
 # BEGIN include sources for the Nitro assembler
 #
 
 ENABLE_YARR_JIT = 1
@@ -881,20 +880,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
+CXXFLAGS += -DUSE_SYSTEM_MALLOC=1 -DENABLE_ASSEMBLER=1
 
 ifneq (,$(ENABLE_YARR_JIT)$(ENABLE_METHODJIT))
-CXXFLAGS +=  -DENABLE_JIT=1 -DENABLE_ASSEMBLER=1
+CXXFLAGS +=  -DENABLE_JIT=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 = \
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -697,19 +697,17 @@ 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),
@@ -861,19 +859,17 @@ JSRuntime::init(uint32_t maxbytes)
     nativeStackBase = GetNativeStackBase();
     return true;
 }
 
 JSRuntime::~JSRuntime()
 {
     JS_ASSERT(onOwnerThread());
 
-#if ENABLE_ASSEMBLER
     delete_<JSC::ExecutableAllocator>(execAlloc_);
-#endif
     delete_<WTF::BumpPointerAllocator>(bumpAlloc_);
 
 #ifdef DEBUG
     /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
     if (!JS_CLIST_IS_EMPTY(&contextList)) {
         unsigned cxcount = 0;
         for (ContextIter acx(this); !acx.done(); acx.next()) {
             fprintf(stderr,
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -100,21 +100,19 @@ 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, &regexp, &unused);
         JS_ASSERT(method == 0);     /* this execAlloc is only used for regexp code */
-#endif
         *regexpCode = regexp + unused;
     }
 
     if (stackCommitted)
         *stackCommitted = stackSpace.sizeOfCommitted();
 
     if (gcMarkerSize)
         *gcMarkerSize = gcMarker.sizeOfExcludingThis(mallocSizeOf);
@@ -129,37 +127,33 @@ 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_<JSC::ExecutableAllocator>(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_<WTF::BumpPointerAllocator>();
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -219,32 +219,26 @@ 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. */
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -313,23 +313,22 @@ typedef Handle<BaseShape*>         Handl
 typedef Handle<types::TypeObject*> HandleTypeObject;
 typedef Handle<JSString*>          HandleString;
 typedef Handle<JSAtom*>            HandleAtom;
 typedef Handle<jsid>               HandleId;
 typedef Handle<Value>              HandleValue;
 
 } /* namespace js */
 
-#if ENABLE_ASSEMBLER
 namespace JSC {
 
 class ExecutableAllocator;
 
 } /* namespace JSC */
-#endif
+
 namespace WTF {
 
 class BumpPointerAllocator;
 
 } /* namespace WTF */
 
 } /* export "C++" */
 
--- a/js/src/vm/RegExpObject-inl.h
+++ b/js/src/vm/RegExpObject-inl.h
@@ -132,28 +132,26 @@ 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);
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -162,16 +162,17 @@ 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)                                                              \
@@ -193,36 +194,73 @@ 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, unsigned *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.
      */
 
-#if ENABLE_YARR_JIT && defined(JS_METHODJIT)
+#ifdef 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);
@@ -233,41 +271,58 @@ 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 = JSC::Yarr::interpret(byteCode, chars, start, length, output);
+    result = jsRegExpExecute(cx, compiled, chars, length, start, output, outputCount);
 #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)
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -46,18 +46,20 @@
 #include <stddef.h>
 #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
-#include "yarr/YarrSyntaxChecker.h"
 
 /*
  * JavaScript Regular Expressions
  *
  * There are several engine concepts associated with a single logical regexp:
  *
  *   RegExpObject - The JS-visible object whose .[[Class]] equals "RegExp"
  *
@@ -105,61 +107,78 @@ 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;
+    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);
 
 
     RegExpRunStatus
     execute(JSContext *cx, const jschar *chars, size_t length, size_t start,
             int *output, size_t outputCount);
--- a/js/src/yarr/wtfbridge.h
+++ b/js/src/yarr/wtfbridge.h
@@ -44,17 +44,19 @@
  * 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;