Bug 921923 (part 2) - Make multi-output sizeOfFoo() functions more consistent in js/src/. r=till.
authorNicholas Nethercote <nnethercote@mozilla.com>
Mon, 30 Sep 2013 16:20:18 -0700
changeset 149390 bfcf75eac94306dc47f455f3eb33445558cc88ef
parent 149389 71c3fc0820385bef18b05957301075d7a02ea7b6
child 149391 d1e2767da13f9c898b4ff38f3ce145802eb59c55
push id34546
push usernnethercote@mozilla.com
push dateTue, 01 Oct 2013 02:34:33 +0000
treeherdermozilla-inbound@613810e31754 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill
bugs921923
milestone27.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 921923 (part 2) - Make multi-output sizeOfFoo() functions more consistent in js/src/. r=till.
js/src/assembler/jit/ExecutableAllocator.cpp
js/src/assembler/jit/ExecutableAllocator.h
js/src/gc/Zone.h
js/src/jit/AsmJSModule.cpp
js/src/jit/AsmJSModule.h
js/src/jit/BaselineJIT.cpp
js/src/jit/BaselineJIT.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsinfer.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/vm/MemoryMetrics.cpp
js/src/vm/Runtime.cpp
js/src/vm/Runtime.h
js/src/vm/Shape.h
--- a/js/src/assembler/jit/ExecutableAllocator.cpp
+++ b/js/src/assembler/jit/ExecutableAllocator.cpp
@@ -37,17 +37,17 @@ size_t ExecutableAllocator::pageSize = 0
 size_t ExecutableAllocator::largeAllocSize = 0;
 
 ExecutablePool::~ExecutablePool()
 {
     m_allocator->releasePoolPages(this);
 }
 
 void
-ExecutableAllocator::sizeOfCode(JS::CodeSizes *sizes) const
+ExecutableAllocator::addSizeOfCode(JS::CodeSizes *sizes) const
 {
     if (m_pools.initialized()) {
         for (ExecPoolHashSet::Range r = m_pools.all(); !r.empty(); r.popFront()) {
             ExecutablePool* pool = r.front();
             sizes->ion      += pool->m_ionCodeBytes;
             sizes->baseline += pool->m_baselineCodeBytes;
             sizes->regexp   += pool->m_regexpCodeBytes;
             sizes->other    += pool->m_otherCodeBytes;
--- a/js/src/assembler/jit/ExecutableAllocator.h
+++ b/js/src/assembler/jit/ExecutableAllocator.h
@@ -252,17 +252,17 @@ public:
         JS_ASSERT(pool->m_allocation.pages);
         if (destroyCallback)
             destroyCallback(pool->m_allocation.pages, pool->m_allocation.size);
         systemRelease(pool->m_allocation);
         JS_ASSERT(m_pools.initialized());
         m_pools.remove(m_pools.lookup(pool));   // this asserts if |pool| is not in m_pools
     }
 
-    void sizeOfCode(JS::CodeSizes *sizes) const;
+    void addSizeOfCode(JS::CodeSizes *sizes) const;
     void toggleAllCodeAsAccessible(bool accessible);
     bool codeContains(char* address);
 
     void setDestroyCallback(DestroyCallback destroyCallback) {
         this->destroyCallback = destroyCallback;
     }
 
     void setRandomize(bool enabled) {
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -255,17 +255,17 @@ struct Zone : public JS::shadow::Zone,
     Zone(JSRuntime *rt);
     ~Zone();
     bool init(JSContext *cx);
 
     void findOutgoingEdges(js::gc::ComponentFinder<JS::Zone> &finder);
 
     void discardJitCode(js::FreeOp *fop, bool discardConstraints);
 
-    void sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t *typePool);
+    void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t *typePool);
 
     void setGCLastBytes(size_t lastBytes, js::JSGCInvocationKind gckind);
     void reduceGCTriggerBytes(size_t amount);
 
     void resetGCMallocBytes();
     void setGCMaxMallocBytes(size_t value);
     void updateMallocCounter(size_t nbytes) {
         /*
--- a/js/src/jit/AsmJSModule.cpp
+++ b/js/src/jit/AsmJSModule.cpp
@@ -320,33 +320,33 @@ AsmJSModule::~AsmJSModule()
         DeallocateExecutableMemory(code_, pod.totalBytes_);
     }
 
     for (size_t i = 0; i < numFunctionCounts(); i++)
         js_delete(functionCounts(i));
 }
 
 void
-AsmJSModule::sizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, size_t *asmJSModuleCode,
-                        size_t *asmJSModuleData)
+AsmJSModule::addSizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, size_t *asmJSModuleCode,
+                           size_t *asmJSModuleData)
 {
-    *asmJSModuleCode = pod.totalBytes_;
-    *asmJSModuleData = mallocSizeOf(this) +
-                       globals_.sizeOfExcludingThis(mallocSizeOf) +
-                       exits_.sizeOfExcludingThis(mallocSizeOf) +
-                       exports_.sizeOfExcludingThis(mallocSizeOf) +
-                       heapAccesses_.sizeOfExcludingThis(mallocSizeOf) +
+    *asmJSModuleCode += pod.totalBytes_;
+    *asmJSModuleData += mallocSizeOf(this) +
+                        globals_.sizeOfExcludingThis(mallocSizeOf) +
+                        exits_.sizeOfExcludingThis(mallocSizeOf) +
+                        exports_.sizeOfExcludingThis(mallocSizeOf) +
+                        heapAccesses_.sizeOfExcludingThis(mallocSizeOf) +
 #if defined(MOZ_VTUNE)
-                       profiledFunctions_.sizeOfExcludingThis(mallocSizeOf) +
+                        profiledFunctions_.sizeOfExcludingThis(mallocSizeOf) +
 #endif
 #if defined(JS_ION_PERF)
-                       profiledFunctions_.sizeOfExcludingThis(mallocSizeOf) +
-                       perfProfiledBlocksFunctions_.sizeOfExcludingThis(mallocSizeOf) +
+                        profiledFunctions_.sizeOfExcludingThis(mallocSizeOf) +
+                        perfProfiledBlocksFunctions_.sizeOfExcludingThis(mallocSizeOf) +
 #endif
-                       functionCounts_.sizeOfExcludingThis(mallocSizeOf);
+                        functionCounts_.sizeOfExcludingThis(mallocSizeOf);
 }
 
 static void
 AsmJSModuleObject_finalize(FreeOp *fop, JSObject *obj)
 {
     fop->delete_(&obj->as<AsmJSModuleObject>().module());
 }
 
--- a/js/src/jit/AsmJSModule.h
+++ b/js/src/jit/AsmJSModule.h
@@ -735,19 +735,18 @@ class AsmJSModule
     PropertyName *bufferArgumentName() const {
         return bufferArgumentName_;
     }
 
     void detachIonCompilation(size_t exitIndex) const {
         exitIndexToGlobalDatum(exitIndex).exit = interpExitTrampoline(exit(exitIndex));
     }
 
-    // Part of about:memory reporting:
-    void sizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, size_t *asmJSModuleCode,
-                    size_t *asmJSModuleData);
+    void addSizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, size_t *asmJSModuleCode,
+                       size_t *asmJSModuleData);
 };
 
 // An AsmJSModuleObject is an internal implementation object (i.e., not exposed
 // directly to user script) which manages the lifetime of an AsmJSModule. A
 // JSObject is necessary since we want LinkAsmJS/CallAsmJS JSFunctions to be
 // able to point to their module via their extended slots.
 class AsmJSModuleObject : public JSObject
 {
@@ -757,19 +756,19 @@ class AsmJSModuleObject : public JSObjec
     static const unsigned RESERVED_SLOTS = 1;
 
     // On success, return an AsmJSModuleClass JSObject that has taken ownership
     // (and release()ed) the given module.
     static AsmJSModuleObject *create(ExclusiveContext *cx, ScopedJSDeletePtr<AsmJSModule> *module);
 
     AsmJSModule &module() const;
 
-    void sizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, size_t *asmJSModuleCode,
-                    size_t *asmJSModuleData) {
-        module().sizeOfMisc(mallocSizeOf, asmJSModuleCode, asmJSModuleData);
+    void addSizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, size_t *asmJSModuleCode,
+                       size_t *asmJSModuleData) {
+        module().addSizeOfMisc(mallocSizeOf, asmJSModuleCode, asmJSModuleData);
     }
 
     static const Class class_;
 };
 
 }  // namespace js
 
 #endif  // JS_ION
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -877,24 +877,21 @@ jit::IonCompartment::toggleBaselineStubB
 {
     for (ICStubCodeMap::Enum e(*stubCodes_); !e.empty(); e.popFront()) {
         IonCode *code = *e.front().value.unsafeGet();
         code->togglePreBarriers(enabled);
     }
 }
 
 void
-jit::SizeOfBaselineData(JSScript *script, mozilla::MallocSizeOf mallocSizeOf, size_t *data,
-                        size_t *fallbackStubs)
+jit::AddSizeOfBaselineData(JSScript *script, mozilla::MallocSizeOf mallocSizeOf, size_t *data,
+                           size_t *fallbackStubs)
 {
-    *data = 0;
-    *fallbackStubs = 0;
-
     if (script->hasBaselineScript())
-        script->baselineScript()->sizeOfIncludingThis(mallocSizeOf, data, fallbackStubs);
+        script->baselineScript()->addSizeOfIncludingThis(mallocSizeOf, data, fallbackStubs);
 }
 
 void
 jit::ToggleBaselineSPS(JSRuntime *runtime, bool enable)
 {
     for (ZonesIter zone(runtime); !zone.done(); zone.next()) {
         for (gc::CellIter i(zone, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
             JSScript *script = i.get<JSScript>();
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -157,23 +157,23 @@ struct BaselineScript
     static void Destroy(FreeOp *fop, BaselineScript *script);
 
     void purgeOptimizedStubs(Zone *zone);
 
     static inline size_t offsetOfMethod() {
         return offsetof(BaselineScript, method_);
     }
 
-    void sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t *data,
-                             size_t *fallbackStubs) const {
-        *data = mallocSizeOf(this);
+    void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t *data,
+                                size_t *fallbackStubs) const {
+        *data += mallocSizeOf(this);
 
-        // data already includes the ICStubSpace itself, so use
+        // |data| already includes the ICStubSpace itself, so use
         // sizeOfExcludingThis.
-        *fallbackStubs = fallbackStubSpace_.sizeOfExcludingThis(mallocSizeOf);
+        *fallbackStubs += fallbackStubSpace_.sizeOfExcludingThis(mallocSizeOf);
     }
 
     bool active() const {
         return flags_ & ACTIVE;
     }
     void setActive() {
         flags_ |= ACTIVE;
     }
@@ -288,18 +288,18 @@ EnterBaselineMethod(JSContext *cx, RunSt
 
 IonExecStatus
 EnterBaselineAtBranch(JSContext *cx, StackFrame *fp, jsbytecode *pc);
 
 void
 FinishDiscardBaselineScript(FreeOp *fop, JSScript *script);
 
 void
-SizeOfBaselineData(JSScript *script, mozilla::MallocSizeOf mallocSizeOf, size_t *data,
-                   size_t *fallbackStubs);
+AddSizeOfBaselineData(JSScript *script, mozilla::MallocSizeOf mallocSizeOf, size_t *data,
+                      size_t *fallbackStubs);
 
 void
 ToggleBaselineSPS(JSRuntime *runtime, bool enable);
 
 struct BaselineBailoutInfo
 {
     // Pointer into the current C stack, where overwriting will start.
     uint8_t *incomingStack;
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -847,36 +847,39 @@ JSCompartment::clearTraps(FreeOp *fop)
     for (gc::CellIter i(zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
         JSScript *script = i.get<JSScript>();
         if (script->compartment() == this && script->hasAnyBreakpointsOrStepMode())
             script->clearTraps(fop);
     }
 }
 
 void
-JSCompartment::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t *compartmentObject,
-                                   JS::TypeInferenceSizes *tiSizes, size_t *shapesCompartmentTables,
-                                   size_t *crossCompartmentWrappersArg, size_t *regexpCompartment,
-                                   size_t *debuggeesSet, size_t *baselineStubsOptimized)
+JSCompartment::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
+                                      size_t *compartmentObject,
+                                      JS::TypeInferenceSizes *tiSizes,
+                                      size_t *shapesCompartmentTables,
+                                      size_t *crossCompartmentWrappersArg,
+                                      size_t *regexpCompartment,
+                                      size_t *debuggeesSet,
+                                      size_t *baselineStubsOptimized)
 {
-    *compartmentObject = mallocSizeOf(this);
-    sizeOfTypeInferenceData(tiSizes, mallocSizeOf);
-    *shapesCompartmentTables = baseShapes.sizeOfExcludingThis(mallocSizeOf)
-                             + initialShapes.sizeOfExcludingThis(mallocSizeOf)
-                             + newTypeObjects.sizeOfExcludingThis(mallocSizeOf)
-                             + lazyTypeObjects.sizeOfExcludingThis(mallocSizeOf);
-    *crossCompartmentWrappersArg = crossCompartmentWrappers.sizeOfExcludingThis(mallocSizeOf);
-    *regexpCompartment = regExps.sizeOfExcludingThis(mallocSizeOf);
-    *debuggeesSet = debuggees.sizeOfExcludingThis(mallocSizeOf);
+    *compartmentObject += mallocSizeOf(this);
+    addSizeOfTypeInferenceData(mallocSizeOf, tiSizes);
+    *shapesCompartmentTables += baseShapes.sizeOfExcludingThis(mallocSizeOf)
+                              + initialShapes.sizeOfExcludingThis(mallocSizeOf)
+                              + newTypeObjects.sizeOfExcludingThis(mallocSizeOf)
+                              + lazyTypeObjects.sizeOfExcludingThis(mallocSizeOf);
+    *crossCompartmentWrappersArg += crossCompartmentWrappers.sizeOfExcludingThis(mallocSizeOf);
+    *regexpCompartment += regExps.sizeOfExcludingThis(mallocSizeOf);
+    *debuggeesSet += debuggees.sizeOfExcludingThis(mallocSizeOf);
 #ifdef JS_ION
-    *baselineStubsOptimized = ionCompartment()
-        ? ionCompartment()->optimizedStubSpace()->sizeOfExcludingThis(mallocSizeOf)
-        : 0;
-#else
-    *baselineStubsOptimized = 0;
+    if (ionCompartment()) {
+        *baselineStubsOptimized +=
+            ionCompartment()->optimizedStubSpace()->sizeOfExcludingThis(mallocSizeOf);
+    }
 #endif
 }
 
 void
 JSCompartment::adoptWorkerAllocator(Allocator *workerAllocator)
 {
     zone()->allocator.arenas.adoptArenas(runtimeFromMainThread(), &workerAllocator->arenas);
 }
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -215,24 +215,28 @@ struct JSCompartment
      * compartment's global to the store buffer since the last minor GC.
      *
      * This is used to avoid adding it to the store buffer on every write, which
      * can quickly fill the buffer and also cause performance problems.
      */
     bool                         globalWriteBarriered;
 
   private:
-    void sizeOfTypeInferenceData(JS::TypeInferenceSizes *stats, mozilla::MallocSizeOf mallocSizeOf);
+    void addSizeOfTypeInferenceData(mozilla::MallocSizeOf mallocSizeOf,
+                                    JS::TypeInferenceSizes *stats);
 
   public:
-    void sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t *compartmentObject,
-                             JS::TypeInferenceSizes *tiSizes,
-                             size_t *shapesCompartmentTables, size_t *crossCompartmentWrappers,
-                             size_t *regexpCompartment, size_t *debuggeesSet,
-                             size_t *baselineStubsOptimized);
+    void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
+                                size_t *compartmentObject,
+                                JS::TypeInferenceSizes *tiSizes,
+                                size_t *shapesCompartmentTables,
+                                size_t *crossCompartmentWrappers,
+                                size_t *regexpCompartment,
+                                size_t *debuggeesSet,
+                                size_t *baselineStubsOptimized);
 
     /*
      * Shared scope property tree, and arena-pool for allocating its nodes.
      */
     js::PropertyTree             propertyTree;
 
     /* Set of all unowned base shapes in the compartment. */
     js::BaseShapeSet             baseShapes;
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -3850,51 +3850,52 @@ TypeScript::AddFreezeConstraints(JSConte
     for (size_t i = 0; i < count; i++) {
         TypeSet *types = &array[i];
         JS_ASSERT(types->isStackSet());
         types->add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeStack>(script), false);
     }
 }
 
 static void
-SizeOfScriptTypeInferenceData(JSScript *script, JS::TypeInferenceSizes *sizes,
-                              mozilla::MallocSizeOf mallocSizeOf)
+AddSizeOfScriptTypeInferenceData(JSScript *script, JS::TypeInferenceSizes *sizes,
+                                 mozilla::MallocSizeOf mallocSizeOf)
 {
     TypeScript *typeScript = script->types;
     if (!typeScript)
         return;
 
     /* If TI is disabled, a single TypeScript is still present. */
     if (!script->compartment()->zone()->types.inferenceEnabled) {
         sizes->typeScripts += mallocSizeOf(typeScript);
         return;
     }
 
     sizes->typeScripts += mallocSizeOf(typeScript);
 }
 
 void
-Zone::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t *typePool)
+Zone::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t *typePool)
 {
     *typePool += types.typeLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
 }
 
 void
-JSCompartment::sizeOfTypeInferenceData(JS::TypeInferenceSizes *sizes, mozilla::MallocSizeOf mallocSizeOf)
+JSCompartment::addSizeOfTypeInferenceData(mozilla::MallocSizeOf mallocSizeOf,
+                                          JS::TypeInferenceSizes *sizes)
 {
     /* Pending arrays are cleared on GC along with the analysis pool. */
     sizes->pendingArrays += mallocSizeOf(types.pendingArray);
 
     /* TypeCompartment::pendingRecompiles is non-NULL only while inference code is running. */
     JS_ASSERT(!types.pendingRecompiles);
 
     for (gc::CellIter i(zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
         JSScript *script = i.get<JSScript>();
         if (script->compartment() == this)
-            SizeOfScriptTypeInferenceData(script, sizes, mallocSizeOf);
+            AddSizeOfScriptTypeInferenceData(script, sizes, mallocSizeOf);
     }
 
     if (types.allocationSiteTable)
         sizes->allocationSiteTables += types.allocationSiteTable->sizeOfIncludingThis(mallocSizeOf);
 
     if (types.arrayTypeTable)
         sizes->arrayTypeTables += types.arrayTypeTable->sizeOfIncludingThis(mallocSizeOf);
 
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -5566,50 +5566,50 @@ js_DumpBacktrace(JSContext *cx)
         JSScript *script = i.script();
         sprinter.printf("#%d %14p   %s:%d (%p @ %d)\n",
                         depth, (i.isJit() ? 0 : i.interpFrame()), filename, line,
                         script, i.pc() - script->code);
     }
     fprintf(stdout, "%s", sprinter.string());
 }
 void
-JSObject::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ObjectsExtraSizes *sizes)
+JSObject::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ObjectsExtraSizes *sizes)
 {
     if (hasDynamicSlots())
-        sizes->mallocHeapSlots = mallocSizeOf(slots);
+        sizes->mallocHeapSlots += mallocSizeOf(slots);
 
     if (hasDynamicElements()) {
         js::ObjectElements *elements = getElementsHeader();
         if (JS_UNLIKELY(elements->isAsmJSArrayBuffer())) {
 #if defined (JS_CPU_X64)
             // On x64, ArrayBufferObject::prepareForAsmJS switches the
             // ArrayBufferObject to use mmap'd storage.
-            sizes->nonHeapElementsAsmJS = as<ArrayBufferObject>().byteLength();
+            sizes->nonHeapElementsAsmJS += as<ArrayBufferObject>().byteLength();
 #else
-            sizes->mallocHeapElementsAsmJS = mallocSizeOf(elements);
+            sizes->mallocHeapElementsAsmJS += mallocSizeOf(elements);
 #endif
         } else {
-            sizes->mallocHeapElementsNonAsmJS = mallocSizeOf(elements);
+            sizes->mallocHeapElementsNonAsmJS += mallocSizeOf(elements);
         }
     }
 
     // Other things may be measured in the future if DMD indicates it is worthwhile.
     // Note that sizes->private_ is measured elsewhere.
     if (is<ArgumentsObject>()) {
-        sizes->mallocHeapArgumentsData = as<ArgumentsObject>().sizeOfMisc(mallocSizeOf);
+        sizes->mallocHeapArgumentsData += as<ArgumentsObject>().sizeOfMisc(mallocSizeOf);
     } else if (is<RegExpStaticsObject>()) {
-        sizes->mallocHeapRegExpStatics = as<RegExpStaticsObject>().sizeOfData(mallocSizeOf);
+        sizes->mallocHeapRegExpStatics += as<RegExpStaticsObject>().sizeOfData(mallocSizeOf);
     } else if (is<PropertyIteratorObject>()) {
-        sizes->mallocHeapPropertyIteratorData = as<PropertyIteratorObject>().sizeOfMisc(mallocSizeOf);
+        sizes->mallocHeapPropertyIteratorData += as<PropertyIteratorObject>().sizeOfMisc(mallocSizeOf);
 #ifdef JS_ION
     } else if (is<AsmJSModuleObject>()) {
-        as<AsmJSModuleObject>().sizeOfMisc(mallocSizeOf, &sizes->nonHeapCodeAsmJS,
-                                           &sizes->mallocHeapAsmJSModuleData);
+        as<AsmJSModuleObject>().addSizeOfMisc(mallocSizeOf, &sizes->nonHeapCodeAsmJS,
+                                              &sizes->mallocHeapAsmJSModuleData);
 #endif
 #ifdef JS_HAS_CTYPES
     } else {
         // This must be the last case.
-        sizes->mallocHeapCtypesData =
+        sizes->mallocHeapCtypesData +=
             js::SizeOfDataIfCDataObject(mallocSizeOf, const_cast<JSObject *>(this));
 #endif
     }
 }
 
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -338,17 +338,17 @@ class JSObject : public js::ObjectImpl
     uint32_t propertyCount() const {
         return lastProperty()->entryCount();
     }
 
     bool hasShapeTable() const {
         return lastProperty()->hasTable();
     }
 
-    void sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ObjectsExtraSizes *sizes);
+    void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ObjectsExtraSizes *sizes);
 
     bool hasIdempotentProtoChain() const;
 
     static const uint32_t MAX_FIXED_SLOTS = 16;
 
   public:
 
     /* Accessors for properties. */
--- a/js/src/vm/MemoryMetrics.cpp
+++ b/js/src/vm/MemoryMetrics.cpp
@@ -187,42 +187,41 @@ StatsZoneCallback(JSRuntime *rt, void *d
     RuntimeStats *rtStats = static_cast<StatsClosure *>(data)->rtStats;
 
     // CollectRuntimeStats reserves enough space.
     MOZ_ALWAYS_TRUE(rtStats->zoneStatsVector.growBy(1));
     ZoneStats &zStats = rtStats->zoneStatsVector.back();
     rtStats->initExtraZoneStats(zone, &zStats);
     rtStats->currZoneStats = &zStats;
 
-    zone->sizeOfIncludingThis(rtStats->mallocSizeOf_,
-                              &zStats.typePool);
+    zone->addSizeOfIncludingThis(rtStats->mallocSizeOf_, &zStats.typePool);
 }
 
 static void
 StatsCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment)
 {
     // Append a new CompartmentStats to the vector.
     RuntimeStats *rtStats = static_cast<StatsClosure *>(data)->rtStats;
 
     // CollectRuntimeStats reserves enough space.
     MOZ_ALWAYS_TRUE(rtStats->compartmentStatsVector.growBy(1));
     CompartmentStats &cStats = rtStats->compartmentStatsVector.back();
     rtStats->initExtraCompartmentStats(compartment, &cStats);
 
     compartment->compartmentStats = &cStats;
 
     // Measure the compartment object itself, and things hanging off it.
-    compartment->sizeOfIncludingThis(rtStats->mallocSizeOf_,
-                                     &cStats.compartmentObject,
-                                     &cStats.typeInference,
-                                     &cStats.shapesMallocHeapCompartmentTables,
-                                     &cStats.crossCompartmentWrappersTable,
-                                     &cStats.regexpCompartment,
-                                     &cStats.debuggeesSet,
-                                     &cStats.baselineStubsOptimized);
+    compartment->addSizeOfIncludingThis(rtStats->mallocSizeOf_,
+                                        &cStats.compartmentObject,
+                                        &cStats.typeInference,
+                                        &cStats.shapesMallocHeapCompartmentTables,
+                                        &cStats.crossCompartmentWrappersTable,
+                                        &cStats.regexpCompartment,
+                                        &cStats.debuggeesSet,
+                                        &cStats.baselineStubsOptimized);
 }
 
 static void
 StatsArenaCallback(JSRuntime *rt, void *data, gc::Arena *arena,
                    JSGCTraceKind traceKind, size_t thingSize)
 {
     RuntimeStats *rtStats = static_cast<StatsClosure *>(data)->rtStats;
 
@@ -259,19 +258,17 @@ StatsCellCallback(JSRuntime *rt, void *d
             cStats->objectsGCHeapFunction += thingSize;
         else if (obj->is<ArrayObject>())
             cStats->objectsGCHeapDenseArray += thingSize;
         else if (obj->is<CrossCompartmentWrapperObject>())
             cStats->objectsGCHeapCrossCompartmentWrapper += thingSize;
         else
             cStats->objectsGCHeapOrdinary += thingSize;
 
-        JS::ObjectsExtraSizes objectsExtra;
-        obj->sizeOfExcludingThis(rtStats->mallocSizeOf_, &objectsExtra);
-        cStats->objectsExtra.add(objectsExtra);
+        obj->addSizeOfExcludingThis(rtStats->mallocSizeOf_, &cStats->objectsExtra);
 
         // JSObject::sizeOfExcludingThis() doesn't measure objectsPrivate,
         // so we do it here.
         if (ObjectPrivateVisitor *opv = closure->opv) {
             nsISupports *iface;
             if (opv->getISupports_(obj, &iface) && iface) {
                 cStats->objectsPrivate += opv->sizeOfIncludingThis(iface);
             }
@@ -302,30 +299,32 @@ StatsCellCallback(JSRuntime *rt, void *d
         zStats->stringsNormalMallocHeap += strCharsSize;
 
         break;
       }
 
       case JSTRACE_SHAPE: {
         Shape *shape = static_cast<Shape *>(thing);
         CompartmentStats *cStats = GetCompartmentStats(shape->compartment());
-        size_t propTableSize, kidsSize;
-        shape->sizeOfExcludingThis(rtStats->mallocSizeOf_, &propTableSize, &kidsSize);
         if (shape->inDictionary()) {
             cStats->shapesGCHeapDict += thingSize;
-            cStats->shapesMallocHeapDictTables += propTableSize;
-            JS_ASSERT(kidsSize == 0);
+
+            // nullptr because kidsSize shouldn't be incremented in this case.
+            shape->addSizeOfExcludingThis(rtStats->mallocSizeOf_,
+                                          &cStats->shapesMallocHeapDictTables, nullptr);
         } else {
             JSObject *parent = shape->base()->getObjectParent();
             if (parent && parent->is<GlobalObject>())
                 cStats->shapesGCHeapTreeGlobalParented += thingSize;
             else
                 cStats->shapesGCHeapTreeNonGlobalParented += thingSize;
-            cStats->shapesMallocHeapTreeTables += propTableSize;
-            cStats->shapesMallocHeapTreeShapeKids += kidsSize;
+
+            shape->addSizeOfExcludingThis(rtStats->mallocSizeOf_,
+                                          &cStats->shapesMallocHeapTreeTables,
+                                          &cStats->shapesMallocHeapTreeShapeKids);
         }
         break;
       }
 
       case JSTRACE_BASE_SHAPE: {
         BaseShape *base = static_cast<BaseShape *>(thing);
         CompartmentStats *cStats = GetCompartmentStats(base->compartment());
         cStats->shapesGCHeapBase += thingSize;
@@ -333,21 +332,18 @@ StatsCellCallback(JSRuntime *rt, void *d
       }
 
       case JSTRACE_SCRIPT: {
         JSScript *script = static_cast<JSScript *>(thing);
         CompartmentStats *cStats = GetCompartmentStats(script->compartment());
         cStats->scriptsGCHeap += thingSize;
         cStats->scriptsMallocHeapData += script->sizeOfData(rtStats->mallocSizeOf_);
 #ifdef JS_ION
-        size_t baselineData = 0, baselineStubsFallback = 0;
-        jit::SizeOfBaselineData(script, rtStats->mallocSizeOf_, &baselineData,
-                                &baselineStubsFallback);
-        cStats->baselineData += baselineData;
-        cStats->baselineStubsFallback += baselineStubsFallback;
+        jit::AddSizeOfBaselineData(script, rtStats->mallocSizeOf_, &cStats->baselineData,
+                                   &cStats->baselineStubsFallback);
         cStats->ionData += jit::SizeOfIonData(script, rtStats->mallocSizeOf_);
 #endif
 
         ScriptSource *ss = script->scriptSource();
         SourceSet::AddPtr entry = closure->seenSources.lookupForAdd(ss);
         if (!entry) {
             closure->seenSources.add(entry, ss); // Not much to be done on failure.
             rtStats->runtime.scriptSources += ss->sizeOfIncludingThis(rtStats->mallocSizeOf_);
@@ -372,16 +368,18 @@ StatsCellCallback(JSRuntime *rt, void *d
 
       case JSTRACE_TYPE_OBJECT: {
         types::TypeObject *obj = static_cast<types::TypeObject *>(thing);
         zStats->typeObjectsGCHeap += thingSize;
         zStats->typeObjectsMallocHeap += obj->sizeOfExcludingThis(rtStats->mallocSizeOf_);
         break;
       }
 
+      default:
+        MOZ_ASSUME_UNREACHABLE("invalid traceKind");
     }
 
     // Yes, this is a subtraction:  see StatsArenaCallback() for details.
     zStats->unusedGCThings -= thingSize;
 }
 
 static void
 FindNotableStrings(ZoneStats &zStats)
@@ -443,17 +441,17 @@ JS::CollectRuntimeStats(JSRuntime *rt, R
     StatsClosure closure(rtStats, opv);
     if (!closure.init())
         return false;
     rtStats->runtime.scriptSources = 0;
     IterateZonesCompartmentsArenasCells(rt, &closure, StatsZoneCallback, StatsCompartmentCallback,
                                         StatsArenaCallback, StatsCellCallback);
 
     // Take the "explicit/js/runtime/" measurements.
-    rt->sizeOfIncludingThis(rtStats->mallocSizeOf_, &rtStats->runtime);
+    rt->addSizeOfIncludingThis(rtStats->mallocSizeOf_, &rtStats->runtime);
 
     rtStats->gcHeapGCThings = 0;
     for (size_t i = 0; i < rtStats->zoneStatsVector.length(); i++) {
         ZoneStats &zStats = rtStats->zoneStatsVector[i];
 
         rtStats->zTotals.add(zStats);
 
         // Move any strings which take up more than the sundries threshold
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -534,56 +534,54 @@ NewObjectCache::clearNurseryObjects(JSRu
             IsInsideNursery(rt, obj->elements))
         {
             PodZero(&e);
         }
     }
 }
 
 void
-JSRuntime::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes *rtSizes)
+JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes *rtSizes)
 {
     // Several tables in the runtime enumerated below can be used off thread.
     AutoLockForExclusiveAccess lock(this);
 
-    rtSizes->object = mallocSizeOf(this);
+    rtSizes->object += mallocSizeOf(this);
 
-    rtSizes->atomsTable = atoms().sizeOfExcludingThis(mallocSizeOf);
+    rtSizes->atomsTable += atoms().sizeOfExcludingThis(mallocSizeOf);
 
-    rtSizes->contexts = 0;
     for (ContextIter acx(this); !acx.done(); acx.next())
         rtSizes->contexts += acx->sizeOfIncludingThis(mallocSizeOf);
 
-    rtSizes->dtoa = mallocSizeOf(mainThread.dtoaState);
-
-    rtSizes->temporary = tempLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
+    rtSizes->dtoa += mallocSizeOf(mainThread.dtoaState);
 
-    rtSizes->code = JS::CodeSizes();
+    rtSizes->temporary += tempLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
+
     if (execAlloc_)
-        execAlloc_->sizeOfCode(&rtSizes->code);
+        execAlloc_->addSizeOfCode(&rtSizes->code);
 
 #ifdef JS_ION
     {
         AutoLockForOperationCallback lock(this);
         if (ionRuntime()) {
             if (JSC::ExecutableAllocator *ionAlloc = ionRuntime()->ionAlloc(this))
-                ionAlloc->sizeOfCode(&rtSizes->code);
+                ionAlloc->addSizeOfCode(&rtSizes->code);
         }
     }
 #endif
 
-    rtSizes->regexpData = bumpAlloc_ ? bumpAlloc_->sizeOfNonHeapData() : 0;
+    rtSizes->regexpData += bumpAlloc_ ? bumpAlloc_->sizeOfNonHeapData() : 0;
 
-    rtSizes->interpreterStack = interpreterStack_.sizeOfExcludingThis(mallocSizeOf);
+    rtSizes->interpreterStack += interpreterStack_.sizeOfExcludingThis(mallocSizeOf);
 
-    rtSizes->gcMarker = gcMarker.sizeOfExcludingThis(mallocSizeOf);
+    rtSizes->gcMarker += gcMarker.sizeOfExcludingThis(mallocSizeOf);
 
-    rtSizes->mathCache = mathCache_ ? mathCache_->sizeOfIncludingThis(mallocSizeOf) : 0;
+    rtSizes->mathCache += mathCache_ ? mathCache_->sizeOfIncludingThis(mallocSizeOf) : 0;
 
-    rtSizes->scriptData = scriptDataTable().sizeOfExcludingThis(mallocSizeOf);
+    rtSizes->scriptData += scriptDataTable().sizeOfExcludingThis(mallocSizeOf);
     for (ScriptDataTable::Range r = scriptDataTable().all(); !r.empty(); r.popFront())
         rtSizes->scriptData += mallocSizeOf(r.front());
 }
 
 void
 JSRuntime::triggerOperationCallback(OperationCallbackTrigger trigger)
 {
     AutoLockForOperationCallback lock(this);
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -1581,17 +1581,17 @@ struct JSRuntime : public JS::shadow::Ru
 
     void triggerOperationCallback(OperationCallbackTrigger trigger);
 
     void setJitHardening(bool enabled);
     bool getJitHardening() const {
         return jitHardening;
     }
 
-    void sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes *runtime);
+    void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes *runtime);
 
   private:
 
     JSUseHelperThreads useHelperThreads_;
     int32_t requestedHelperThreadCount;
 
     // Settings for how helper threads can be used.
     bool useHelperThreadsForIonCompilation_;
--- a/js/src/vm/Shape.h
+++ b/js/src/vm/Shape.h
@@ -968,22 +968,23 @@ class Shape : public gc::BarrieredCell<S
     }
 
     bool makeOwnBaseShape(ExclusiveContext *cx);
 
   public:
     bool hasTable() const { return base()->hasTable(); }
     ShapeTable &table() const { return base()->table(); }
 
-    void sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf,
-                             size_t *propTableSize, size_t *kidsSize) const {
-        *propTableSize = hasTable() ? table().sizeOfIncludingThis(mallocSizeOf) : 0;
-        *kidsSize = !inDictionary() && kids.isHash()
-                  ? kids.toHash()->sizeOfIncludingThis(mallocSizeOf)
-                  : 0;
+    void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf,
+                                size_t *propTableSize, size_t *kidsSize) const {
+        if (hasTable())
+            *propTableSize += table().sizeOfIncludingThis(mallocSizeOf);
+
+        if (!inDictionary() && kids.isHash())
+            *kidsSize += kids.toHash()->sizeOfIncludingThis(mallocSizeOf);
     }
 
     bool isNative() const {
         JS_ASSERT(!(flags & NON_NATIVE) == getObjectClass()->isNative());
         return !(flags & NON_NATIVE);
     }
 
     const HeapPtrShape &previous() const { return parent; }