Bug 1485615 - Make RegExpZone a separate allocation to Zone r=sfink
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 23 Aug 2018 16:58:47 +0100
changeset 481359 c70943a6b070698c59db4802c912a6c682b49ba4
parent 481358 f7d550d783449a155a5681f0db3939bd9ecad58b
child 481360 40001671f508bd5673f365c47cbbdbe6c9cdbdf2
push id232
push userfmarier@mozilla.com
push dateWed, 05 Sep 2018 20:45:54 +0000
reviewerssfink
bugs1485615
milestone63.0a1
Bug 1485615 - Make RegExpZone a separate allocation to Zone r=sfink
js/src/builtin/RegExp.cpp
js/src/gc/Marking.cpp
js/src/gc/Zone.cpp
js/src/gc/Zone.h
js/src/proxy/CrossCompartmentWrapper.cpp
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpStatics.cpp
js/src/vm/TypeInference.cpp
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -181,33 +181,33 @@ CheckPatternSyntaxSlow(JSContext* cx, Ha
 }
 
 static RegExpShared*
 CheckPatternSyntax(JSContext* cx, HandleAtom pattern, RegExpFlag flags)
 {
     // If we already have a RegExpShared for this pattern/flags, we can
     // avoid the much slower CheckPatternSyntaxSlow call.
 
-    if (RegExpShared* shared = cx->zone()->regExps.maybeGet(pattern, flags)) {
+    if (RegExpShared* shared = cx->zone()->regExps().maybeGet(pattern, flags)) {
 #ifdef DEBUG
         // Assert the pattern is valid.
         if (!CheckPatternSyntaxSlow(cx, pattern, flags)) {
             MOZ_ASSERT(cx->isThrowingOutOfMemory() || cx->isThrowingOverRecursed());
             return nullptr;
         }
 #endif
         return shared;
     }
 
     if (!CheckPatternSyntaxSlow(cx, pattern, flags))
         return nullptr;
 
     // Allocate and return a new RegExpShared so we will hit the fast path
     // next time.
-    return cx->zone()->regExps.get(cx, pattern, flags);
+    return cx->zone()->regExps().get(cx, pattern, flags);
 }
 
 /*
  * ES 2016 draft Mar 25, 2016 21.2.3.2.2.
  *
  * Steps 14-15 set |obj|'s "lastIndex" property to zero.  Some of
  * RegExpInitialize's callers have a fresh RegExp not yet exposed to script:
  * in these cases zeroing "lastIndex" is infallible.  But others have a RegExp
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -21,17 +21,16 @@
 #include "js/SliceBudget.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/ArrayObject.h"
 #ifdef ENABLE_BIGINT
 #include "vm/BigIntType.h"
 #endif
 #include "vm/Debugger.h"
 #include "vm/EnvironmentObject.h"
-#include "vm/RegExpObject.h"
 #include "vm/RegExpShared.h"
 #include "vm/Scope.h"
 #include "vm/Shape.h"
 #include "vm/SymbolType.h"
 #include "vm/TypedArrayObject.h"
 #include "vm/UnboxedObject.h"
 #include "wasm/WasmJS.h"
 
--- a/js/src/gc/Zone.cpp
+++ b/js/src/gc/Zone.cpp
@@ -38,17 +38,16 @@ JS::Zone::Zone(JSRuntime* rt)
     types(this),
     gcWeakMapList_(this),
     compartments_(),
     gcGrayRoots_(this),
     gcWeakRefs_(this),
     weakCaches_(this),
     gcWeakKeys_(this, SystemAllocPolicy(), rt->randomHashCodeScrambler()),
     typeDescrObjects_(this, this),
-    regExps(this),
     markedAtoms_(this),
     atomCache_(this),
     externalStringCache_(this),
     functionToStringCache_(this),
     keepAtomsCount(this, 0),
     purgeAtomsDeferred(this, 0),
     usage(&rt->gc.usage),
     threshold(),
@@ -92,26 +91,27 @@ Zone::~Zone()
     js_delete(debuggers.ref());
     js_delete(jitZone_.ref());
 
 #ifdef DEBUG
     // Avoid assertions failures warning that not everything has been destroyed
     // if the embedding leaked GC things.
     if (!rt->gc.shutdownCollectedEverything()) {
         gcWeakMapList().clear();
-        regExps.clear();
+        regExps().clear();
     }
 #endif
 }
 
 bool
 Zone::init(bool isSystemArg)
 {
     isSystem = isSystemArg;
-    return gcWeakKeys().init();
+    regExps_.ref() = make_unique<RegExpZone>(this);
+    return regExps_.ref() && gcWeakKeys().init();
 }
 
 void
 Zone::setNeedsIncrementalBarrier(bool needs)
 {
     MOZ_ASSERT_IF(needs, canCollect());
     needsIncrementalBarrier_ = needs;
 }
@@ -352,17 +352,17 @@ Zone::nextZone() const
 {
     MOZ_ASSERT(isOnList());
     return listNext_;
 }
 
 void
 Zone::clearTables()
 {
-    MOZ_ASSERT(regExps.empty());
+    MOZ_ASSERT(regExps().empty());
 
     baseShapes().clear();
     initialShapes().clear();
 }
 
 void
 Zone::fixupAfterMovingGC()
 {
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -9,22 +9,22 @@
 
 #include "mozilla/Atomics.h"
 #include "mozilla/HashFunctions.h"
 
 #include "gc/FindSCCs.h"
 #include "gc/GCRuntime.h"
 #include "js/GCHashTable.h"
 #include "vm/MallocProvider.h"
-#include "vm/RegExpShared.h"
 #include "vm/Runtime.h"
 
 namespace js {
 
 class Debugger;
+class RegExpZone;
 
 namespace jit {
 class JitZone;
 } // namespace jit
 
 namespace gc {
 
 struct ZoneComponentFinder : public ComponentFinder<JS::Zone, ZoneComponentFinder>
@@ -454,18 +454,20 @@ class Zone : public JS::shadow::Zone,
                                   counter.bytes(), counter.maxBytes()))
         {
             return;
         }
 
         counter.recordTrigger(trigger);
     }
 
+    js::MainThreadData<js::UniquePtr<js::RegExpZone>> regExps_;
+
   public:
-    js::RegExpZone regExps;
+    js::RegExpZone& regExps() { return *regExps_.ref(); }
 
     JS::WeakCache<TypeDescrObjectSet>& typeDescrObjects() { return typeDescrObjects_.ref(); }
 
     bool addTypeDescrObject(JSContext* cx, HandleObject obj);
 
     void setGCMaxMallocBytes(size_t value, const js::AutoLockGC& lock) {
         gcMallocCounter.setMax(value, lock);
     }
--- a/js/src/proxy/CrossCompartmentWrapper.cpp
+++ b/js/src/proxy/CrossCompartmentWrapper.cpp
@@ -452,17 +452,17 @@ CrossCompartmentWrapper::regexp_toShared
         re = Wrapper::regexp_toShared(cx, wrapper);
         if (!re)
             return nullptr;
     }
 
     // Get an equivalent RegExpShared associated with the current compartment.
     RootedAtom source(cx, re->getSource());
     cx->markAtom(source);
-    return cx->zone()->regExps.get(cx, source, re->getFlags());
+    return cx->zone()->regExps().get(cx, source, re->getFlags());
 }
 
 bool
 CrossCompartmentWrapper::boxedValue_unbox(JSContext* cx, HandleObject wrapper, MutableHandleValue vp) const
 {
     PIERCE(cx, wrapper,
            NOTHING,
            Wrapper::boxedValue_unbox(cx, wrapper, vp),
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -282,17 +282,17 @@ RegExpObject::create(JSContext* cx, Hand
     return regexp;
 }
 
 /* static */ RegExpShared*
 RegExpObject::createShared(JSContext* cx, Handle<RegExpObject*> regexp)
 {
     MOZ_ASSERT(!regexp->hasShared());
     RootedAtom source(cx, regexp->getSource());
-    RegExpShared* shared = cx->zone()->regExps.get(cx, source, regexp->getFlags());
+    RegExpShared* shared = cx->zone()->regExps().get(cx, source, regexp->getFlags());
     if (!shared)
         return nullptr;
 
     regexp->setShared(*shared);
     return shared;
 }
 
 Shape*
--- a/js/src/vm/RegExpStatics.cpp
+++ b/js/src/vm/RegExpStatics.cpp
@@ -77,17 +77,17 @@ RegExpStatics::executeLazy(JSContext* cx
         return true;
 
     MOZ_ASSERT(lazySource);
     MOZ_ASSERT(matchesInput);
     MOZ_ASSERT(lazyIndex != size_t(-1));
 
     /* Retrieve or create the RegExpShared in this zone. */
     RootedAtom source(cx, lazySource);
-    RootedRegExpShared shared(cx, cx->zone()->regExps.get(cx, source, lazyFlags));
+    RootedRegExpShared shared(cx, cx->zone()->regExps().get(cx, source, lazyFlags));
     if (!shared)
         return false;
 
     /*
      * It is not necessary to call aboutToWrite(): evaluation of
      * implicit copies is safe.
      */
 
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -4627,17 +4627,17 @@ Zone::addSizeOfIncludingThis(mozilla::Ma
                              size_t* uniqueIdMap,
                              size_t* shapeTables,
                              size_t* atomsMarkBitmaps,
                              size_t* compartmentObjects,
                              size_t* crossCompartmentWrappersTables,
                              size_t* compartmentsPrivateData)
 {
     *typePool += types.typeLifoAlloc().sizeOfExcludingThis(mallocSizeOf);
-    *regexpZone += regExps.sizeOfExcludingThis(mallocSizeOf);
+    *regexpZone += regExps().sizeOfExcludingThis(mallocSizeOf);
     if (jitZone_)
         jitZone_->addSizeOfIncludingThis(mallocSizeOf, jitZone, baselineStubsOptimized, cachedCFG);
     *uniqueIdMap += uniqueIds().shallowSizeOfExcludingThis(mallocSizeOf);
     *shapeTables += baseShapes().sizeOfExcludingThis(mallocSizeOf)
                   + initialShapes().sizeOfExcludingThis(mallocSizeOf);
     *atomsMarkBitmaps += markedAtoms().sizeOfExcludingThis(mallocSizeOf);
 
     for (CompartmentsInZoneIter comp(this); !comp.done(); comp.next()) {