]> git.proxmox.com Git - rustc.git/blob - src/liballoc/alloc.rs
New upstream version 1.28.0~beta.14+dfsg1
[rustc.git] / src / liballoc / alloc.rs
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
11 //! Memory allocation APIs
12
13 #![stable(feature = "alloc_module", since = "1.28.0")]
14
15 use core::intrinsics::{min_align_of_val, size_of_val};
16 use core::ptr::{NonNull, Unique};
17 use core::usize;
18
19 #[stable(feature = "alloc_module", since = "1.28.0")]
20 #[doc(inline)]
21 pub use core::alloc::*;
22
23 extern "Rust" {
24 #[allocator]
25 #[rustc_allocator_nounwind]
26 fn __rust_alloc(size: usize, align: usize) -> *mut u8;
27 #[rustc_allocator_nounwind]
28 fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
29 #[rustc_allocator_nounwind]
30 fn __rust_realloc(ptr: *mut u8,
31 old_size: usize,
32 align: usize,
33 new_size: usize) -> *mut u8;
34 #[rustc_allocator_nounwind]
35 fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
36 }
37
38 /// The global memory allocator.
39 ///
40 /// This type implements the [`Alloc`] trait by forwarding calls
41 /// to the allocator registered with the `#[global_allocator]` attribute
42 /// if there is one, or the `std` crate’s default.
43 #[unstable(feature = "allocator_api", issue = "32838")]
44 #[derive(Copy, Clone, Default, Debug)]
45 pub struct Global;
46
47 /// Allocate memory with the global allocator.
48 ///
49 /// This function forwards calls to the [`GlobalAlloc::alloc`] method
50 /// of the allocator registered with the `#[global_allocator]` attribute
51 /// if there is one, or the `std` crate’s default.
52 ///
53 /// This function is expected to be deprecated in favor of the `alloc` method
54 /// of the [`Global`] type when it and the [`Alloc`] trait become stable.
55 ///
56 /// # Safety
57 ///
58 /// See [`GlobalAlloc::alloc`].
59 #[stable(feature = "global_alloc", since = "1.28.0")]
60 #[inline]
61 pub unsafe fn alloc(layout: Layout) -> *mut u8 {
62 __rust_alloc(layout.size(), layout.align())
63 }
64
65 /// Deallocate memory with the global allocator.
66 ///
67 /// This function forwards calls to the [`GlobalAlloc::dealloc`] method
68 /// of the allocator registered with the `#[global_allocator]` attribute
69 /// if there is one, or the `std` crate’s default.
70 ///
71 /// This function is expected to be deprecated in favor of the `dealloc` method
72 /// of the [`Global`] type when it and the [`Alloc`] trait become stable.
73 ///
74 /// # Safety
75 ///
76 /// See [`GlobalAlloc::dealloc`].
77 #[stable(feature = "global_alloc", since = "1.28.0")]
78 #[inline]
79 pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
80 __rust_dealloc(ptr, layout.size(), layout.align())
81 }
82
83 /// Reallocate memory with the global allocator.
84 ///
85 /// This function forwards calls to the [`GlobalAlloc::realloc`] method
86 /// of the allocator registered with the `#[global_allocator]` attribute
87 /// if there is one, or the `std` crate’s default.
88 ///
89 /// This function is expected to be deprecated in favor of the `realloc` method
90 /// of the [`Global`] type when it and the [`Alloc`] trait become stable.
91 ///
92 /// # Safety
93 ///
94 /// See [`GlobalAlloc::realloc`].
95 #[stable(feature = "global_alloc", since = "1.28.0")]
96 #[inline]
97 pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
98 __rust_realloc(ptr, layout.size(), layout.align(), new_size)
99 }
100
101 /// Allocate zero-initialized memory with the global allocator.
102 ///
103 /// This function forwards calls to the [`GlobalAlloc::alloc_zeroed`] method
104 /// of the allocator registered with the `#[global_allocator]` attribute
105 /// if there is one, or the `std` crate’s default.
106 ///
107 /// This function is expected to be deprecated in favor of the `alloc_zeroed` method
108 /// of the [`Global`] type when it and the [`Alloc`] trait become stable.
109 ///
110 /// # Safety
111 ///
112 /// See [`GlobalAlloc::alloc_zeroed`].
113 #[stable(feature = "global_alloc", since = "1.28.0")]
114 #[inline]
115 pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
116 __rust_alloc_zeroed(layout.size(), layout.align())
117 }
118
119 #[unstable(feature = "allocator_api", issue = "32838")]
120 unsafe impl Alloc for Global {
121 #[inline]
122 unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
123 NonNull::new(alloc(layout)).ok_or(AllocErr)
124 }
125
126 #[inline]
127 unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
128 dealloc(ptr.as_ptr(), layout)
129 }
130
131 #[inline]
132 unsafe fn realloc(&mut self,
133 ptr: NonNull<u8>,
134 layout: Layout,
135 new_size: usize)
136 -> Result<NonNull<u8>, AllocErr>
137 {
138 NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
139 }
140
141 #[inline]
142 unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
143 NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr)
144 }
145 }
146
147 /// The allocator for unique pointers.
148 // This function must not unwind. If it does, MIR codegen will fail.
149 #[cfg(not(test))]
150 #[lang = "exchange_malloc"]
151 #[inline]
152 unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
153 if size == 0 {
154 align as *mut u8
155 } else {
156 let layout = Layout::from_size_align_unchecked(size, align);
157 let ptr = alloc(layout);
158 if !ptr.is_null() {
159 ptr
160 } else {
161 handle_alloc_error(layout)
162 }
163 }
164 }
165
166 #[cfg_attr(not(test), lang = "box_free")]
167 #[inline]
168 pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
169 let ptr = ptr.as_ptr();
170 let size = size_of_val(&*ptr);
171 let align = min_align_of_val(&*ptr);
172 // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
173 if size != 0 {
174 let layout = Layout::from_size_align_unchecked(size, align);
175 dealloc(ptr as *mut u8, layout);
176 }
177 }
178
179 /// Abort on memory allocation error or failure.
180 ///
181 /// Callers of memory allocation APIs wishing to abort computation
182 /// in response to an allocation error are encouraged to call this function,
183 /// rather than directly invoking `panic!` or similar.
184 ///
185 /// The default behavior of this function is to print a message to standard error
186 /// and abort the process.
187 /// It can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`].
188 ///
189 /// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html
190 /// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html
191 #[stable(feature = "global_alloc", since = "1.28.0")]
192 #[rustc_allocator_nounwind]
193 pub fn handle_alloc_error(layout: Layout) -> ! {
194 #[allow(improper_ctypes)]
195 extern "Rust" {
196 #[lang = "oom"]
197 fn oom_impl(layout: Layout) -> !;
198 }
199 unsafe { oom_impl(layout) }
200 }
201
202 #[cfg(test)]
203 mod tests {
204 extern crate test;
205 use self::test::Bencher;
206 use boxed::Box;
207 use alloc::{Global, Alloc, Layout, handle_alloc_error};
208
209 #[test]
210 fn allocate_zeroed() {
211 unsafe {
212 let layout = Layout::from_size_align(1024, 1).unwrap();
213 let ptr = Global.alloc_zeroed(layout.clone())
214 .unwrap_or_else(|_| handle_alloc_error(layout));
215
216 let mut i = ptr.cast::<u8>().as_ptr();
217 let end = i.offset(layout.size() as isize);
218 while i < end {
219 assert_eq!(*i, 0);
220 i = i.offset(1);
221 }
222 Global.dealloc(ptr, layout);
223 }
224 }
225
226 #[bench]
227 fn alloc_owned_small(b: &mut Bencher) {
228 b.iter(|| {
229 let _: Box<_> = box 10;
230 })
231 }
232 }