mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Auto merge of #18474 - nnethercote:malloc_size_of-tweaks, r=jdm
malloc_size_of tweaks <!-- Please describe your changes on the following line: --> A couple of tweaks. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #18473 (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [X] These changes do not require tests because they are tested in Gecko. <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- 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/18474) <!-- Reviewable:end -->
This commit is contained in:
commit
8ee055fdc1
3 changed files with 34 additions and 17 deletions
|
@ -103,25 +103,32 @@ 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<T>(ptr: *const T) -> bool {
|
||||
return ptr as usize <= ::std::mem::align_of::<T>();
|
||||
fn is_empty<T: ?Sized>(ptr: *const T) -> bool {
|
||||
// The correct condition is this:
|
||||
// `ptr as usize <= ::std::mem::align_of::<T>()`
|
||||
// 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 fn malloc_size_of<T>(&self, ptr: *const T) -> usize {
|
||||
pub unsafe fn malloc_size_of<T: ?Sized>(&self, ptr: *const T) -> usize {
|
||||
if MallocSizeOfOps::is_empty(ptr) {
|
||||
0
|
||||
} else {
|
||||
unsafe { (self.size_of_op)(ptr as *const c_void) }
|
||||
(self.size_of_op)(ptr as *const c_void)
|
||||
}
|
||||
}
|
||||
|
||||
/// Call `enclosing_size_of_op` on `ptr`, which must not be empty.
|
||||
pub fn malloc_enclosing_size_of<T>(&self, ptr: *const T) -> usize {
|
||||
pub unsafe fn malloc_enclosing_size_of<T>(&self, ptr: *const T) -> usize {
|
||||
assert!(!MallocSizeOfOps::is_empty(ptr));
|
||||
let enclosing_size_of_op = self.enclosing_size_of_op.expect("missing enclosing_size_of_op");
|
||||
unsafe { enclosing_size_of_op(ptr as *const c_void) }
|
||||
enclosing_size_of_op(ptr as *const c_void)
|
||||
}
|
||||
|
||||
/// Call `have_seen_ptr_op` on `ptr`.
|
||||
|
@ -179,13 +186,13 @@ pub trait MallocConditionalShallowSizeOf {
|
|||
fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
|
||||
}
|
||||
|
||||
impl<T> MallocShallowSizeOf for Box<T> {
|
||||
impl<T: ?Sized> MallocShallowSizeOf for Box<T> {
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
ops.malloc_size_of(&**self)
|
||||
unsafe { ops.malloc_size_of(&**self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> MallocSizeOf for Box<T> {
|
||||
impl<T: MallocSizeOf + ?Sized> MallocSizeOf for Box<T> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.shallow_size_of(ops) + (**self).size_of(ops)
|
||||
}
|
||||
|
@ -207,9 +214,19 @@ impl<T: MallocSizeOf> MallocSizeOf for Option<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> 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<T> MallocShallowSizeOf for Vec<T> {
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
ops.malloc_size_of(self.as_ptr())
|
||||
unsafe { ops.malloc_size_of(self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,7 +243,7 @@ impl<T: MallocSizeOf> MallocSizeOf for Vec<T> {
|
|||
impl<A: Array> MallocShallowSizeOf for SmallVec<A> {
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
if self.spilled() {
|
||||
ops.malloc_size_of(self.as_ptr())
|
||||
unsafe { ops.malloc_size_of(self.as_ptr()) }
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
@ -255,7 +272,7 @@ impl<T, S> MallocShallowSizeOf for HashSet<T, S>
|
|||
// `ops.malloc_enclosing_size_of()` then gives us the storage size.
|
||||
// This assumes that the `HashSet`'s contents (values and hashes) are
|
||||
// all stored in a single contiguous heap allocation.
|
||||
self.iter().next().map_or(0, |t| ops.malloc_enclosing_size_of(t))
|
||||
self.iter().next().map_or(0, |t| unsafe { ops.malloc_enclosing_size_of(t) })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,7 +298,7 @@ impl<K, V, S> MallocShallowSizeOf for HashMap<K, V, S>
|
|||
// `ops.malloc_enclosing_size_of()` then gives us the storage size.
|
||||
// This assumes that the `HashMap`'s contents (keys, values, and
|
||||
// hashes) are all stored in a single contiguous heap allocation.
|
||||
self.values().next().map_or(0, |v| ops.malloc_enclosing_size_of(v))
|
||||
self.values().next().map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,7 +326,7 @@ impl<K, V, S> MallocSizeOf for HashMap<K, V, S>
|
|||
|
||||
impl<T> MallocUnconditionalShallowSizeOf for Arc<T> {
|
||||
fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
ops.malloc_size_of(self.heap_ptr())
|
||||
unsafe { ops.malloc_size_of(self.heap_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ impl Drop for RuleTree {
|
|||
#[cfg(feature = "gecko")]
|
||||
impl MallocSizeOf for RuleTree {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let mut n = ops.malloc_size_of(self.root.ptr());
|
||||
let mut n = unsafe { ops.malloc_size_of(self.root.ptr()) };
|
||||
n += self.root.get().size_of(ops);
|
||||
n
|
||||
}
|
||||
|
@ -806,7 +806,7 @@ impl MallocSizeOf for RuleNode {
|
|||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let mut n = 0;
|
||||
for child in self.iter_children() {
|
||||
n += ops.malloc_size_of(child.ptr());
|
||||
n += unsafe { ops.malloc_size_of(child.ptr()) };
|
||||
n += unsafe { (*child.ptr()).size_of(ops) };
|
||||
}
|
||||
n
|
||||
|
|
|
@ -55,7 +55,7 @@ impl StyleRule {
|
|||
// It's safe to measure this ThinArc directly because it's the
|
||||
// "primary" reference. (The secondary references are on the
|
||||
// Stylist.)
|
||||
n += ops.malloc_size_of(selector.thin_arc_heap_ptr());
|
||||
n += unsafe { ops.malloc_size_of(selector.thin_arc_heap_ptr()) };
|
||||
}
|
||||
|
||||
n += self.block.unconditional_shallow_size_of(ops) +
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue