Merge mozilla-central to autoland. a=merge CLOSED TREE
authorBogdan Tara <btara@mozilla.com>
Fri, 23 Nov 2018 23:40:33 +0200
changeset 507107 59536376337ed2a23ebd1794d3dd2eedc79107f2
parent 507106 0bb898d00ed7b9d1bdaf3b4320cbc2ac5bca00fc (current diff)
parent 507099 8264fe75578f62fa4f14d48ec8ca86d109e8ddf5 (diff)
child 507108 b4a6bd0a9e002eee161b2b7a804f56a821e82590
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone65.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
Merge mozilla-central to autoland. a=merge CLOSED TREE
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: