Bug 1362154: Part 6: Fall back to OOL call for named captures in Ion r=jandem
authorIain Ireland <iireland@mozilla.com>
Thu, 21 May 2020 06:37:19 +0000
changeset 531651 9bad8ab13f064e49d2a01d8fe0343712322ba44e
parent 531650 00d2e220a57535825b59e92df5201119109f55e4
child 531652 c296b98a4e227826a27bafc1d9e3c200e1e36fe3
push id37441
push userapavel@mozilla.com
push dateFri, 22 May 2020 21:38:53 +0000
treeherdermozilla-central@d6abd35b54ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1362154
milestone78.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 1362154: Part 6: Fall back to OOL call for named captures in Ion r=jandem Named captures add a `groups` property to the match result. The shape of that group depends on the regexp. Allocating an object in masm requires monomorphizing on a particular template object, but all of our existing Ion regexp code is designed to handle arbitrary regexps. This means we can't allocate the `groups` object in jitcode without a lot of work. Given that we have to call into C++ to allocate, we might as well just use the existing OOL fallback. This performs a VM call to RegExpMatcherRaw, which will simply call CreateRegExpMatchResult. Differential Revision: https://phabricator.services.mozilla.com/D76038
js/src/jit/CodeGenerator.cpp
js/src/vm/RegExpShared.h
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -2873,48 +2873,68 @@ JitCode* JitRealm::generateRegExpMatcher
 
   Label notFound, oolEntry;
   if (!PrepareAndExecuteRegExp(cx, masm, regexp, input, lastIndex, temp1, temp2,
                                temp3, inputOutputDataStartOffset,
                                stringsCanBeInNursery, &notFound, &oolEntry)) {
     return nullptr;
   }
 
+#ifdef ENABLE_NEW_REGEXP
+  // If a regexp has named captures, fall back to the OOL stub, which
+  // will end up calling CreateRegExpMatchResults.
+  Register shared = temp2;
+  masm.loadPtr(Address(regexp, NativeObject::getFixedSlotOffset(
+                                   RegExpObject::PRIVATE_SLOT)),
+               shared);
+  masm.branchPtr(Assembler::NotEqual,
+                 Address(shared, RegExpShared::offsetOfGroupsTemplate()),
+                 ImmWord(0), &oolEntry);
+#endif
+
   // Construct the result.
   Register object = temp1;
   Label matchResultFallback, matchResultJoin;
   masm.createGCObject(object, temp2, templateObj, gc::DefaultHeap,
                       &matchResultFallback);
   masm.bind(&matchResultJoin);
 
 #ifdef ENABLE_NEW_REGEXP
   MOZ_ASSERT(nativeTemplateObj.numFixedSlots() == 0);
-  MOZ_ASSERT(nativeTemplateObj.numDynamicSlots() == 3);
+  // Dynamic slot count is always rounded to a power of 2
+  MOZ_ASSERT(nativeTemplateObj.numDynamicSlots() == 4);
   static_assert(RegExpRealm::MatchResultObjectIndexSlot == 0,
                 "First slot holds the 'index' property");
   static_assert(RegExpRealm::MatchResultObjectInputSlot == 1,
                 "Second slot holds the 'input' property");
   static_assert(RegExpRealm::MatchResultObjectGroupsSlot == 2,
                 "Third slot holds the 'groups' property");
 #else
   MOZ_ASSERT(nativeTemplateObj.numFixedSlots() == 0);
   MOZ_ASSERT(nativeTemplateObj.numDynamicSlots() == 2);
   static_assert(RegExpRealm::MatchResultObjectIndexSlot == 0,
                 "First slot holds the 'index' property");
   static_assert(RegExpRealm::MatchResultObjectInputSlot == 1,
                 "Second slot holds the 'input' property");
 #endif
 
+  // Initialize the slots of the result object with the dummy values
+  // defined in createMatchResultTemplateObject.
   masm.loadPtr(Address(object, NativeObject::offsetOfSlots()), temp2);
   masm.storeValue(
       nativeTemplateObj.getSlot(RegExpRealm::MatchResultObjectIndexSlot),
       Address(temp2, 0));
   masm.storeValue(
       nativeTemplateObj.getSlot(RegExpRealm::MatchResultObjectInputSlot),
       Address(temp2, sizeof(Value)));
+#ifdef ENABLE_NEW_REGEXP
+  masm.storeValue(
+      nativeTemplateObj.getSlot(RegExpRealm::MatchResultObjectGroupsSlot),
+      Address(temp2, 2 * sizeof(Value)));
+#endif
 
   // clang-format off
    /*
     * [SMDOC] Stack layout for the RegExpMatcher stub
     *
     *                                    +---------------+
     *                                    |Return-Address |
     *                                    +---------------+
--- a/js/src/vm/RegExpShared.h
+++ b/js/src/vm/RegExpShared.h
@@ -285,16 +285,21 @@ class RegExpShared : public gc::TenuredC
     return offsetof(RegExpShared, pairCount_);
   }
 
   static size_t offsetOfJitCode(bool latin1) {
     return offsetof(RegExpShared, compilationArray) +
            (CompilationIndex(latin1) * sizeof(RegExpCompilation)) +
            offsetof(RegExpCompilation, jitCode);
   }
+#ifdef ENABLE_NEW_REGEXP
+  static size_t offsetOfGroupsTemplate() {
+    return offsetof(RegExpShared, groupsTemplate_);
+  }
+#endif
 
   size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
 
 #ifdef DEBUG
   static bool dumpBytecode(JSContext* cx, MutableHandleRegExpShared res,
                            HandleLinearString input);
 #endif