Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lots of Arc’s in style, and prepare for using DOMRefCell #13134

Merged
merged 11 commits into from Aug 31, 2016
Merged

Conversation

@SimonSapin
Copy link
Member

SimonSapin commented Aug 31, 2016

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


  • ./mach build -d does not report any errors
  • ./mach test-tidy does not report any errors
  • These changes fix #__ (github issue number if applicable).
  • There are tests for these changes OR
  • These changes do not require new tests because refactor

This change is Reviewable

SimonSapin added 10 commits Aug 23, 2016
`@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.
@SimonSapin
Copy link
Member Author

SimonSapin commented Aug 31, 2016

@bors-servo
Copy link
Contributor

bors-servo commented Aug 31, 2016

Trying commit 7ef4930 with merge 0f4b7b0...

bors-servo added a commit that referenced this pull request Aug 31, 2016
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.

@emilio

emilio Aug 31, 2016

Member

heh, was about to ask for this while reviewing the previous commit.

unsafe { transmute(&declarations.declarations) }
})
let opt_ptr = GeckoDeclarationBlock::with(declarations, |declarations| {
// Use a raw poointer to extend the lifetime

This comment has been minimized.

@emilio

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.

@SimonSapin

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.

@emilio

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.

@SimonSapin

SimonSapin Aug 31, 2016

Author Member

Moved into a pair of methods.

@@ -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.

@emilio

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.

@SimonSapin

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.

@emilio
Copy link
Member

emilio commented Aug 31, 2016

Looks basically great to me. Please add a few comments to avoid people introducing subtle bugs like on the append! macro, and I think you can pretty much r=me.

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.

@emilio

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.

@SimonSapin

SimonSapin Aug 31, 2016

Author Member

It could, but that’s changing (see previous inline comment).

@emilio
Copy link
Member

emilio commented Aug 31, 2016

@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.

@upsuper

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.

@SimonSapin

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.

@upsuper

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.

@emilio

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
Copy link
Contributor

bors-servo commented Aug 31, 2016

@emilio
Copy link
Member

emilio commented Aug 31, 2016

@bors-servo
Copy link
Contributor

bors-servo commented Aug 31, 2016

📌 Commit 95033e1 has been approved by emilio

@bors-servo
Copy link
Contributor

bors-servo commented Aug 31, 2016

Testing commit 95033e1 with merge bbfe38e...

bors-servo added a commit that referenced this pull request Aug 31, 2016
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 -->
@bors-servo
Copy link
Contributor

bors-servo commented Aug 31, 2016

💔 Test failed - linux-rel

@highfive
Copy link

highfive commented Aug 31, 2016

  ▶ FAIL [expected PASS] /css-transforms-1_dev/html/transform-table-007.htm
  └   → /css-transforms-1_dev/html/transform-table-007.htm a5c014b20ef1363bea6f24eda28c7efb7c45698a
/css-transforms-1_dev/html/reference/transform-blank-ref.htm fa6407b1acbbfea27e27061e7d1bdeca98e4a728
Testing a5c014b20ef1363bea6f24eda28c7efb7c45698a == fa6407b1acbbfea27e27061e7d1bdeca98e4a728
@emilio
Copy link
Member

emilio commented Aug 31, 2016

@bors-servo retry p=1

  • #9087, and blocks other PRs
@bors-servo
Copy link
Contributor

bors-servo commented Aug 31, 2016

Previous build results for arm32, arm64, linux-dev, mac-dev-unit, mac-rel-css, mac-rel-wpt, windows-dev are reusable. Rebuilding only linux-rel...

@bors-servo
Copy link
Contributor

bors-servo commented Aug 31, 2016

@bors-servo bors-servo merged commit 95033e1 into master Aug 31, 2016
3 of 4 checks passed
3 of 4 checks passed
dependency-ci Failed dependency checks
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
homu Test successful
Details
@SimonSapin SimonSapin deleted the archery branch Aug 31, 2016
SimonSapin added a commit that referenced this pull request Sep 6, 2016
Since #13134, the "normal" and "important" parts of `Stylist` are identical,
so we don’t need to store them twice.
@SimonSapin SimonSapin mentioned this pull request Sep 6, 2016
3 of 5 tasks complete
bors-servo added a commit that referenced this pull request Sep 6, 2016
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 -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

5 participants
You can’t perform that action at this time.