Merge inbound to mozilla-central. a=merge
authorBogdan Tara <btara@mozilla.com>
Fri, 23 Nov 2018 23:38:28 +0200
changeset 447909 8264fe75578f62fa4f14d48ec8ca86d109e8ddf5
parent 447908 2317749c5abfb7eab139a2545d2fa5362d2309f0 (current diff)
parent 447798 606abc9b203e38cd66f2498bf6c5eb98f39eeadf (diff)
child 447910 7e7bf210330b1a491e30a75917d8b9aafa790458
child 447919 59536376337ed2a23ebd1794d3dd2eedc79107f2
push id110089
push userbtara@mozilla.com
push dateFri, 23 Nov 2018 21:42:24 +0000
treeherdermozilla-inbound@7e7bf210330b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone65.0a1
first release with
nightly linux32
8264fe75578f / 65.0a1 / 20181123220228 / files
nightly linux64
8264fe75578f / 65.0a1 / 20181123220228 / files
nightly mac
8264fe75578f / 65.0a1 / 20181123220228 / files
nightly win32
8264fe75578f / 65.0a1 / 20181123220228 / files
nightly win64
8264fe75578f / 65.0a1 / 20181123220228 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
gfx/webrender/src/storage.rs
deleted file mode 100644
--- a/gfx/webrender/src/storage.rs
+++ /dev/null
@@ -1,127 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-use std::{iter::Extend, ops, marker::PhantomData, u32};
-use util::recycle_vec;
-
-#[derive(Debug, Hash)]
-#[cfg_attr(feature = "capture", derive(Serialize))]
-#[cfg_attr(feature = "replay", derive(Deserialize))]
-pub struct Index<T>(u32, PhantomData<T>);
-
-// We explicitly implement Copy + Clone instead of using #[derive(Copy, Clone)]
-// because we don't want to require that T implements Clone + Copy.
-impl<T> Clone for Index<T> {
-    fn clone(&self) -> Self { *self }
-}
-
-impl<T> Copy for Index<T> {}
-
-impl<T> PartialEq for Index<T> {
-    fn eq(&self, other: &Self) -> bool {
-        self.0 == other.0
-    }
-}
-
-impl<T> Index<T> {
-    fn new(idx: usize) -> Self {
-        debug_assert!(idx < u32::max_value() as usize);
-        Index(idx as u32, PhantomData)
-    }
-
-    pub const INVALID: Index<T> = Index(u32::MAX, PhantomData);
-}
-
-#[derive(Debug)]
-pub struct Range<T> {
-    pub start: Index<T>,
-    pub end: Index<T>,
-}
-
-// We explicitly implement Copy + Clone instead of using #[derive(Copy, Clone)]
-// because we don't want to require that T implements Clone + Copy.
-impl<T> Clone for Range<T> {
-    fn clone(&self) -> Self {
-        Range { start: self.start, end: self.end }
-    }
-}
-impl<T> Copy for Range<T> {}
-
-impl<T> Range<T> {
-    /// Create an empty `Range`
-    pub fn empty() -> Self {
-        Range {
-            start: Index::new(0),
-            end: Index::new(0),
-        }
-    }
-
-    /// Check for an empty `Range`
-    pub fn is_empty(&self) -> bool {
-        !(self.start.0 < self.end.0)
-    }
-}
-
-pub struct Storage<T> {
-    data: Vec<T>,
-}
-
-impl<T> Storage<T> {
-    pub fn new(initial_capacity: usize) -> Self {
-        Storage {
-            data: Vec::with_capacity(initial_capacity),
-        }
-    }
-
-    pub fn len(&self) -> usize {
-        self.data.len()
-    }
-
-    pub fn push(&mut self, t: T) -> Index<T> {
-        let index = self.data.len();
-        self.data.push(t);
-        Index(index as u32, PhantomData)
-    }
-
-    pub fn recycle(&mut self) {
-        recycle_vec(&mut self.data);
-    }
-
-    pub fn extend<II: IntoIterator<Item=T>>(&mut self, iter: II) -> Range<T> {
-        let start = Index::new(self.data.len());
-        self.data.extend(iter);
-        let end = Index::new(self.data.len());
-        Range { start, end }
-    }
-}
-
-impl<T> ops::Index<Index<T>> for Storage<T> {
-    type Output = T;
-    fn index(&self, index: Index<T>) -> &Self::Output {
-        &self.data[index.0 as usize]
-    }
-}
-
-impl<T> ops::IndexMut<Index<T>> for Storage<T> {
-    fn index_mut(&mut self, index: Index<T>) -> &mut Self::Output {
-        &mut self.data[index.0 as usize]
-    }
-}
-
-impl<T> ops::Index<Range<T>> for Storage<T> {
-    type Output = [T];
-    fn index(&self, index: Range<T>) -> &Self::Output {
-        let start = index.start.0 as _;
-        let end = index.end.0 as _;
-        &self.data[start..end]
-    }
-}
-
-impl<T> ops::IndexMut<Range<T>> for Storage<T> {
-    fn index_mut(&mut self, index: Range<T>) -> &mut Self::Output {
-        let start = index.start.0 as _;
-        let end = index.end.0 as _;
-        &mut self.data[start..end]
-    }
-}
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -737,18 +737,16 @@ ChunkPool::push(Chunk* chunk)
     MOZ_ASSERT(!chunk->info.prev);
 
     chunk->info.next = head_;
     if (head_) {
         head_->info.prev = chunk;
     }
     head_ = chunk;
     ++count_;
-
-    MOZ_ASSERT(verify());
 }
 
 Chunk*
 ChunkPool::remove(Chunk* chunk)
 {
     MOZ_ASSERT(count_ > 0);
     MOZ_ASSERT(contains(chunk));
 
@@ -759,17 +757,16 @@ ChunkPool::remove(Chunk* chunk)
         chunk->info.prev->info.next = chunk->info.next;
     }
     if (chunk->info.next) {
         chunk->info.next->info.prev = chunk->info.prev;
     }
     chunk->info.next = chunk->info.prev = nullptr;
     --count_;
 
-    MOZ_ASSERT(verify());
     return chunk;
 }
 
 #ifdef DEBUG
 bool
 ChunkPool::contains(Chunk* chunk) const
 {
     verify();
@@ -947,19 +944,17 @@ Chunk::updateChunkListAfterAlloc(JSRunti
 
 void
 Chunk::updateChunkListAfterFree(JSRuntime* rt, const AutoLockGC& lock)
 {
     if (info.numArenasFree == 1) {
         rt->gc.fullChunks(lock).remove(this);
         rt->gc.availableChunks(lock).push(this);
     } else if (!unused()) {
-        MOZ_ASSERT(!rt->gc.fullChunks(lock).contains(this));
         MOZ_ASSERT(rt->gc.availableChunks(lock).contains(this));
-        MOZ_ASSERT(!rt->gc.emptyChunks(lock).contains(this));
     } else {
         MOZ_ASSERT(unused());
         rt->gc.availableChunks(lock).remove(this);
         decommitAllArenas();
         MOZ_ASSERT(info.numArenasFreeCommitted == 0);
         rt->gc.recycleChunk(this, lock);
     }
 }
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -2821,19 +2821,17 @@ js::gc::StoreBuffer::SlotsEdge::trace(Te
     NativeObject* obj = object();
     MOZ_ASSERT(IsCellPointerValid(obj));
 
     // Beware JSObject::swap exchanging a native object for a non-native one.
     if (!obj->isNative()) {
         return;
     }
 
-    if (IsInsideNursery(obj)) {
-        return;
-    }
+    MOZ_ASSERT(!IsInsideNursery(obj), "obj shouldn't live in nursery.");
 
     if (kind() == ElementKind) {
         uint32_t initLen = obj->getDenseInitializedLength();
         uint32_t numShifted = obj->getElementsHeader()->numShiftedElements();
         uint32_t clampedStart = start_;
         clampedStart = numShifted < clampedStart ? clampedStart - numShifted : 0;
         clampedStart = Min(clampedStart, initLen);
         uint32_t clampedEnd = start_ + count_;
--- a/toolkit/components/aboutperformance/content/aboutPerformance.js
+++ b/toolkit/components/aboutperformance/content/aboutPerformance.js
@@ -421,41 +421,53 @@ var State = {
     let addonHosts = new Map();
     for (let addon of addons)
       addonHosts.set(addon.mozExtensionHostname, addon.id);
 
     let counters = await ChromeUtils.requestPerformanceMetrics();
     let tabs = {};
     for (let counter of counters) {
       let {items, host, pid, counterId, windowId, duration, isWorker,
-           isTopLevel} = counter;
+           memoryInfo, isTopLevel} = counter;
       // If a worker has a windowId of 0 or max uint64, attach it to the
       // browser UI (doc group with id 1).
       if (isWorker && (windowId == 18446744073709552000 || !windowId))
         windowId = 1;
       let dispatchCount = 0;
       for (let {count} of items) {
         dispatchCount += count;
       }
 
+      let memory = 0;
+      for (let field in memoryInfo) {
+        if (field == "media") {
+          for (let mediaField of ["audioSize", "videoSize", "resourcesSize"]) {
+            memory += memoryInfo.media[mediaField];
+          }
+          continue;
+        }
+        memory += memoryInfo[field];
+      }
+
       let tab;
       let id = windowId;
       if (addonHosts.has(host)) {
         id = addonHosts.get(host);
       }
       if (id in tabs) {
         tab = tabs[id];
       } else {
-        tab = {windowId, host, dispatchCount: 0, duration: 0, children: []};
+        tab = {windowId, host, dispatchCount: 0, duration: 0, memory: 0, children: []};
         tabs[id] = tab;
       }
       tab.dispatchCount += dispatchCount;
       tab.duration += duration;
+      tab.memory += memory;
       if (!isTopLevel || isWorker) {
-        tab.children.push({host, isWorker, dispatchCount, duration,
+        tab.children.push({host, isWorker, dispatchCount, duration, memory,
                            counterId: pid + ":" + counterId});
       }
     }
 
     if (extensionCountersEnabled()) {
       let extCounters = await ExtensionParent.ParentAPIManager.retrievePerformanceCounters();
       for (let [id, apiMap] of extCounters) {
         let dispatchCount = 0, duration = 0;
@@ -463,17 +475,17 @@ var State = {
           dispatchCount += counter.calls;
           duration += counter.duration;
         }
 
         let tab;
         if (id in tabs) {
           tab = tabs[id];
         } else {
-          tab = {windowId: 0, host: id, dispatchCount: 0, duration: 0, children: []};
+          tab = {windowId: 0, host: id, dispatchCount: 0, duration: 0, memory: 0, children: []};
           tabs[id] = tab;
         }
         tab.dispatchCount += dispatchCount;
         tab.duration += duration;
       }
     }
 
     return {tabs, date: Cu.now()};
@@ -664,28 +676,27 @@ var State = {
       let prevChildren = new Map();
       if (prev) {
         for (let child of prev.children) {
           prevChildren.set(child.counterId, child);
         }
       }
       // For each subitem, create a new object including the deltas since the previous time.
       let children = tab.children.map(child => {
-        let {host, dispatchCount, duration, isWorker, counterId} = child;
-
+        let {host, dispatchCount, duration, memory, isWorker, counterId} = child;
         let dispatchesSincePrevious = dispatchCount;
         let durationSincePrevious = duration;
         if (prevChildren.has(counterId)) {
           let prevCounter = prevChildren.get(counterId);
           dispatchesSincePrevious -= prevCounter.dispatchCount;
           durationSincePrevious -= prevCounter.duration;
           prevChildren.delete(counterId);
         }
 
-        return {host, dispatchCount, duration, isWorker,
+        return {host, dispatchCount, duration, isWorker, memory,
                 dispatchesSincePrevious, durationSincePrevious};
       });
 
       // Any item that remains in prevChildren is a subitem that no longer
       // exists in the current sample; remember the values of its counters
       // so that the values don't go down for the parent item.
       tab.dispatchesFromFormerChildren = prev && prev.dispatchesFromFormerChildren || 0;
       tab.durationFromFormerChildren = prev && prev.durationFromFormerChildren || 0;
@@ -709,17 +720,17 @@ var State = {
           dispatches - prev.dispatchCount - (prev.dispatchesFromFormerChildren || 0);
       }
       if (oldest) {
         dispatchesSinceStartOfBuffer =
           dispatches - oldest.dispatchCount - (oldest.dispatchesFromFormerChildren || 0);
         durationSinceStartOfBuffer =
           duration - oldest.duration - (oldest.durationFromFormerChildren || 0);
       }
-      counters.push({id, name, image, type,
+      counters.push({id, name, image, type, memory: tab.memory,
                      totalDispatches: dispatches, totalDuration: duration,
                      durationSincePrevious, dispatchesSincePrevious,
                      durationSinceStartOfBuffer, dispatchesSinceStartOfBuffer,
                      children});
     }
     return counters;
   },
 };
@@ -1032,17 +1043,17 @@ var View = {
       if (energyImpact < 1)
         impact = "low";
       else if (energyImpact < 25)
         impact = "medium";
       document.l10n.setAttributes(elt, "energy-impact-" + impact,
                                   {value: energyImpact});
     }
   },
-  appendRow(name, energyImpact, tooltip, type, image = "") {
+  appendRow(name, energyImpact, memory, tooltip, type, image = "") {
     let row = document.createElement("tr");
 
     let elt = document.createElement("td");
     if (typeof name == "string") {
       elt.textContent = name;
     } else if (name.title) {
       document.l10n.setAttributes(elt, name.id, {title: name.title});
     } else {
@@ -1064,16 +1075,34 @@ var View = {
       type = "addon";
     document.l10n.setAttributes(elt, "type-" + type);
     row.appendChild(elt);
 
     elt = document.createElement("td");
     this.displayEnergyImpact(elt, energyImpact);
     row.appendChild(elt);
 
+    elt = document.createElement("td");
+    if (!memory) {
+      elt.textContent = "–";
+    } else {
+      let unit = "KB";
+      memory = Math.ceil(memory / 1024);
+      if (memory > 1024) {
+        memory = Math.ceil(memory / 1024 * 10) / 10;
+        unit = "MB";
+        if (memory > 1024) {
+          memory = Math.ceil(memory / 1024 * 100) / 100;
+          unit = "GB";
+        }
+      }
+      document.l10n.setAttributes(elt, "size-" + unit, {value: memory});
+    }
+    row.appendChild(elt);
+
     if (tooltip)
       document.l10n.setAttributes(row, "item", tooltip);
 
     elt = document.createElement("td");
     if (type == "tab") {
       let img = document.createElement("span");
       img.className = "action-icon close-icon";
       document.l10n.setAttributes(img, "close-tab");
@@ -1199,16 +1228,18 @@ var Control = {
       await wait(0);
 
       // Make sure that we do not keep obsolete stuff around.
       View.DOMCache.trimTo(state.deltas);
     } else {
       // If the mouse has been moved recently, update the data displayed
       // without moving any item to avoid the risk of users clicking an action
       // button for the wrong item.
+      // Memory use is unlikely to change dramatically within a few seconds, so
+      // it's probably fine to not update the Memory column in this case.
       if (Date.now() - this._lastMouseEvent < TIME_BEFORE_SORTING_AGAIN) {
         let energyImpactPerId = new Map();
         for (let {id, dispatchesSincePrevious,
                   durationSincePrevious} of State.getCounters()) {
           let energyImpact = this._computeEnergyImpact(dispatchesSincePrevious,
                                                        durationSincePrevious);
           energyImpactPerId.set(id, energyImpact);
         }
@@ -1235,21 +1266,22 @@ var Control = {
         selectedId = this.selectedRow.windowId;
         this.selectedRow = null;
       }
       let openItems = this._openItems;
       this._openItems = new Set();
 
       let counters = this._sortCounters(State.getCounters());
       for (let {id, name, image, type, totalDispatches, dispatchesSincePrevious,
-                totalDuration, durationSincePrevious, children} of counters) {
+                memory, totalDuration, durationSincePrevious, children} of counters) {
         let row =
           View.appendRow(name,
                          this._computeEnergyImpact(dispatchesSincePrevious,
                                                    durationSincePrevious),
+                         memory,
                          {totalDispatches, totalDuration: Math.ceil(totalDuration / 1000),
                           dispatchesSincePrevious,
                           durationSincePrevious: Math.ceil(durationSincePrevious / 1000)},
                          type, image);
         row.windowId = id;
         if (id == selectedId) {
           row.setAttribute("selected", "true");
           this.selectedRow = row;
@@ -1302,16 +1334,17 @@ var Control = {
       let type = "subframe";
       if (State.isTracker(host))
         type = "tracker";
       if (row.isWorker)
         type = "worker";
       View.appendRow(row.host,
                      this._computeEnergyImpact(row.dispatchesSincePrevious,
                                                row.durationSincePrevious),
+                     row.memory,
                      {totalDispatches: row.dispatchCount,
                       totalDuration: Math.ceil(row.duration / 1000),
                       dispatchesSincePrevious: row.dispatchesSincePrevious,
                       durationSincePrevious: Math.ceil(row.durationSincePrevious / 1000)},
                      type);
     }
   },
   _computeEnergyImpact(dispatches, duration) {
--- a/toolkit/components/aboutperformance/content/aboutPerformance.xhtml
+++ b/toolkit/components/aboutperformance/content/aboutPerformance.xhtml
@@ -139,19 +139,25 @@
         display: table;
         table-layout: fixed;
         width: 100%;
       }
       #dispatch-table td:nth-child(2) {
         width: 8em;
       }
       #dispatch-table td:nth-child(3) {
-        width: 12em;
+        width: 9em;
       }
       #dispatch-table td:nth-child(4) {
+        width: 5em;
+      }
+      #dispatch-tbody td:nth-child(4) {
+        text-align: end;
+      }
+      #dispatch-table td:nth-child(5) {
         width: 20px;
       }
 
       /* Show action icons on selected or hovered rows */
       tr:-moz-any([selected], :hover) > td > .action-icon {
         padding: 1px 10px;
         opacity: 1;
       }
@@ -328,16 +334,17 @@
     </div>
     <div>
       <table id="dispatch-table">
         <thead id="dispatch-thead">
           <tr>
             <td data-l10n-id="column-name"/>
             <td data-l10n-id="column-type"/>
             <td data-l10n-id="column-energy-impact"/>
+            <td data-l10n-id="column-memory"/>
             <td></td><!-- actions -->
           </tr>
         </thead>
         <tbody id="dispatch-tbody"></tbody>
       </table>
     </div>
   </body>
 </html>
--- a/toolkit/locales/en-US/toolkit/about/aboutPerformance.ftl
+++ b/toolkit/locales/en-US/toolkit/about/aboutPerformance.ftl
@@ -4,16 +4,17 @@
 
 # Page title
 about-performance-title = Task Manager
 
 ## Column headers
 column-name = Name
 column-type = Type
 column-energy-impact = Energy Impact
+column-memory = Memory
 
 ## Special values for the Name column
 ghost-windows = Recently closed tabs
 # Variables:
 #   $title (String) - the title of the preloaded page, typically 'New Tab'
 preloaded-tab = Preloaded: { $title }
 
 ## Values for the Type column
@@ -29,16 +30,24 @@ type-other = Other
 ##
 ## Variables:
 ##   $value (Number) - Value of the energy impact, eg. 0.25 (low),
 ##                     5.38 (medium), 105.38 (high)
 energy-impact-high = High ({ $value })
 energy-impact-medium = Medium ({ $value })
 energy-impact-low = Low ({ $value })
 
+## Values for the Memory column
+##
+## Variables:
+##   $value (Number) - How much memory is used
+size-KB = { $value } KB
+size-MB = { $value } MB
+size-GB = { $value } GB
+
 ## Tooltips for the action buttons
 close-tab =
     .title = Close tab
 show-addon =
     .title = Show in Add-ons Manager
 
 # Tooltip when hovering an item of the about:performance table
 # Variables: