]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_arena/src/tests.rs
rustc_metadata: Encode/decode some `LazyArray`s without an `Option`
[rust.git] / compiler / rustc_arena / src / tests.rs
1 extern crate test;
2 use super::TypedArena;
3 use std::cell::Cell;
4 use test::Bencher;
5
6 #[allow(dead_code)]
7 #[derive(Debug, Eq, PartialEq)]
8 struct Point {
9     x: i32,
10     y: i32,
11     z: i32,
12 }
13
14 impl<T> TypedArena<T> {
15     /// Clears the arena. Deallocates all but the longest chunk which may be reused.
16     fn clear(&mut self) {
17         unsafe {
18             // Clear the last chunk, which is partially filled.
19             let mut chunks_borrow = self.chunks.borrow_mut();
20             if let Some(mut last_chunk) = chunks_borrow.last_mut() {
21                 self.clear_last_chunk(&mut last_chunk);
22                 let len = chunks_borrow.len();
23                 // If `T` is ZST, code below has no effect.
24                 for mut chunk in chunks_borrow.drain(..len - 1) {
25                     chunk.destroy(chunk.entries);
26                 }
27             }
28         }
29     }
30 }
31
32 #[test]
33 pub fn test_unused() {
34     let arena: TypedArena<Point> = TypedArena::default();
35     assert!(arena.chunks.borrow().is_empty());
36 }
37
38 #[test]
39 fn test_arena_alloc_nested() {
40     struct Inner {
41         value: u8,
42     }
43     struct Outer<'a> {
44         inner: &'a Inner,
45     }
46     enum EI<'e> {
47         I(Inner),
48         O(Outer<'e>),
49     }
50
51     struct Wrap<'a>(TypedArena<EI<'a>>);
52
53     impl<'a> Wrap<'a> {
54         fn alloc_inner<F: Fn() -> Inner>(&self, f: F) -> &Inner {
55             match self.0.alloc(EI::I(f())) {
56                 EI::I(i) => i,
57                 _ => panic!("mismatch"),
58             }
59         }
60         fn alloc_outer<F: Fn() -> Outer<'a>>(&self, f: F) -> &Outer<'_> {
61             match self.0.alloc(EI::O(f())) {
62                 EI::O(o) => o,
63                 _ => panic!("mismatch"),
64             }
65         }
66     }
67
68     let arena = Wrap(TypedArena::default());
69
70     let result = arena.alloc_outer(|| Outer { inner: arena.alloc_inner(|| Inner { value: 10 }) });
71
72     assert_eq!(result.inner.value, 10);
73 }
74
75 #[test]
76 pub fn test_copy() {
77     let arena = TypedArena::default();
78     #[cfg(not(miri))]
79     const N: usize = 100000;
80     #[cfg(miri)]
81     const N: usize = 1000;
82     for _ in 0..N {
83         arena.alloc(Point { x: 1, y: 2, z: 3 });
84     }
85 }
86
87 #[bench]
88 pub fn bench_copy(b: &mut Bencher) {
89     let arena = TypedArena::default();
90     b.iter(|| arena.alloc(Point { x: 1, y: 2, z: 3 }))
91 }
92
93 #[bench]
94 pub fn bench_copy_nonarena(b: &mut Bencher) {
95     b.iter(|| {
96         let _: Box<_> = Box::new(Point { x: 1, y: 2, z: 3 });
97     })
98 }
99
100 #[allow(dead_code)]
101 struct Noncopy {
102     string: String,
103     array: Vec<i32>,
104 }
105
106 #[test]
107 pub fn test_noncopy() {
108     let arena = TypedArena::default();
109     #[cfg(not(miri))]
110     const N: usize = 100000;
111     #[cfg(miri)]
112     const N: usize = 1000;
113     for _ in 0..N {
114         arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] });
115     }
116 }
117
118 #[test]
119 pub fn test_typed_arena_zero_sized() {
120     let arena = TypedArena::default();
121     #[cfg(not(miri))]
122     const N: usize = 100000;
123     #[cfg(miri)]
124     const N: usize = 1000;
125     for _ in 0..N {
126         arena.alloc(());
127     }
128 }
129
130 #[test]
131 pub fn test_typed_arena_clear() {
132     let mut arena = TypedArena::default();
133     for _ in 0..10 {
134         arena.clear();
135         #[cfg(not(miri))]
136         const N: usize = 10000;
137         #[cfg(miri)]
138         const N: usize = 100;
139         for _ in 0..N {
140             arena.alloc(Point { x: 1, y: 2, z: 3 });
141         }
142     }
143 }
144
145 #[bench]
146 pub fn bench_typed_arena_clear(b: &mut Bencher) {
147     let mut arena = TypedArena::default();
148     b.iter(|| {
149         arena.alloc(Point { x: 1, y: 2, z: 3 });
150         arena.clear();
151     })
152 }
153
154 #[bench]
155 pub fn bench_typed_arena_clear_100(b: &mut Bencher) {
156     let mut arena = TypedArena::default();
157     b.iter(|| {
158         for _ in 0..100 {
159             arena.alloc(Point { x: 1, y: 2, z: 3 });
160         }
161         arena.clear();
162     })
163 }
164
165 // Drop tests
166
167 struct DropCounter<'a> {
168     count: &'a Cell<u32>,
169 }
170
171 impl Drop for DropCounter<'_> {
172     fn drop(&mut self) {
173         self.count.set(self.count.get() + 1);
174     }
175 }
176
177 #[test]
178 fn test_typed_arena_drop_count() {
179     let counter = Cell::new(0);
180     {
181         let arena: TypedArena<DropCounter<'_>> = TypedArena::default();
182         for _ in 0..100 {
183             // Allocate something with drop glue to make sure it doesn't leak.
184             arena.alloc(DropCounter { count: &counter });
185         }
186     };
187     assert_eq!(counter.get(), 100);
188 }
189
190 #[test]
191 fn test_typed_arena_drop_on_clear() {
192     let counter = Cell::new(0);
193     let mut arena: TypedArena<DropCounter<'_>> = TypedArena::default();
194     for i in 0..10 {
195         for _ in 0..100 {
196             // Allocate something with drop glue to make sure it doesn't leak.
197             arena.alloc(DropCounter { count: &counter });
198         }
199         arena.clear();
200         assert_eq!(counter.get(), i * 100 + 100);
201     }
202 }
203
204 thread_local! {
205     static DROP_COUNTER: Cell<u32> = Cell::new(0)
206 }
207
208 struct SmallDroppable;
209
210 impl Drop for SmallDroppable {
211     fn drop(&mut self) {
212         DROP_COUNTER.with(|c| c.set(c.get() + 1));
213     }
214 }
215
216 #[test]
217 fn test_typed_arena_drop_small_count() {
218     DROP_COUNTER.with(|c| c.set(0));
219     {
220         let arena: TypedArena<SmallDroppable> = TypedArena::default();
221         for _ in 0..100 {
222             // Allocate something with drop glue to make sure it doesn't leak.
223             arena.alloc(SmallDroppable);
224         }
225         // dropping
226     };
227     assert_eq!(DROP_COUNTER.with(|c| c.get()), 100);
228 }
229
230 #[bench]
231 pub fn bench_noncopy(b: &mut Bencher) {
232     let arena = TypedArena::default();
233     b.iter(|| {
234         arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] })
235     })
236 }
237
238 #[bench]
239 pub fn bench_noncopy_nonarena(b: &mut Bencher) {
240     b.iter(|| {
241         let _: Box<_> =
242             Box::new(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] });
243     })
244 }