]> git.proxmox.com Git - rustc.git/blame - src/liballoc/heap.rs
Imported Upstream version 1.6.0+dfsg1
[rustc.git] / src / liballoc / heap.rs
CommitLineData
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 \
e9174d1e
SL
15 tracing garbage collector",
16 issue = "27700")]
62682a34 17
d9579d0f
AL
18use core::{isize, usize};
19
e9174d1e 20#[allow(improper_ctypes)]
92a42be0 21extern "C" {
e9174d1e
SL
22 #[allocator]
23 fn __rust_allocate(size: usize, align: usize) -> *mut u8;
24 fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize);
b039eaaf
SL
25 fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8;
26 fn __rust_reallocate_inplace(ptr: *mut u8,
27 old_size: usize,
28 size: usize,
29 align: usize)
30 -> usize;
e9174d1e
SL
31 fn __rust_usable_size(size: usize, align: usize) -> usize;
32}
33
d9579d0f
AL
34#[inline(always)]
35fn check_size_and_alignment(size: usize, align: usize) {
36 debug_assert!(size != 0);
b039eaaf
SL
37 debug_assert!(size <= isize::MAX as usize,
38 "Tried to allocate too much: {} bytes",
39 size);
40 debug_assert!(usize::is_power_of_two(align),
41 "Invalid alignment of allocation: {}",
42 align);
d9579d0f
AL
43}
44
1a4d82fc
JJ
45// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
46
47/// Return a pointer to `size` bytes of memory aligned to `align`.
48///
49/// On failure, return a null pointer.
50///
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.
54#[inline]
85aaf69f 55pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
d9579d0f 56 check_size_and_alignment(size, align);
e9174d1e 57 __rust_allocate(size, align)
1a4d82fc
JJ
58}
59
60/// Resize the allocation referenced by `ptr` to `size` bytes.
61///
62/// On failure, return a null pointer and leave the original allocation intact.
63///
c34b1796
AL
64/// If the allocation was relocated, the memory at the passed-in pointer is
65/// undefined after the call.
66///
1a4d82fc
JJ
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.
70///
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).
74#[inline]
85aaf69f 75pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
d9579d0f 76 check_size_and_alignment(size, align);
e9174d1e 77 __rust_reallocate(ptr, old_size, size, align)
1a4d82fc
JJ
78}
79
80/// Resize the allocation referenced by `ptr` to `size` bytes.
81///
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)`.
84///
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.
88///
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).
92#[inline]
b039eaaf
SL
93pub unsafe fn reallocate_inplace(ptr: *mut u8,
94 old_size: usize,
95 size: usize,
96 align: usize)
97 -> usize {
d9579d0f 98 check_size_and_alignment(size, align);
e9174d1e 99 __rust_reallocate_inplace(ptr, old_size, size, align)
1a4d82fc
JJ
100}
101
102/// Deallocates the memory referenced by `ptr`.
103///
104/// The `ptr` parameter must not be null.
105///
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).
109#[inline]
85aaf69f 110pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) {
e9174d1e 111 __rust_deallocate(ptr, old_size, align)
1a4d82fc
JJ
112}
113
114/// Returns the usable size of an allocation created with the specified the
115/// `size` and `align`.
116#[inline]
85aaf69f 117pub fn usable_size(size: usize, align: usize) -> usize {
e9174d1e 118 unsafe { __rust_usable_size(size, align) }
1a4d82fc
JJ
119}
120
121/// An arbitrary non-null address to represent zero-size allocations.
122///
e9174d1e
SL
123/// This preserves the non-null invariant for types like `Box<T>`. The address
124/// may overlap with non-zero-size memory allocations.
1a4d82fc
JJ
125pub const EMPTY: *mut () = 0x1 as *mut ();
126
127/// The allocator for unique pointers.
128#[cfg(not(test))]
d9579d0f 129#[lang = "exchange_malloc"]
1a4d82fc 130#[inline]
85aaf69f 131unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
1a4d82fc
JJ
132 if size == 0 {
133 EMPTY as *mut u8
134 } else {
135 let ptr = allocate(size, align);
b039eaaf
SL
136 if ptr.is_null() {
137 ::oom()
138 }
1a4d82fc
JJ
139 ptr
140 }
141}
142
143#[cfg(not(test))]
d9579d0f 144#[lang = "exchange_free"]
1a4d82fc 145#[inline]
85aaf69f 146unsafe fn exchange_free(ptr: *mut u8, old_size: usize, align: usize) {
1a4d82fc
JJ
147 deallocate(ptr, old_size, align);
148}
149
1a4d82fc 150#[cfg(test)]
d9579d0f 151mod tests {
1a4d82fc
JJ
152 extern crate test;
153 use self::test::Bencher;
c34b1796 154 use boxed::Box;
1a4d82fc
JJ
155 use heap;
156
157 #[test]
158 fn basic_reallocate_inplace_noop() {
159 unsafe {
160 let size = 4000;
161 let ptr = heap::allocate(size, 8);
b039eaaf
SL
162 if ptr.is_null() {
163 ::oom()
164 }
1a4d82fc
JJ
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));
168 }
169 }
170
171 #[bench]
172 fn alloc_owned_small(b: &mut Bencher) {
173 b.iter(|| {
c34b1796 174 let _: Box<_> = box 10;
1a4d82fc
JJ
175 })
176 }
177}