Closed
Bug 822906
Opened 12 years ago
Closed 12 years ago
Crash [@ mozilla::css::OverflowChangedTracker::Flush] with table and transform
Categories
(Core :: Layout, defect)
Tracking
()
VERIFIED
FIXED
mozilla21
Tracking | Status | |
---|---|---|
firefox19 | + | unaffected |
firefox20 | + | verified |
firefox21 | --- | verified |
People
(Reporter: jruderman, Assigned: mattwoodrow)
References
Details
(Keywords: crash, regression, testcase)
Crash Data
Attachments
(4 files, 5 obsolete files)
376 bytes,
application/xhtml+xml
|
Details | |
4.43 KB,
text/plain
|
Details | |
6.44 KB,
patch
|
roc
:
review+
akeybl
:
approval-mozilla-aurora+
akeybl
:
approval-mozilla-beta-
|
Details | Diff | Splinter Review |
8.05 KB,
patch
|
Waldo
:
review+
|
Details | Diff | Splinter Review |
No description provided.
Reporter | ||
Comment 1•12 years ago
|
||
Reporter | ||
Comment 2•12 years ago
|
||
Nightly: bp-08da0359-f8e6-419c-ab9d-6f4cc2121219
(Btw, this crash signature is #86 for Nightly. But I don't know if my testcase demonstrates the same bug that other people are hitting.)
![]() |
||
Comment 3•12 years ago
|
||
bp-66ded069-f032-49e8-b237-e268f2121219
Regression window(m-c)
Good:
http://hg.mozilla.org/mozilla-central/rev/c6970a82a686
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20121210 Firefox/20.0 ID:20121210104701
Bad:
http://hg.mozilla.org/mozilla-central/rev/00e26dece6ea
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20121210 Firefox/20.0 ID:20121210105701
Pushlog:
http://hg.mozilla.org/mozilla-central/pushloghtml?fromchange=c6970a82a686&tochange=00e26dece6ea
Regression window(m-c)
Good:
http://hg.mozilla.org/integration/mozilla-inbound/rev/fe0abb4decb6
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20121209 Firefox/20.0 ID:20121209173350
Bad:
http://hg.mozilla.org/integration/mozilla-inbound/rev/0319dd845d53
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20121209 Firefox/20.0 ID:20121209183350
Pushlog:
http://hg.mozilla.org/integration/mozilla-inbound/pushloghtml?fromchange=fe0abb4decb6&tochange=0319dd845d53
Suspected: Bug 815666
tracking-firefox20:
--- → ?
OS: Mac OS X → All
![]() |
||
Updated•12 years ago
|
Crash Signature: [@ mozilla::css::OverflowChangedTracker::Flush] → [@ mozilla::css::OverflowChangedTracker::Flush]
[@ mozilla::css::OverflowChangedTracker::Flush()]
Assignee | ||
Comment 4•12 years ago
|
||
Looks like something is updating the overflow of a frame, and then we delete the frame in the same set of style changes.
Attachment #693707 -
Flags: review?(roc)
Comment on attachment 693707 [details] [diff] [review]
Use nsWeakFrame
Review of attachment 693707 [details] [diff] [review]:
-----------------------------------------------------------------
I don't think nsWeakFrame scales to large numbers of frames so we probably don't want to use it here.
Could you be more specific about what exactly happens here? Is something doing frame reconstruction for frames that are in OverflowChangedTracker? Perhaps we should explicitly notify the OverflowChangedTracker to delete entries for all descendants of a given frame?
Assignee | ||
Comment 6•12 years ago
|
||
Yes, that's exactly what happens. Seems like a reasonable approach.
My first ever use case for 'mutable'! I think it's actually legitimate in this case.
Attachment #693707 -
Attachment is obsolete: true
Attachment #693707 -
Flags: review?(roc)
Attachment #693744 -
Flags: review?(roc)
Comment on attachment 693744 [details] [diff] [review]
Remove deleted frames
Review of attachment 693744 [details] [diff] [review]:
-----------------------------------------------------------------
This seems a bit scary performance-wise ... for every reconstructed frame, we iterate over all the entries in the tracker. That could be O(N^2) in the number of restyled frames.
It seems to me that it would be safer to iterate through all the descendants of the reconstructed frame, checking each one to see if it's in the tracker. Each check is O(log N), so that would be O(D log N) where D is the number of frames we're going to destroy (so we're already doing O(D) work at least).
Also I'm pretty sure you can remove entries from the heap in O(log N) time.
Updated•12 years ago
|
status-firefox19:
--- → unaffected
status-firefox20:
--- → affected
Keywords: regression
Hardware: x86_64 → All
Version: Trunk → 20 Branch
Updated•12 years ago
|
Crash Signature: [@ mozilla::css::OverflowChangedTracker::Flush]
[@ mozilla::css::OverflowChangedTracker::Flush()] → [@ mozilla::css::OverflowChangedTracker::Flush ]
[@ mozilla::css::OverflowChangedTracker::Flush() ]
Assignee | ||
Comment 8•12 years ago
|
||
I guess so, I assumed that the number of reconstructed frames would be small, whereas the number of descendants could be a lot if we reconstruct of the root frames for a document.
I would hesitate to guess. I think we should plan for the worst case.
If you're reconstructing the root frame for a document then I guess we shouldn't have any entries in OverflowChangedTracker. We can skip traversing descendants if OverflowChangedTracker is already empty or becomes so during traversal.
Assignee | ||
Comment 10•12 years ago
|
||
Attachment #693744 -
Attachment is obsolete: true
Attachment #693744 -
Flags: review?(roc)
Attachment #694263 -
Flags: review?(roc)
Comment on attachment 694263 [details] [diff] [review]
Remove deleted frames v2
Review of attachment 694263 [details] [diff] [review]:
-----------------------------------------------------------------
::: xpcom/glue/nsTPriorityQueue.h
@@ +108,4 @@
>
> + bool Remove(const T& aElement)
> + {
> + size_type index = mElements.IndexOf(aElement);
This is an O(N) lookup.
Actually I think I was wrong :-(. We can't search the heap in O(log N) time :-(.
@@ +137,5 @@
> }
>
> protected:
> + T RemoveIndex(size_type aIndex)
> + {
This should be an nsTArray method.
So I think the most straightforward approach here would be to use a balanced binary tree, which gives us add/remove/search/find-min all in O(log N) time. JS has a SplayTree implementation you could steal.
Assignee | ||
Comment 13•12 years ago
|
||
Takes SplayTree from js, and adds it to mfbt. I also changed the allocation code to match what LinkedList.h does.
Seems to work, probably needs more cleaning up to pass review for mfbt/ though.
Comment 14•12 years ago
|
||
This is the top crasher in my fuzzing as well, will be great to see it go away.
Comment 15•12 years ago
|
||
(In reply to Abhishek Arya from comment #14)
> This is the top crasher in my fuzzing as well, will be great to see it go
> away.
Not the right time for this comment. Enjoy the holidays!!
Updated•12 years ago
|
Updated•12 years ago
|
Assignee: nobody → matt.woodrow
Comment 16•12 years ago
|
||
(In reply to Matt Woodrow (:mattwoodrow) from comment #13)
> Created attachment 694697 [details] [diff] [review]
> Removed deleted frames v3
>
> Takes SplayTree from js, and adds it to mfbt. I also changed the allocation
> code to match what LinkedList.h does.
>
> Seems to work, probably needs more cleaning up to pass review for mfbt/
> though.
Any updates here? Firefox 20 is now on Aurora, and bug 815666 is blocked on uplift by this.
Assignee | ||
Comment 17•12 years ago
|
||
Takes the SplayTree.h file from js/src/ds and converts it to match the style used by LinkedList.h
Attachment #694263 -
Attachment is obsolete: true
Attachment #694697 -
Attachment is obsolete: true
Attachment #694263 -
Flags: review?(roc)
Attachment #699501 -
Flags: review?(jwalden+bmo)
Assignee | ||
Comment 18•12 years ago
|
||
Attachment #699503 -
Flags: review?(roc)
Attachment #699503 -
Flags: review?(roc) → review+
Comment 19•12 years ago
|
||
Comment on attachment 699501 [details] [diff] [review]
Add SplayTree to mfbt
Review of attachment 699501 [details] [diff] [review]:
-----------------------------------------------------------------
No comments on the correctness of this implementation -- I didn't look, haven't taken the time to grok splay trees previously, and assume this was mostly copied from the JS implementation anyway, so correctness concerns should have been dealt with already, inductively.
::: mfbt/SplayTree.h
@@ +3,5 @@
> + *
> + * This Source Code Form is subject to the terms of the Mozilla Public
> + * 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/. */
> +
Add a one-line description comment to show up in MXR listings, perhaps describing what a splay tree does, since SplayTree.h is obviously going to contain a splay tree implementation ;-) :
/* A sorted tree with optimal access times, where recently-accessed elements are faster to access again. */
@@ +7,5 @@
> +
> +#ifndef mozilla_SplayTree_h_
> +#define mozilla_SplayTree_h_
> +
> +#include "mozilla/Assertions.h"
Add a #include "mozilla/NullPtr.h" here, and use nullptr instead of NULL throughout here. (mfbt hasn't yet switched to nullptr totally, but it will.)
@@ +9,5 @@
> +#define mozilla_SplayTree_h_
> +
> +#include "mozilla/Assertions.h"
> +
> +#ifdef __cplusplus
You can get rid of this; we had it in the past mostly for JS's sake, when jsapi.h was C-compatible. Now that we've dropped it I don't believe there's reason to #ifdef __cplusplus for C++-specific stuff.
@@ +13,5 @@
> +#ifdef __cplusplus
> +
> +namespace mozilla {
> +
> +template <class T, class C>
template<typename T, class Comparator> (typename because it's not a misnomer when T isn't a class, Comparator for more clarity)
@@ +29,5 @@
> + {}
> +
> +private:
> +
> + T *left, *right, *parent;
These should be |T* foo| and all on separate lines. Really, every place that has |T *foo| should be |T* foo| (and same for &, so |T& bar| rather than |T &bar|. I'd suggest searching for " *" and " &" to find all the places to adjust.
@@ +30,5 @@
> +
> +private:
> +
> + T *left, *right, *parent;
> +};
Indentation should look like this:
class SplayTreeNode
{
public:
...
...
private:
...
...
...
};
@@ +36,5 @@
> +
> +/*
> + * Class which represents a splay tree with nodes allocated from a LifoAlloc.
> + * Splay trees are balanced binary search trees for which search, insert and
> + * remove are all amortized O(log n).
That comment doesn't really capture the cases where play trees can be useful -- it should say something additional like ", but where accessing a node makes it faster to access that node in the future."
@@ +39,5 @@
> + * Splay trees are balanced binary search trees for which search, insert and
> + * remove are all amortized O(log n).
> + *
> + * T indicates the type of tree elements, C must have a static
> + * compare(const T&, const T&) method ordering the elements. As for LifoAlloc
Please note that compare() must be side-effect-free. (Because we're using it in assertions -- but don't put that in the comment, no reason the user has to know that.)
@@ +40,5 @@
> + * remove are all amortized O(log n).
> + *
> + * T indicates the type of tree elements, C must have a static
> + * compare(const T&, const T&) method ordering the elements. As for LifoAlloc
> + * objects, T objects stored in the tree will not be explicitly destroyed.
These comments still mention the LifoAlloc bits from the JS version of this. I guess just remove the last sentence of the second paragraph, and remove "with...LifoAlloc" from the first paragraph.
@@ +45,5 @@
> + */
> +template <class T, class C>
> +class SplayTree
> +{
> + T *root, *freeList;
As a corollary to the *-goes-by-type rule, these should be two separate declarations. Same a couple other places.
@@ +48,5 @@
> +{
> + T *root, *freeList;
> +
> + SplayTree(const SplayTree &) MOZ_DELETE;
> + SplayTree &operator=(const SplayTree &) MOZ_DELETE;
Make the operator= return void -- that'll make accidental assignments into compile errors even when MOZ_DELETE doesn't expand to anything, I think.
Also, move these deleted methods to the end of the class to get them out of the way for the interested reader.
@@ +51,5 @@
> + SplayTree(const SplayTree &) MOZ_DELETE;
> + SplayTree &operator=(const SplayTree &) MOZ_DELETE;
> +
> + public:
> +
No blank line needed at the start of a public:/private:/protected: section.
@@ +54,5 @@
> + public:
> +
> + SplayTree()
> + : root(NULL), freeList(NULL)
> + {}
You could make this whole constructor a one-liner if you wanted, doesn't really matter, tho.
@@ +57,5 @@
> + : root(NULL), freeList(NULL)
> + {}
> +
> + bool empty() const {
> + return !root;
The contents of methods should be two-space-indented, throughout the whole patch. Right now indentation everywhere's pretty inconsistent.
@@ +63,5 @@
> +
> + bool contains(const T &v)
> + {
> + if (!root)
> + return false;
Let's make this:
if (empty())
return false;
for a little more clarity. And since this special-ish case is logically separate from the rest of the method, let's add a blank line between this and the rest.
@@ +69,5 @@
> + splay(last);
> + checkCoherency(root, NULL);
> + if (C::compare(v, *last) == 0) {
> + return true;
> + }
mfbt doesn't brace single-line anything (at least, not unless the head -- the condition of the if, the stuff in parens for a for-loop, etc. -- occupies multiple lines). (Well, except do-while loops, because who doesn't brace those?)
@@ +70,5 @@
> + checkCoherency(root, NULL);
> + if (C::compare(v, *last) == 0) {
> + return true;
> + }
> + return false;
return Comparator::compare(v, *last) == 0;
@@ +83,5 @@
> + T *last = lookup(*v);
> + int cmp = C::compare(*v, *last);
> +
> + // Don't tolerate duplicate elements.
> + MOZ_ASSERT(cmp);
MOZ_ASSERT(cmp != 0, "Duplicate elements are not allowed.");
Or perhaps, since this is really a precondition, we should make it
MOZ_ASSERT(!contains(*v), "Duplicate elements are not allowed.");
and put it right at the start of insert(). Actually, yeah, that's better -- do that.
@@ +85,5 @@
> +
> + // Don't tolerate duplicate elements.
> + MOZ_ASSERT(cmp);
> +
> + T *&parentPointer = (cmp < 0) ? last->left : last->right;
It's less obvious there's mutation going on when a reference is assigned to, so let's make this |T** parentPointer = ... &last->left : &last->right;|, adding explicit dereferences below as needed.
@@ +98,5 @@
> +
> + T* remove(const T &v)
> + {
> + T *last = lookup(v);
> + MOZ_ASSERT(last && C::compare(v, *last) == 0);
MOZ_ASSERT(last, "This tree must contain the element being removed.");
MOZ_ASSERT(Comparator::compare(v, *last) == 0);
This makes the reason for the first assertion obvious if it's hit in, say, tinderbox debug-testing runs, and it splits them so that the reader doesn't have to guess which condition failed, if a failure were to happen.
@@ +149,5 @@
> + checkCoherency(root, NULL);
> + return last;
> + }
> +
> + T* remove_min()
This should be removeMin (camelCaps like all method names).
@@ +161,5 @@
> + }
> +
> + private:
> +
> + T *lookup(const T &v)
There should be a comment by this explaining what it returns, I think something like this if I understand the code:
/* Returns the node in this comparing equal to |v|, or a node just greater or just less than |v| if there is no such node. */
@@ +163,5 @@
> + private:
> +
> + T *lookup(const T &v)
> + {
> + MOZ_ASSERT(root);
MOZ_ASSERT(!isEmpty());
@@ +164,5 @@
> +
> + T *lookup(const T &v)
> + {
> + MOZ_ASSERT(root);
> + T *node = root, *parent;
Separate decls for these.
@@ +178,5 @@
> + } while (node);
> + return parent;
> + }
> +
> + void splay(T *node)
/* Reorganizes this tree to improve access speeds to |node|. */ or somesuch.
@@ +269,5 @@
> +
> +} /* namespace mozilla */
> +
> +#endif /* ifdef __cplusplus */
> +#endif /* ifdef mozilla_SplayTree_h_ */
Don't put the "ifdef " part here.
::: mfbt/exported_headers.mk
@@ +29,5 @@
> RefPtr.h \
> Scoped.h \
> StandardInteger.h \
> SHA1.h \
> + SplayTree.h \
Let's realphabetize while we're here -- Scoped, SHA1, SplayTree, StandardInteger.
Attachment #699501 -
Flags: review?(jwalden+bmo) → review-
Assignee | ||
Comment 20•12 years ago
|
||
Thanks Waldo!
Hopefully this addresses all your review comments.
Attachment #699501 -
Attachment is obsolete: true
Attachment #701631 -
Flags: review?(jwalden+bmo)
Comment 21•12 years ago
|
||
Let's leave the status flag for FF19 untouched for now, so that this doesn't fall off of our tracking queries. Uplifting this fix to mozilla-beta is blocking bug 815666 from landing.
status-firefox19:
unaffected → ---
tracking-firefox19:
--- → +
Comment 22•12 years ago
|
||
Comment on attachment 701631 [details] [diff] [review]
Add SplayTree to mfbt v2
Review of attachment 701631 [details] [diff] [review]:
-----------------------------------------------------------------
Feel free to make the class-overview comment, and the method-overview comments, doxygen-style if you want:
/**
* line one...
* line two...
*/
We take either that style or the single-star style right now, to accommodate Gecko people used to the doxygen format.
::: mfbt/SplayTree.h
@@ +5,5 @@
> + * 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/. */
> +
> +/* A sorted tree with optimal access times, where recently-accessed elements
> + * are faster to access again. */
/*
* line one...
* line two...
*/
@@ +16,5 @@
> +
> +namespace mozilla {
> +
> +template <class T, class C>
> +class SplayTree;
Super-nitpick: template<class T, class C>
@@ +23,5 @@
> +class SplayTreeNode
> +{
> + public:
> + template <class A, class B>
> + friend class SplayTree;
template<... here too
@@ +47,5 @@
> + * compare(const T&, const T&) method ordering the elements. The compare
> + * method must be free from side effects.
> + */
> +template <typename T, class Comparator>
> +class SplayTree
template<
@@ +75,5 @@
> +
> + bool insert(T* v)
> + {
> + // Don't tolerate duplicate elements.
> + MOZ_ASSERT(!contains(*v), "Duplicate elements are not allowed.");
The assertion reason makes the comment redundant. :-) (And if I do say so myself, it's a prime example of how assertion reasons can be occasionally useful.)
@@ +150,5 @@
> + checkCoherency(root, nullptr);
> + return last;
> + }
> +
> + T* removeMin()
Just to get it on the record, I had thought of requesting removeMax be added, too, but figured someone would request it when they wanted it. No need to add it here.
@@ +152,5 @@
> + }
> +
> + T* removeMin()
> + {
> + MOZ_ASSERT(root);
MOZ_ASSERT(!empty(), "No min to remove!"); is again clearer about what's being done.
Add a blank line after it, too, since it's separate from the actual lookup/remove steps. Actually, if you could do that on all the precondition-ish sequences of assertions, that'd be great.
@@ +156,5 @@
> + MOZ_ASSERT(root);
> + T* min = root;
> + while (min->left) {
> + min = min->left;
> + }
Remove the braces.
@@ +162,5 @@
> + }
> +
> + private:
> + /* Returns the node in this comparing equal to |v|, or a node just greater or
> + * just less than |v| if there is no such node. */
/*
* line one
* line two
*/
@@ +181,5 @@
> + } while (node);
> + return parent;
> + }
> +
> + /**
Remove the trailing whitespace.
@@ +269,5 @@
> +#else
> + return nullptr;
> +#endif
> + }
> +
Remove the trailing whitespace.
Attachment #701631 -
Flags: review?(jwalden+bmo) → review+
Assignee | ||
Comment 23•12 years ago
|
||
Comment 24•12 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/5afe6e43be75
https://hg.mozilla.org/mozilla-central/rev/d8a11c7c37b5
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla21
Comment 25•12 years ago
|
||
Please nominate for aurora uplift since we're waiting on this for bug 815666
Comment 26•12 years ago
|
||
It's not fixed. See https://crash-stats.mozilla.com/report/list?version=Firefox:21.0a1&signature=mozilla%3A%3Acss%3A%3AOverflowChangedTracker%3A%3AFlush%28%29
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
Reporter | ||
Comment 27•12 years ago
|
||
Scoobidiver, please file a new bug for the topcrash. This bug is fixed.
Status: REOPENED → RESOLVED
Closed: 12 years ago → 12 years ago
Resolution: --- → FIXED
Assignee | ||
Comment 28•12 years ago
|
||
Comment on attachment 699503 [details] [diff] [review]
Use SplayTree to remove deleted frames.
[Approval Request Comment]
Bug caused by (feature/regressing bug #): Bug 815666
User impact if declined: Crashes.
Testing completed (on m-c, etc.): Been on m-c for a few days
Risk to taking this patch (and alternatives if risky): Low risk, just avoids processing deleted frames.
String or UUID changes made by this patch: None
Attachment #699503 -
Flags: approval-mozilla-beta?
Attachment #699503 -
Flags: approval-mozilla-aurora?
Comment 29•12 years ago
|
||
Comment on attachment 699503 [details] [diff] [review]
Use SplayTree to remove deleted frames.
Approving for Beta alongside bug 815666. Please land asap today to make it into Beta 3.
Attachment #699503 -
Flags: approval-mozilla-beta?
Attachment #699503 -
Flags: approval-mozilla-beta+
Attachment #699503 -
Flags: approval-mozilla-aurora?
Attachment #699503 -
Flags: approval-mozilla-aurora+
Reporter | ||
Comment 30•12 years ago
|
||
(In reply to Jesse Ruderman from comment #27)
> Scoobidiver, please file a new bug for the topcrash. This bug is fixed.
Thanks for filing bug 832611 to track the topcrash.
Assignee | ||
Comment 31•12 years ago
|
||
Comment 32•12 years ago
|
||
Updated•12 years ago
|
status-firefox21:
--- → fixed
Updated•12 years ago
|
status-firefox19:
--- → affected
Updated•12 years ago
|
Attachment #699503 -
Flags: approval-mozilla-beta+ → approval-mozilla-beta?
Comment 33•12 years ago
|
||
We're going to be backing out bug 806256 and bug 807563 from FF19, so this bug won't be necessary.
Updated•12 years ago
|
Attachment #699503 -
Flags: approval-mozilla-beta? → approval-mozilla-beta-
Updated•12 years ago
|
Comment 34•12 years ago
|
||
Verified fixed using the testcase on FF 20b6, FF 21.0a2 (2013-03-20) on Win 7, Ubuntu 12.04 and Mac OS X 10.7.5
You need to log in
before you can comment on or make changes to this bug.
Description
•