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.
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.
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",
18 use core::{isize, usize};
20 #[allow(improper_ctypes)]
23 fn __rust_allocate(size: usize, align: usize) -> *mut u8;
24 fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize);
25 fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8;
26 fn __rust_reallocate_inplace(ptr: *mut u8,
31 fn __rust_usable_size(size: usize, align: usize) -> usize;
35 fn check_size_and_alignment(size: usize, align: usize) {
36 debug_assert!(size != 0);
37 debug_assert!(size <= isize::MAX as usize,
38 "Tried to allocate too much: {} bytes",
40 debug_assert!(usize::is_power_of_two(align),
41 "Invalid alignment of allocation: {}",
45 // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
47 /// Return a pointer to `size` bytes of memory aligned to `align`.
49 /// On failure, return a null pointer.
51 /// Behavior is undefined if the requested size is 0 or the alignment is not a
52 /// power of 2. The alignment must be no larger than the largest supported page
53 /// size on the platform.
55 pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
56 check_size_and_alignment(size, align);
57 __rust_allocate(size, align)
60 /// Resize the allocation referenced by `ptr` to `size` bytes.
62 /// On failure, return a null pointer and leave the original allocation intact.
64 /// If the allocation was relocated, the memory at the passed-in pointer is
65 /// undefined after the call.
67 /// Behavior is undefined if the requested size is 0 or the alignment is not a
68 /// power of 2. The alignment must be no larger than the largest supported page
69 /// size on the platform.
71 /// The `old_size` and `align` parameters are the parameters that were used to
72 /// create the allocation referenced by `ptr`. The `old_size` parameter may be
73 /// any value in range_inclusive(requested_size, usable_size).
75 pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
76 check_size_and_alignment(size, align);
77 __rust_reallocate(ptr, old_size, size, align)
80 /// Resize the allocation referenced by `ptr` to `size` bytes.
82 /// If the operation succeeds, it returns `usable_size(size, align)` and if it
83 /// fails (or is a no-op) it returns `usable_size(old_size, align)`.
85 /// Behavior is undefined if the requested size is 0 or the alignment is not a
86 /// power of 2. The alignment must be no larger than the largest supported page
87 /// size on the platform.
89 /// The `old_size` and `align` parameters are the parameters that were used to
90 /// create the allocation referenced by `ptr`. The `old_size` parameter may be
91 /// any value in range_inclusive(requested_size, usable_size).
93 pub unsafe fn reallocate_inplace(ptr: *mut u8,
98 check_size_and_alignment(size, align);
99 __rust_reallocate_inplace(ptr, old_size, size, align)
102 /// Deallocates the memory referenced by `ptr`.
104 /// The `ptr` parameter must not be null.
106 /// The `old_size` and `align` parameters are the parameters that were used to
107 /// create the allocation referenced by `ptr`. The `old_size` parameter may be
108 /// any value in range_inclusive(requested_size, usable_size).
110 pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) {
111 __rust_deallocate(ptr, old_size, align)
114 /// Returns the usable size of an allocation created with the specified the
115 /// `size` and `align`.
117 pub fn usable_size(size: usize, align: usize) -> usize {
118 unsafe { __rust_usable_size(size, align) }
121 /// An arbitrary non-null address to represent zero-size allocations.
123 /// This preserves the non-null invariant for types like `Box<T>`. The address
124 /// may overlap with non-zero-size memory allocations.
125 pub const EMPTY: *mut () = 0x1 as *mut ();
127 /// The allocator for unique pointers.
129 #[lang = "exchange_malloc"]
131 unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
135 let ptr = allocate(size, align);
144 #[lang = "exchange_free"]
146 unsafe fn exchange_free(ptr: *mut u8, old_size: usize, align: usize) {
147 deallocate(ptr, old_size, align);
153 use self::test::Bencher;
158 fn basic_reallocate_inplace_noop() {
161 let ptr = heap::allocate(size, 8);
165 let ret = heap::reallocate_inplace(ptr, size, size, 8);
166 heap::deallocate(ptr, size, 8);
167 assert_eq!(ret, heap::usable_size(size, 8));
172 fn alloc_owned_small(b: &mut Bencher) {
174 let _: Box<_> = box 10;