]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
62682a34 SL |
11 | #![unstable(feature = "heap_api", |
12 | reason = "the precise API and guarantees it provides may be tweaked \ | |
13 | slightly, especially to possibly take into account the \ | |
14 | types being stored to make room for a future \ | |
15 | tracing garbage collector")] | |
16 | ||
d9579d0f AL |
17 | use core::{isize, usize}; |
18 | ||
19 | #[inline(always)] | |
20 | fn check_size_and_alignment(size: usize, align: usize) { | |
21 | debug_assert!(size != 0); | |
22 | debug_assert!(size <= isize::MAX as usize, "Tried to allocate too much: {} bytes", size); | |
23 | debug_assert!(usize::is_power_of_two(align), "Invalid alignment of allocation: {}", align); | |
24 | } | |
25 | ||
1a4d82fc JJ |
26 | // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias` |
27 | ||
28 | /// Return a pointer to `size` bytes of memory aligned to `align`. | |
29 | /// | |
30 | /// On failure, return a null pointer. | |
31 | /// | |
32 | /// Behavior is undefined if the requested size is 0 or the alignment is not a | |
33 | /// power of 2. The alignment must be no larger than the largest supported page | |
34 | /// size on the platform. | |
35 | #[inline] | |
85aaf69f | 36 | pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { |
d9579d0f | 37 | check_size_and_alignment(size, align); |
1a4d82fc JJ |
38 | imp::allocate(size, align) |
39 | } | |
40 | ||
41 | /// Resize the allocation referenced by `ptr` to `size` bytes. | |
42 | /// | |
43 | /// On failure, return a null pointer and leave the original allocation intact. | |
44 | /// | |
c34b1796 AL |
45 | /// If the allocation was relocated, the memory at the passed-in pointer is |
46 | /// undefined after the call. | |
47 | /// | |
1a4d82fc JJ |
48 | /// Behavior is undefined if the requested size is 0 or the alignment is not a |
49 | /// power of 2. The alignment must be no larger than the largest supported page | |
50 | /// size on the platform. | |
51 | /// | |
52 | /// The `old_size` and `align` parameters are the parameters that were used to | |
53 | /// create the allocation referenced by `ptr`. The `old_size` parameter may be | |
54 | /// any value in range_inclusive(requested_size, usable_size). | |
55 | #[inline] | |
85aaf69f | 56 | pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { |
d9579d0f | 57 | check_size_and_alignment(size, align); |
1a4d82fc JJ |
58 | imp::reallocate(ptr, old_size, size, align) |
59 | } | |
60 | ||
61 | /// Resize the allocation referenced by `ptr` to `size` bytes. | |
62 | /// | |
63 | /// If the operation succeeds, it returns `usable_size(size, align)` and if it | |
64 | /// fails (or is a no-op) it returns `usable_size(old_size, align)`. | |
65 | /// | |
66 | /// Behavior is undefined if the requested size is 0 or the alignment is not a | |
67 | /// power of 2. The alignment must be no larger than the largest supported page | |
68 | /// size on the platform. | |
69 | /// | |
70 | /// The `old_size` and `align` parameters are the parameters that were used to | |
71 | /// create the allocation referenced by `ptr`. The `old_size` parameter may be | |
72 | /// any value in range_inclusive(requested_size, usable_size). | |
73 | #[inline] | |
85aaf69f SL |
74 | pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize, |
75 | align: usize) -> usize { | |
d9579d0f | 76 | check_size_and_alignment(size, align); |
1a4d82fc JJ |
77 | imp::reallocate_inplace(ptr, old_size, size, align) |
78 | } | |
79 | ||
80 | /// Deallocates the memory referenced by `ptr`. | |
81 | /// | |
82 | /// The `ptr` parameter must not be null. | |
83 | /// | |
84 | /// The `old_size` and `align` parameters are the parameters that were used to | |
85 | /// create the allocation referenced by `ptr`. The `old_size` parameter may be | |
86 | /// any value in range_inclusive(requested_size, usable_size). | |
87 | #[inline] | |
85aaf69f | 88 | pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) { |
1a4d82fc JJ |
89 | imp::deallocate(ptr, old_size, align) |
90 | } | |
91 | ||
92 | /// Returns the usable size of an allocation created with the specified the | |
93 | /// `size` and `align`. | |
94 | #[inline] | |
85aaf69f | 95 | pub fn usable_size(size: usize, align: usize) -> usize { |
1a4d82fc JJ |
96 | imp::usable_size(size, align) |
97 | } | |
98 | ||
99 | /// Prints implementation-defined allocator statistics. | |
100 | /// | |
101 | /// These statistics may be inconsistent if other threads use the allocator | |
102 | /// during the call. | |
1a4d82fc JJ |
103 | pub fn stats_print() { |
104 | imp::stats_print(); | |
105 | } | |
106 | ||
107 | /// An arbitrary non-null address to represent zero-size allocations. | |
108 | /// | |
109 | /// This preserves the non-null invariant for types like `Box<T>`. The address may overlap with | |
110 | /// non-zero-size memory allocations. | |
111 | pub const EMPTY: *mut () = 0x1 as *mut (); | |
112 | ||
113 | /// The allocator for unique pointers. | |
114 | #[cfg(not(test))] | |
d9579d0f | 115 | #[lang = "exchange_malloc"] |
1a4d82fc | 116 | #[inline] |
85aaf69f | 117 | unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { |
1a4d82fc JJ |
118 | if size == 0 { |
119 | EMPTY as *mut u8 | |
120 | } else { | |
121 | let ptr = allocate(size, align); | |
122 | if ptr.is_null() { ::oom() } | |
123 | ptr | |
124 | } | |
125 | } | |
126 | ||
127 | #[cfg(not(test))] | |
d9579d0f | 128 | #[lang = "exchange_free"] |
1a4d82fc | 129 | #[inline] |
85aaf69f | 130 | unsafe fn exchange_free(ptr: *mut u8, old_size: usize, align: usize) { |
1a4d82fc JJ |
131 | deallocate(ptr, old_size, align); |
132 | } | |
133 | ||
134 | // The minimum alignment guaranteed by the architecture. This value is used to | |
135 | // add fast paths for low alignment values. In practice, the alignment is a | |
136 | // constant at the call site and the branch will be optimized out. | |
137 | #[cfg(all(not(feature = "external_funcs"), | |
138 | not(feature = "external_crate"), | |
139 | any(target_arch = "arm", | |
140 | target_arch = "mips", | |
85aaf69f SL |
141 | target_arch = "mipsel", |
142 | target_arch = "powerpc")))] | |
143 | const MIN_ALIGN: usize = 8; | |
1a4d82fc JJ |
144 | #[cfg(all(not(feature = "external_funcs"), |
145 | not(feature = "external_crate"), | |
146 | any(target_arch = "x86", | |
147 | target_arch = "x86_64", | |
148 | target_arch = "aarch64")))] | |
85aaf69f | 149 | const MIN_ALIGN: usize = 16; |
1a4d82fc JJ |
150 | |
151 | #[cfg(feature = "external_funcs")] | |
152 | mod imp { | |
d9579d0f | 153 | #[allow(improper_ctypes)] |
1a4d82fc | 154 | extern { |
85aaf69f SL |
155 | fn rust_allocate(size: usize, align: usize) -> *mut u8; |
156 | fn rust_deallocate(ptr: *mut u8, old_size: usize, align: usize); | |
157 | fn rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8; | |
158 | fn rust_reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize, | |
159 | align: usize) -> usize; | |
160 | fn rust_usable_size(size: usize, align: usize) -> usize; | |
1a4d82fc JJ |
161 | fn rust_stats_print(); |
162 | } | |
163 | ||
164 | #[inline] | |
85aaf69f | 165 | pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { |
1a4d82fc JJ |
166 | rust_allocate(size, align) |
167 | } | |
168 | ||
169 | #[inline] | |
85aaf69f | 170 | pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) { |
1a4d82fc JJ |
171 | rust_deallocate(ptr, old_size, align) |
172 | } | |
173 | ||
174 | #[inline] | |
85aaf69f | 175 | pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { |
1a4d82fc JJ |
176 | rust_reallocate(ptr, old_size, size, align) |
177 | } | |
178 | ||
179 | #[inline] | |
85aaf69f SL |
180 | pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize, |
181 | align: usize) -> usize { | |
1a4d82fc JJ |
182 | rust_reallocate_inplace(ptr, old_size, size, align) |
183 | } | |
184 | ||
185 | #[inline] | |
85aaf69f | 186 | pub fn usable_size(size: usize, align: usize) -> usize { |
1a4d82fc JJ |
187 | unsafe { rust_usable_size(size, align) } |
188 | } | |
189 | ||
190 | #[inline] | |
191 | pub fn stats_print() { | |
192 | unsafe { rust_stats_print() } | |
193 | } | |
194 | } | |
195 | ||
196 | #[cfg(feature = "external_crate")] | |
197 | mod imp { | |
198 | extern crate external; | |
199 | pub use self::external::{allocate, deallocate, reallocate_inplace, reallocate}; | |
200 | pub use self::external::{usable_size, stats_print}; | |
201 | } | |
202 | ||
203 | #[cfg(all(not(feature = "external_funcs"), | |
204 | not(feature = "external_crate"), | |
205 | jemalloc))] | |
206 | mod imp { | |
207 | use core::option::Option; | |
208 | use core::option::Option::None; | |
209 | use core::ptr::{null_mut, null}; | |
1a4d82fc JJ |
210 | use libc::{c_char, c_int, c_void, size_t}; |
211 | use super::MIN_ALIGN; | |
212 | ||
213 | #[link(name = "jemalloc", kind = "static")] | |
214 | #[cfg(not(test))] | |
215 | extern {} | |
216 | ||
217 | extern { | |
c34b1796 | 218 | #[allocator] |
1a4d82fc JJ |
219 | fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void; |
220 | fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void; | |
221 | fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t; | |
222 | fn je_sdallocx(ptr: *mut c_void, size: size_t, flags: c_int); | |
223 | fn je_nallocx(size: size_t, flags: c_int) -> size_t; | |
224 | fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void, | |
225 | *const c_char)>, | |
226 | cbopaque: *mut c_void, | |
227 | opts: *const c_char); | |
228 | } | |
229 | ||
230 | // -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough | |
d9579d0f AL |
231 | #[cfg(all(not(windows), |
232 | not(target_os = "android"), | |
233 | not(target_env = "musl")))] | |
1a4d82fc JJ |
234 | #[link(name = "pthread")] |
235 | extern {} | |
236 | ||
237 | // MALLOCX_ALIGN(a) macro | |
238 | #[inline(always)] | |
85aaf69f | 239 | fn mallocx_align(a: usize) -> c_int { a.trailing_zeros() as c_int } |
1a4d82fc JJ |
240 | |
241 | #[inline(always)] | |
85aaf69f | 242 | fn align_to_flags(align: usize) -> c_int { |
1a4d82fc JJ |
243 | if align <= MIN_ALIGN { 0 } else { mallocx_align(align) } |
244 | } | |
245 | ||
246 | #[inline] | |
85aaf69f | 247 | pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { |
1a4d82fc JJ |
248 | let flags = align_to_flags(align); |
249 | je_mallocx(size as size_t, flags) as *mut u8 | |
250 | } | |
251 | ||
252 | #[inline] | |
85aaf69f | 253 | pub unsafe fn reallocate(ptr: *mut u8, _old_size: usize, size: usize, align: usize) -> *mut u8 { |
1a4d82fc JJ |
254 | let flags = align_to_flags(align); |
255 | je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 | |
256 | } | |
257 | ||
258 | #[inline] | |
85aaf69f SL |
259 | pub unsafe fn reallocate_inplace(ptr: *mut u8, _old_size: usize, size: usize, |
260 | align: usize) -> usize { | |
1a4d82fc | 261 | let flags = align_to_flags(align); |
85aaf69f | 262 | je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as usize |
1a4d82fc JJ |
263 | } |
264 | ||
265 | #[inline] | |
85aaf69f | 266 | pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) { |
1a4d82fc JJ |
267 | let flags = align_to_flags(align); |
268 | je_sdallocx(ptr as *mut c_void, old_size as size_t, flags) | |
269 | } | |
270 | ||
271 | #[inline] | |
85aaf69f | 272 | pub fn usable_size(size: usize, align: usize) -> usize { |
1a4d82fc | 273 | let flags = align_to_flags(align); |
85aaf69f | 274 | unsafe { je_nallocx(size as size_t, flags) as usize } |
1a4d82fc JJ |
275 | } |
276 | ||
277 | pub fn stats_print() { | |
278 | unsafe { | |
279 | je_malloc_stats_print(None, null_mut(), null()) | |
280 | } | |
281 | } | |
282 | } | |
283 | ||
284 | #[cfg(all(not(feature = "external_funcs"), | |
285 | not(feature = "external_crate"), | |
286 | not(jemalloc), | |
287 | unix))] | |
288 | mod imp { | |
289 | use core::cmp; | |
290 | use core::ptr; | |
291 | use libc; | |
292 | use super::MIN_ALIGN; | |
293 | ||
294 | extern { | |
295 | fn posix_memalign(memptr: *mut *mut libc::c_void, | |
296 | align: libc::size_t, | |
297 | size: libc::size_t) -> libc::c_int; | |
298 | } | |
299 | ||
300 | #[inline] | |
85aaf69f | 301 | pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { |
1a4d82fc JJ |
302 | if align <= MIN_ALIGN { |
303 | libc::malloc(size as libc::size_t) as *mut u8 | |
304 | } else { | |
85aaf69f | 305 | let mut out = ptr::null_mut(); |
1a4d82fc JJ |
306 | let ret = posix_memalign(&mut out, |
307 | align as libc::size_t, | |
308 | size as libc::size_t); | |
309 | if ret != 0 { | |
310 | ptr::null_mut() | |
311 | } else { | |
312 | out as *mut u8 | |
313 | } | |
314 | } | |
315 | } | |
316 | ||
317 | #[inline] | |
85aaf69f | 318 | pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { |
1a4d82fc JJ |
319 | if align <= MIN_ALIGN { |
320 | libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8 | |
321 | } else { | |
322 | let new_ptr = allocate(size, align); | |
c34b1796 | 323 | ptr::copy(ptr, new_ptr, cmp::min(size, old_size)); |
1a4d82fc JJ |
324 | deallocate(ptr, old_size, align); |
325 | new_ptr | |
326 | } | |
327 | } | |
328 | ||
329 | #[inline] | |
85aaf69f SL |
330 | pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: usize, _size: usize, |
331 | _align: usize) -> usize { | |
1a4d82fc JJ |
332 | old_size |
333 | } | |
334 | ||
335 | #[inline] | |
85aaf69f | 336 | pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, _align: usize) { |
1a4d82fc JJ |
337 | libc::free(ptr as *mut libc::c_void) |
338 | } | |
339 | ||
340 | #[inline] | |
85aaf69f | 341 | pub fn usable_size(size: usize, _align: usize) -> usize { |
1a4d82fc JJ |
342 | size |
343 | } | |
344 | ||
345 | pub fn stats_print() {} | |
346 | } | |
347 | ||
348 | #[cfg(all(not(feature = "external_funcs"), | |
349 | not(feature = "external_crate"), | |
350 | not(jemalloc), | |
351 | windows))] | |
352 | mod imp { | |
62682a34 SL |
353 | use core::mem::size_of; |
354 | use libc::{BOOL, DWORD, HANDLE, LPVOID, SIZE_T, INVALID_HANDLE_VALUE}; | |
355 | use libc::{WriteFile}; | |
1a4d82fc JJ |
356 | use super::MIN_ALIGN; |
357 | ||
62682a34 SL |
358 | extern "system" { |
359 | fn GetProcessHeap() -> HANDLE; | |
360 | fn GetStdHandle(nStdHandle: DWORD) -> HANDLE; | |
361 | fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; | |
362 | fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID; | |
363 | fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; | |
364 | fn HeapSummary(hHeap: HANDLE, dwFlags: DWORD, lpSummary: LPHEAP_SUMMARY) -> BOOL; | |
365 | } | |
366 | ||
367 | #[repr(C)] #[allow(non_snake_case)] | |
368 | struct HEAP_SUMMARY { | |
369 | cb: DWORD, | |
370 | cbAllocated: SIZE_T, | |
371 | cbCommitted: SIZE_T, | |
372 | cbReserved: SIZE_T, | |
373 | cbMaxReserve: SIZE_T, | |
374 | } | |
375 | #[allow(non_camel_case_types)] | |
376 | type LPHEAP_SUMMARY = *mut HEAP_SUMMARY; | |
377 | ||
378 | #[repr(C)] | |
379 | struct Header(*mut u8); | |
380 | ||
381 | const HEAP_REALLOC_IN_PLACE_ONLY: DWORD = 0x00000010; | |
382 | const STD_OUTPUT_HANDLE: DWORD = -11i32 as u32; | |
383 | ||
384 | #[inline] | |
385 | unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header { | |
386 | &mut *(ptr as *mut Header).offset(-1) | |
387 | } | |
388 | ||
389 | #[inline] | |
390 | unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 { | |
391 | let aligned = ptr.offset((align - (ptr as usize & (align - 1))) as isize); | |
392 | *get_header(aligned) = Header(ptr); | |
393 | aligned | |
1a4d82fc JJ |
394 | } |
395 | ||
396 | #[inline] | |
85aaf69f | 397 | pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { |
1a4d82fc | 398 | if align <= MIN_ALIGN { |
62682a34 | 399 | HeapAlloc(GetProcessHeap(), 0, size as SIZE_T) as *mut u8 |
1a4d82fc | 400 | } else { |
62682a34 SL |
401 | let ptr = HeapAlloc(GetProcessHeap(), 0, (size + align) as SIZE_T) as *mut u8; |
402 | if ptr.is_null() { return ptr } | |
403 | align_ptr(ptr, align) | |
1a4d82fc JJ |
404 | } |
405 | } | |
406 | ||
407 | #[inline] | |
85aaf69f | 408 | pub unsafe fn reallocate(ptr: *mut u8, _old_size: usize, size: usize, align: usize) -> *mut u8 { |
1a4d82fc | 409 | if align <= MIN_ALIGN { |
62682a34 | 410 | HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, size as SIZE_T) as *mut u8 |
1a4d82fc | 411 | } else { |
62682a34 SL |
412 | let header = get_header(ptr); |
413 | let new = HeapReAlloc(GetProcessHeap(), 0, header.0 as LPVOID, | |
414 | (size + align) as SIZE_T) as *mut u8; | |
415 | if new.is_null() { return new } | |
416 | align_ptr(new, align) | |
1a4d82fc JJ |
417 | } |
418 | } | |
419 | ||
420 | #[inline] | |
62682a34 SL |
421 | pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize, |
422 | align: usize) -> usize { | |
423 | if align <= MIN_ALIGN { | |
424 | let new = HeapReAlloc(GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, ptr as LPVOID, | |
425 | size as SIZE_T) as *mut u8; | |
426 | if new.is_null() { old_size } else { size } | |
427 | } else { | |
428 | old_size | |
429 | } | |
1a4d82fc JJ |
430 | } |
431 | ||
432 | #[inline] | |
85aaf69f | 433 | pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, align: usize) { |
1a4d82fc | 434 | if align <= MIN_ALIGN { |
62682a34 SL |
435 | let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID); |
436 | debug_assert!(err != 0); | |
1a4d82fc | 437 | } else { |
62682a34 SL |
438 | let header = get_header(ptr); |
439 | let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID); | |
440 | debug_assert!(err != 0); | |
1a4d82fc JJ |
441 | } |
442 | } | |
443 | ||
444 | #[inline] | |
85aaf69f | 445 | pub fn usable_size(size: usize, _align: usize) -> usize { |
1a4d82fc JJ |
446 | size |
447 | } | |
448 | ||
62682a34 SL |
449 | pub fn stats_print() { |
450 | use core::fmt::{Error, Result, Write}; | |
451 | use core::ptr::null_mut; | |
452 | use core::raw::Repr; | |
453 | use core::result::Result::{Ok, Err}; | |
454 | struct Console(HANDLE); | |
455 | impl Write for Console { | |
456 | fn write_str(&mut self, s: &str) -> Result { | |
457 | let repr = s.repr(); | |
458 | let mut written = 0; | |
459 | let err = unsafe { WriteFile(self.0, repr.data as LPVOID, repr.len as DWORD, | |
460 | &mut written, null_mut()) }; | |
461 | if written as usize != repr.len { return Err(Error) } | |
462 | if err == 0 { return Err(Error) } | |
463 | Ok(()) | |
464 | } | |
465 | } | |
466 | let mut hs = HEAP_SUMMARY { | |
467 | cb: size_of::<HEAP_SUMMARY>() as DWORD, | |
468 | cbAllocated: 0, | |
469 | cbCommitted: 0, | |
470 | cbReserved: 0, | |
471 | cbMaxReserve: 0, | |
472 | }; | |
473 | let err = unsafe { HeapSummary(GetProcessHeap(), 0, &mut hs) }; | |
474 | assert!(err != 0); | |
475 | let handle = unsafe { GetStdHandle(STD_OUTPUT_HANDLE) }; | |
476 | if handle.is_null() || handle == INVALID_HANDLE_VALUE { panic!("Failed to open stdout") } | |
477 | let mut out = Console(handle); | |
478 | writeln!(&mut out, "Allocated: {}", hs.cbAllocated).unwrap(); | |
479 | writeln!(&mut out, "Committed: {}", hs.cbCommitted).unwrap(); | |
480 | writeln!(&mut out, "Reserved: {}", hs.cbReserved).unwrap(); | |
481 | writeln!(&mut out, "MaxReserve: {}", hs.cbMaxReserve).unwrap(); | |
482 | } | |
483 | ||
484 | #[test] | |
485 | fn alignment_header_size() { | |
486 | assert!(size_of::<Header>() <= MIN_ALIGN); | |
487 | } | |
1a4d82fc JJ |
488 | } |
489 | ||
490 | #[cfg(test)] | |
d9579d0f | 491 | mod tests { |
1a4d82fc JJ |
492 | extern crate test; |
493 | use self::test::Bencher; | |
c34b1796 | 494 | use boxed::Box; |
1a4d82fc JJ |
495 | use heap; |
496 | ||
497 | #[test] | |
498 | fn basic_reallocate_inplace_noop() { | |
499 | unsafe { | |
500 | let size = 4000; | |
501 | let ptr = heap::allocate(size, 8); | |
502 | if ptr.is_null() { ::oom() } | |
503 | let ret = heap::reallocate_inplace(ptr, size, size, 8); | |
504 | heap::deallocate(ptr, size, 8); | |
505 | assert_eq!(ret, heap::usable_size(size, 8)); | |
506 | } | |
507 | } | |
508 | ||
509 | #[bench] | |
510 | fn alloc_owned_small(b: &mut Bencher) { | |
511 | b.iter(|| { | |
c34b1796 | 512 | let _: Box<_> = box 10; |
1a4d82fc JJ |
513 | }) |
514 | } | |
515 | } |