Auto merge of #19504 - BorisChiou:stylo/crash/out_of_memory, r=emilio

hashglobe: Dump more information if out of memory while allocating a table

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

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19504)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-12-06 02:38:22 -06:00 committed by GitHub
commit 7fd7c21c4c
2 changed files with 15 additions and 10 deletions

View file

@ -29,12 +29,14 @@ trait Recover<Q: ?Sized> {
#[derive(Debug)] #[derive(Debug)]
pub struct FailedAllocationError { pub struct FailedAllocationError {
reason: &'static str, reason: &'static str,
/// The size we are allocating, if needed.
allocation_size: Option<usize>,
} }
impl FailedAllocationError { impl FailedAllocationError {
#[inline] #[inline]
pub fn new(reason: &'static str) -> Self { pub fn new(reason: &'static str) -> Self {
Self { reason } Self { reason, allocation_size: None }
} }
} }
@ -46,6 +48,9 @@ impl error::Error for FailedAllocationError {
impl fmt::Display for FailedAllocationError { impl fmt::Display for FailedAllocationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 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),
}
} }
} }

View file

@ -757,7 +757,7 @@ impl<K, V> RawTable<K, V> {
align_of::<(K, V)>()); align_of::<(K, V)>());
if oflo { 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. // One check for overflow that covers calculation and rounding of size.
@ -767,21 +767,21 @@ impl<K, V> RawTable<K, V> {
if let Some(cap_bytes) = cap_bytes { if let Some(cap_bytes) = cap_bytes {
if size < 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 { } else {
return Err(FailedAllocationError::new("capacity overflow when allocating RawTable"));
return Err(FailedAllocationError { reason: "capacity overflow when allocating RawTable" });
} }
// FORK NOTE: Uses alloc shim instead of Heap.alloc // FORK NOTE: Uses alloc shim instead of Heap.alloc
let buffer = alloc(size, alignment); let buffer = alloc(size, alignment);
if buffer.is_null() { if buffer.is_null() {
return Err(FailedAllocationError {
return Err(FailedAllocationError { reason: "out of memory when allocating RawTable" }); reason: "out of memory when allocating RawTable",
allocation_size: Some(size),
});
} }
let hashes = buffer.offset(hash_offset as isize) as *mut HashUint; let hashes = buffer.offset(hash_offset as isize) as *mut HashUint;