From 654661df3615439891084a2f8ace89a63973275c Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 29 Jun 2017 23:56:23 -0700 Subject: [PATCH] Hook into the Gecko leak checking machinery. Since we're going to stop asserting that all RuleNodes have been destroyed by the time the RuleTree is destroyed, we want reliable leak checking. --- components/style/rule_tree/mod.rs | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index d6f5abfe3d4..abbfe7f3efb 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -571,6 +571,53 @@ pub struct RuleNode { unsafe impl Sync for RuleTree {} unsafe impl Send for RuleTree {} +// On Gecko builds, hook into the leak checking machinery. +#[cfg(feature = "gecko")] +#[cfg(debug_assertions)] +mod gecko_leak_checking { +use std::mem::size_of; +use std::os::raw::{c_char, c_void}; +use super::RuleNode; + +extern "C" { + pub fn NS_LogCtor(aPtr: *const c_void, aTypeName: *const c_char, aSize: u32); + pub fn NS_LogDtor(aPtr: *const c_void, aTypeName: *const c_char, aSize: u32); +} + +static NAME: &'static [u8] = b"RuleNode\0"; + +/// Logs the creation of a heap-allocated object to Gecko's leak-checking machinery. +pub fn log_ctor(ptr: *const RuleNode) { + let s = NAME as *const [u8] as *const u8 as *const c_char; + unsafe { + NS_LogCtor(ptr as *const c_void, s, size_of::() as u32); + } +} + +/// Logs the destruction of a heap-allocated object to Gecko's leak-checking machinery. +pub fn log_dtor(ptr: *const RuleNode) { + let s = NAME as *const [u8] as *const u8 as *const c_char; + unsafe { + NS_LogDtor(ptr as *const c_void, s, size_of::() as u32); + } +} + +} + +#[inline(always)] +fn log_new(_ptr: *const RuleNode) { + #[cfg(feature = "gecko")] + #[cfg(debug_assertions)] + gecko_leak_checking::log_ctor(_ptr); +} + +#[inline(always)] +fn log_drop(_ptr: *const RuleNode) { + #[cfg(feature = "gecko")] + #[cfg(debug_assertions)] + gecko_leak_checking::log_dtor(_ptr); +} + impl RuleNode { fn new(root: WeakRuleNode, parent: StrongRuleNode, @@ -730,6 +777,7 @@ impl StrongRuleNode { debug_assert!(n.parent.is_none() == !n.source.is_some()); let ptr = Box::into_raw(n); + log_new(ptr); debug!("Creating rule node: {:p}", ptr); @@ -948,6 +996,7 @@ impl StrongRuleNode { debug!("GC'ing {:?}", weak.ptr()); node.remove_from_child_list(); + log_drop(weak.ptr()); let _ = Box::from_raw(weak.ptr()); } @@ -1331,6 +1380,7 @@ impl Drop for StrongRuleNode { debug!("Dropping root node!"); // The free list should be null by this point debug_assert!(node.next_free.load(Ordering::Relaxed).is_null()); + log_drop(self.ptr()); let _ = unsafe { Box::from_raw(self.ptr()) }; return; }