]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_arena/src/tests.rs
Rollup merge of #100351 - compiler-errors:diagnostic-convention, r=fee1-dead
[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     #[cfg(not(miri))]
83     const N: usize = 100000;
84     #[cfg(miri)]
85     const N: usize = 1000;
86     for _ in 0..N {
87         arena.alloc(Point { x: 1, y: 2, z: 3 });
88     }
89 }
90
91 #[bench]
92 pub fn bench_copy(b: &mut Bencher) {
93     let arena = TypedArena::default();
94     b.iter(|| arena.alloc(Point { x: 1, y: 2, z: 3 }))
95 }
96
97 #[bench]
98 pub fn bench_copy_nonarena(b: &mut Bencher) {
99     b.iter(|| {
100         let _: Box<_> = Box::new(Point { x: 1, y: 2, z: 3 });
101     })
102 }
103
104 #[allow(dead_code)]
105 struct Noncopy {
106     string: String,
107     array: Vec<i32>,
108 }
109
110 #[test]
111 pub fn test_noncopy() {
112     let arena = TypedArena::default();
113     #[cfg(not(miri))]
114     const N: usize = 100000;
115     #[cfg(miri)]
116     const N: usize = 1000;
117     for _ in 0..N {
118         arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] });
119     }
120 }
121
122 #[test]
123 pub fn test_typed_arena_zero_sized() {
124     let arena = TypedArena::default();
125     #[cfg(not(miri))]
126     const N: usize = 100000;
127     #[cfg(miri)]
128     const N: usize = 1000;
129     for _ in 0..N {
130         arena.alloc(());
131     }
132 }
133
134 #[test]
135 pub fn test_typed_arena_clear() {
136     let mut arena = TypedArena::default();
137     for _ in 0..10 {
138         arena.clear();
139         #[cfg(not(miri))]
140         const N: usize = 10000;
141         #[cfg(miri)]
142         const N: usize = 100;
143         for _ in 0..N {
144             arena.alloc(Point { x: 1, y: 2, z: 3 });
145         }
146     }
147 }
148
149 #[bench]
150 pub fn bench_typed_arena_clear(b: &mut Bencher) {
151     let mut arena = TypedArena::default();
152     b.iter(|| {
153         arena.alloc(Point { x: 1, y: 2, z: 3 });
154         arena.clear();
155     })
156 }
157
158 #[bench]
159 pub fn bench_typed_arena_clear_100(b: &mut Bencher) {
160     let mut arena = TypedArena::default();
161     b.iter(|| {
162         for _ in 0..100 {
163             arena.alloc(Point { x: 1, y: 2, z: 3 });
164         }
165         arena.clear();
166     })
167 }
168
169 // Drop tests
170
171 struct DropCounter<'a> {
172     count: &'a Cell<u32>,
173 }
174
175 impl Drop for DropCounter<'_> {
176     fn drop(&mut self) {
177         self.count.set(self.count.get() + 1);
178     }
179 }
180
181 #[test]
182 fn test_typed_arena_drop_count() {
183     let counter = Cell::new(0);
184     {
185         let arena: TypedArena<DropCounter<'_>> = TypedArena::default();
186         for _ in 0..100 {
187             // Allocate something with drop glue to make sure it doesn't leak.
188             arena.alloc(DropCounter { count: &counter });
189         }
190     };
191     assert_eq!(counter.get(), 100);
192 }
193
194 #[test]
195 fn test_typed_arena_drop_on_clear() {
196     let counter = Cell::new(0);
197     let mut arena: TypedArena<DropCounter<'_>> = TypedArena::default();
198     for i in 0..10 {
199         for _ in 0..100 {
200             // Allocate something with drop glue to make sure it doesn't leak.
201             arena.alloc(DropCounter { count: &counter });
202         }
203         arena.clear();
204         assert_eq!(counter.get(), i * 100 + 100);
205     }
206 }
207
208 thread_local! {
209     static DROP_COUNTER: Cell<u32> = Cell::new(0)
210 }
211
212 struct SmallDroppable;
213
214 impl Drop for SmallDroppable {
215     fn drop(&mut self) {
216         DROP_COUNTER.with(|c| c.set(c.get() + 1));
217     }
218 }
219
220 #[test]
221 fn test_typed_arena_drop_small_count() {
222     DROP_COUNTER.with(|c| c.set(0));
223     {
224         let arena: TypedArena<SmallDroppable> = TypedArena::default();
225         for _ in 0..100 {
226             // Allocate something with drop glue to make sure it doesn't leak.
227             arena.alloc(SmallDroppable);
228         }
229         // dropping
230     };
231     assert_eq!(DROP_COUNTER.with(|c| c.get()), 100);
232 }
233
234 #[bench]
235 pub fn bench_noncopy(b: &mut Bencher) {
236     let arena = TypedArena::default();
237     b.iter(|| {
238         arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] })
239     })
240 }
241
242 #[bench]
243 pub fn bench_noncopy_nonarena(b: &mut Bencher) {
244     b.iter(|| {
245         let _: Box<_> =
246             Box::new(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] });
247     })
248 }