]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_arena/src/tests.rs
Merge commit '7c21f91b15b7604f818565646b686d90f99d1baf' into clippyup
[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             let r: &EI<'_> = self.0.alloc(EI::I(f()));
56             if let &EI::I(ref i) = r {
57                 i
58             } else {
59                 panic!("mismatch");
60             }
61         }
62         fn alloc_outer<F: Fn() -> Outer<'a>>(&self, f: F) -> &Outer<'_> {
63             let r: &EI<'_> = self.0.alloc(EI::O(f()));
64             if let &EI::O(ref o) = r {
65                 o
66             } else {
67                 panic!("mismatch");
68             }
69         }
70     }
71
72     let arena = Wrap(TypedArena::default());
73
74     let result = arena.alloc_outer(|| Outer { inner: arena.alloc_inner(|| Inner { value: 10 }) });
75
76     assert_eq!(result.inner.value, 10);
77 }
78
79 #[test]
80 pub fn test_copy() {
81     let arena = TypedArena::default();
82     for _ in 0..100000 {
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     for _ in 0..100000 {
110         arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] });
111     }
112 }
113
114 #[test]
115 pub fn test_typed_arena_zero_sized() {
116     let arena = TypedArena::default();
117     for _ in 0..100000 {
118         arena.alloc(());
119     }
120 }
121
122 #[test]
123 pub fn test_typed_arena_clear() {
124     let mut arena = TypedArena::default();
125     for _ in 0..10 {
126         arena.clear();
127         for _ in 0..10000 {
128             arena.alloc(Point { x: 1, y: 2, z: 3 });
129         }
130     }
131 }
132
133 #[bench]
134 pub fn bench_typed_arena_clear(b: &mut Bencher) {
135     let mut arena = TypedArena::default();
136     b.iter(|| {
137         arena.alloc(Point { x: 1, y: 2, z: 3 });
138         arena.clear();
139     })
140 }
141
142 #[bench]
143 pub fn bench_typed_arena_clear_100(b: &mut Bencher) {
144     let mut arena = TypedArena::default();
145     b.iter(|| {
146         for _ in 0..100 {
147             arena.alloc(Point { x: 1, y: 2, z: 3 });
148         }
149         arena.clear();
150     })
151 }
152
153 // Drop tests
154
155 struct DropCounter<'a> {
156     count: &'a Cell<u32>,
157 }
158
159 impl Drop for DropCounter<'_> {
160     fn drop(&mut self) {
161         self.count.set(self.count.get() + 1);
162     }
163 }
164
165 #[test]
166 fn test_typed_arena_drop_count() {
167     let counter = Cell::new(0);
168     {
169         let arena: TypedArena<DropCounter<'_>> = TypedArena::default();
170         for _ in 0..100 {
171             // Allocate something with drop glue to make sure it doesn't leak.
172             arena.alloc(DropCounter { count: &counter });
173         }
174     };
175     assert_eq!(counter.get(), 100);
176 }
177
178 #[test]
179 fn test_typed_arena_drop_on_clear() {
180     let counter = Cell::new(0);
181     let mut arena: TypedArena<DropCounter<'_>> = TypedArena::default();
182     for i in 0..10 {
183         for _ in 0..100 {
184             // Allocate something with drop glue to make sure it doesn't leak.
185             arena.alloc(DropCounter { count: &counter });
186         }
187         arena.clear();
188         assert_eq!(counter.get(), i * 100 + 100);
189     }
190 }
191
192 thread_local! {
193     static DROP_COUNTER: Cell<u32> = Cell::new(0)
194 }
195
196 struct SmallDroppable;
197
198 impl Drop for SmallDroppable {
199     fn drop(&mut self) {
200         DROP_COUNTER.with(|c| c.set(c.get() + 1));
201     }
202 }
203
204 #[test]
205 fn test_typed_arena_drop_small_count() {
206     DROP_COUNTER.with(|c| c.set(0));
207     {
208         let arena: TypedArena<SmallDroppable> = TypedArena::default();
209         for _ in 0..100 {
210             // Allocate something with drop glue to make sure it doesn't leak.
211             arena.alloc(SmallDroppable);
212         }
213         // dropping
214     };
215     assert_eq!(DROP_COUNTER.with(|c| c.get()), 100);
216 }
217
218 #[bench]
219 pub fn bench_noncopy(b: &mut Bencher) {
220     let arena = TypedArena::default();
221     b.iter(|| {
222         arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] })
223     })
224 }
225
226 #[bench]
227 pub fn bench_noncopy_nonarena(b: &mut Bencher) {
228     b.iter(|| {
229         let _: Box<_> =
230             Box::new(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] });
231     })
232 }