Bug 1266107 - Update type descriptors first when compacting r=terrence
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 21 Apr 2016 11:06:29 +0100
changeset 332141 67aee454e51e22247ab45b54fdc6701d20584912
parent 332140 eeb033507f6a98b44ff57581b05acc469d838b39
child 332142 72615136e898b1dd36fe23e069288fd43feb2e02
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1266107
milestone48.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 1266107 - Update type descriptors first when compacting r=terrence
js/src/gc/GCRuntime.h
js/src/jsgc.cpp
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -964,16 +964,17 @@ class GCRuntime
     bool shouldCompact();
     void beginCompactPhase();
     IncrementalProgress compactPhase(JS::gcreason::Reason reason, SliceBudget& sliceBudget);
     void endCompactPhase(JS::gcreason::Reason reason);
     void sweepTypesAfterCompacting(Zone* zone);
     void sweepZoneAfterCompacting(Zone* zone);
     bool relocateArenas(Zone* zone, JS::gcreason::Reason reason, Arena*& relocatedListOut,
                         SliceBudget& sliceBudget);
+    void updateTypeDescrObjects(MovingTracer* trc, Zone* zone);
     void updateAllCellPointers(MovingTracer* trc, Zone* zone);
     void updatePointersToRelocatedCells(Zone* zone);
     void protectAndHoldArenas(Arena* arenaList);
     void unprotectHeldRelocatedArenas();
     void releaseRelocatedArenas(Arena* arenaList);
     void releaseRelocatedArenasWithoutUnlocking(Arena* arenaList, const AutoLockGC& lock);
     void finishCollection(JS::gcreason::Reason reason);
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2471,31 +2471,36 @@ GCRuntime::sweepZoneAfterCompacting(Zone
         c->sweepDebugScopes();
         c->sweepJitCompartment(fop);
         c->sweepNativeIterators();
         c->sweepTemplateObjects();
     }
 }
 
 template <typename T>
+static inline void
+UpdateCellPointers(MovingTracer* trc, T* cell)
+{
+    cell->fixupAfterMovingGC();
+    cell->traceChildren(trc);
+}
+
+template <typename T>
 static void
-UpdateCellPointersTyped(MovingTracer* trc, Arena* arena, JS::TraceKind traceKind)
-{
-    for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) {
-        T* cell = reinterpret_cast<T*>(i.getCell());
-        cell->fixupAfterMovingGC();
-        TraceChildren(trc, cell, traceKind);
-    }
+UpdateArenaPointersTyped(MovingTracer* trc, Arena* arena, JS::TraceKind traceKind)
+{
+    for (ArenaCellIterUnderGC i(arena); !i.done(); i.next())
+        UpdateCellPointers(trc, reinterpret_cast<T*>(i.getCell()));
 }
 
 /*
  * Update the internal pointers for all cells in an arena.
  */
 static void
-UpdateCellPointers(MovingTracer* trc, Arena* arena)
+UpdateArenaPointers(MovingTracer* trc, Arena* arena)
 {
     AllocKind kind = arena->getAllocKind();
     JS::TraceKind traceKind = MapAllocToTraceKind(kind);
 
     switch (kind) {
       case AllocKind::FUNCTION:
       case AllocKind::FUNCTION_EXTENDED:
       case AllocKind::OBJECT0:
@@ -2505,44 +2510,44 @@ UpdateCellPointers(MovingTracer* trc, Ar
       case AllocKind::OBJECT4:
       case AllocKind::OBJECT4_BACKGROUND:
       case AllocKind::OBJECT8:
       case AllocKind::OBJECT8_BACKGROUND:
       case AllocKind::OBJECT12:
       case AllocKind::OBJECT12_BACKGROUND:
       case AllocKind::OBJECT16:
       case AllocKind::OBJECT16_BACKGROUND:
-        UpdateCellPointersTyped<JSObject>(trc, arena, traceKind);
+        UpdateArenaPointersTyped<JSObject>(trc, arena, traceKind);
         return;
       case AllocKind::SCRIPT:
-        UpdateCellPointersTyped<JSScript>(trc, arena, traceKind);
+        UpdateArenaPointersTyped<JSScript>(trc, arena, traceKind);
         return;
       case AllocKind::LAZY_SCRIPT:
-        UpdateCellPointersTyped<LazyScript>(trc, arena, traceKind);
+        UpdateArenaPointersTyped<LazyScript>(trc, arena, traceKind);
         return;
       case AllocKind::SHAPE:
-        UpdateCellPointersTyped<Shape>(trc, arena, traceKind);
+        UpdateArenaPointersTyped<Shape>(trc, arena, traceKind);
         return;
       case AllocKind::ACCESSOR_SHAPE:
-        UpdateCellPointersTyped<AccessorShape>(trc, arena, traceKind);
+        UpdateArenaPointersTyped<AccessorShape>(trc, arena, traceKind);
         return;
       case AllocKind::BASE_SHAPE:
-        UpdateCellPointersTyped<BaseShape>(trc, arena, traceKind);
+        UpdateArenaPointersTyped<BaseShape>(trc, arena, traceKind);
         return;
       case AllocKind::OBJECT_GROUP:
-        UpdateCellPointersTyped<ObjectGroup>(trc, arena, traceKind);
+        UpdateArenaPointersTyped<ObjectGroup>(trc, arena, traceKind);
         return;
       case AllocKind::STRING:
-        UpdateCellPointersTyped<JSString>(trc, arena, traceKind);
+        UpdateArenaPointersTyped<JSString>(trc, arena, traceKind);
         return;
       case AllocKind::JITCODE:
-        UpdateCellPointersTyped<jit::JitCode>(trc, arena, traceKind);
+        UpdateArenaPointersTyped<jit::JitCode>(trc, arena, traceKind);
         return;
       default:
-        MOZ_CRASH("Invalid alloc kind for UpdateCellPointers");
+        MOZ_CRASH("Invalid alloc kind for UpdateArenaPointers");
     }
 }
 
 namespace js {
 namespace gc {
 
 struct ArenaListSegment
 {
@@ -2651,59 +2656,59 @@ ArenasToUpdate::getArenasToUpdate(AutoLo
         last = last->next;
         count++;
     }
 
     arena = last;
     return { begin, last->next };
 }
 
-struct UpdateCellPointersTask : public GCParallelTask
+struct UpdatePointersTask : public GCParallelTask
 {
     // Maximum number of arenas to update in one block.
 #ifdef DEBUG
     static const unsigned MaxArenasToProcess = 16;
 #else
     static const unsigned MaxArenasToProcess = 256;
 #endif
 
-    UpdateCellPointersTask(JSRuntime* rt, ArenasToUpdate* source, AutoLockHelperThreadState& lock)
+    UpdatePointersTask(JSRuntime* rt, ArenasToUpdate* source, AutoLockHelperThreadState& lock)
       : rt_(rt), source_(source)
     {}
 
-    ~UpdateCellPointersTask() override { join(); }
+    ~UpdatePointersTask() override { join(); }
 
   private:
     JSRuntime* rt_;
     ArenasToUpdate* source_;
     ArenaListSegment arenas_;
 
     virtual void run() override;
     bool getArenasToUpdate();
     void updateArenas();
 };
 
 bool
-UpdateCellPointersTask::getArenasToUpdate()
+UpdatePointersTask::getArenasToUpdate()
 {
     AutoLockHelperThreadState lock;
     arenas_ = source_->getArenasToUpdate(lock, MaxArenasToProcess);
     return arenas_.begin != nullptr;
 }
 
 void
-UpdateCellPointersTask::updateArenas()
+UpdatePointersTask::updateArenas()
 {
     MovingTracer trc(rt_);
     for (Arena* arena = arenas_.begin; arena != arenas_.end; arena = arena->next)
-        UpdateCellPointers(&trc, arena);
+        UpdateArenaPointers(&trc, arena);
 }
 
 /* virtual */ void
-UpdateCellPointersTask::run()
+UpdatePointersTask::run()
 {
     while (getArenasToUpdate())
         updateArenas();
 }
 
 } // namespace gc
 } // namespace js
 
@@ -2727,18 +2732,18 @@ GCRuntime::updateAllCellPointers(MovingT
 
     size_t bgTaskCount = CellUpdateBackgroundTaskCount();
 
     ArenasToUpdate
         fgArenas(zone, bgTaskCount == 0 ? ArenasToUpdate::ALL : ArenasToUpdate::FOREGROUND);
     ArenasToUpdate
         bgArenas(zone, bgTaskCount == 0 ? ArenasToUpdate::NONE : ArenasToUpdate::BACKGROUND);
 
-    Maybe<UpdateCellPointersTask> fgTask;
-    Maybe<UpdateCellPointersTask> bgTasks[MaxCellUpdateBackgroundTasks];
+    Maybe<UpdatePointersTask> fgTask;
+    Maybe<UpdatePointersTask> bgTasks[MaxCellUpdateBackgroundTasks];
 
     size_t tasksStarted = 0;
 
     {
         AutoLockHelperThreadState lock;
 
         fgTask.emplace(rt, &fgArenas, lock);
 
@@ -2754,16 +2759,24 @@ GCRuntime::updateAllCellPointers(MovingT
     {
         AutoLockHelperThreadState lock;
 
         for (size_t i = 0; i < tasksStarted; i++)
             joinTask(*bgTasks[i], gcstats::PHASE_COMPACT_UPDATE_CELLS);
     }
 }
 
+void
+GCRuntime::updateTypeDescrObjects(MovingTracer* trc, Zone* zone)
+{
+    zone->typeDescrObjects.sweep();
+    for (auto r = zone->typeDescrObjects.all(); !r.empty(); r.popFront())
+        UpdateCellPointers(trc, r.front().get());
+}
+
 /*
  * Update pointers to relocated cells by doing a full heap traversal and sweep.
  *
  * The latter is necessary to update weak references which are not marked as
  * part of the traversal.
  */
 void
 GCRuntime::updatePointersToRelocatedCells(Zone* zone)
@@ -2775,16 +2788,20 @@ GCRuntime::updatePointersToRelocatedCell
     MovingTracer trc(rt);
 
     // Fixup compartment global pointers as these get accessed during marking.
     for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
         comp->fixupAfterMovingGC();
     JSCompartment::fixupCrossCompartmentWrappersAfterMovingGC(&trc);
     rt->spsProfiler.fixupStringsMapAfterMovingGC();
 
+    // Update TypeDescrs before all other objects as typed objects access these
+    // objects when we trace them.
+    updateTypeDescrObjects(&trc, zone);
+
     // Iterate through all cells that can contain relocatable pointers to update
     // them. Since updating each cell is independent we try to parallelize this
     // as much as possible.
     updateAllCellPointers(&trc, zone);
 
     // Mark roots to update them.
     {
         markRuntime(&trc, MarkRuntime);