mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Use a bitmap to optimize adding to a PropertyDeclarationBlock.
This commit is contained in:
parent
f70a49974a
commit
60f454d7c4
3 changed files with 61 additions and 18 deletions
|
@ -41,7 +41,7 @@ impl Importance {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Overridden declarations are skipped.
|
/// Overridden declarations are skipped.
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PropertyDeclarationBlock {
|
pub struct PropertyDeclarationBlock {
|
||||||
/// The group of declarations, along with their importance.
|
/// The group of declarations, along with their importance.
|
||||||
///
|
///
|
||||||
|
@ -50,6 +50,14 @@ pub struct PropertyDeclarationBlock {
|
||||||
|
|
||||||
/// The number of entries in `self.declaration` with `Importance::Important`
|
/// The number of entries in `self.declaration` with `Importance::Important`
|
||||||
important_count: usize,
|
important_count: usize,
|
||||||
|
|
||||||
|
longhands: LonghandIdSet,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for PropertyDeclarationBlock {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
self.declarations.fmt(f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PropertyDeclarationBlock {
|
impl PropertyDeclarationBlock {
|
||||||
|
@ -58,14 +66,20 @@ impl PropertyDeclarationBlock {
|
||||||
PropertyDeclarationBlock {
|
PropertyDeclarationBlock {
|
||||||
declarations: Vec::new(),
|
declarations: Vec::new(),
|
||||||
important_count: 0,
|
important_count: 0,
|
||||||
|
longhands: LonghandIdSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a block with a single declaration
|
/// Create a block with a single declaration
|
||||||
pub fn with_one(declaration: PropertyDeclaration, importance: Importance) -> Self {
|
pub fn with_one(declaration: PropertyDeclaration, importance: Importance) -> Self {
|
||||||
|
let mut longhands = LonghandIdSet::new();
|
||||||
|
if let PropertyDeclarationId::Longhand(id) = declaration.id() {
|
||||||
|
longhands.insert(id);
|
||||||
|
}
|
||||||
PropertyDeclarationBlock {
|
PropertyDeclarationBlock {
|
||||||
declarations: vec![(declaration, importance)],
|
declarations: vec![(declaration, importance)],
|
||||||
important_count: if importance.important() { 1 } else { 0 },
|
important_count: if importance.important() { 1 } else { 0 },
|
||||||
|
longhands: longhands,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,28 +212,39 @@ impl PropertyDeclarationBlock {
|
||||||
|
|
||||||
fn push_common(&mut self, declaration: PropertyDeclaration, importance: Importance,
|
fn push_common(&mut self, declaration: PropertyDeclaration, importance: Importance,
|
||||||
overwrite_more_important: bool) -> bool {
|
overwrite_more_important: bool) -> bool {
|
||||||
for slot in &mut *self.declarations {
|
let definitely_new = if let PropertyDeclarationId::Longhand(id) = declaration.id() {
|
||||||
if slot.0.id() == declaration.id() {
|
!self.longhands.contains(id)
|
||||||
match (slot.1, importance) {
|
} else {
|
||||||
(Importance::Normal, Importance::Important) => {
|
false // For custom properties, always scan
|
||||||
self.important_count += 1;
|
};
|
||||||
}
|
|
||||||
(Importance::Important, Importance::Normal) => {
|
if !definitely_new {
|
||||||
if overwrite_more_important {
|
for slot in &mut *self.declarations {
|
||||||
self.important_count -= 1;
|
if slot.0.id() == declaration.id() {
|
||||||
} else {
|
match (slot.1, importance) {
|
||||||
return false
|
(Importance::Normal, Importance::Important) => {
|
||||||
|
self.important_count += 1;
|
||||||
|
}
|
||||||
|
(Importance::Important, Importance::Normal) => {
|
||||||
|
if overwrite_more_important {
|
||||||
|
self.important_count -= 1;
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => if slot.0 == declaration {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => if slot.0 == declaration {
|
*slot = (declaration, importance);
|
||||||
return false;
|
return true
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*slot = (declaration, importance);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let PropertyDeclarationId::Longhand(id) = declaration.id() {
|
||||||
|
self.longhands.insert(id);
|
||||||
|
}
|
||||||
self.declarations.push((declaration, importance));
|
self.declarations.push((declaration, importance));
|
||||||
if importance.important() {
|
if importance.important() {
|
||||||
self.important_count += 1;
|
self.important_count += 1;
|
||||||
|
@ -256,6 +281,11 @@ impl PropertyDeclarationBlock {
|
||||||
///
|
///
|
||||||
/// Returns whether any declaration was actually removed.
|
/// Returns whether any declaration was actually removed.
|
||||||
pub fn remove_property(&mut self, property: &PropertyId) -> bool {
|
pub fn remove_property(&mut self, property: &PropertyId) -> bool {
|
||||||
|
if let PropertyId::Longhand(id) = *property {
|
||||||
|
if !self.longhands.contains(id) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
let important_count = &mut self.important_count;
|
let important_count = &mut self.important_count;
|
||||||
let mut removed_at_least_one = false;
|
let mut removed_at_least_one = false;
|
||||||
self.declarations.retain(|&(ref declaration, importance)| {
|
self.declarations.retain(|&(ref declaration, importance)| {
|
||||||
|
@ -269,6 +299,10 @@ impl PropertyDeclarationBlock {
|
||||||
!remove
|
!remove
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if let PropertyId::Longhand(id) = *property {
|
||||||
|
debug_assert!(removed_at_least_one);
|
||||||
|
self.longhands.remove(id);
|
||||||
|
}
|
||||||
removed_at_least_one
|
removed_at_least_one
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,6 +177,7 @@ pub mod animated_properties {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A set of longhand properties
|
/// A set of longhand properties
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct LonghandIdSet {
|
pub struct LonghandIdSet {
|
||||||
storage: [u32; (${len(data.longhands)} - 1 + 32) / 32]
|
storage: [u32; (${len(data.longhands)} - 1 + 32) / 32]
|
||||||
}
|
}
|
||||||
|
@ -202,6 +203,13 @@ impl LonghandIdSet {
|
||||||
self.storage[bit / 32] |= 1 << (bit % 32);
|
self.storage[bit / 32] |= 1 << (bit % 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove the given property from the set
|
||||||
|
#[inline]
|
||||||
|
pub fn remove(&mut self, id: LonghandId) {
|
||||||
|
let bit = id as usize;
|
||||||
|
self.storage[bit / 32] &= !(1 << (bit % 32));
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the corresponding bit of TransitionProperty.
|
/// Set the corresponding bit of TransitionProperty.
|
||||||
/// This function will panic if TransitionProperty::All is given.
|
/// This function will panic if TransitionProperty::All is given.
|
||||||
pub fn set_transition_property_bit(&mut self, property: &TransitionProperty) {
|
pub fn set_transition_property_bit(&mut self, property: &TransitionProperty) {
|
||||||
|
|
|
@ -738,7 +738,8 @@ pub extern "C" fn Servo_DeclarationBlock_Clone(declarations: RawServoDeclaration
|
||||||
pub extern "C" fn Servo_DeclarationBlock_Equals(a: RawServoDeclarationBlockBorrowed,
|
pub extern "C" fn Servo_DeclarationBlock_Equals(a: RawServoDeclarationBlockBorrowed,
|
||||||
b: RawServoDeclarationBlockBorrowed)
|
b: RawServoDeclarationBlockBorrowed)
|
||||||
-> bool {
|
-> bool {
|
||||||
*RwLock::<PropertyDeclarationBlock>::as_arc(&a).read() == *RwLock::<PropertyDeclarationBlock>::as_arc(&b).read()
|
*RwLock::<PropertyDeclarationBlock>::as_arc(&a).read().declarations() ==
|
||||||
|
*RwLock::<PropertyDeclarationBlock>::as_arc(&b).read().declarations()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue