Bug 903519 - Reparent JSString from TenuredCell to Cell, r=jonco
☠☠ backed out by 65e92478e09d ☠ ☠
authorSteve Fink <sfink@mozilla.com>
Mon, 12 Jun 2017 15:38:51 -0700
changeset 450634 1fc5ee0d0116300963a2490fb485207eaa9ada02
parent 450633 9316d8f7b92ad2746505218b30fb8acd376e6edd
child 450635 80b9d97bf1fe4e23066f4ac7283ab276c3e942f0
push id8531
push userryanvm@gmail.com
push dateFri, 12 Jan 2018 16:47:01 +0000
treeherdermozilla-beta@0bc627ade5a0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs903519
milestone59.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
     {
@@ -520,16 +521,47 @@ class JSString : public js::gc::TenuredC
         static_assert(offsetof(JSString, d.s.u2.nonInlineCharsTwoByte) ==
                       offsetof(JSString, d.s.u2.nonInlineCharsLatin1),
                       "nonInlineCharsTwoByte and nonInlineCharsLatin1 must have same offset");
         return offsetof(JSString, d.s.u2.nonInlineCharsTwoByte);
     }
 
     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;
 
@@ -540,26 +572,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
 {
@@ -1562,9 +1596,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 */