Bug 1208002: Optimize creation of RegExpMatch result for 'str.match', r=bhackett
authorHannes Verschore <hv1989@gmail.com>
Fri, 02 Oct 2015 17:47:11 +0200
changeset 265757 54e7351f2a6ac4abb285f0768df545726b2c4e80
parent 265756 7347b9d55c3c4fe71a278ad8d437713e2f4b9a38
child 265758 1b4ce33cbf8f047fed094474ef8b08de90ebd9d7
push id66015
push userhv1989@gmail.com
push dateFri, 02 Oct 2015 15:47:46 +0000
treeherdermozilla-inbound@54e7351f2a6a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs1208002
milestone44.0a1
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
Bug 1208002: Optimize creation of RegExpMatch result for 'str.match', r=bhackett
js/src/jsstr.cpp
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -2381,33 +2381,48 @@ DoMatchGlobal(JSContext* cx, const CallA
 static bool
 BuildFlatMatchArray(JSContext* cx, HandleString textstr, const FlatMatch& fm, CallArgs* args)
 {
     if (fm.match() < 0) {
         args->rval().setNull();
         return true;
     }
 
-    /* For this non-global match, produce a RegExp.exec-style array. */
-    RootedObject obj(cx, NewDenseEmptyArray(cx));
-    if (!obj)
+    /* Get the templateObject that defines the shape and type of the output object */
+    JSObject* templateObject = cx->compartment()->regExps.getOrCreateMatchResultTemplateObject(cx);
+    if (!templateObject)
+        return false;
+
+    RootedArrayObject arr(cx, NewDenseFullyAllocatedArrayWithTemplate(cx, 1, templateObject));
+    if (!arr)
         return false;
 
-    RootedValue patternVal(cx, StringValue(fm.pattern()));
-    RootedValue matchVal(cx, Int32Value(fm.match()));
-    RootedValue textVal(cx, StringValue(textstr));
-
-    if (!DefineElement(cx, obj, 0, patternVal) ||
-        !DefineProperty(cx, obj, cx->names().index, matchVal) ||
-        !DefineProperty(cx, obj, cx->names().input, textVal))
-    {
+    /* Store a Value for each pair. */
+    arr->setDenseInitializedLength(1);
+    arr->initDenseElement(0, StringValue(fm.pattern()));
+
+    /* Set the |index| property. (TemplateObject positions it in slot 0) */
+    arr->setSlot(0, Int32Value(fm.match()));
+
+    /* Set the |input| property. (TemplateObject positions it in slot 1) */
+    arr->setSlot(1, StringValue(textstr));
+
+#ifdef DEBUG
+    RootedValue test(cx);
+    RootedId id(cx, NameToId(cx->names().index));
+    if (!NativeGetProperty(cx, arr, id, &test))
         return false;
-    }
-
-    args->rval().setObject(*obj);
+    MOZ_ASSERT(test == arr->getSlot(0));
+    id = NameToId(cx->names().input);
+    if (!NativeGetProperty(cx, arr, id, &test))
+        return false;
+    MOZ_ASSERT(test == arr->getSlot(1));
+#endif
+
+    args->rval().setObject(*arr);
     return true;
 }
 
 /* ES5 15.5.4.10. */
 bool
 js::str_match(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);