on master help sign in
Ensure that we always encode opcodes and immediates as u32s w/out padding
42d221aNick Fitzgerald
src/change_list.rs+53−27
@@ -170,79 +170,105 @@ pub enum ChangeDiscriminant {
170
170
171impl BumpAllocSafe for ChangeDiscriminant {}
171impl BumpAllocSafe for ChangeDiscriminant {}
172
172
173+// Allocation utilities to ensure that we only allocation sequences of `u32`s
174+// into the change list's bump arena without any padding. This helps maintain
175+// the invariants required for `Bump::each_allocated_chunk`'s safety.
176+impl ChangeList {
177+ // Allocate an opcode with zero immediates.
178+ fn op0(&self, discriminant: ChangeDiscriminant) {
179+ self.bump.alloc(discriminant as u32);
180+ }
181+
182+ // Note: no 1-immediate opcodes at this time.
183+
184+ // Allocate an opcode with two immediates.
185+ fn op2(&self, discriminant: ChangeDiscriminant, a: u32, b: u32) {
186+ self.bump.alloc([discriminant as u32, a, b]);
187+ }
188+
189+ // Note: no 3-immediates opcodes at this time.
190+
191+ // Allocate an opcode with four immediates.
192+ fn op4(&self, discriminant: ChangeDiscriminant, a: u32, b: u32, c: u32, d: u32) {
193+ self.bump.alloc([discriminant as u32, a, b, c, d]);
194+ }
195+}
196+
173impl ChangeList {
197impl ChangeList {
174 pub(crate) fn emit_set_text(&self, text: &str) {
198 pub(crate) fn emit_set_text(&self, text: &str) {
175 debug!("emit_set_text({:?})", text);
199 debug!("emit_set_text({:?})", text);
176− self.bump
200+ self.op2(
177− .alloc((ChangeDiscriminant::SetText, text.as_ptr(), text.len()));
201+ ChangeDiscriminant::SetText,
202+ text.as_ptr() as u32,
203+ text.len() as u32,
204+ );
178 }
205 }
179
206
180 pub(crate) fn emit_remove_self_and_next_siblings(&self) {
207 pub(crate) fn emit_remove_self_and_next_siblings(&self) {
181 debug!("emit_remove_self_and_next_siblings()");
208 debug!("emit_remove_self_and_next_siblings()");
182− self.bump
183− .alloc(ChangeDiscriminant::RemoveSelfAndNextSiblings);
209+ self.op0(ChangeDiscriminant::RemoveSelfAndNextSiblings);
184 }
210 }
185
211
186 pub(crate) fn emit_replace_with(&self) {
212 pub(crate) fn emit_replace_with(&self) {
187 debug!("emit_replace_with()");
213 debug!("emit_replace_with()");
188− self.bump.alloc(ChangeDiscriminant::ReplaceWith);
214+ self.op0(ChangeDiscriminant::ReplaceWith);
189 }
215 }
190
216
191 pub(crate) fn emit_set_attribute(&self, name: &str, value: &str) {
217 pub(crate) fn emit_set_attribute(&self, name: &str, value: &str) {
192 debug!("emit_set_attribute({:?}, {:?})", name, value);
218 debug!("emit_set_attribute({:?}, {:?})", name, value);
193− self.bump.alloc((
219+ self.op4(
194 ChangeDiscriminant::SetAttribute,
220 ChangeDiscriminant::SetAttribute,
195− name.as_ptr(),
221+ name.as_ptr() as u32,
196− name.len(),
222+ name.len() as u32,
197− value.as_ptr(),
223+ value.as_ptr() as u32,
198− value.len(),
224+ value.len() as u32,
199− ));
225+ );
200 }
226 }
201
227
202 pub(crate) fn emit_remove_attribute(&self, name: &str) {
228 pub(crate) fn emit_remove_attribute(&self, name: &str) {
203 debug!("emit_remove_attribute({:?})", name);
229 debug!("emit_remove_attribute({:?})", name);
204− self.bump.alloc((
230+ self.op2(
205 ChangeDiscriminant::RemoveAttribute,
231 ChangeDiscriminant::RemoveAttribute,
206− name.as_ptr(),
232+ name.as_ptr() as u32,
207− name.len(),
233+ name.len() as u32,
208− ));
234+ );
209 }
235 }
210
236
211 pub(crate) fn emit_push_first_child(&self) {
237 pub(crate) fn emit_push_first_child(&self) {
212 debug!("emit_push_first_child()");
238 debug!("emit_push_first_child()");
213− self.bump.alloc(ChangeDiscriminant::PushFirstChild);
239+ self.op0(ChangeDiscriminant::PushFirstChild);
214 }
240 }
215
241
216 pub(crate) fn emit_pop_push_next_sibling(&self) {
242 pub(crate) fn emit_pop_push_next_sibling(&self) {
217 debug!("emit_pop_push_next_sibling()");
243 debug!("emit_pop_push_next_sibling()");
218− self.bump.alloc(ChangeDiscriminant::PopPushNextSibling);
244+ self.op0(ChangeDiscriminant::PopPushNextSibling);
219 }
245 }
220
246
221 pub(crate) fn emit_pop(&self) {
247 pub(crate) fn emit_pop(&self) {
222 debug!("emit_pop()");
248 debug!("emit_pop()");
223− self.bump.alloc(ChangeDiscriminant::Pop);
249+ self.op0(ChangeDiscriminant::Pop);
224 }
250 }
225
251
226 pub(crate) fn emit_append_child(&self) {
252 pub(crate) fn emit_append_child(&self) {
227 debug!("emit_append_child()");
253 debug!("emit_append_child()");
228− self.bump.alloc(ChangeDiscriminant::AppendChild);
254+ self.op0(ChangeDiscriminant::AppendChild);
229 }
255 }
230
256
231 pub(crate) fn emit_create_text_node(&self, text: &str) {
257 pub(crate) fn emit_create_text_node(&self, text: &str) {
232 debug!("emit_create_text_node({:?})", text);
258 debug!("emit_create_text_node({:?})", text);
233− self.bump.alloc((
259+ self.op2(
234 ChangeDiscriminant::CreateTextNode,
260 ChangeDiscriminant::CreateTextNode,
235− text.as_ptr(),
261+ text.as_ptr() as u32,
236− text.len(),
262+ text.len() as u32,
237− ));
263+ );
238 }
264 }
239
265
240 pub(crate) fn emit_create_element(&self, tag_name: &str) {
266 pub(crate) fn emit_create_element(&self, tag_name: &str) {
241 debug!("emit_create_element({:?})", tag_name);
267 debug!("emit_create_element({:?})", tag_name);
242− self.bump.alloc((
268+ self.op2(
243 ChangeDiscriminant::CreateElement,
269 ChangeDiscriminant::CreateElement,
244− tag_name.as_ptr(),
270+ tag_name.as_ptr() as u32,
245− tag_name.len(),
271+ tag_name.len() as u32,
246− ));
272+ );
247 }
273 }
248}
274}