]> git.lizzy.rs Git - rust.git/blob - src/libstd/rt/local_heap.rs
12ec19a1ecc67af345c332a072da5055da186c87
[rust.git] / src / libstd / rt / local_heap.rs
1 // Copyright 2013 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 //! The local, garbage collected heap
12
13 use libc;
14 use libc::{c_void, uintptr_t, size_t};
15 use ops::Drop;
16 use option::{Option, None, Some};
17 use rt::local::Local;
18 use rt::task::Task;
19 use unstable::raw;
20
21 type MemoryRegion = c_void;
22
23 struct Env { priv opaque: () }
24
25 struct BoxedRegion {
26     env: *Env,
27     backing_region: *MemoryRegion,
28     live_allocs: *raw::Box<()>,
29 }
30
31 pub type OpaqueBox = c_void;
32 pub type TypeDesc = c_void;
33
34 pub struct LocalHeap {
35     memory_region: *MemoryRegion,
36     boxed_region: *BoxedRegion
37 }
38
39 impl LocalHeap {
40     #[fixed_stack_segment] #[inline(never)]
41     pub fn new() -> LocalHeap {
42         unsafe {
43             // XXX: These usually come from the environment
44             let detailed_leaks = false as uintptr_t;
45             let poison_on_free = false as uintptr_t;
46             let region = rust_new_memory_region(detailed_leaks, poison_on_free);
47             assert!(region.is_not_null());
48             let boxed = rust_new_boxed_region(region, poison_on_free);
49             assert!(boxed.is_not_null());
50             LocalHeap {
51                 memory_region: region,
52                 boxed_region: boxed
53             }
54         }
55     }
56
57     #[fixed_stack_segment] #[inline(never)]
58     pub fn alloc(&mut self, td: *TypeDesc, size: uint) -> *OpaqueBox {
59         unsafe {
60             return rust_boxed_region_malloc(self.boxed_region, td, size as size_t);
61         }
62     }
63
64     #[fixed_stack_segment] #[inline(never)]
65     pub fn realloc(&mut self, ptr: *OpaqueBox, size: uint) -> *OpaqueBox {
66         unsafe {
67             return rust_boxed_region_realloc(self.boxed_region, ptr, size as size_t);
68         }
69     }
70
71     #[fixed_stack_segment] #[inline(never)]
72     pub fn free(&mut self, box: *OpaqueBox) {
73         unsafe {
74             return rust_boxed_region_free(self.boxed_region, box);
75         }
76     }
77 }
78
79 impl Drop for LocalHeap {
80     #[fixed_stack_segment] #[inline(never)]
81     fn drop(&self) {
82         unsafe {
83             rust_delete_boxed_region(self.boxed_region);
84             rust_delete_memory_region(self.memory_region);
85         }
86     }
87 }
88
89 // A little compatibility function
90 pub unsafe fn local_free(ptr: *libc::c_char) {
91     // XXX: Unsafe borrow for speed. Lame.
92     let task_ptr: Option<*mut Task> = Local::try_unsafe_borrow();
93     match task_ptr {
94         Some(task) => {
95             (*task).heap.free(ptr as *libc::c_void);
96         }
97         None => rtabort!("local free outside of task")
98     }
99 }
100
101 pub fn live_allocs() -> *raw::Box<()> {
102     let region = do Local::borrow |task: &mut Task| {
103         task.heap.boxed_region
104     };
105
106     return unsafe { (*region).live_allocs };
107 }
108
109 extern {
110     #[fast_ffi]
111     fn rust_new_memory_region(detailed_leaks: uintptr_t,
112                                poison_on_free: uintptr_t) -> *MemoryRegion;
113     #[fast_ffi]
114     fn rust_delete_memory_region(region: *MemoryRegion);
115     #[fast_ffi]
116     fn rust_new_boxed_region(region: *MemoryRegion,
117                              poison_on_free: uintptr_t) -> *BoxedRegion;
118     #[fast_ffi]
119     fn rust_delete_boxed_region(region: *BoxedRegion);
120     #[fast_ffi]
121     fn rust_boxed_region_malloc(region: *BoxedRegion,
122                                 td: *TypeDesc,
123                                 size: size_t) -> *OpaqueBox;
124     #[fast_ffi]
125     fn rust_boxed_region_realloc(region: *BoxedRegion,
126                                  ptr: *OpaqueBox,
127                                  size: size_t) -> *OpaqueBox;
128     #[fast_ffi]
129     fn rust_boxed_region_free(region: *BoxedRegion, box: *OpaqueBox);
130 }
131
132 #[cfg(test)]
133 mod bench {
134     use extra::test::BenchHarness;
135
136     #[bench]
137     fn alloc_managed_small(bh: &mut BenchHarness) {
138         do bh.iter {
139             @10;
140         }
141     }
142
143     #[bench]
144     fn alloc_managed_big(bh: &mut BenchHarness) {
145         do bh.iter {
146             @[10, ..1000];
147         }
148     }
149 }