Bug 1709935 - Support XPCOM refcount logging with rust-xpcom, r=xpcom-reviewers,mccr8

Differential Revision: https://phabricator.services.mozilla.com/D115086
This commit is contained in:
Nika Layzell 2021-05-19 17:29:23 +00:00
Родитель 59028b25c8
Коммит 40a0ecc65f
4 изменённых файлов: 86 добавлений и 2 удалений

Просмотреть файл

@ -85,7 +85,7 @@ cubeb-remoting = ["cubeb-sys", "audioipc-client", "audioipc-server"]
cubeb_coreaudio_rust = ["cubeb-sys", "cubeb-coreaudio"]
cubeb_pulse_rust = ["cubeb-sys", "cubeb-pulse"]
gecko_debug = ["geckoservo/gecko_debug", "nsstring/gecko_debug"]
gecko_refcount_logging = ["geckoservo/gecko_refcount_logging"]
gecko_refcount_logging = ["geckoservo/gecko_refcount_logging", "xpcom/gecko_refcount_logging"]
simd-accel = ["encoding_glue/simd-accel", "jsrust_shared/simd-accel"]
moz_memory = []
moz_places = ["bookmark_sync"]

Просмотреть файл

@ -15,3 +15,4 @@ thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
[features]
thread_sanitizer = []
gecko_refcount_logging = []

Просмотреть файл

@ -319,3 +319,57 @@ impl AtomicRefcnt {
self.0.load(Ordering::Acquire) as nsrefcnt
}
}
#[cfg(feature = "gecko_refcount_logging")]
pub mod trace_refcnt {
use crate::interfaces::nsrefcnt;
extern "C" {
pub fn NS_LogCtor(aPtr: *mut libc::c_void, aTypeName: *const libc::c_char, aSize: u32);
pub fn NS_LogDtor(aPtr: *mut libc::c_void, aTypeName: *const libc::c_char, aSize: u32);
pub fn NS_LogAddRef(
aPtr: *mut libc::c_void,
aRefcnt: nsrefcnt,
aClass: *const libc::c_char,
aClassSize: u32,
);
pub fn NS_LogRelease(
aPtr: *mut libc::c_void,
aRefcnt: nsrefcnt,
aClass: *const libc::c_char,
aClassSize: u32,
);
}
}
// stub inline methods for the refcount logging functions for when the feature
// is disabled.
#[cfg(not(feature = "gecko_refcount_logging"))]
pub mod trace_refcnt {
use crate::interfaces::nsrefcnt;
#[inline]
#[allow(non_snake_case)]
pub unsafe extern "C" fn NS_LogCtor(_: *mut libc::c_void, _: *const libc::c_char, _: u32) {}
#[inline]
#[allow(non_snake_case)]
pub unsafe extern "C" fn NS_LogDtor(_: *mut libc::c_void, _: *const libc::c_char, _: u32) {}
#[inline]
#[allow(non_snake_case)]
pub unsafe extern "C" fn NS_LogAddRef(
_: *mut libc::c_void,
_: nsrefcnt,
_: *const libc::c_char,
_: u32,
) {
}
#[inline]
#[allow(non_snake_case)]
pub unsafe extern "C" fn NS_LogRelease(
_: *mut libc::c_void,
_: nsrefcnt,
_: *const libc::c_char,
_: u32,
) {
}
}

Просмотреть файл

@ -658,7 +658,23 @@ fn xpcom(init: DeriveInput) -> Result<TokenStream, syn::Error> {
coerce_impl.push(coerce);
}
let size_for_logs = if real.generics.params.is_empty() {
quote!(::std::mem::size_of::<Self>() as u32)
} else {
// Refcount logging requires all types with the same name to have the
// same size, and generics aren't taken into account when creating our
// name string, so we need to make sure that all possible instantiations
// report the same size. To do that, we fake a size based on the number
// of vtable pointers and the known refcount field.
let fake_size_npointers = bases.len() + 1;
quote!((::std::mem::size_of::<usize>() * #fake_size_npointers) as u32)
};
let (impl_generics, ty_generics, where_clause) = real.generics.split_for_impl();
let name_for_logs = quote!(
concat!(module_path!(), "::", stringify!(#name #ty_generics), "\0").as_ptr()
as *const ::xpcom::reexports::libc::c_char
);
Ok(quote! {
#real
@ -695,12 +711,25 @@ fn xpcom(init: DeriveInput) -> Result<TokenStream, syn::Error> {
/// Automatically generated implementation of AddRef for nsISupports.
#vis unsafe fn AddRef(&self) -> ::xpcom::interfaces::nsrefcnt {
self.__refcnt.inc()
let new = self.__refcnt.inc();
::xpcom::trace_refcnt::NS_LogAddRef(
self as *const _ as *mut ::xpcom::reexports::libc::c_void,
new,
#name_for_logs,
#size_for_logs,
);
new
}
/// Automatically generated implementation of Release for nsISupports.
#vis unsafe fn Release(&self) -> ::xpcom::interfaces::nsrefcnt {
let new = self.__refcnt.dec();
::xpcom::trace_refcnt::NS_LogRelease(
self as *const _ as *mut ::xpcom::reexports::libc::c_void,
new,
#name_for_logs,
#size_for_logs,
);
if new == 0 {
// dealloc
::std::boxed::Box::from_raw(self as *const Self as *mut Self);