Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upAdd lots of Arc’s in style, and prepare for using DOMRefCell #13134
Conversation
`@charset` rules are not reflected in CSSOM.
`Stylist` contains separate hashmaps for important and normal declarations, but typically a given block only contains declarations of one importance. Before this commit, there is an optimization where a `PropertyDeclarationBlock` is only inserted in the corresponding map if it has a non-zero number of declaration of a given importance. With CSSOM, `PropertyDeclarationBlock` is gonna have interior mutability: the importance (priority) of a declaration could change. This optimization would become incorrect when the block is missing in a hashmap where it should be. This commits removes the original optimization, and replaces it with a slightly weaker one: if a block doesn’t have any declaration with the importance we’re cascading for, skip selector matching.
|
@bors-servo try |
Add lots of Arc’s in style, and prepare for using DOMRefCell <!-- Please describe your changes on the following line: --> `DOMRefCell` usage is not there year because of thread-safety questions, but I have this much already that I’d like to land before it bitrots. r? @emilio --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require new tests because refactor <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13134) <!-- Reviewable:end -->
| @@ -330,7 +330,7 @@ impl LayoutElementHelpers for LayoutJS<Element> { | |||
| fn from_declaration(rule: PropertyDeclaration) -> DeclarationBlock { | |||
| DeclarationBlock::from_declarations( | |||
| Arc::new(PropertyDeclarationBlock { | |||
| declarations: Arc::new(vec![(rule, Importance::Normal)]), | |||
This comment has been minimized.
This comment has been minimized.
| unsafe { transmute(&declarations.declarations) } | ||
| }) | ||
| let opt_ptr = GeckoDeclarationBlock::with(declarations, |declarations| { | ||
| // Use a raw poointer to extend the lifetime |
This comment has been minimized.
This comment has been minimized.
emilio
Aug 31, 2016
Member
Can you comment here why it's fine? (Basically, because we keep a strong reference to it during all the styling process?)
@upsuper, may you know about a better way of describing this? If so, I'd appreciate leaving a reply here so Simon can include it, or adding it in another patch.
This comment has been minimized.
This comment has been minimized.
SimonSapin
Aug 31, 2016
Author
Member
Well, I don’t know if this is fine! That’s why I was asking about it on IRC. I don’t really understand the lifetime (in the sense of when it is destroyed) of various values here and in HasArcFFI, so I’m assuming that someone did review this code when it landed.
The raw pointer deref is just less wildly dangerous than the unqualified transmute.
| let any_declaration_for_importance = if importance.important() { | ||
| block.important_count > 0 | ||
| } else { | ||
| block.declarations.len() > block.important_count as usize |
This comment has been minimized.
This comment has been minimized.
emilio
Aug 31, 2016
Member
I think block.declarations.len() != block.important_count would be clearer (or maybe adding a helper method to get the normal count?)
This comment has been minimized.
This comment has been minimized.
| @@ -165,39 +165,35 @@ impl Stylist { | |||
| // Take apart the StyleRule into individual Rules and insert | |||
| // them into the SelectorMap of that priority. | |||
| macro_rules! append( | |||
| ($style_rule: ident, $priority: ident, $importance: expr, $count: expr) => { | |||
This comment has been minimized.
This comment has been minimized.
emilio
Aug 31, 2016
Member
Could you add a comment here about why we can't rip this out if we know there are no declarations?
This comment has been minimized.
This comment has been minimized.
SimonSapin
Aug 31, 2016
Author
Member
Now that I think about it, with this change the two SelectorMaps in a given PerOriginSelectorMap become identical… so we don’t need to have two anymore.
I’ll do that in a new commit and add a comment here that we insert empty blocks in case CSSOM adds something to them later.
|
Looks basically great to me. Please add a few comments to avoid people introducing subtle bugs like on the Since I think you're not landing this right now, I'd still like to give another careful look, but this is awesome :-). I'd like @nox or @Ms2ger to sign-off the movement of DOMRefCell (or you to confirm that they're fine with it). |
| @@ -373,7 +369,8 @@ impl Stylist { | |||
| map.user_agent.normal.get_all_matching_rules(element, | |||
| parent_bf, | |||
| applicable_declarations, | |||
| &mut relations); | |||
This comment has been minimized.
This comment has been minimized.
emilio
Aug 31, 2016
Member
Maybe, since each map contains rules for a given importance, the importance could be stored on the map itself?
This comment has been minimized.
This comment has been minimized.
|
@upsuper had a few concerns in terms of how it interacts with the Gecko side, those will need to be discussed before merging, I guess. |
| @@ -356,7 +356,7 @@ pub extern "C" fn Servo_StyleSet_Drop(data: *mut RawServoStyleSet) -> () { | |||
| } | |||
|
|
|||
| pub struct GeckoDeclarationBlock { | |||
| pub declarations: Option<PropertyDeclarationBlock>, | |||
| pub declarations: Option<Arc<PropertyDeclarationBlock>>, | |||
This comment has been minimized.
This comment has been minimized.
upsuper
Aug 31, 2016
Member
I'm concerned about this one. GeckoDeclarationBlock is refcounted in the Gecko side, and I thought the whole point of removing Arc inside PropertyDeclarationBlock is to remove the double indirection that a refcounted object holding another refcounted object while they are expected to have the same lifetime.
Do you have plan to remove this Arc as well, or probably we'd better redisign GeckoDeclarationBlock so that we can refcount PropertyDeclarationBlock from the Gecko side directly? Or do we have to live with the double indirection if both changes are hard?
This comment has been minimized.
This comment has been minimized.
SimonSapin
Aug 31, 2016
Author
Member
Arc<_> is needed somewhere to allow things like Stylist, SelectorMap, and ApplicableDeclarations to reference blocks without copying them.
Before this PR this was Arc<Vec<(PropertyDeclaration, Importance)>> (one of which was a field of PropertyDeclarationBlock). This PR makes it Arc<PropertyDeclarationBlock>, but the plan is to have it pretty soon be Arc<DOMRefCell<PropertyDeclarationBlock>>.
I’m not sure what you mean by refcount from the Gecko side directly, but to deal with Arc<_> from Gecko you need FFI back into Rust to clone or drop it (increment or decrement the refcount). (Unless you want to make assumptions about the memory representation of private implementation details of Arc, but I strongly recommend against that.)
This comment has been minimized.
This comment has been minimized.
upsuper
Aug 31, 2016
Member
Yeah, I mean refcounting via FFI. But it isn't quite realistic either, given there are some additional fields in this struct.
I wonder whether it is feasible to make all those things only hold a immutable reference to PropertyDeclarationBlock, so that we don't need to wrap it with Arc? If not, probably we need to live with the double indirection, then.
This comment has been minimized.
This comment has been minimized.
emilio
Aug 31, 2016
•
Member
I don't think so, I think the double indirection is fine for now. If for some reason it becomes a perf issue we can try to be a bit smarter, maybe conditionally compiling the extra Gecko fields inside PropertyDeclarationBlock, or similar.
Edit: Well, that suggestion doesn't make that much sense, but I think doing the simple thing first, then profiling and refactoring if necessary is better than discussing it without any actual numbers.
|
|
|
@bors-servo: r+ |
|
|
Add lots of Arc’s in style, and prepare for using DOMRefCell <!-- Please describe your changes on the following line: --> `DOMRefCell` usage is not there year because of thread-safety questions, but I have this much already that I’d like to land before it bitrots. r? @emilio --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require new tests because refactor <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13134) <!-- Reviewable:end -->
|
|
highfive
commented
Aug 31, 2016
|
|
@bors-servo retry p=1
|
|
|
|
|
Remove one level of nesting in `Stylist` <!-- Please describe your changes on the following line: --> Since #13134, the "normal" and "important" parts of `Stylist` are identical, so we don’t need to store them twice. r? @emilio --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13179) <!-- Reviewable:end -->
SimonSapin commentedAug 31, 2016
•
edited by larsbergstrom
DOMRefCellusage is not there year because of thread-safety questions, but I have this much already that I’d like to land before it bitrots.r? @emilio
./mach build -ddoes not report any errors./mach test-tidydoes not report any errorsThis change is