diff --git a/components/malloc_size_of/lib.rs b/components/malloc_size_of/lib.rs index 7cb04b6e634..5ecd29d794a 100644 --- a/components/malloc_size_of/lib.rs +++ b/components/malloc_size_of/lib.rs @@ -103,13 +103,20 @@ impl MallocSizeOfOps { /// Check if an allocation is empty. This relies on knowledge of how Rust /// handles empty allocations, which may change in the future. - fn is_empty(ptr: *const T) -> bool { - return ptr as usize <= ::std::mem::align_of::(); + fn is_empty(ptr: *const T) -> bool { + // The correct condition is this: + // `ptr as usize <= ::std::mem::align_of::()` + // But we can't call align_of() on a ?Sized T. So we approximate it + // with the following. 256 is large enough that it should always be + // larger than the required alignment, but small enough that it is + // always in the first page of memory and therefore not a legitimate + // address. + return ptr as *const usize as usize <= 256 } /// Call `size_of_op` on `ptr`, first checking that the allocation isn't /// empty, because some types (such as `Vec`) utilize empty allocations. - pub unsafe fn malloc_size_of(&self, ptr: *const T) -> usize { + pub unsafe fn malloc_size_of(&self, ptr: *const T) -> usize { if MallocSizeOfOps::is_empty(ptr) { 0 } else { @@ -179,13 +186,13 @@ pub trait MallocConditionalShallowSizeOf { fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize; } -impl MallocShallowSizeOf for Box { +impl MallocShallowSizeOf for Box { fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { unsafe { ops.malloc_size_of(&**self) } } } -impl MallocSizeOf for Box { +impl MallocSizeOf for Box { fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { self.shallow_size_of(ops) + (**self).size_of(ops) } @@ -207,6 +214,16 @@ impl MallocSizeOf for Option { } } +impl MallocSizeOf for [T] { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + let mut n = 0; + for elem in self.iter() { + n += elem.size_of(ops); + } + n + } +} + impl MallocShallowSizeOf for Vec { fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { unsafe { ops.malloc_size_of(self.as_ptr()) }