Bug 1418806 - hashglobe: Dump more information if out of memory while allocating a table. r=emilio, a=jcristau
authorBoris Chiou <boris.chiou@gmail.com>
Wed, 06 Dec 2017 02:38:22 -0600
changeset 445284 cc9318833c015f22f8bf57ff75e87bac07818761
parent 445283 ff2ac648087a6f224cb5ed79663c016237a56cc2
child 445285 8409d8b905182bd075f9a93ae022baf118fe8072
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio, jcristau
bugs1418806, 1416903
milestone58.0
Bug 1418806 - hashglobe: Dump more information if out of memory while allocating a table. r=emilio, a=jcristau This is for Bug 1418806 and Bug 1416903. Sometimes, we got a crash message on stylo: > called `Result::unwrap()` on an `Err` value: FailedAllocationError { > reason: "out of memory when allocating RawTable" } but this is not enough to debug, so let's add one more field in FailedAllocationError, so we can know the size we are allocating. --- - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors Source-Repo: https://github.com/servo/servo Source-Revision: 7fd7c21c4c99dd9f8e118948f0c52d4b4073d559
servo/components/hashglobe/src/lib.rs
servo/components/hashglobe/src/table.rs
--- a/servo/components/hashglobe/src/lib.rs
+++ b/servo/components/hashglobe/src/lib.rs
@@ -24,28 +24,33 @@ trait Recover<Q: ?Sized> {
     fn get(&self, key: &Q) -> Option<&Self::Key>;
     fn take(&mut self, key: &Q) -> Option<Self::Key>;
     fn replace(&mut self, key: Self::Key) -> Option<Self::Key>;
 }
 
 #[derive(Debug)]
 pub struct FailedAllocationError {
     reason: &'static str,
+    /// The size we are allocating, if needed.
+    allocation_size: Option<usize>,
 }
 
 impl FailedAllocationError {
     #[inline]
     pub fn new(reason: &'static str) -> Self {
-        Self { reason }
+        Self { reason, allocation_size: None }
     }
 }
 
 impl error::Error for FailedAllocationError {
     fn description(&self) -> &str {
         self.reason
     }
 }
 
 impl fmt::Display for FailedAllocationError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.reason.fmt(f)
+        match self.allocation_size {
+            Some(size) => write!(f, "{}, allocation size: {}", self.reason, size),
+            None => self.reason.fmt(f),
+        }
     }
 }
--- a/servo/components/hashglobe/src/table.rs
+++ b/servo/components/hashglobe/src/table.rs
@@ -752,41 +752,41 @@ impl<K, V> RawTable<K, V> {
         // right is a little subtle. Therefore, calculating offsets has been
         // factored out into a different function.
         let (alignment, hash_offset, size, oflo) = calculate_allocation(hashes_size,
                                                                         align_of::<HashUint>(),
                                                                         pairs_size,
                                                                         align_of::<(K, V)>());
 
         if oflo {
-            return Err(FailedAllocationError { reason: "capacity overflow when allocating RawTable" });
+            return Err(FailedAllocationError::new("capacity overflow when allocating RawTable" ));
         }
 
         // One check for overflow that covers calculation and rounding of size.
         let size_of_bucket = size_of::<HashUint>().checked_add(size_of::<(K, V)>()).unwrap();
 
         let cap_bytes = capacity.checked_mul(size_of_bucket);
 
         if let Some(cap_bytes) = cap_bytes {
             if size < cap_bytes {
-                return Err(FailedAllocationError { reason: "capacity overflow when allocating RawTable" });
+                return Err(FailedAllocationError::new("capacity overflow when allocating RawTable"));
             }
         } else {
-            
-            return Err(FailedAllocationError { reason: "capacity overflow when allocating RawTable" });
+            return Err(FailedAllocationError::new("capacity overflow when allocating RawTable"));
         }
 
 
-
         // FORK NOTE: Uses alloc shim instead of Heap.alloc
         let buffer = alloc(size, alignment);
-        
+
         if buffer.is_null() {
-            
-            return Err(FailedAllocationError { reason: "out of memory when allocating RawTable" });
+            return Err(FailedAllocationError {
+                reason: "out of memory when allocating RawTable",
+                allocation_size: Some(size),
+            });
         }
 
         let hashes = buffer.offset(hash_offset as isize) as *mut HashUint;
 
         Ok(RawTable {
             capacity_mask: capacity.wrapping_sub(1),
             size: 0,
             hashes: TaggedHashUintPtr::new(hashes),