Bug 903519 - Reparent JSString from TenuredCell to Cell, r=jonco
authorSteve Fink <sfink@mozilla.com>
Mon, 12 Jun 2017 15:38:51 -0700
changeset 456312 a59293001f00865439b5fe73f7796af1b7bdd04d
parent 456311 5acea87ec5dde79c71f2b97a699dea8a9b6e34bc
child 456313 84c7cf744deca855af00faf04c0d4bb859c8de31
push id8799
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 16:46:23 +0000
treeherdermozilla-beta@15334014dc67 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs903519
milestone60.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 903519 - Reparent JSString from TenuredCell to Cell, r=jonco
js/src/gc/AtomMarking-inl.h
js/src/gc/AtomMarking.cpp
js/src/gc/Marking.cpp
js/src/jsgcinlines.h
js/src/vm/String.h
--- a/js/src/gc/AtomMarking-inl.h
+++ b/js/src/gc/AtomMarking-inl.h
@@ -38,27 +38,28 @@ template <typename T>
 MOZ_ALWAYS_INLINE void
 AtomMarkingRuntime::inlinedMarkAtom(JSContext* cx, T* thing)
 {
     static_assert(mozilla::IsSame<T, JSAtom>::value ||
                   mozilla::IsSame<T, JS::Symbol>::value,
                   "Should only be called with JSAtom* or JS::Symbol* argument");
 
     MOZ_ASSERT(thing);
-    MOZ_ASSERT(thing->zoneFromAnyThread()->isAtomsZone());
+    js::gc::TenuredCell* cell = &thing->asTenured();
+    MOZ_ASSERT(cell->zoneFromAnyThread()->isAtomsZone());
 
     // The context's zone will be null during initialization of the runtime.
     if (!cx->zone())
         return;
     MOZ_ASSERT(!cx->zone()->isAtomsZone());
 
     if (ThingIsPermanent(thing))
         return;
 
-    size_t bit = GetAtomBit(thing);
+    size_t bit = GetAtomBit(cell);
     MOZ_ASSERT(bit / JS_BITS_PER_WORD < allocatedWords);
 
     cx->zone()->markedAtoms().setBit(bit);
 
     if (!cx->helperThread()) {
         // Trigger a read barrier on the atom, in case there is an incremental
         // GC in progress. This is necessary if the atom is being marked
         // because a reference to it was obtained from another zone which is
--- a/js/src/gc/AtomMarking.cpp
+++ b/js/src/gc/AtomMarking.cpp
@@ -218,33 +218,35 @@ AtomMarkingRuntime::atomIsMarked(Zone* z
         return true;
 
     if (mozilla::IsSame<T, JSAtom>::value) {
         JSAtom* atom = reinterpret_cast<JSAtom*>(thing);
         if (AtomIsPinnedInRuntime(zone->runtimeFromAnyThread(), atom))
             return true;
     }
 
-    size_t bit = GetAtomBit(thing);
+    size_t bit = GetAtomBit(&thing->asTenured());
     return zone->markedAtoms().getBit(bit);
 }
 
 template bool AtomMarkingRuntime::atomIsMarked(Zone* zone, JSAtom* thing);
 template bool AtomMarkingRuntime::atomIsMarked(Zone* zone, JS::Symbol* thing);
 
 template<>
 bool
 AtomMarkingRuntime::atomIsMarked(Zone* zone, TenuredCell* thing)
 {
     if (!thing)
         return true;
 
     if (thing->is<JSString>()) {
         JSString* str = thing->as<JSString>();
-        return str->isAtom() ? atomIsMarked(zone, &str->asAtom()) : true;
+        if (!str->isAtom())
+            return true;
+        return atomIsMarked(zone, &str->asAtom());
     }
 
     if (thing->is<JS::Symbol>())
         return atomIsMarked(zone, thing->as<JS::Symbol>());
 
     return true;
 }
 
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -620,17 +620,17 @@ js::TraceProcessGlobalRoot(JSTracer* trc
     // We have to mark permanent atoms and well-known symbols through a special
     // method because the default DoMarking implementation automatically skips
     // them. Fortunately, atoms (permanent and non) cannot refer to other GC
     // things so they do not need to go through the mark stack and may simply
     // be marked directly.  Moreover, well-known symbols can refer only to
     // permanent atoms, so likewise require no subsquent marking.
     CheckTracedThing(trc, *ConvertToBase(&thing));
     if (trc->isMarkingTracer())
-        thing->markIfUnmarked(gc::MarkColor::Black);
+        thing->asTenured().markIfUnmarked(gc::MarkColor::Black);
     else
         DoCallback(trc->asCallbackTracer(), ConvertToBase(&thing), name);
 }
 template void js::TraceProcessGlobalRoot<JSAtom>(JSTracer*, JSAtom*, const char*);
 template void js::TraceProcessGlobalRoot<JS::Symbol>(JSTracer*, JS::Symbol*, const char*);
 
 // A typed functor adaptor for TraceRoot.
 struct TraceRootFunctor {
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -162,17 +162,17 @@ class ArenaCellIterImpl
             ExposeGCThingToActiveJS(JS::GCCellPtr(cell, traceKind));
 
         return cell;
     }
 
     template<typename T> T* get() const {
         MOZ_ASSERT(!done());
         MOZ_ASSERT(JS::MapTypeToTraceKind<T>::kind == traceKind);
-        return static_cast<T*>(getCell());
+        return reinterpret_cast<T*>(getCell());
     }
 
     void next() {
         MOZ_ASSERT(!done());
         thing += thingSize;
         if (thing < ArenaSize)
             moveForwardIfFree();
     }
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -12,16 +12,17 @@
 #include "mozilla/Range.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "jsstr.h"
 
 #include "gc/Barrier.h"
 #include "gc/Heap.h"
+#include "gc/Cell.h"
 #include "gc/Rooting.h"
 #include "js/CharacterEncoding.h"
 #include "js/RootingAPI.h"
 
 #include "vm/Printer.h"
 
 class JSDependentString;
 class JSExtensibleString;
@@ -148,17 +149,17 @@ static const size_t UINT32_CHAR_BUFFER_L
  *
  * Derived string types can be queried from ancestor types via isX() and
  * retrieved with asX() debug-only-checked casts.
  *
  * The ensureX() operations mutate 'this' in place to effectively the type to be
  * at least X (e.g., ensureLinear will change a JSRope to be a JSFlatString).
  */
 
-class JSString : public js::gc::TenuredCell
+class JSString : public js::gc::Cell
 {
   protected:
     static const size_t NUM_INLINE_CHARS_LATIN1   = 2 * sizeof(void*) / sizeof(JS::Latin1Char);
     static const size_t NUM_INLINE_CHARS_TWO_BYTE = 2 * sizeof(void*) / sizeof(char16_t);
 
     /* Fields only apply to string types commented on the right. */
     struct Data
     {
@@ -525,16 +526,47 @@ class JSString : public js::gc::TenuredC
                       offsetof(JSString, d.s.u2.nonInlineCharsLatin1),
                       "nonInlineCharsTwoByte and nonInlineCharsLatin1 must have same offset");
         return offsetof(JSString, d.s.u2.nonInlineCharsTwoByte);
     }
 
   public:
     static const JS::TraceKind TraceKind = JS::TraceKind::String;
 
+    JS::Zone* zone() const {
+            return asTenured().zone();
+    }
+
+    // Implement TenuredZone members needed for template instantiations.
+
+    JS::Zone* zoneFromAnyThread() const {
+            return asTenured().zoneFromAnyThread();
+    }
+
+    void fixupAfterMovingGC() {}
+
+    js::gc::AllocKind getAllocKind() const {
+        using js::gc::AllocKind;
+        AllocKind kind;
+        if (isAtom())
+            if (isFatInline())
+                kind = AllocKind::FAT_INLINE_ATOM;
+            else
+                kind = AllocKind::ATOM;
+        else if (isFatInline())
+            kind = AllocKind::FAT_INLINE_STRING;
+        else if (isExternal())
+            kind = AllocKind::EXTERNAL_STRING;
+        else
+            kind = AllocKind::STRING;
+
+        MOZ_ASSERT_IF(isTenured(), kind == asTenured().getAllocKind());
+        return kind;
+    }
+
 #ifdef DEBUG
     void dump(); // Debugger-friendly stderr dump.
     void dump(js::GenericPrinter& out);
     void dumpNoNewline(js::GenericPrinter& out);
     void dumpCharsNoNewline(js::GenericPrinter& out);
     void dumpRepresentation(js::GenericPrinter& out, int indent) const;
     void dumpRepresentationHeader(js::GenericPrinter& out, int indent, const char* subclass) const;
 
@@ -545,26 +577,28 @@ class JSString : public js::gc::TenuredC
 #endif
 
     void traceChildren(JSTracer* trc);
 
     static MOZ_ALWAYS_INLINE void readBarrier(JSString* thing) {
         if (thing->isPermanentAtom())
             return;
 
-        TenuredCell::readBarrier(thing);
+        js::gc::TenuredCell::readBarrier(&thing->asTenured());
     }
 
     static MOZ_ALWAYS_INLINE void writeBarrierPre(JSString* thing) {
         if (!thing || thing->isPermanentAtom())
             return;
 
-        TenuredCell::writeBarrierPre(thing);
+        js::gc::TenuredCell::writeBarrierPre(&thing->asTenured());
     }
 
+    static void writeBarrierPost(void* ptr, JSString* prev, JSString* next) {};
+
   private:
     JSString() = delete;
     JSString(const JSString& other) = delete;
     void operator=(const JSString& other) = delete;
 };
 
 class JSRope : public JSString
 {
@@ -1583,9 +1617,27 @@ JSAtom::asPropertyName()
 {
 #ifdef DEBUG
     uint32_t dummy;
     MOZ_ASSERT(!isIndex(&dummy));
 #endif
     return static_cast<js::PropertyName*>(this);
 }
 
+namespace js {
+namespace gc {
+template<>
+inline JSString*
+Cell::as<JSString>() {
+    MOZ_ASSERT(is<JSString>());
+    return reinterpret_cast<JSString*>(this);
+}
+
+template<>
+inline JSString*
+TenuredCell::as<JSString>() {
+    MOZ_ASSERT(is<JSString>());
+    return reinterpret_cast<JSString*>(this);
+}
+}
+}
+
 #endif /* vm_String_h */