From 76a2653f8f974d23df56caf1dbc1d3f3fe68503d Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Thu, 12 Feb 2015 10:37:00 -0800 Subject: [PATCH 1/2] Replace append_from and prepend_from with DList::append --- components/gfx/display_list/mod.rs | 14 ++++----- components/util/dlist.rs | 50 ++---------------------------- 2 files changed, 8 insertions(+), 56 deletions(-) diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 9dacfd41b72..2b5b8707780 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -109,14 +109,12 @@ impl DisplayList { /// `other` in the process. #[inline] pub fn append_from(&mut self, other: &mut DisplayList) { - servo_dlist::append_from(&mut self.background_and_borders, - &mut other.background_and_borders); - servo_dlist::append_from(&mut self.block_backgrounds_and_borders, - &mut other.block_backgrounds_and_borders); - servo_dlist::append_from(&mut self.floats, &mut other.floats); - servo_dlist::append_from(&mut self.content, &mut other.content); - servo_dlist::append_from(&mut self.outlines, &mut other.outlines); - servo_dlist::append_from(&mut self.children, &mut other.children); + self.background_and_borders.append(&mut other.background_and_borders); + self.block_backgrounds_and_borders.append(&mut other.block_backgrounds_and_borders); + self.floats.append(&mut other.floats); + self.content.append(&mut other.content); + self.outlines.append(&mut other.outlines); + self.children.append(&mut other.children); } /// Merges all display items from all non-float stacking levels to the `float` stacking level. diff --git a/components/util/dlist.rs b/components/util/dlist.rs index f22c07268ba..f6df1b3d127 100644 --- a/components/util/dlist.rs +++ b/components/util/dlist.rs @@ -71,55 +71,9 @@ pub fn split(list: &mut DList) -> DList { } } -/// Appends the items in the other list to this one, leaving the other list empty. -#[inline] -pub fn append_from(this: &mut DList, other: &mut DList) { - unsafe { - let this = mem::transmute::<&mut DList,&mut RawDList>(this); - let other = mem::transmute::<&mut DList,&mut RawDList>(other); - if this.length == 0 { - this.head = mem::replace(&mut other.head, ptr::null_mut()); - this.tail = mem::replace(&mut other.tail, ptr::null_mut()); - this.length = mem::replace(&mut other.length, 0); - return - } - - let old_other_head = mem::replace(&mut other.head, ptr::null_mut()); - if old_other_head.is_null() { - return - } - (*old_other_head).prev = this.tail; - (*this.tail).next = old_other_head; - - this.tail = mem::replace(&mut other.tail, ptr::null_mut()); - this.length += other.length; - other.length = 0; - } -} - /// Prepends the items in the other list to this one, leaving the other list empty. #[inline] pub fn prepend_from(this: &mut DList, other: &mut DList) { - unsafe { - let this = mem::transmute::<&mut DList,&mut RawDList>(this); - let other = mem::transmute::<&mut DList,&mut RawDList>(other); - if this.length == 0 { - this.head = mem::replace(&mut other.head, ptr::null_mut()); - this.tail = mem::replace(&mut other.tail, ptr::null_mut()); - this.length = mem::replace(&mut other.length, 0); - return - } - - let old_other_tail = mem::replace(&mut other.tail, ptr::null_mut()); - if old_other_tail.is_null() { - return - } - (*old_other_tail).next = this.head; - (*this.head).prev = old_other_tail; - - this.head = mem::replace(&mut other.head, ptr::null_mut()); - this.length += other.length; - other.length = 0; - } + other.append(this); + mem::swap(this, other); } - From 04fb3a52671596c8499f673bf0236aad9e96a23e Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Thu, 12 Feb 2015 10:41:01 -0800 Subject: [PATCH 2/2] Make dlist::split use new DList::split_off. --- components/layout/text.rs | 4 +-- components/util/dlist.rs | 68 ++++----------------------------------- 2 files changed, 9 insertions(+), 63 deletions(-) diff --git a/components/layout/text.rs b/components/layout/text.rs index 23541e3358a..697b2301738 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -50,13 +50,13 @@ impl TextRunScanner { let mut last_whitespace = true; while !fragments.is_empty() { // Create a clump. - self.clump.append(&mut dlist::split(&mut fragments)); + self.clump.append(&mut dlist::split_off_head(&mut fragments)); while !fragments.is_empty() && self.clump .back() .unwrap() .can_merge_with_fragment(fragments.front() .unwrap()) { - self.clump.append(&mut dlist::split(&mut fragments)); + self.clump.append(&mut dlist::split_off_head(&mut fragments)); } // Flush that clump to the list of fragments we're building up. diff --git a/components/util/dlist.rs b/components/util/dlist.rs index f6df1b3d127..ce55743f14b 100644 --- a/components/util/dlist.rs +++ b/components/util/dlist.rs @@ -6,69 +6,15 @@ use std::collections::DList; use std::mem; -use std::ptr; -struct RawDList { - length: uint, - head: *mut RawNode, - tail: *mut RawNode, -} - -#[allow(dead_code)] -struct RawNode { - next: *mut RawNode, - prev: *mut RawNode, - value: T, -} - -#[unsafe_destructor] -impl Drop for RawDList { - fn drop(&mut self) { - panic!("shouldn't happen") - } -} - -/// Workaround for a missing method on Rust's `DList` type. Splits the head off a list in O(1) -/// time. -pub fn split(list: &mut DList) -> DList { - let list = unsafe { - mem::transmute::<&mut DList,&mut RawDList>(list) - }; - - if list.length == 0 { - panic!("split_dlist(): empty list") - } - let head_node = mem::replace(&mut list.head, ptr::null_mut()); - let head_list = RawDList { - length: 1, - head: head_node, - tail: head_node, - }; - debug_assert!(list.head.is_null()); - - unsafe { - mem::swap(&mut (*head_list.head).next, &mut list.head); - debug_assert!((*head_list.head).next.is_null()); - debug_assert!((*head_list.head).prev.is_null()); - (*head_list.head).prev = ptr::null_mut(); - } - - list.length -= 1; - if list.length == 0 { - list.tail = ptr::null_mut() - } else { - if list.length == 1 { - list.tail = list.head - } - - unsafe { - (*list.head).prev = ptr::null_mut() - } - } - - unsafe { - mem::transmute::,DList>(head_list) +/// Splits the head off a list in O(1) time, and returns the head. +pub fn split_off_head(list: &mut DList) -> DList { + // FIXME: Work around https://github.com/rust-lang/rust/issues/22244 + if list.len() == 1 { + return mem::replace(list, DList::new()); } + let tail = list.split_off(1); + mem::replace(list, tail) } /// Prepends the items in the other list to this one, leaving the other list empty.