Bug 887016 - Part 1: Add native RegExpCreate. r=h4writer
☠☠ backed out by 2cf8ca358a38 ☠ ☠
authorTooru Fujisawa <arai_a@mac.com>
Sat, 05 Sep 2015 21:55:01 +0900
changeset 290619 10621b5e7de50d4df6190354e334309a7b6987d9
parent 290618 52a142a57bf629018a0b16e85d75450e1699c0da
child 290620 adca5076bc4605316984c719bbc4729e0a7f1d58
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersh4writer
bugs887016
milestone48.0a1
Bug 887016 - Part 1: Add native RegExpCreate. r=h4writer
js/src/builtin/RegExp.cpp
js/src/builtin/RegExp.h
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -147,59 +147,98 @@ js::ExecuteRegExpLegacy(JSContext* cx, R
         /* Forbid an array, as an optimization. */
         rval.setBoolean(true);
         return true;
     }
 
     return CreateRegExpMatchResult(cx, input, matches, rval);
 }
 
+enum RegExpSharedUse {
+    UseRegExpShared,
+    DontUseRegExpShared
+};
+
 /*
- * ES6 21.2.3.2.2.  Because this function only ever returns |obj| in the spec,
- * provided by the user, we omit it and just return the usual success/failure.
+ * ES 2016 draft Mar 25, 2016 21.2.3.2.2.
+ * Because this function only ever returns |obj| in the spec, provided by the
+ * user, we omit it and just return the usual success/failure.
  */
 static bool
 RegExpInitializeIgnoringLastIndex(JSContext* cx, Handle<RegExpObject*> obj,
-                                  HandleValue patternValue, HandleValue flagsValue)
+                                  HandleValue patternValue, HandleValue flagsValue,
+                                  RegExpSharedUse sharedUse = DontUseRegExpShared)
 {
     RootedAtom pattern(cx);
     if (patternValue.isUndefined()) {
         /* Step 1. */
         pattern = cx->names().empty;
     } else {
-        /* Steps 2-3. */
+        /* Step 2. */
         pattern = ToAtom<CanGC>(cx, patternValue);
         if (!pattern)
             return false;
     }
 
-    /* Step 4. */
+    /* Step 3. */
     RegExpFlag flags = RegExpFlag(0);
     if (!flagsValue.isUndefined()) {
-        /* Steps 5-6. */
+        /* Step 4. */
         RootedString flagStr(cx, ToString<CanGC>(cx, flagsValue));
         if (!flagStr)
             return false;
 
-        /* Step 7. */
+        /* Step 5. */
         if (!ParseRegExpFlags(cx, flagStr, &flags))
             return false;
     }
 
-    /* Steps 8-10. */
-    CompileOptions options(cx);
-    frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
-    if (!irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), pattern,
-                                      flags & UnicodeFlag))
-    {
-        return false;
+    if (sharedUse == UseRegExpShared) {
+        /* Steps 7-8. */
+        RegExpGuard re(cx);
+        if (!cx->compartment()->regExps.get(cx, pattern, flags, &re))
+            return false;
+
+        /* Steps 9-12. */
+        obj->initIgnoringLastIndex(pattern, flags);
+
+        obj->setShared(*re);
+    } else {
+        /* Steps 7-8. */
+        CompileOptions options(cx);
+        frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
+        if (!irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), pattern,
+                                          flags & UnicodeFlag))
+        {
+            return false;
+        }
+
+        /* Steps 9-12. */
+        obj->initIgnoringLastIndex(pattern, flags);
     }
 
-    /* Steps 11-13. */
-    obj->initIgnoringLastIndex(pattern, flags);
+    return true;
+}
+
+/* ES 2016 draft Mar 25, 2016 21.2.3.2.3. */
+bool
+js::RegExpCreate(JSContext* cx, HandleValue patternValue, HandleValue flagsValue,
+                 MutableHandleValue rval)
+{
+    /* Step 1. */
+    Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, nullptr));
+    if (!regexp)
+         return false;
+
+    /* Step 2. */
+    if (!RegExpInitializeIgnoringLastIndex(cx, regexp, patternValue, flagsValue, UseRegExpShared))
+        return false;
+    regexp->zeroLastIndex(cx);
+
+    rval.setObject(*regexp);
     return true;
 }
 
 MOZ_ALWAYS_INLINE bool
 IsRegExpObject(HandleValue v)
 {
     return v.isObject() && v.toObject().is<RegExpObject>();
 }
--- a/js/src/builtin/RegExp.h
+++ b/js/src/builtin/RegExp.h
@@ -83,16 +83,19 @@ regexp_test_no_statics(JSContext* cx, un
  *        re = regexp_construct(pattern, flags)
  */
 extern bool
 regexp_construct_self_hosting(JSContext* cx, unsigned argc, Value* vp);
 
 extern bool
 IsRegExp(JSContext* cx, HandleValue value, bool* result);
 
+extern bool
+RegExpCreate(JSContext* cx, HandleValue pattern, HandleValue flags, MutableHandleValue rval);
+
 // RegExp ClassSpec members used in RegExpObject.cpp.
 extern bool
 regexp_construct(JSContext* cx, unsigned argc, Value* vp);
 extern const JSPropertySpec regexp_static_props[];
 extern const JSPropertySpec regexp_properties[];
 extern const JSFunctionSpec regexp_methods[];
 
 // Used in RegExpObject::isOriginalFlagGetter.