]> git.lizzy.rs Git - rust.git/blob - src/libstd/rt/global_heap.rs
auto merge of #11386 : rcatolino/rust/ice-10955, r=pcwalton
[rust.git] / src / libstd / rt / global_heap.rs
1 // Copyright 2012 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 use libc::{c_void, c_char, size_t, uintptr_t, free, malloc, realloc};
12 use ptr::RawPtr;
13 use unstable::intrinsics::TyDesc;
14 use unstable::raw;
15 use mem::size_of;
16
17 extern {
18     fn abort();
19 }
20
21 #[inline]
22 pub fn get_box_size(body_size: uint, body_align: uint) -> uint {
23     let header_size = size_of::<raw::Box<()>>();
24     let total_size = align_to(header_size, body_align) + body_size;
25     total_size
26 }
27
28 // Rounds |size| to the nearest |alignment|. Invariant: |alignment| is a power
29 // of two.
30 #[inline]
31 fn align_to(size: uint, align: uint) -> uint {
32     assert!(align != 0);
33     (size + align - 1) & !(align - 1)
34 }
35
36 /// A wrapper around libc::malloc, aborting on out-of-memory
37 pub unsafe fn malloc_raw(size: uint) -> *c_void {
38     let p = malloc(size as size_t);
39     if p.is_null() {
40         // we need a non-allocating way to print an error here
41         abort();
42     }
43     p
44 }
45
46 /// A wrapper around libc::realloc, aborting on out-of-memory
47 pub unsafe fn realloc_raw(ptr: *mut c_void, size: uint) -> *mut c_void {
48     let p = realloc(ptr, size as size_t);
49     if p.is_null() {
50         // we need a non-allocating way to print an error here
51         abort();
52     }
53     p
54 }
55
56 /// The allocator for unique pointers without contained managed pointers.
57 #[cfg(not(test))]
58 #[lang="exchange_malloc"]
59 #[inline]
60 pub unsafe fn exchange_malloc(size: uintptr_t) -> *c_char {
61     malloc_raw(size as uint) as *c_char
62 }
63
64 // FIXME: #7496
65 #[cfg(not(test))]
66 #[lang="closure_exchange_malloc"]
67 #[inline]
68 pub unsafe fn closure_exchange_malloc_(td: *c_char, size: uintptr_t) -> *c_char {
69     closure_exchange_malloc(td, size)
70 }
71
72 #[inline]
73 pub unsafe fn closure_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
74     let td = td as *TyDesc;
75     let size = size as uint;
76
77     assert!(td.is_not_null());
78
79     let total_size = get_box_size(size, (*td).align);
80     let p = malloc_raw(total_size);
81
82     let alloc = p as *mut raw::Box<()>;
83     (*alloc).type_desc = td;
84
85     alloc as *c_char
86 }
87
88 // NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
89 // inside a landing pad may corrupt the state of the exception handler.
90 #[cfg(not(test))]
91 #[lang="exchange_free"]
92 #[inline]
93 pub unsafe fn exchange_free_(ptr: *c_char) {
94     exchange_free(ptr)
95 }
96
97 pub unsafe fn exchange_free(ptr: *c_char) {
98     free(ptr as *c_void);
99 }
100
101 #[cfg(test)]
102 mod bench {
103     use extra::test::BenchHarness;
104
105     #[bench]
106     fn alloc_owned_small(bh: &mut BenchHarness) {
107         bh.iter(|| {
108             ~10;
109         })
110     }
111
112     #[bench]
113     fn alloc_owned_big(bh: &mut BenchHarness) {
114         bh.iter(|| {
115             ~[10, ..1000];
116         })
117     }
118 }