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};
19 use core::intrinsics::{min_align_of_val, size_of_val};
21 #[allow(improper_ctypes)]
24 fn __rust_allocate(size: usize, align: usize) -> *mut u8;
25 fn __rust_allocate_zeroed(size: usize, align: usize) -> *mut u8;
26 fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize);
27 fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8;
28 fn __rust_reallocate_inplace(ptr: *mut u8,
33 fn __rust_usable_size(size: usize, align: usize) -> usize;
37 fn check_size_and_alignment(size: usize, align: usize) {
38 debug_assert!(size != 0);
39 debug_assert!(size <= isize::MAX as usize,
40 "Tried to allocate too much: {} bytes",
42 debug_assert!(usize::is_power_of_two(align),
43 "Invalid alignment of allocation: {}",
47 // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
49 /// Return a pointer to `size` bytes of memory aligned to `align`.
51 /// On failure, return a null pointer.
53 /// Behavior is undefined if the requested size is 0 or the alignment is not a
54 /// power of 2. The alignment must be no larger than the largest supported page
55 /// size on the platform.
57 pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
58 check_size_and_alignment(size, align);
59 __rust_allocate(size, align)
62 /// Return a pointer to `size` bytes of memory aligned to `align` and
63 /// initialized to zeroes.
65 /// On failure, return a null pointer.
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 pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 {
72 check_size_and_alignment(size, align);
73 __rust_allocate_zeroed(size, align)
76 /// Resize the allocation referenced by `ptr` to `size` bytes.
78 /// On failure, return a null pointer and leave the original allocation intact.
80 /// If the allocation was relocated, the memory at the passed-in pointer is
81 /// undefined after the call.
83 /// Behavior is undefined if the requested size is 0 or the alignment is not a
84 /// power of 2. The alignment must be no larger than the largest supported page
85 /// size on the platform.
87 /// The `old_size` and `align` parameters are the parameters that were used to
88 /// create the allocation referenced by `ptr`. The `old_size` parameter may be
89 /// any value in range_inclusive(requested_size, usable_size).
91 pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
92 check_size_and_alignment(size, align);
93 __rust_reallocate(ptr, old_size, size, align)
96 /// Resize the allocation referenced by `ptr` to `size` bytes.
98 /// If the operation succeeds, it returns `usable_size(size, align)` and if it
99 /// fails (or is a no-op) it returns `usable_size(old_size, align)`.
101 /// Behavior is undefined if the requested size is 0 or the alignment is not a
102 /// power of 2. The alignment must be no larger than the largest supported page
103 /// size on the platform.
105 /// The `old_size` and `align` parameters are the parameters that were used to
106 /// create the allocation referenced by `ptr`. The `old_size` parameter may be
107 /// any value in range_inclusive(requested_size, usable_size).
109 pub unsafe fn reallocate_inplace(ptr: *mut u8,
114 check_size_and_alignment(size, align);
115 __rust_reallocate_inplace(ptr, old_size, size, align)
118 /// Deallocates the memory referenced by `ptr`.
120 /// The `ptr` parameter must not be null.
122 /// The `old_size` and `align` parameters are the parameters that were used to
123 /// create the allocation referenced by `ptr`. The `old_size` parameter may be
124 /// any value in range_inclusive(requested_size, usable_size).
126 pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) {
127 __rust_deallocate(ptr, old_size, align)
130 /// Returns the usable size of an allocation created with the specified the
131 /// `size` and `align`.
133 pub fn usable_size(size: usize, align: usize) -> usize {
134 unsafe { __rust_usable_size(size, align) }
137 /// An arbitrary non-null address to represent zero-size allocations.
139 /// This preserves the non-null invariant for types like `Box<T>`. The address
140 /// may overlap with non-zero-size memory allocations.
141 pub const EMPTY: *mut () = 0x1 as *mut ();
143 /// The allocator for unique pointers.
144 // This function must not unwind. If it does, MIR trans will fail.
146 #[lang = "exchange_malloc"]
148 unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
152 let ptr = allocate(size, align);
160 #[cfg_attr(not(test), lang = "box_free")]
162 pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
163 let size = size_of_val(&*ptr);
164 let align = min_align_of_val(&*ptr);
165 // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
167 deallocate(ptr as *mut u8, size, align);
174 use self::test::Bencher;
179 fn allocate_zeroed() {
182 let ptr = heap::allocate_zeroed(size, 1);
187 let end = ptr.offset(size as isize);
193 heap::deallocate(ptr, size, 1);
198 fn basic_reallocate_inplace_noop() {
201 let ptr = heap::allocate(size, 8);
205 let ret = heap::reallocate_inplace(ptr, size, size, 8);
206 heap::deallocate(ptr, size, 8);
207 assert_eq!(ret, heap::usable_size(size, 8));
212 fn alloc_owned_small(b: &mut Bencher) {
214 let _: Box<_> = box 10;