From a115a91e05a5c928ab267e53dad26152e3cab947 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Mon, 20 Jul 2020 15:29:49 +0000 Subject: [PATCH] Bug 1572421 - Tack on a temporary red zone to the data buffer for iteration. r=miko When iterating a "built display list" the iterator expects there to be a red zone at the end of the data buffer. The incremental display list emitter fakes having a built display list, but it still needs to tack on the red zone to satisfy the iterator (and assertions inside peek-poke). However we don't want to keep this red zone there after we're done, so this patch also adds a new method to peek-poke that strips away the red zone. The churn caused on the vector capacity should be negligible because this churn would happen anyway as new items are added to the display list and when the display list is actually finalized at the end. Differential Revision: https://phabricator.services.mozilla.com/D83788 --- gfx/wr/peek-poke/src/lib.rs | 14 ++++++++++++++ gfx/wr/webrender_api/src/display_list.rs | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/gfx/wr/peek-poke/src/lib.rs b/gfx/wr/peek-poke/src/lib.rs index 55864599bbd3..034799c594dd 100644 --- a/gfx/wr/peek-poke/src/lib.rs +++ b/gfx/wr/peek-poke/src/lib.rs @@ -113,6 +113,20 @@ pub fn ensure_red_zone(bytes: &mut Vec) { } } +/// Remove the "red zone" (padding of zeroes) from the end of the vec of `bytes`. +/// This is effectively the inverse of `ensure_red_zone`, with the caveat that +/// space reserved for the red zone is not un-reserved. Callers are repsonsible +/// for making sure the vec actually has a red zone, otherwise data bytes can +/// get stripped instead. +pub fn strip_red_zone(bytes: &mut Vec) { + assert!(bytes.len() >= T::max_size()); + unsafe { + let end_ptr = bytes.as_end_mut_ptr(); + end_ptr.write_bytes(0, T::max_size()); + bytes.set_end_ptr(end_ptr.sub(T::max_size())); + } +} + #[inline] unsafe fn read_verbatim(src: *const u8, dst: *mut T) -> *const u8 { *dst = (src as *const T).read_unaligned(); diff --git a/gfx/wr/webrender_api/src/display_list.rs b/gfx/wr/webrender_api/src/display_list.rs index 917ec84b5fb7..9f43b0d749bf 100644 --- a/gfx/wr/webrender_api/src/display_list.rs +++ b/gfx/wr/webrender_api/src/display_list.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use euclid::SideOffsets2D; -use peek_poke::{ensure_red_zone, peek_from_slice, poke_extend_vec}; +use peek_poke::{ensure_red_zone, peek_from_slice, poke_extend_vec, strip_red_zone}; use peek_poke::{poke_inplace_slice, poke_into_vec, Poke}; #[cfg(feature = "deserialize")] use serde::de::Deserializer; @@ -1075,6 +1075,7 @@ impl DisplayListBuilder { W: Write { let mut temp = BuiltDisplayList::default(); + ensure_red_zone::(&mut self.data); temp.descriptor.extra_data_offset = self.data.len(); mem::swap(&mut temp.data, &mut self.data); @@ -1090,6 +1091,7 @@ impl DisplayListBuilder { } self.data = temp.data; + strip_red_zone::(&mut self.data); index }