mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Use dynamically-sized Arcs for Selector.
MozReview-Commit-ID: hq0jYrx8Sg
This commit is contained in:
parent
21448cf266
commit
852efb825f
6 changed files with 29 additions and 340 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2523,6 +2523,7 @@ dependencies = [
|
||||||
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"servo_arc 0.0.1",
|
||||||
"size_of_test 0.0.1",
|
"size_of_test 0.0.1",
|
||||||
"smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
|
@ -28,6 +28,7 @@ cssparser = "0.13.7"
|
||||||
fnv = "1.0"
|
fnv = "1.0"
|
||||||
phf = "0.7.18"
|
phf = "0.7.18"
|
||||||
precomputed-hash = "0.1"
|
precomputed-hash = "0.1"
|
||||||
|
servo_arc = { path = "../servo_arc" }
|
||||||
smallvec = "0.4"
|
smallvec = "0.4"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -1,326 +0,0 @@
|
||||||
/* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
* <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
* option. This file may not be copied, modified, or distributed
|
|
||||||
* except according to those terms.
|
|
||||||
*
|
|
||||||
* See the COPYRIGHT file at the top-level directory of this distribution */
|
|
||||||
//! A thread-safe reference-counted slice type.
|
|
||||||
//!
|
|
||||||
//! Forked from https://github.com/huonw/shared_slice , which doesn't work on
|
|
||||||
//! rust stable.
|
|
||||||
|
|
||||||
use std::{cmp, fmt, ops};
|
|
||||||
use std::hash::{Hash, Hasher};
|
|
||||||
use std::sync::{Arc, Weak};
|
|
||||||
|
|
||||||
|
|
||||||
/// A reference-counted slice type.
|
|
||||||
pub struct ArcSlice<T> {
|
|
||||||
data: *const [T],
|
|
||||||
counts: Arc<Box<[T]>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl<T: Send + Sync> Send for ArcSlice<T> {}
|
|
||||||
unsafe impl<T: Send + Sync> Sync for ArcSlice<T> {}
|
|
||||||
|
|
||||||
/// A non-owning reference-counted slice type.
|
|
||||||
///
|
|
||||||
/// This is to `ArcSlice` as `std::sync::Weak` is to `std::sync::Arc`, and
|
|
||||||
/// allows one to have cyclic references without stopping memory from
|
|
||||||
/// being deallocated.
|
|
||||||
pub struct WeakSlice<T> {
|
|
||||||
data: *const [T],
|
|
||||||
counts: Weak<Box<[T]>>,
|
|
||||||
}
|
|
||||||
unsafe impl<T: Send + Sync> Send for WeakSlice<T> {}
|
|
||||||
unsafe impl<T: Send + Sync> Sync for WeakSlice<T> {}
|
|
||||||
|
|
||||||
impl<T> ArcSlice<T> {
|
|
||||||
/// Construct a new `ArcSlice` containing the elements of `slice`.
|
|
||||||
///
|
|
||||||
/// This reuses the allocation of `slice`.
|
|
||||||
pub fn new(slice: Box<[T]>) -> ArcSlice<T> {
|
|
||||||
ArcSlice {
|
|
||||||
data: &*slice,
|
|
||||||
counts: Arc::new(slice),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Downgrade self into a weak slice.
|
|
||||||
pub fn downgrade(&self) -> WeakSlice<T> {
|
|
||||||
WeakSlice {
|
|
||||||
data: self.data,
|
|
||||||
counts: Arc::downgrade(&self.counts)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct a new `ArcSlice` that only points to elements at
|
|
||||||
/// indices `lo` (inclusive) through `hi` (exclusive).
|
|
||||||
///
|
|
||||||
/// This consumes `self` to avoid unnecessary reference-count
|
|
||||||
/// modifications. Use `.clone()` if it is necessary to refer to
|
|
||||||
/// `self` after calling this.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if `lo > hi` or if either are strictly greater than
|
|
||||||
/// `self.len()`.
|
|
||||||
pub fn slice(mut self, lo: usize, hi: usize) -> ArcSlice<T> {
|
|
||||||
self.data = &self[lo..hi];
|
|
||||||
self
|
|
||||||
}
|
|
||||||
/// Construct a new `ArcSlice` that only points to elements at
|
|
||||||
/// indices up to `hi` (exclusive).
|
|
||||||
///
|
|
||||||
/// This consumes `self` to avoid unnecessary reference-count
|
|
||||||
/// modifications. Use `.clone()` if it is necessary to refer to
|
|
||||||
/// `self` after calling this.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if `hi > self.len()`.
|
|
||||||
pub fn slice_to(self, hi: usize) -> ArcSlice<T> {
|
|
||||||
self.slice(0, hi)
|
|
||||||
}
|
|
||||||
/// Construct a new `ArcSlice` that only points to elements at
|
|
||||||
/// indices starting at `lo` (inclusive).
|
|
||||||
///
|
|
||||||
/// This consumes `self` to avoid unnecessary reference-count
|
|
||||||
/// modifications. Use `.clone()` if it is necessary to refer to
|
|
||||||
/// `self` after calling this.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if `lo > self.len()`.
|
|
||||||
pub fn slice_from(self, lo: usize) -> ArcSlice<T> {
|
|
||||||
let hi = self.len();
|
|
||||||
self.slice(lo, hi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Clone for ArcSlice<T> {
|
|
||||||
fn clone(&self) -> ArcSlice<T> {
|
|
||||||
ArcSlice {
|
|
||||||
data: self.data,
|
|
||||||
counts: self.counts.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> ops::Deref for ArcSlice<T> {
|
|
||||||
type Target = [T];
|
|
||||||
fn deref<'a>(&'a self) -> &'a [T] {
|
|
||||||
unsafe { &*self.data }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> AsRef<[T]> for ArcSlice<T> {
|
|
||||||
fn as_ref(&self) -> &[T] { &**self }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: PartialEq> PartialEq for ArcSlice<T> {
|
|
||||||
fn eq(&self, other: &ArcSlice<T>) -> bool { **self == **other }
|
|
||||||
fn ne(&self, other: &ArcSlice<T>) -> bool { **self != **other }
|
|
||||||
}
|
|
||||||
impl<T: Eq> Eq for ArcSlice<T> {}
|
|
||||||
|
|
||||||
impl<T: PartialOrd> PartialOrd for ArcSlice<T> {
|
|
||||||
fn partial_cmp(&self, other: &ArcSlice<T>) -> Option<cmp::Ordering> {
|
|
||||||
(**self).partial_cmp(&**other)
|
|
||||||
}
|
|
||||||
fn lt(&self, other: &ArcSlice<T>) -> bool { **self < **other }
|
|
||||||
fn le(&self, other: &ArcSlice<T>) -> bool { **self <= **other }
|
|
||||||
fn gt(&self, other: &ArcSlice<T>) -> bool { **self > **other }
|
|
||||||
fn ge(&self, other: &ArcSlice<T>) -> bool { **self >= **other }
|
|
||||||
}
|
|
||||||
impl<T: Ord> Ord for ArcSlice<T> {
|
|
||||||
fn cmp(&self, other: &ArcSlice<T>) -> cmp::Ordering { (**self).cmp(&**other) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Hash> Hash for ArcSlice<T> {
|
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
||||||
Hash::hash(&**self, state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: fmt::Debug> fmt::Debug for ArcSlice<T> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
fmt::Debug::fmt(&**self, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> WeakSlice<T> {
|
|
||||||
/// Attempt to upgrade `self` to a strongly-counted `ArcSlice`.
|
|
||||||
///
|
|
||||||
/// Returns `None` if this is not possible (the data has already
|
|
||||||
/// been freed).
|
|
||||||
pub fn upgrade(&self) -> Option<ArcSlice<T>> {
|
|
||||||
self.counts.upgrade().map(|counts| {
|
|
||||||
ArcSlice {
|
|
||||||
data: self.data,
|
|
||||||
counts: counts
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use std::cell::Cell;
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use super::{ArcSlice, WeakSlice};
|
|
||||||
#[test]
|
|
||||||
fn clone() {
|
|
||||||
let x = ArcSlice::new(Box::new([Cell::new(false)]));
|
|
||||||
let y = x.clone();
|
|
||||||
|
|
||||||
assert_eq!(x[0].get(), false);
|
|
||||||
assert_eq!(y[0].get(), false);
|
|
||||||
|
|
||||||
x[0].set(true);
|
|
||||||
assert_eq!(x[0].get(), true);
|
|
||||||
assert_eq!(y[0].get(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_upgrade_downgrade() {
|
|
||||||
let x = ArcSlice::new(Box::new([1]));
|
|
||||||
let y: WeakSlice<_> = x.downgrade();
|
|
||||||
|
|
||||||
assert_eq!(y.upgrade(), Some(x.clone()));
|
|
||||||
|
|
||||||
drop(x);
|
|
||||||
|
|
||||||
assert!(y.upgrade().is_none())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_total_cmp() {
|
|
||||||
let x = ArcSlice::new(Box::new([1, 2, 3]));
|
|
||||||
let y = ArcSlice::new(Box::new([1, 2, 3]));
|
|
||||||
let z = ArcSlice::new(Box::new([1, 2, 4]));
|
|
||||||
|
|
||||||
assert_eq!(x, x);
|
|
||||||
assert_eq!(x, y);
|
|
||||||
assert!(x != z);
|
|
||||||
assert!(y != z);
|
|
||||||
|
|
||||||
assert!(x < z);
|
|
||||||
assert!(x <= z);
|
|
||||||
assert!(!(x > z));
|
|
||||||
assert!(!(x >= z));
|
|
||||||
|
|
||||||
assert!(!(z < x));
|
|
||||||
assert!(!(z <= x));
|
|
||||||
assert!(z > x);
|
|
||||||
assert!(z >= x);
|
|
||||||
|
|
||||||
assert_eq!(x.partial_cmp(&x), Some(Ordering::Equal));
|
|
||||||
assert_eq!(x.partial_cmp(&y), Some(Ordering::Equal));
|
|
||||||
assert_eq!(x.partial_cmp(&z), Some(Ordering::Less));
|
|
||||||
assert_eq!(z.partial_cmp(&y), Some(Ordering::Greater));
|
|
||||||
|
|
||||||
assert_eq!(x.cmp(&x), Ordering::Equal);
|
|
||||||
assert_eq!(x.cmp(&y), Ordering::Equal);
|
|
||||||
assert_eq!(x.cmp(&z), Ordering::Less);
|
|
||||||
assert_eq!(z.cmp(&y), Ordering::Greater);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_partial_cmp() {
|
|
||||||
use std::f64;
|
|
||||||
let x = ArcSlice::new(Box::new([1.0, f64::NAN]));
|
|
||||||
let y = ArcSlice::new(Box::new([1.0, f64::NAN]));
|
|
||||||
let z = ArcSlice::new(Box::new([2.0, f64::NAN]));
|
|
||||||
let w = ArcSlice::new(Box::new([f64::NAN, 1.0]));
|
|
||||||
assert!(!(x == y));
|
|
||||||
assert!(x != y);
|
|
||||||
|
|
||||||
assert!(!(x < y));
|
|
||||||
assert!(!(x <= y));
|
|
||||||
assert!(!(x > y));
|
|
||||||
assert!(!(x >= y));
|
|
||||||
|
|
||||||
assert!(x < z);
|
|
||||||
assert!(x <= z);
|
|
||||||
assert!(!(x > z));
|
|
||||||
assert!(!(x >= z));
|
|
||||||
|
|
||||||
assert!(!(z < w));
|
|
||||||
assert!(!(z <= w));
|
|
||||||
assert!(!(z > w));
|
|
||||||
assert!(!(z >= w));
|
|
||||||
|
|
||||||
assert_eq!(x.partial_cmp(&x), None);
|
|
||||||
assert_eq!(x.partial_cmp(&y), None);
|
|
||||||
assert_eq!(x.partial_cmp(&z), Some(Ordering::Less));
|
|
||||||
assert_eq!(z.partial_cmp(&x), Some(Ordering::Greater));
|
|
||||||
|
|
||||||
assert_eq!(x.partial_cmp(&w), None);
|
|
||||||
assert_eq!(y.partial_cmp(&w), None);
|
|
||||||
assert_eq!(z.partial_cmp(&w), None);
|
|
||||||
assert_eq!(w.partial_cmp(&w), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_show() {
|
|
||||||
let x = ArcSlice::new(Box::new([1, 2]));
|
|
||||||
assert_eq!(format!("{:?}", x), "[1, 2]");
|
|
||||||
|
|
||||||
let y: ArcSlice<i32> = ArcSlice::new(Box::new([]));
|
|
||||||
assert_eq!(format!("{:?}", y), "[]");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_slice() {
|
|
||||||
let x = ArcSlice::new(Box::new([1, 2, 3]));
|
|
||||||
let real = [1, 2, 3];
|
|
||||||
for i in 0..3 + 1 {
|
|
||||||
for j in i..3 + 1 {
|
|
||||||
let slice: ArcSlice<_> = x.clone().slice(i, j);
|
|
||||||
assert_eq!(&*slice, &real[i..j]);
|
|
||||||
}
|
|
||||||
assert_eq!(&*x.clone().slice_to(i), &real[..i]);
|
|
||||||
assert_eq!(&*x.clone().slice_from(i), &real[i..]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_send_sync() {
|
|
||||||
fn assert_send<T: Send>() {}
|
|
||||||
fn assert_sync<T: Send>() {}
|
|
||||||
|
|
||||||
assert_send::<ArcSlice<u8>>();
|
|
||||||
assert_sync::<ArcSlice<u8>>();
|
|
||||||
assert_send::<WeakSlice<u8>>();
|
|
||||||
assert_sync::<WeakSlice<u8>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_drop() {
|
|
||||||
let drop_flag = Arc::new(Mutex::new(0));
|
|
||||||
struct Foo(Arc<Mutex<i32>>);
|
|
||||||
|
|
||||||
impl Drop for Foo {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
let mut n = self.0.lock().unwrap();
|
|
||||||
*n += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let whole = ArcSlice::new(Box::new([Foo(drop_flag.clone()), Foo(drop_flag.clone())]));
|
|
||||||
|
|
||||||
drop(whole);
|
|
||||||
assert_eq!(*drop_flag.lock().unwrap(), 2);
|
|
||||||
|
|
||||||
*drop_flag.lock().unwrap() = 0;
|
|
||||||
|
|
||||||
let whole = ArcSlice::new(Box::new([Foo(drop_flag.clone()), Foo(drop_flag.clone())]));
|
|
||||||
let part = whole.slice(1, 2);
|
|
||||||
drop(part);
|
|
||||||
assert_eq!(*drop_flag.lock().unwrap(), 2);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,9 +9,9 @@ extern crate fnv;
|
||||||
extern crate phf;
|
extern crate phf;
|
||||||
extern crate precomputed_hash;
|
extern crate precomputed_hash;
|
||||||
#[cfg(test)] #[macro_use] extern crate size_of_test;
|
#[cfg(test)] #[macro_use] extern crate size_of_test;
|
||||||
|
extern crate servo_arc;
|
||||||
extern crate smallvec;
|
extern crate smallvec;
|
||||||
|
|
||||||
pub mod arcslice;
|
|
||||||
pub mod attr;
|
pub mod attr;
|
||||||
pub mod bloom;
|
pub mod bloom;
|
||||||
pub mod matching;
|
pub mod matching;
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* 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 arcslice::ArcSlice;
|
|
||||||
use attr::{AttrSelectorWithNamespace, ParsedAttrSelectorOperation, AttrSelectorOperator};
|
use attr::{AttrSelectorWithNamespace, ParsedAttrSelectorOperation, AttrSelectorOperator};
|
||||||
use attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE, NamespaceConstraint};
|
use attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE, NamespaceConstraint};
|
||||||
use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter};
|
use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter};
|
||||||
use precomputed_hash::PrecomputedHash;
|
use precomputed_hash::PrecomputedHash;
|
||||||
|
use servo_arc::{Arc, HeaderSlice};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::{Borrow, Cow};
|
use std::borrow::{Borrow, Cow};
|
||||||
|
@ -302,6 +302,19 @@ pub fn namespace_empty_string<Impl: SelectorImpl>() -> Impl::NamespaceUrl {
|
||||||
Impl::NamespaceUrl::default()
|
Impl::NamespaceUrl::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
struct SpecificityAndFlags(u32);
|
||||||
|
|
||||||
|
impl SpecificityAndFlags {
|
||||||
|
fn specificity(&self) -> u32 {
|
||||||
|
self.0 & !HAS_PSEUDO_BIT
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_pseudo_element(&self) -> bool {
|
||||||
|
(self.0 & HAS_PSEUDO_BIT) != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A Selector stores a sequence of simple selectors and combinators. The
|
/// A Selector stores a sequence of simple selectors and combinators. The
|
||||||
/// iterator classes allow callers to iterate at either the raw sequence level or
|
/// iterator classes allow callers to iterate at either the raw sequence level or
|
||||||
/// at the level of sequences of simple selectors separated by combinators. Most
|
/// at the level of sequences of simple selectors separated by combinators. Most
|
||||||
|
@ -311,15 +324,15 @@ pub fn namespace_empty_string<Impl: SelectorImpl>() -> Impl::NamespaceUrl {
|
||||||
/// canonical iteration order is right-to-left (selector matching order). The
|
/// canonical iteration order is right-to-left (selector matching order). The
|
||||||
/// iterators abstract over these details.
|
/// iterators abstract over these details.
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
pub struct Selector<Impl: SelectorImpl>(ArcSlice<Component<Impl>>, u32);
|
pub struct Selector<Impl: SelectorImpl>(Arc<HeaderSlice<SpecificityAndFlags, [Component<Impl>]>>);
|
||||||
|
|
||||||
impl<Impl: SelectorImpl> Selector<Impl> {
|
impl<Impl: SelectorImpl> Selector<Impl> {
|
||||||
pub fn specificity(&self) -> u32 {
|
pub fn specificity(&self) -> u32 {
|
||||||
self.1 & !HAS_PSEUDO_BIT
|
self.0.header.specificity()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_pseudo_element(&self) -> bool {
|
pub fn has_pseudo_element(&self) -> bool {
|
||||||
(self.1 & HAS_PSEUDO_BIT) != 0
|
self.0.header.has_pseudo_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pseudo_element(&self) -> Option<&Impl::PseudoElement> {
|
pub fn pseudo_element(&self) -> Option<&Impl::PseudoElement> {
|
||||||
|
@ -362,8 +375,7 @@ impl<Impl: SelectorImpl> Selector<Impl> {
|
||||||
|
|
||||||
pub fn iter_from(&self, offset: usize) -> SelectorIter<Impl> {
|
pub fn iter_from(&self, offset: usize) -> SelectorIter<Impl> {
|
||||||
// Note: selectors are stored left-to-right but logical order is right-to-left.
|
// Note: selectors are stored left-to-right but logical order is right-to-left.
|
||||||
let slice = self.0.as_ref();
|
let iter = self.0.slice[..(self.0.slice.len() - offset)].iter().rev();
|
||||||
let iter = slice[..(slice.len() - offset)].iter().rev();
|
|
||||||
SelectorIter {
|
SelectorIter {
|
||||||
iter: iter,
|
iter: iter,
|
||||||
next_combinator: None,
|
next_combinator: None,
|
||||||
|
@ -379,12 +391,13 @@ impl<Impl: SelectorImpl> Selector<Impl> {
|
||||||
/// Returns an iterator over the entire sequence of simple selectors and combinators,
|
/// Returns an iterator over the entire sequence of simple selectors and combinators,
|
||||||
/// from left to right.
|
/// from left to right.
|
||||||
pub fn iter_raw_rev(&self) -> slice::Iter<Component<Impl>> {
|
pub fn iter_raw_rev(&self) -> slice::Iter<Component<Impl>> {
|
||||||
self.0.iter()
|
self.0.slice.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a Selector from a vec of Components. Used in tests.
|
/// Creates a Selector from a vec of Components. Used in tests.
|
||||||
pub fn from_vec(vec: Vec<Component<Impl>>, specificity_and_flags: u32) -> Self {
|
pub fn from_vec(vec: Vec<Component<Impl>>, specificity_and_flags: u32) -> Self {
|
||||||
Selector(ArcSlice::new(vec.into_boxed_slice()), specificity_and_flags)
|
let spec = SpecificityAndFlags(specificity_and_flags);
|
||||||
|
Selector(Arc::from_header_and_iter(spec, vec.into_iter()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -985,15 +998,15 @@ fn parse_complex_selector<P, Impl>(
|
||||||
sequence.push(Component::Combinator(combinator));
|
sequence.push(Component::Combinator(combinator));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut specificity = specificity(SelectorIter {
|
let mut spec = SpecificityAndFlags(specificity(SelectorIter {
|
||||||
iter: sequence.iter().rev(),
|
iter: sequence.iter().rev(),
|
||||||
next_combinator: None,
|
next_combinator: None,
|
||||||
});
|
}));
|
||||||
if parsed_pseudo_element {
|
if parsed_pseudo_element {
|
||||||
specificity |= HAS_PSEUDO_BIT;
|
spec.0 |= HAS_PSEUDO_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
let complex = Selector(ArcSlice::new(sequence.into_vec().into_boxed_slice()), specificity);
|
let complex = Selector(Arc::from_header_and_iter(spec, sequence.into_iter()));
|
||||||
Ok(complex)
|
Ok(complex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ fn size_of_selectors_dummy_types() {
|
||||||
// The size of this is critical to performance on the bloom-basic microbenchmark.
|
// The size of this is critical to performance on the bloom-basic microbenchmark.
|
||||||
// When iterating over a large Rule array, we want to be able to fast-reject
|
// When iterating over a large Rule array, we want to be able to fast-reject
|
||||||
// selectors (with the inline hashes) with as few cache misses as possible.
|
// selectors (with the inline hashes) with as few cache misses as possible.
|
||||||
size_of_test!(test_size_of_rule, style::stylist::Rule, 64);
|
size_of_test!(test_size_of_rule, style::stylist::Rule, 48);
|
||||||
|
|
||||||
size_of_test!(test_size_of_property_declaration, style::properties::PropertyDeclaration, 32);
|
size_of_test!(test_size_of_property_declaration, style::properties::PropertyDeclaration, 32);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue