]>
git.proxmox.com Git - rustc.git/blob - compiler/rustc_middle/src/mir/interpret/allocation/init_mask/tests.rs
2 use crate::mir
::interpret
::alloc_range
;
6 let mut mask
= InitMask
::new(Size
::from_bytes(500), false);
7 assert
!(!mask
.get(Size
::from_bytes(499)));
8 mask
.set_range(alloc_range(Size
::from_bytes(499), Size
::from_bytes(1)), true);
9 assert
!(mask
.get(Size
::from_bytes(499)));
10 mask
.set_range((100..256).into(), true);
12 assert
!(!mask
.get(Size
::from_bytes(i
)), "{i} should not be set");
15 assert
!(mask
.get(Size
::from_bytes(i
)), "{i} should be set");
18 assert
!(!mask
.get(Size
::from_bytes(i
)), "{i} should not be set");
22 /// Returns the number of materialized blocks for this mask.
23 fn materialized_block_count(mask
: &InitMask
) -> usize {
25 InitMaskBlocks
::Lazy { .. }
=> 0,
26 InitMaskBlocks
::Materialized(ref blocks
) => blocks
.blocks
.len(),
31 fn materialize_mask_within_range() {
32 // To have spare bits, we use a mask size smaller than its block size of 64.
33 let mut mask
= InitMask
::new(Size
::from_bytes(16), false);
34 assert_eq
!(materialized_block_count(&mask
), 0);
36 // Forces materialization, but doesn't require growth. This is case #1 documented in the
37 // `set_range` method.
38 mask
.set_range((8..16).into(), true);
39 assert_eq
!(materialized_block_count(&mask
), 1);
42 assert
!(!mask
.get(Size
::from_bytes(i
)), "{i} should not be set");
45 assert
!(mask
.get(Size
::from_bytes(i
)), "{i} should be set");
50 fn grow_within_unused_bits_with_full_overwrite() {
51 // To have spare bits, we use a mask size smaller than its block size of 64.
52 let mut mask
= InitMask
::new(Size
::from_bytes(16), true);
54 assert
!(mask
.get(Size
::from_bytes(i
)), "{i} should be set");
57 // Grow without requiring an additional block. Full overwrite.
58 // This can be fully handled without materialization.
59 let range
= (0..32).into();
60 mask
.set_range(range
, true);
63 assert
!(mask
.get(Size
::from_bytes(i
)), "{i} should be set");
66 assert_eq
!(materialized_block_count(&mask
), 0);
69 // This test checks that an initmask's spare capacity is correctly used when growing within block
70 // capacity. This can be fully handled without materialization.
72 fn grow_same_state_within_unused_bits() {
73 // To have spare bits, we use a mask size smaller than its block size of 64.
74 let mut mask
= InitMask
::new(Size
::from_bytes(16), true);
76 assert
!(mask
.get(Size
::from_bytes(i
)), "{i} should be set");
79 // Grow without requiring an additional block. The gap between the current length and the
80 // range's beginning should be set to the same value as the range.
81 let range
= (24..32).into();
82 mask
.set_range(range
, true);
84 // We want to make sure the unused bits in the first block are correct
86 assert
!(mask
.get(Size
::from_bytes(i
)), "{i} should be set");
90 assert
!(mask
.get(Size
::from_bytes(i
)), "{i} should be set");
93 assert_eq
!(1, mask
.range_as_init_chunks((0..32).into()).count());
94 assert_eq
!(materialized_block_count(&mask
), 0);
97 // This is the same test as `grow_same_state_within_unused_bits` but with both init and uninit
98 // states: this forces materialization; otherwise the mask could stay lazy even when needing to
101 fn grow_mixed_state_within_unused_bits() {
102 // To have spare bits, we use a mask size smaller than its block size of 64.
103 let mut mask
= InitMask
::new(Size
::from_bytes(16), true);
105 assert
!(mask
.get(Size
::from_bytes(i
)), "{i} should be set");
108 // Grow without requiring an additional block. The gap between the current length and the
109 // range's beginning should be set to the same value as the range. Note: since this is fully
110 // out-of-bounds of the current mask, this is case #3 described in the `set_range` method.
111 let range
= (24..32).into();
112 mask
.set_range(range
, false);
114 // We want to make sure the unused bits in the first block are correct
116 assert
!(!mask
.get(Size
::from_bytes(i
)), "{i} should not be set");
120 assert
!(!mask
.get(Size
::from_bytes(i
)), "{i} should not be set");
123 assert_eq
!(1, mask
.range_as_init_chunks((0..16).into()).count());
124 assert_eq
!(2, mask
.range_as_init_chunks((0..32).into()).count());
125 assert_eq
!(materialized_block_count(&mask
), 1);
128 // This is similar to `grow_mixed_state_within_unused_bits` to force materialization, but the range
129 // to set partially overlaps the mask, so this requires a different growth + write pattern in the
132 fn grow_within_unused_bits_with_overlap() {
133 // To have spare bits, we use a mask size smaller than its block size of 64.
134 let mut mask
= InitMask
::new(Size
::from_bytes(16), true);
136 assert
!(mask
.get(Size
::from_bytes(i
)), "{i} should be set");
139 // Grow without requiring an additional block, but leave no gap after the current len. Note:
140 // since this is partially out-of-bounds of the current mask, this is case #2 described in the
141 // `set_range` method.
142 let range
= (8..24).into();
143 mask
.set_range(range
, false);
145 // We want to make sure the unused bits in the first block are correct
147 assert
!(!mask
.get(Size
::from_bytes(i
)), "{i} should not be set");
150 assert_eq
!(1, mask
.range_as_init_chunks((0..8).into()).count());
151 assert_eq
!(2, mask
.range_as_init_chunks((0..24).into()).count());
152 assert_eq
!(materialized_block_count(&mask
), 1);
155 // Force materialization before a full overwrite: the mask can now become lazy.
157 fn grow_mixed_state_within_unused_bits_and_full_overwrite() {
158 // To have spare bits, we use a mask size smaller than its block size of 64.
159 let mut mask
= InitMask
::new(Size
::from_bytes(16), true);
160 let range
= (0..16).into();
161 assert
!(mask
.is_range_initialized(range
).is_ok());
163 // Force materialization.
164 let range
= (8..24).into();
165 mask
.set_range(range
, false);
166 assert
!(mask
.is_range_initialized(range
).is_err());
167 assert_eq
!(materialized_block_count(&mask
), 1);
169 // Full overwrite, lazy blocks would be enough from now on.
170 let range
= (0..32).into();
171 mask
.set_range(range
, true);
172 assert
!(mask
.is_range_initialized(range
).is_ok());
174 assert_eq
!(1, mask
.range_as_init_chunks((0..32).into()).count());
175 assert_eq
!(materialized_block_count(&mask
), 0);
178 // Check that growth outside the current capacity can still be lazy: if the init state doesn't
179 // change, we don't need materialized blocks.
181 fn grow_same_state_outside_capacity() {
182 // To have spare bits, we use a mask size smaller than its block size of 64.
183 let mut mask
= InitMask
::new(Size
::from_bytes(16), true);
185 assert
!(mask
.get(Size
::from_bytes(i
)), "{i} should be set");
187 assert_eq
!(materialized_block_count(&mask
), 0);
189 // Grow to 10 blocks with the same init state.
190 let range
= (24..640).into();
191 mask
.set_range(range
, true);
193 assert_eq
!(1, mask
.range_as_init_chunks((0..640).into()).count());
194 assert_eq
!(materialized_block_count(&mask
), 0);