mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Deduplicate declarations when inserting each one, not at the end of parsing.
This will reduce the amount of re-allocations and copies. It will be further optimized with a bit map.
This commit is contained in:
parent
4b4a873c3e
commit
460fd6eba8
3 changed files with 40 additions and 74 deletions
|
@ -362,10 +362,10 @@ impl<'a> QualifiedRuleParser for KeyframeListParser<'a> {
|
||||||
context: self.context,
|
context: self.context,
|
||||||
};
|
};
|
||||||
let mut iter = DeclarationListParser::new(input, parser);
|
let mut iter = DeclarationListParser::new(input, parser);
|
||||||
let mut declarations = Vec::new();
|
let mut block = PropertyDeclarationBlock::new();
|
||||||
while let Some(declaration) = iter.next() {
|
while let Some(declaration) = iter.next() {
|
||||||
match declaration {
|
match declaration {
|
||||||
Ok(parsed) => parsed.expand(|d| declarations.push((d, Importance::Normal))),
|
Ok(parsed) => parsed.expand(|d| block.push(d, Importance::Normal)),
|
||||||
Err(range) => {
|
Err(range) => {
|
||||||
let pos = range.start;
|
let pos = range.start;
|
||||||
let message = format!("Unsupported keyframe property declaration: '{}'",
|
let message = format!("Unsupported keyframe property declaration: '{}'",
|
||||||
|
@ -377,10 +377,7 @@ impl<'a> QualifiedRuleParser for KeyframeListParser<'a> {
|
||||||
}
|
}
|
||||||
Ok(Arc::new(RwLock::new(Keyframe {
|
Ok(Arc::new(RwLock::new(Keyframe {
|
||||||
selector: prelude,
|
selector: prelude,
|
||||||
block: Arc::new(RwLock::new(PropertyDeclarationBlock {
|
block: Arc::new(RwLock::new(block)),
|
||||||
declarations: declarations,
|
|
||||||
important_count: 0,
|
|
||||||
})),
|
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,14 @@ pub struct PropertyDeclarationBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PropertyDeclarationBlock {
|
impl PropertyDeclarationBlock {
|
||||||
|
/// Create an empty block
|
||||||
|
pub fn new() -> Self {
|
||||||
|
PropertyDeclarationBlock {
|
||||||
|
declarations: Vec::new(),
|
||||||
|
important_count: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns wheather this block contains any declaration with `!important`.
|
/// Returns wheather this block contains any declaration with `!important`.
|
||||||
///
|
///
|
||||||
/// This is based on the `important_count` counter,
|
/// This is based on the `important_count` counter,
|
||||||
|
@ -169,11 +177,21 @@ impl PropertyDeclarationBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds or overrides the declaration for a given property in this block,
|
/// Adds or overrides the declaration for a given property in this block,
|
||||||
/// without taking into account any kind of priority. Returns whether the
|
/// except if an existing declaration for the same property is more important.
|
||||||
/// declaration block is actually changed.
|
pub fn push(&mut self, declaration: PropertyDeclaration, importance: Importance) {
|
||||||
|
self.push_common(declaration, importance, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds or overrides the declaration for a given property in this block,
|
||||||
|
/// Returns whether the declaration block is actually changed.
|
||||||
pub fn set_parsed_declaration(&mut self,
|
pub fn set_parsed_declaration(&mut self,
|
||||||
declaration: PropertyDeclaration,
|
declaration: PropertyDeclaration,
|
||||||
importance: Importance) -> bool {
|
importance: Importance) -> bool {
|
||||||
|
self.push_common(declaration, importance, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_common(&mut self, declaration: PropertyDeclaration, importance: Importance,
|
||||||
|
overwrite_more_important: bool) -> bool {
|
||||||
for slot in &mut *self.declarations {
|
for slot in &mut *self.declarations {
|
||||||
if slot.0.id() == declaration.id() {
|
if slot.0.id() == declaration.id() {
|
||||||
match (slot.1, importance) {
|
match (slot.1, importance) {
|
||||||
|
@ -181,7 +199,11 @@ impl PropertyDeclarationBlock {
|
||||||
self.important_count += 1;
|
self.important_count += 1;
|
||||||
}
|
}
|
||||||
(Importance::Important, Importance::Normal) => {
|
(Importance::Important, Importance::Normal) => {
|
||||||
self.important_count -= 1;
|
if overwrite_more_important {
|
||||||
|
self.important_count -= 1;
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => if slot.0 == declaration {
|
_ => if slot.0 == declaration {
|
||||||
return false;
|
return false;
|
||||||
|
@ -276,39 +298,6 @@ impl PropertyDeclarationBlock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Only keep the "winning" declaration for any given property, by importance then source order.
|
|
||||||
pub fn deduplicate(&mut self) {
|
|
||||||
let mut deduplicated = Vec::with_capacity(self.declarations.len());
|
|
||||||
let mut seen_normal = PropertyDeclarationIdSet::new();
|
|
||||||
let mut seen_important = PropertyDeclarationIdSet::new();
|
|
||||||
|
|
||||||
for (declaration, importance) in self.declarations.drain(..).rev() {
|
|
||||||
if importance.important() {
|
|
||||||
let id = declaration.id();
|
|
||||||
if seen_important.contains(id) {
|
|
||||||
self.important_count -= 1;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if seen_normal.contains(id) {
|
|
||||||
let previous_len = deduplicated.len();
|
|
||||||
deduplicated.retain(|&(ref d, _)| PropertyDeclaration::id(d) != id);
|
|
||||||
debug_assert_eq!(deduplicated.len(), previous_len - 1);
|
|
||||||
}
|
|
||||||
seen_important.insert(id);
|
|
||||||
} else {
|
|
||||||
let id = declaration.id();
|
|
||||||
if seen_normal.contains(id) ||
|
|
||||||
seen_important.contains(id) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
seen_normal.insert(id)
|
|
||||||
}
|
|
||||||
deduplicated.push((declaration, importance))
|
|
||||||
}
|
|
||||||
deduplicated.reverse();
|
|
||||||
self.declarations = deduplicated;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for PropertyDeclarationBlock {
|
impl ToCss for PropertyDeclarationBlock {
|
||||||
|
@ -603,21 +592,14 @@ impl<'a, 'b> DeclarationParser for PropertyDeclarationParser<'a, 'b> {
|
||||||
pub fn parse_property_declaration_list(context: &ParserContext,
|
pub fn parse_property_declaration_list(context: &ParserContext,
|
||||||
input: &mut Parser)
|
input: &mut Parser)
|
||||||
-> PropertyDeclarationBlock {
|
-> PropertyDeclarationBlock {
|
||||||
let mut declarations = Vec::new();
|
let mut block = PropertyDeclarationBlock::new();
|
||||||
let mut important_count = 0;
|
|
||||||
let parser = PropertyDeclarationParser {
|
let parser = PropertyDeclarationParser {
|
||||||
context: context,
|
context: context,
|
||||||
};
|
};
|
||||||
let mut iter = DeclarationListParser::new(input, parser);
|
let mut iter = DeclarationListParser::new(input, parser);
|
||||||
while let Some(declaration) = iter.next() {
|
while let Some(declaration) = iter.next() {
|
||||||
match declaration {
|
match declaration {
|
||||||
Ok((parsed, importance)) => {
|
Ok((parsed, importance)) => parsed.expand(|d| block.push(d, importance)),
|
||||||
let old_len = declarations.len();
|
|
||||||
parsed.expand(|d| declarations.push((d, importance)));
|
|
||||||
if importance.important() {
|
|
||||||
important_count += declarations.len() - old_len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(range) => {
|
Err(range) => {
|
||||||
let pos = range.start;
|
let pos = range.start;
|
||||||
let message = format!("Unsupported property declaration: '{}'",
|
let message = format!("Unsupported property declaration: '{}'",
|
||||||
|
@ -626,10 +608,5 @@ pub fn parse_property_declaration_list(context: &ParserContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut block = PropertyDeclarationBlock {
|
|
||||||
declarations: declarations,
|
|
||||||
important_count: important_count,
|
|
||||||
};
|
|
||||||
block.deduplicate();
|
|
||||||
block
|
block
|
||||||
}
|
}
|
||||||
|
|
|
@ -251,18 +251,13 @@ pub extern "C" fn Servo_AnimationValues_Uncompute(value: RawServoAnimationValueB
|
||||||
-> RawServoDeclarationBlockStrong
|
-> RawServoDeclarationBlockStrong
|
||||||
{
|
{
|
||||||
let value = unsafe { value.as_ref().unwrap() };
|
let value = unsafe { value.as_ref().unwrap() };
|
||||||
let uncomputed_values = value.into_iter()
|
let mut block = PropertyDeclarationBlock::new();
|
||||||
.map(|v| {
|
for v in value.iter() {
|
||||||
let raw_anim = unsafe { v.as_ref().unwrap() };
|
let raw_anim = unsafe { v.as_ref().unwrap() };
|
||||||
let anim = AnimationValue::as_arc(&raw_anim);
|
let anim = AnimationValue::as_arc(&raw_anim);
|
||||||
(anim.uncompute(), Importance::Normal)
|
block.push(anim.uncompute(), Importance::Normal);
|
||||||
})
|
}
|
||||||
.collect();
|
Arc::new(RwLock::new(block)).into_strong()
|
||||||
|
|
||||||
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
|
||||||
declarations: uncomputed_values,
|
|
||||||
important_count: 0,
|
|
||||||
})).into_strong()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! get_property_id_from_nscsspropertyid {
|
macro_rules! get_property_id_from_nscsspropertyid {
|
||||||
|
@ -715,12 +710,9 @@ pub extern "C" fn Servo_ParseProperty(property: *const nsACString, value: *const
|
||||||
|
|
||||||
match ParsedDeclaration::parse(id, &context, &mut Parser::new(value), false) {
|
match ParsedDeclaration::parse(id, &context, &mut Parser::new(value), false) {
|
||||||
Ok(parsed) => {
|
Ok(parsed) => {
|
||||||
let mut declarations = Vec::new();
|
let mut block = PropertyDeclarationBlock::new();
|
||||||
parsed.expand(|d| declarations.push((d, Importance::Normal)));
|
parsed.expand(|d| block.push(d, Importance::Normal));
|
||||||
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
Arc::new(RwLock::new(block)).into_strong()
|
||||||
declarations: declarations,
|
|
||||||
important_count: 0,
|
|
||||||
})).into_strong()
|
|
||||||
}
|
}
|
||||||
Err(_) => RawServoDeclarationBlockStrong::null()
|
Err(_) => RawServoDeclarationBlockStrong::null()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue