mozilla-yarr-pcre.patch
changeset 391 5425f43ef15c
parent 386 7784e72b1a3a
child 401 aafdccaf5ded
equal deleted inserted replaced
387:5f37cb170013 391:5425f43ef15c
     1 From: Mike Hommey <mh@glandium.org>
     1 # HG changeset patch
     2 Date: Sat, 24 Dec 2011 09:56:58 +0100
     2 # Parent a45e9e6825a2d7e7f4f64df34ccf9fa74fcac6cb
     3 Subject: Bug 691898 - Use YARR interpreter instead of PCRE on platforms where
     3 # User Landry Breuil <landry@openbsd.org>
     4  YARR JIT is not supported
     4 Use YARR interpreter instead of PCRE on platforms where YARR JIT is not
     5 
     5 supported
     6 ---
       
     7  js/src/Makefile.in           |   21 +++++++++++++--------
       
     8  js/src/vm/RegExpObject-inl.h |   28 ++++++----------------------
       
     9  js/src/vm/RegExpObject.cpp   |   36 ------------------------------------
       
    10  js/src/vm/RegExpObject.h     |   27 ++++++---------------------
       
    11  js/src/yarr/wtfbridge.h      |    2 --
       
    12  5 files changed, 25 insertions(+), 89 deletions(-)
       
    13 
     6 
    14 diff --git a/js/src/Makefile.in b/js/src/Makefile.in
     7 diff --git a/js/src/Makefile.in b/js/src/Makefile.in
    15 --- a/js/src/Makefile.in
     8 --- a/js/src/Makefile.in
    16 +++ b/js/src/Makefile.in
     9 +++ b/js/src/Makefile.in
    17 @@ -356,25 +356,30 @@ CPPSRCS += 	checks.cc \
    10 @@ -356,25 +356,30 @@ CPPSRCS += 	checks.cc \
    23  
    16  
    24  ifeq (,$(filter arm% sparc %86 x86_64,$(TARGET_CPU)))
    17  ifeq (,$(filter arm% sparc %86 x86_64,$(TARGET_CPU)))
    25  
    18  
    26 -VPATH +=        $(srcdir)/yarr/pcre \
    19 -VPATH +=        $(srcdir)/yarr/pcre \
    27 +VPATH +=        $(srcdir)/assembler \
    20 +VPATH +=        $(srcdir)/assembler \
    28 +                $(srcdir)/assembler/wtf \
    21 +		$(srcdir)/assembler/wtf \
    29 +                $(srcdir)/yarr \
    22 +		$(srcdir)/yarr \
    30  		$(NULL)
    23  		$(NULL)
    31  
    24  
    32  CPPSRCS += \
    25  CPPSRCS += \
    33 -                pcre_compile.cpp \
    26 -                pcre_compile.cpp \
    34 -                pcre_exec.cpp \
    27 -                pcre_exec.cpp \
    35 -                pcre_tables.cpp \
    28 -                pcre_tables.cpp \
    36 -                pcre_xclass.cpp \
    29 -                pcre_xclass.cpp \
    37 -                pcre_ucp_searchfuncs.cpp \
    30 -                pcre_ucp_searchfuncs.cpp \
    38 +                Assertions.cpp \
    31 +		Assertions.cpp \
    39 +                OSAllocatorOS2.cpp \
    32 +		OSAllocatorOS2.cpp \
    40 +                OSAllocatorPosix.cpp \
    33 +		OSAllocatorPosix.cpp \
    41 +                OSAllocatorWin.cpp \
    34 +		OSAllocatorWin.cpp \
    42 +                PageBlock.cpp \
    35 +		PageBlock.cpp \
    43 +                YarrInterpreter.cpp \
    36 +		YarrInterpreter.cpp \
    44 +                YarrPattern.cpp \
    37 +		YarrPattern.cpp \
    45 +                YarrSyntaxChecker.cpp \
    38 +		YarrSyntaxChecker.cpp \
    46  		$(NULL)
    39  		$(NULL)
    47  else
    40  else
    48  
    41  
    49  ###############################################
    42  ###############################################
    50  # BEGIN include sources for the Nitro assembler
    43  # BEGIN include sources for the Nitro assembler
    72  
    65  
    73  ifdef ENABLE_METHODJIT
    66  ifdef ENABLE_METHODJIT
    74  # Build a standalone test program that exercises the assembler
    67  # Build a standalone test program that exercises the assembler
    75  # sources a bit.
    68  # sources a bit.
    76  TESTMAIN_OBJS = \
    69  TESTMAIN_OBJS = \
    77 diff --git a/js/src/vm/RegExpObject-inl.h b/js/src/vm/RegExpObject-inl.h
       
    78 --- a/js/src/vm/RegExpObject-inl.h
       
    79 +++ b/js/src/vm/RegExpObject-inl.h
       
    80 @@ -362,49 +362,50 @@ detail::RegExpPrivate::create(JSContext 
       
    81          return RetType(NULL);
       
    82  
       
    83      if (!cacheInsert(cx, sourceAtom, RegExpPrivateCache_ExecCapable, priv))
       
    84          return RetType(NULL);
       
    85  
       
    86      return RetType(priv);
       
    87  }
       
    88  
       
    89 +#if ENABLE_YARR_JIT
       
    90  /* This function should be deleted once bad Android platforms phase out. See bug 604774. */
       
    91  inline bool
       
    92  detail::RegExpPrivateCode::isJITRuntimeEnabled(JSContext *cx)
       
    93  {
       
    94  #if defined(ANDROID) && defined(JS_METHODJIT)
       
    95      return cx->methodJitEnabled;
       
    96  #else
       
    97      return true;
       
    98  #endif
       
    99  }
       
   100 +#endif
       
   101  
       
   102  inline bool
       
   103  detail::RegExpPrivateCode::compile(JSContext *cx, JSLinearString &pattern, TokenStream *ts,
       
   104                                     uintN *parenCount, RegExpFlag flags)
       
   105  {
       
   106 -#if ENABLE_YARR_JIT
       
   107      /* Parse the pattern. */
       
   108      ErrorCode yarrError;
       
   109      YarrPattern yarrPattern(pattern, bool(flags & IgnoreCaseFlag), bool(flags & MultilineFlag),
       
   110                              &yarrError);
       
   111      if (yarrError) {
       
   112          reportYarrError(cx, ts, yarrError);
       
   113          return false;
       
   114      }
       
   115      *parenCount = yarrPattern.m_numSubpatterns;
       
   116  
       
   117      /*
       
   118       * The YARR JIT compiler attempts to compile the parsed pattern. If
       
   119       * it cannot, it informs us via |codeBlock.isFallBack()|, in which
       
   120       * case we have to bytecode compile it.
       
   121       */
       
   122  
       
   123 -#ifdef JS_METHODJIT
       
   124 +#if ENABLE_YARR_JIT && defined(JS_METHODJIT)
       
   125      if (isJITRuntimeEnabled(cx) && !yarrPattern.m_containsBackreferences) {
       
   126          JSC::ExecutableAllocator *execAlloc = cx->threadData()->getOrCreateExecutableAllocator(cx);
       
   127          if (!execAlloc) {
       
   128              js_ReportOutOfMemory(cx);
       
   129              return false;
       
   130          }
       
   131  
       
   132          JSGlobalData globalData(execAlloc);
       
   133 @@ -415,31 +416,21 @@ detail::RegExpPrivateCode::compile(JSCon
       
   134  #endif
       
   135  
       
   136      WTF::BumpPointerAllocator *bumpAlloc = cx->threadData()->getOrCreateBumpPointerAllocator(cx);
       
   137      if (!bumpAlloc) {
       
   138          js_ReportOutOfMemory(cx);
       
   139          return false;
       
   140      }
       
   141  
       
   142 +#if ENABLE_YARR_JIT
       
   143      codeBlock.setFallBack(true);
       
   144 +#endif
       
   145      byteCode = byteCompile(yarrPattern, bumpAlloc).get();
       
   146      return true;
       
   147 -#else /* !defined(ENABLE_YARR_JIT) */
       
   148 -    int error = 0;
       
   149 -    compiled = jsRegExpCompile(pattern.chars(), pattern.length(),
       
   150 -                  ignoreCase() ? JSRegExpIgnoreCase : JSRegExpDoNotIgnoreCase,
       
   151 -                  multiline() ? JSRegExpMultiline : JSRegExpSingleLine,
       
   152 -                  parenCount, &error);
       
   153 -    if (error) {
       
   154 -        reportPCREError(cx, error);
       
   155 -        return false;
       
   156 -    }
       
   157 -    return true;
       
   158 -#endif
       
   159  }
       
   160  
       
   161  inline bool
       
   162  detail::RegExpPrivate::compile(JSContext *cx, TokenStream *ts)
       
   163  {
       
   164      if (!sticky())
       
   165          return code.compile(cx, *source, ts, &parenCount, getFlags());
       
   166  
       
   167 @@ -471,29 +462,22 @@ detail::RegExpPrivateCode::execute(JSCon
       
   168      int result;
       
   169  #if ENABLE_YARR_JIT
       
   170      (void) cx; /* Unused. */
       
   171      if (codeBlock.isFallBack())
       
   172          result = JSC::Yarr::interpret(byteCode, chars, start, length, output);
       
   173      else
       
   174          result = JSC::Yarr::execute(codeBlock, chars, start, length, output);
       
   175  #else
       
   176 -    result = jsRegExpExecute(cx, compiled, chars, length, start, output, outputCount);
       
   177 +    result = JSC::Yarr::interpret(byteCode, chars, start, length, output);
       
   178  #endif
       
   179  
       
   180      if (result == -1)
       
   181          return RegExpRunStatus_Success_NotFound;
       
   182  
       
   183 -#if !ENABLE_YARR_JIT
       
   184 -    if (result < 0) {
       
   185 -        reportPCREError(cx, result);
       
   186 -        return RegExpRunStatus_Error;
       
   187 -    }
       
   188 -#endif
       
   189 -
       
   190      JS_ASSERT(result >= 0);
       
   191      return RegExpRunStatus_Success;
       
   192  }
       
   193  
       
   194  inline void
       
   195  detail::RegExpPrivate::incref(JSContext *cx)
       
   196  {
       
   197      ++refCount;
       
   198 diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
       
   199 --- a/js/src/vm/RegExpObject.cpp
       
   200 +++ b/js/src/vm/RegExpObject.cpp
       
   201 @@ -387,17 +387,16 @@ Class js::RegExpClass = {
       
   202      NULL,                    /* checkAccess */
       
   203      NULL,                    /* call */
       
   204      NULL,                    /* construct */
       
   205      js_XDRRegExpObject,
       
   206      NULL,                    /* hasInstance */
       
   207      regexp_trace
       
   208  };
       
   209  
       
   210 -#if ENABLE_YARR_JIT
       
   211  void
       
   212  RegExpPrivateCode::reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error)
       
   213  {
       
   214      switch (error) {
       
   215        case JSC::Yarr::NoError:
       
   216          JS_NOT_REACHED("Called reportYarrError with value for no error");
       
   217          return;
       
   218  #define COMPILE_EMSG(__code, __msg)                                                              \
       
   219 @@ -419,52 +418,16 @@ RegExpPrivateCode::reportYarrError(JSCon
       
   220        COMPILE_EMSG(QuantifierTooLarge, JSMSG_BAD_QUANTIFIER);
       
   221        COMPILE_EMSG(EscapeUnterminated, JSMSG_TRAILING_SLASH);
       
   222  #undef COMPILE_EMSG
       
   223        default:
       
   224          JS_NOT_REACHED("Unknown Yarr error code");
       
   225      }
       
   226  }
       
   227  
       
   228 -#else /* !ENABLE_YARR_JIT */
       
   229 -
       
   230 -void
       
   231 -RegExpPrivateCode::reportPCREError(JSContext *cx, int error)
       
   232 -{
       
   233 -#define REPORT(msg_) \
       
   234 -    JS_ReportErrorFlagsAndNumberUC(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL, msg_); \
       
   235 -    return
       
   236 -    switch (error) {
       
   237 -      case -2: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
       
   238 -      case 0: JS_NOT_REACHED("Precondition violation: an error must have occurred.");
       
   239 -      case 1: REPORT(JSMSG_TRAILING_SLASH);
       
   240 -      case 2: REPORT(JSMSG_TRAILING_SLASH);
       
   241 -      case 3: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
       
   242 -      case 4: REPORT(JSMSG_BAD_QUANTIFIER);
       
   243 -      case 5: REPORT(JSMSG_BAD_QUANTIFIER);
       
   244 -      case 6: REPORT(JSMSG_BAD_CLASS_RANGE);
       
   245 -      case 7: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
       
   246 -      case 8: REPORT(JSMSG_BAD_CLASS_RANGE);
       
   247 -      case 9: REPORT(JSMSG_BAD_QUANTIFIER);
       
   248 -      case 10: REPORT(JSMSG_UNMATCHED_RIGHT_PAREN);
       
   249 -      case 11: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
       
   250 -      case 12: REPORT(JSMSG_UNMATCHED_RIGHT_PAREN);
       
   251 -      case 13: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
       
   252 -      case 14: REPORT(JSMSG_MISSING_PAREN);
       
   253 -      case 15: REPORT(JSMSG_BAD_BACKREF);
       
   254 -      case 16: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
       
   255 -      case 17: REPORT(JSMSG_REGEXP_TOO_COMPLEX);
       
   256 -      default:
       
   257 -        JS_NOT_REACHED("Precondition violation: unknown PCRE error code.");
       
   258 -    }
       
   259 -#undef REPORT
       
   260 -}
       
   261 -
       
   262 -#endif /* ENABLE_YARR_JIT */
       
   263 -
       
   264  bool
       
   265  js::ParseRegExpFlags(JSContext *cx, JSString *flagStr, RegExpFlag *flagsOut)
       
   266  {
       
   267      size_t n = flagStr->length();
       
   268      const jschar *s = flagStr->getChars(cx);
       
   269      if (!s)
       
   270          return false;
       
   271  
       
   272 diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h
       
   273 --- a/js/src/vm/RegExpObject.h
       
   274 +++ b/js/src/vm/RegExpObject.h
       
   275 @@ -45,18 +45,16 @@
       
   276  #include "jsobj.h"
       
   277  
       
   278  #include "js/TemplateLib.h"
       
   279  
       
   280  #include "yarr/Yarr.h"
       
   281  #if ENABLE_YARR_JIT
       
   282  #include "yarr/YarrJIT.h"
       
   283  #include "yarr/YarrSyntaxChecker.h"
       
   284 -#else
       
   285 -#include "yarr/pcre/pcre.h"
       
   286  #endif
       
   287  
       
   288  namespace js {
       
   289  
       
   290  enum RegExpRunStatus
       
   291  {
       
   292      RegExpRunStatus_Error,
       
   293      RegExpRunStatus_Success,
       
   294 @@ -235,50 +233,43 @@ class RegExpObjectBuilder
       
   295  
       
   296  namespace detail {
       
   297  
       
   298  static const jschar GreedyStarChars[] = {'.', '*'};
       
   299  
       
   300  /* Abstracts away the gross |RegExpPrivate| backend details. */
       
   301  class RegExpPrivateCode
       
   302  {
       
   303 -#if ENABLE_YARR_JIT
       
   304      typedef JSC::Yarr::BytecodePattern BytecodePattern;
       
   305      typedef JSC::Yarr::ErrorCode ErrorCode;
       
   306 +    typedef JSC::Yarr::YarrPattern YarrPattern;
       
   307 +#if ENABLE_YARR_JIT
       
   308      typedef JSC::Yarr::JSGlobalData JSGlobalData;
       
   309      typedef JSC::Yarr::YarrCodeBlock YarrCodeBlock;
       
   310 -    typedef JSC::Yarr::YarrPattern YarrPattern;
       
   311  
       
   312      /* Note: Native code is valid only if |codeBlock.isFallBack() == false|. */
       
   313      YarrCodeBlock   codeBlock;
       
   314 +#endif
       
   315      BytecodePattern *byteCode;
       
   316 -#else
       
   317 -    JSRegExp        *compiled;
       
   318 -#endif
       
   319  
       
   320    public:
       
   321      RegExpPrivateCode()
       
   322        :
       
   323  #if ENABLE_YARR_JIT
       
   324          codeBlock(),
       
   325 +#endif
       
   326          byteCode(NULL)
       
   327 -#else
       
   328 -        compiled(NULL)
       
   329 -#endif
       
   330      { }
       
   331  
       
   332      ~RegExpPrivateCode() {
       
   333  #if ENABLE_YARR_JIT
       
   334          codeBlock.release();
       
   335 +#endif
       
   336          if (byteCode)
       
   337              Foreground::delete_<BytecodePattern>(byteCode);
       
   338 -#else
       
   339 -        if (compiled)
       
   340 -            jsRegExpFree(compiled);
       
   341 -#endif
       
   342      }
       
   343  
       
   344      static bool checkSyntax(JSContext *cx, TokenStream *tokenStream, JSLinearString *source) {
       
   345  #if ENABLE_YARR_JIT
       
   346          ErrorCode error = JSC::Yarr::checkSyntax(*source);
       
   347          if (error == JSC::Yarr::NoError)
       
   348              return true;
       
   349  
       
   350 @@ -286,27 +277,21 @@ class RegExpPrivateCode
       
   351          return false;
       
   352  #else
       
   353  # error "Syntax checking not implemented for !ENABLE_YARR_JIT"
       
   354  #endif
       
   355      }
       
   356  
       
   357  #if ENABLE_YARR_JIT
       
   358      static inline bool isJITRuntimeEnabled(JSContext *cx);
       
   359 -    static void reportYarrError(JSContext *cx, TokenStream *ts, JSC::Yarr::ErrorCode error);
       
   360 -#else
       
   361 -    static void reportPCREError(JSContext *cx, int error);
       
   362  #endif
       
   363 +    void reportYarrError(JSContext *cx, TokenStream *ts, JSC::Yarr::ErrorCode error);
       
   364  
       
   365      static size_t getOutputSize(size_t pairCount) {
       
   366 -#if ENABLE_YARR_JIT
       
   367          return pairCount * 2;
       
   368 -#else
       
   369 -        return pairCount * 3; /* Should be x2, but PCRE has... needs. */
       
   370 -#endif
       
   371      }
       
   372  
       
   373      inline bool compile(JSContext *cx, JSLinearString &pattern, TokenStream *ts, uintN *parenCount,
       
   374                          RegExpFlag flags);
       
   375  
       
   376  
       
   377      inline RegExpRunStatus execute(JSContext *cx, const jschar *chars, size_t length, size_t start,
       
   378                                     int *output, size_t outputCount);
       
   379 diff --git a/js/src/yarr/wtfbridge.h b/js/src/yarr/wtfbridge.h
    70 diff --git a/js/src/yarr/wtfbridge.h b/js/src/yarr/wtfbridge.h
   380 --- a/js/src/yarr/wtfbridge.h
    71 --- a/js/src/yarr/wtfbridge.h
   381 +++ b/js/src/yarr/wtfbridge.h
    72 +++ b/js/src/yarr/wtfbridge.h
   382 @@ -44,19 +44,17 @@
    73 @@ -44,19 +44,17 @@
   383   * WTF compatibility layer. This file provides various type and data
    74   * WTF compatibility layer. This file provides various type and data