12
12
// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
13
13
// and `nonnull`
14
14
15
- use core:: intrinsics:: { abort, cttz32} ;
16
- use core:: option:: { None , Option } ;
17
- use core:: ptr:: { RawPtr , mut_null, null} ;
18
- use libc:: { c_char, c_int, c_void, size_t} ;
19
-
20
15
#[ cfg( not( test) ) ] use core:: raw;
21
16
#[ cfg( not( test) ) ] use util;
22
17
23
- #[ link( name = "jemalloc" , kind = "static" ) ]
24
- extern {
25
- fn je_mallocx ( size : size_t , flags : c_int ) -> * mut c_void ;
26
- fn je_rallocx ( ptr : * mut c_void , size : size_t , flags : c_int ) -> * mut c_void ;
27
- fn je_xallocx ( ptr : * mut c_void , size : size_t , extra : size_t ,
28
- flags : c_int ) -> size_t ;
29
- fn je_dallocx ( ptr : * mut c_void , flags : c_int ) ;
30
- fn je_nallocx ( size : size_t , flags : c_int ) -> size_t ;
31
- fn je_malloc_stats_print ( write_cb : Option < extern "C" fn ( cbopaque : * mut c_void , * c_char ) > ,
32
- cbopaque : * mut c_void ,
33
- opts : * c_char ) ;
34
- }
35
-
36
- // -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
37
- #[ cfg( not( windows) , not( target_os = "android" ) ) ]
38
- #[ link( name = "pthread" ) ]
39
- extern { }
40
-
41
- // MALLOCX_ALIGN(a) macro
42
- #[ inline( always) ]
43
- fn mallocx_align ( a : uint ) -> c_int { unsafe { cttz32 ( a as u32 ) as c_int } }
44
-
45
18
/// Return a pointer to `size` bytes of memory.
46
19
///
47
20
/// Behavior is undefined if the requested size is 0 or the alignment is not a
48
21
/// power of 2. The alignment must be no larger than the largest supported page
49
22
/// size on the platform.
50
23
#[ inline]
51
24
pub unsafe fn allocate ( size : uint , align : uint ) -> * mut u8 {
52
- let ptr = je_mallocx ( size as size_t , mallocx_align ( align) ) as * mut u8 ;
53
- if ptr. is_null ( ) {
54
- abort ( )
55
- }
56
- ptr
25
+ imp:: allocate ( size, align)
57
26
}
58
27
59
28
/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of
@@ -67,15 +36,9 @@ pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
67
36
/// create the allocation referenced by `ptr`. The `old_size` parameter may also
68
37
/// be the value returned by `usable_size` for the requested size.
69
38
#[ inline]
70
- #[ allow( unused_variable) ] // for the parameter names in the documentation
71
39
pub unsafe fn reallocate ( ptr : * mut u8 , size : uint , align : uint ,
72
40
old_size : uint ) -> * mut u8 {
73
- let ptr = je_rallocx ( ptr as * mut c_void , size as size_t ,
74
- mallocx_align ( align) ) as * mut u8 ;
75
- if ptr. is_null ( ) {
76
- abort ( )
77
- }
78
- ptr
41
+ imp:: reallocate ( ptr, size, align, old_size)
79
42
}
80
43
81
44
/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of
@@ -92,11 +55,9 @@ pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
92
55
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
93
56
/// any value in range_inclusive(requested_size, usable_size).
94
57
#[ inline]
95
- #[ allow( unused_variable) ] // for the parameter names in the documentation
96
58
pub unsafe fn reallocate_inplace ( ptr : * mut u8 , size : uint , align : uint ,
97
59
old_size : uint ) -> bool {
98
- je_xallocx ( ptr as * mut c_void , size as size_t , 0 ,
99
- mallocx_align ( align) ) == size as size_t
60
+ imp:: reallocate_inplace ( ptr, size, align, old_size)
100
61
}
101
62
102
63
/// Deallocate the memory referenced by `ptr`.
@@ -107,16 +68,15 @@ pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
107
68
/// create the allocation referenced by `ptr`. The `size` parameter may also be
108
69
/// the value returned by `usable_size` for the requested size.
109
70
#[ inline]
110
- #[ allow( unused_variable) ] // for the parameter names in the documentation
111
71
pub unsafe fn deallocate ( ptr : * mut u8 , size : uint , align : uint ) {
112
- je_dallocx ( ptr as * mut c_void , mallocx_align ( align) )
72
+ imp :: deallocate ( ptr, size , align)
113
73
}
114
74
115
75
/// Return the usable size of an allocation created with the specified the
116
76
/// `size` and `align`.
117
77
#[ inline]
118
78
pub fn usable_size ( size : uint , align : uint ) -> uint {
119
- unsafe { je_nallocx ( size as size_t , mallocx_align ( align) ) as uint }
79
+ imp :: usable_size ( size, align)
120
80
}
121
81
122
82
/// Print implementation-defined allocator statistics.
@@ -125,9 +85,7 @@ pub fn usable_size(size: uint, align: uint) -> uint {
125
85
/// during the call.
126
86
#[ unstable]
127
87
pub fn stats_print ( ) {
128
- unsafe {
129
- je_malloc_stats_print ( None , mut_null ( ) , null ( ) )
130
- }
88
+ imp:: stats_print ( ) ;
131
89
}
132
90
133
91
// The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
@@ -170,6 +128,199 @@ unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint,
170
128
alloc as * mut u8
171
129
}
172
130
131
+ #[ cfg( jemalloc) ]
132
+ mod imp {
133
+ use core:: intrinsics:: abort;
134
+ use core:: option:: { None , Option } ;
135
+ use core:: ptr:: { RawPtr , mut_null, null} ;
136
+ use core:: num:: Bitwise ;
137
+ use libc:: { c_char, c_int, c_void, size_t} ;
138
+
139
+ #[ link( name = "jemalloc" , kind = "static" ) ]
140
+ extern {
141
+ fn je_mallocx ( size : size_t , flags : c_int ) -> * mut c_void ;
142
+ fn je_rallocx ( ptr : * mut c_void , size : size_t ,
143
+ flags : c_int ) -> * mut c_void ;
144
+ fn je_xallocx ( ptr : * mut c_void , size : size_t , extra : size_t ,
145
+ flags : c_int ) -> size_t ;
146
+ fn je_dallocx ( ptr : * mut c_void , flags : c_int ) ;
147
+ fn je_nallocx ( size : size_t , flags : c_int ) -> size_t ;
148
+ fn je_malloc_stats_print ( write_cb : Option < extern "C" fn ( cbopaque : * mut c_void , * c_char ) > ,
149
+ cbopaque : * mut c_void ,
150
+ opts : * c_char ) ;
151
+ }
152
+
153
+ // -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
154
+ #[ cfg( not( windows) , not( target_os = "android" ) ) ]
155
+ #[ link( name = "pthread" ) ]
156
+ extern { }
157
+
158
+ // MALLOCX_ALIGN(a) macro
159
+ #[ inline( always) ]
160
+ fn mallocx_align ( a : uint ) -> c_int { a. trailing_zeros ( ) as c_int }
161
+
162
+ #[ inline]
163
+ pub unsafe fn allocate ( size : uint , align : uint ) -> * mut u8 {
164
+ let ptr = je_mallocx ( size as size_t , mallocx_align ( align) ) as * mut u8 ;
165
+ if ptr. is_null ( ) {
166
+ abort ( )
167
+ }
168
+ ptr
169
+ }
170
+
171
+ #[ inline]
172
+ pub unsafe fn reallocate ( ptr : * mut u8 , size : uint , align : uint ,
173
+ _old_size : uint ) -> * mut u8 {
174
+ let ptr = je_rallocx ( ptr as * mut c_void , size as size_t ,
175
+ mallocx_align ( align) ) as * mut u8 ;
176
+ if ptr. is_null ( ) {
177
+ abort ( )
178
+ }
179
+ ptr
180
+ }
181
+
182
+ #[ inline]
183
+ pub unsafe fn reallocate_inplace ( ptr : * mut u8 , size : uint , align : uint ,
184
+ _old_size : uint ) -> bool {
185
+ je_xallocx ( ptr as * mut c_void , size as size_t , 0 ,
186
+ mallocx_align ( align) ) == size as size_t
187
+ }
188
+
189
+ #[ inline]
190
+ pub unsafe fn deallocate ( ptr : * mut u8 , _size : uint , align : uint ) {
191
+ je_dallocx ( ptr as * mut c_void , mallocx_align ( align) )
192
+ }
193
+
194
+ #[ inline]
195
+ pub fn usable_size ( size : uint , align : uint ) -> uint {
196
+ unsafe { je_nallocx ( size as size_t , mallocx_align ( align) ) as uint }
197
+ }
198
+
199
+ pub fn stats_print ( ) {
200
+ unsafe {
201
+ je_malloc_stats_print ( None , mut_null ( ) , null ( ) )
202
+ }
203
+ }
204
+ }
205
+
206
+ #[ cfg( not( jemalloc) , unix) ]
207
+ mod imp {
208
+ use core:: mem;
209
+ use core:: ptr;
210
+ use libc;
211
+ use libc_heap;
212
+
213
+ extern {
214
+ fn posix_memalign ( memptr : * mut * mut libc:: c_void ,
215
+ align : libc:: size_t ,
216
+ size : libc:: size_t ) -> libc:: c_int ;
217
+ }
218
+
219
+ #[ inline]
220
+ pub unsafe fn allocate ( size : uint , align : uint ) -> * mut u8 {
221
+ // The posix_memalign manpage states
222
+ //
223
+ // alignment [...] must be a power of and a multiple of
224
+ // sizeof(void *)
225
+ //
226
+ // The `align` parameter to this function is the *minimum* alignment for
227
+ // a block of memory, so we special case everything under `*uint` to
228
+ // just pass it to malloc, which is guaranteed to align to at least the
229
+ // size of `*uint`.
230
+ if align < mem:: size_of :: < * uint > ( ) {
231
+ libc_heap:: malloc_raw ( size)
232
+ } else {
233
+ let mut out = 0 as * mut libc:: c_void ;
234
+ let ret = posix_memalign ( & mut out,
235
+ align as libc:: size_t ,
236
+ size as libc:: size_t ) ;
237
+ if ret != 0 {
238
+ :: oom ( ) ;
239
+ }
240
+ out as * mut u8
241
+ }
242
+ }
243
+
244
+ #[ inline]
245
+ pub unsafe fn reallocate ( ptr : * mut u8 , size : uint , align : uint ,
246
+ old_size : uint ) -> * mut u8 {
247
+ let new_ptr = allocate ( size, align) ;
248
+ ptr:: copy_memory ( new_ptr, ptr as * u8 , old_size) ;
249
+ deallocate ( ptr, old_size, align) ;
250
+ return new_ptr;
251
+ }
252
+
253
+ #[ inline]
254
+ pub unsafe fn reallocate_inplace ( _ptr : * mut u8 , _size : uint , _align : uint ,
255
+ _old_size : uint ) -> bool {
256
+ false
257
+ }
258
+
259
+ #[ inline]
260
+ pub unsafe fn deallocate ( ptr : * mut u8 , _size : uint , _align : uint ) {
261
+ libc:: free ( ptr as * mut libc:: c_void )
262
+ }
263
+
264
+ #[ inline]
265
+ pub fn usable_size ( size : uint , _align : uint ) -> uint {
266
+ size
267
+ }
268
+
269
+ pub fn stats_print ( ) {
270
+ }
271
+ }
272
+
273
+ #[ cfg( not( jemalloc) , windows) ]
274
+ mod imp {
275
+ use libc:: { c_void, size_t} ;
276
+ use core:: ptr:: RawPtr ;
277
+
278
+ extern {
279
+ fn _aligned_malloc ( size : size_t , align : size_t ) -> * mut c_void ;
280
+ fn _aligned_realloc ( block : * mut c_void , size : size_t ,
281
+ align : size_t ) -> * mut c_void ;
282
+ fn _aligned_free ( ptr : * mut c_void ) ;
283
+ }
284
+
285
+ #[ inline]
286
+ pub unsafe fn allocate ( size : uint , align : uint ) -> * mut u8 {
287
+ let ptr = _aligned_malloc ( size as size_t , align as size_t ) ;
288
+ if ptr. is_null ( ) {
289
+ :: oom ( ) ;
290
+ }
291
+ ptr as * mut u8
292
+ }
293
+
294
+ #[ inline]
295
+ pub unsafe fn reallocate ( ptr : * mut u8 , size : uint , align : uint ,
296
+ _old_size : uint ) -> * mut u8 {
297
+ let ptr = _aligned_realloc ( ptr as * mut c_void , size as size_t ,
298
+ align as size_t ) ;
299
+ if ptr. is_null ( ) {
300
+ :: oom ( ) ;
301
+ }
302
+ ptr as * mut u8
303
+ }
304
+
305
+ #[ inline]
306
+ pub unsafe fn reallocate_inplace ( _ptr : * mut u8 , _size : uint , _align : uint ,
307
+ _old_size : uint ) -> bool {
308
+ false
309
+ }
310
+
311
+ #[ inline]
312
+ pub unsafe fn deallocate ( ptr : * mut u8 , _size : uint , _align : uint ) {
313
+ _aligned_free ( ptr as * mut c_void )
314
+ }
315
+
316
+ #[ inline]
317
+ pub fn usable_size ( size : uint , _align : uint ) -> uint {
318
+ size
319
+ }
320
+
321
+ pub fn stats_print ( ) { }
322
+ }
323
+
173
324
#[ cfg( test) ]
174
325
mod bench {
175
326
extern crate test;
0 commit comments