44
55//! Selecting the default global allocator for Servo
66
7- #![ cfg_attr( all( feature = "unstable" , windows) , feature( alloc_system, allocator_api) ) ]
8- #![ cfg_attr( feature = "unstable" , feature( global_allocator) ) ]
7+ #![ cfg_attr( feature = "unstable" , feature( global_allocator, allocator_api, alloc_system) ) ]
98
109#[ cfg( feature = "unstable" ) ]
1110#[ global_allocator]
@@ -16,19 +15,90 @@ pub use platform::*;
1615
1716#[ cfg( all( feature = "unstable" , not( windows) ) ) ]
1817mod platform {
19- extern crate jemallocator ;
18+ extern crate jemalloc_sys as ffi ;
2019
21- pub use self :: jemallocator :: Jemalloc as Allocator ;
22- use std:: os:: raw:: c_void;
20+ use std :: alloc :: { GlobalAlloc , Layout , Opaque , System } ;
21+ use std:: os:: raw:: { c_int , c_void} ;
2322
2423 /// Get the size of a heap block.
2524 pub unsafe extern "C" fn usable_size ( ptr : * const c_void ) -> usize {
26- jemallocator :: usable_size ( ptr)
25+ ffi :: malloc_usable_size ( ptr as * const _ )
2726 }
2827
2928 /// Memory allocation APIs compatible with libc
3029 pub mod libc_compat {
31- pub use super :: jemallocator:: ffi:: { malloc, realloc, free} ;
30+ pub use super :: ffi:: { malloc, realloc, free} ;
31+ }
32+
33+ pub struct Allocator ;
34+
35+ // The minimum alignment guaranteed by the architecture. This value is used to
36+ // add fast paths for low alignment values.
37+ #[ cfg( all( any( target_arch = "arm" ,
38+ target_arch = "mips" ,
39+ target_arch = "mipsel" ,
40+ target_arch = "powerpc" ) ) ) ]
41+ const MIN_ALIGN : usize = 8 ;
42+ #[ cfg( all( any( target_arch = "x86" ,
43+ target_arch = "x86_64" ,
44+ target_arch = "aarch64" ,
45+ target_arch = "powerpc64" ,
46+ target_arch = "powerpc64le" ,
47+ target_arch = "mips64" ,
48+ target_arch = "s390x" ,
49+ target_arch = "sparc64" ) ) ) ]
50+ const MIN_ALIGN : usize = 16 ;
51+
52+ fn layout_to_flags ( align : usize , size : usize ) -> c_int {
53+ // If our alignment is less than the minimum alignment they we may not
54+ // have to pass special flags asking for a higher alignment. If the
55+ // alignment is greater than the size, however, then this hits a sort of odd
56+ // case where we still need to ask for a custom alignment. See #25 for more
57+ // info.
58+ if align <= MIN_ALIGN && align <= size {
59+ 0
60+ } else {
61+ // Equivalent to the MALLOCX_ALIGN(a) macro.
62+ align. trailing_zeros ( ) as _
63+ }
64+ }
65+
66+ unsafe impl GlobalAlloc for Allocator {
67+ #[ inline]
68+ unsafe fn alloc ( & self , layout : Layout ) -> * mut Opaque {
69+ let flags = layout_to_flags ( layout. align ( ) , layout. size ( ) ) ;
70+ ffi:: mallocx ( layout. size ( ) , flags) as * mut Opaque
71+ }
72+
73+ #[ inline]
74+ unsafe fn alloc_zeroed ( & self , layout : Layout ) -> * mut Opaque {
75+ if layout. align ( ) <= MIN_ALIGN && layout. align ( ) <= layout. size ( ) {
76+ ffi:: calloc ( 1 , layout. size ( ) ) as * mut Opaque
77+ } else {
78+ let flags = layout_to_flags ( layout. align ( ) , layout. size ( ) ) | ffi:: MALLOCX_ZERO ;
79+ ffi:: mallocx ( layout. size ( ) , flags) as * mut Opaque
80+ }
81+ }
82+
83+ #[ inline]
84+ unsafe fn dealloc ( & self , ptr : * mut Opaque , layout : Layout ) {
85+ let flags = layout_to_flags ( layout. align ( ) , layout. size ( ) ) ;
86+ ffi:: sdallocx ( ptr as * mut _ , layout. size ( ) , flags)
87+ }
88+
89+ #[ inline]
90+ unsafe fn realloc ( & self ,
91+ ptr : * mut Opaque ,
92+ layout : Layout ,
93+ new_size : usize ) -> * mut Opaque {
94+ let flags = layout_to_flags ( layout. align ( ) , new_size) ;
95+ ffi:: rallocx ( ptr as * mut _ , new_size, flags) as * mut Opaque
96+ }
97+
98+ #[ inline]
99+ fn oom ( & self ) -> ! {
100+ System . oom ( )
101+ }
32102 }
33103}
34104
0 commit comments