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
This commit is contained in:
Kartikaya Gupta 2020-07-20 15:29:49 +00:00
Родитель 25810fd2c7
Коммит a115a91e05
2 изменённых файлов: 17 добавлений и 1 удалений

Просмотреть файл

@ -113,6 +113,20 @@ pub fn ensure_red_zone<T: Poke>(bytes: &mut Vec<u8>) {
} }
} }
/// 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<T: Poke>(bytes: &mut Vec<u8>) {
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] #[inline]
unsafe fn read_verbatim<T>(src: *const u8, dst: *mut T) -> *const u8 { unsafe fn read_verbatim<T>(src: *const u8, dst: *mut T) -> *const u8 {
*dst = (src as *const T).read_unaligned(); *dst = (src as *const T).read_unaligned();

Просмотреть файл

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use euclid::SideOffsets2D; 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}; use peek_poke::{poke_inplace_slice, poke_into_vec, Poke};
#[cfg(feature = "deserialize")] #[cfg(feature = "deserialize")]
use serde::de::Deserializer; use serde::de::Deserializer;
@ -1075,6 +1075,7 @@ impl DisplayListBuilder {
W: Write W: Write
{ {
let mut temp = BuiltDisplayList::default(); let mut temp = BuiltDisplayList::default();
ensure_red_zone::<di::DisplayItem>(&mut self.data);
temp.descriptor.extra_data_offset = self.data.len(); temp.descriptor.extra_data_offset = self.data.len();
mem::swap(&mut temp.data, &mut self.data); mem::swap(&mut temp.data, &mut self.data);
@ -1090,6 +1091,7 @@ impl DisplayListBuilder {
} }
self.data = temp.data; self.data = temp.data;
strip_red_zone::<di::DisplayItem>(&mut self.data);
index index
} }