Closed
Bug 1001653
Opened 11 years ago
Closed 11 years ago
Return earlier from ResolveFlexibleLengths if all of our flex items are frozen
Categories
(Core :: Layout, defect, P4)
Core
Layout
Tracking
()
RESOLVED
FIXED
mozilla32
People
(Reporter: dholbert, Assigned: dholbert)
Details
Attachments
(3 files, 5 obsolete files)
14.75 KB,
patch
|
Details | Diff | Splinter Review | |
12.97 KB,
patch
|
MatsPalmgren_bugz
:
review+
|
Details | Diff | Splinter Review |
15.02 KB,
patch
|
Details | Diff | Splinter Review |
Per end of bug 985304 comment 10 & second-to-last chunk in bug 985304 comment 13, we should perhaps make FlexLine::ResolveFlexibleLengths() return early for cases where all flex items have "flex:none".
The most efficient way to do this is perhaps to give FlexLine a member-variable that indicates whether any of its flex items started out un-frozen.
Assignee | ||
Updated•11 years ago
|
Priority: -- → P4
Summary: Make FlexLine track whether all of its flex items are frozen up-front → Return earlier from ResolveFlexibleLengths if all of our flex items are frozen
Comment 1•11 years ago
|
||
It might also be worth keeping track of how many unfrozen items there still
are and bail out of the loops that only deals with unfrozen items when we
have seen that many, something like this:
auto cnt = remainingFrozenItems;
for (FlexItem* item = mItems.getFirst(); cnt; item = item->getNext()) {
if (!item->IsFrozen()) {
--cnt;
Slightly more complicated, so maybe not worth it: maintain a sentinel after
the last frozen item so you could do:
auto cnt = remainingFrozenItems;
for (FlexItem* item = firstMaybeUnfrozenItem; cnt; item = item->getNext()) {
if (!item->IsFrozen()) {
--cnt;
and then when you freeze an item just set it to getNext().
I'm not sure it would pay off to actually go look for the next
unfrozen item there (unless the code is already iterating items).
Assignee | ||
Comment 2•11 years ago
|
||
(In reply to Mats Palmgren (:mats) from comment #1)
> It might also be worth keeping track of how many unfrozen items there still
> are and bail out of the loops that only deals with unfrozen items when we
> have seen that many, something like this:
I'm opting to go with something like this first proposal. The firstMaybeUnfrozenItem part (second suggestion in comment 1) may be worth it, but it's a bit messier in terms of maintaining state, so I'm going to hold off on that part for now.
Assignee | ||
Comment 3•11 years ago
|
||
Assignee: nobody → dholbert
Status: NEW → ASSIGNED
Assignee | ||
Comment 4•11 years ago
|
||
Assignee | ||
Comment 5•11 years ago
|
||
This version adds this optimization to one more loop.
Attachment #8416345 -
Attachment is obsolete: true
Attachment #8416346 -
Attachment is obsolete: true
Assignee | ||
Comment 6•11 years ago
|
||
Assignee | ||
Comment 7•11 years ago
|
||
Attachment #8416347 -
Attachment is obsolete: true
Attachment #8416348 -
Attachment is obsolete: true
Assignee | ||
Comment 8•11 years ago
|
||
Notes on the patch:
* FlexLine now keeps track of its count of frozen items: "mNumFrozenItems"
* This value is incremented in two spots:
- when FlexItems are added (if they're already frozen)
- when FlexItems are frozen in FreezeOrRestoreEachFlexibleSize())
So, the count remains up-to-date.
* Eventually, it becomes equal to mNumItems, when we've resolved all flexible sizes. If they're already equal when we enter ResolveFlexibleLengths, we can return immediately. (This is a generalization of the existing "IsEmpty()" early-return.)
* Given mNumItems and mNumFrozenItems, we can easily compute the number of *unfrozen* items, which lets us bail out of loops early (after we iterate through that many unfrozen items).
ALSO:
- Previously, I hadn't bothered with an !IsFrozen() check in the second loop touched by this patch (where we compute "weightSum" & a few other things) -- instead, I just made frozen items return 0 from GetWeight(). BUT, now that I'm guarding that loop's contents with !IsFrozen(), we can assert about frozenness inside of GetWeight()/GetFlexFactor(). (That's the topmost change in the patch.)
- Also, this patch adjusts the scope of the FreezeOrRestoreEachFlexibleSize() assertion for "Can have either min or max violation", to now be inside of an !IsFrozen() check. This is because *only* unfrozen items can have min/max-size violations. (which can be seen by the fact that our SetHadMinViolation/SetHadMaxViolation calls are inside of an !IsFrozen() check, combined with the fact that we clear violations after freezing items.)
Attachment #8416575 -
Flags: review?(matspal)
Assignee | ||
Comment 9•11 years ago
|
||
(Might also be worth asserting that remainingUnfrozenItems is 0 at the end of each of these loops, too. I'll add that before landing, if you don't object.)
Comment 10•11 years ago
|
||
Comment on attachment 8416575 [details] [diff] [review]
fix v3 "diff -w" version
>+ // Since this loop only operates on unfrozen flex items, we can break as
>+ // soon as we know there are no unfrozen items remaining.
>+ uint32_t remainingUnfrozenItems = mNumItems - mNumFrozenItems;
>+ for (FlexItem* item = mItems.getFirst();
>+ item && remainingUnfrozenItems > 0; item = item->getNext()) {
>+ if (!item->IsFrozen()) {
>+ remainingUnfrozenItems--;
I'm a little worried that the code comment might lead a casual reader
to misunderstand what these loops are actually doing.
The two "mNumFrozenItems++" which are both in conditional branches,
so there might still be some !IsFrozen() items after the loop.
This is fine, but I think it contradicts the "no unfrozen items
remaining". The name 'remainingUnfrozenItems' is slightly ambiguous
as well, since it could be misunderstood as "remaining unfrozen items
*in the list*", and that this loop freezes all the items.
So I would suggest changing the "remaining" part of the comment/name
to something different to avoid that. (It's probably my fault since
I suggested it in comment 1, sorry!)
Perhaps this is a better wording:
// Since this loop only operates on unfrozen flex items, we can break as
// soon as we have seen all of them.
I'm not sure about the loop variable name... perhaps 'itemsToProcess'?
or a bland name, like 'count', 'num', 'i'?
Also, the 'item' null checks seems redundant - we must have at least
that many items (assuming these loops don't manipulate the list).
Other than that, the code looks good!
r=mats with the nits addressed as you see fit
Attachment #8416575 -
Flags: review?(matspal) → review+
Comment 11•11 years ago
|
||
(In reply to Daniel Holbert [:dholbert] from comment #9)
> (Might also be worth asserting that remainingUnfrozenItems is 0 at the end
> of each of these loops, too. I'll add that before landing, if you don't
> object.)
That'd be fine, except perhaps if the loops fit within one page, it might
not be necessary if we drop the 'item' null-check. It's rather obvious
if it becomes:
for (FlexItem* item = mItems.getFirst();
remainingUnfrozenItems > 0; item = item->getNext()) {
...
}
MOZ_ASSERT(remainingUnfrozenItems == 0);
Assignee | ||
Comment 12•11 years ago
|
||
(In reply to Mats Palmgren (:mats) from comment #10)
> The name 'remainingUnfrozenItems' is slightly ambiguous
> as well, since it could be misunderstood as "remaining unfrozen items
> *in the list*",
Ah, I see what you mean.
> I'm not sure about the loop variable name... perhaps 'itemsToProcess'?
> or a bland name, like 'count', 'num', 'i'?
I'd prefer something indicating "unfrozen", but I agree "remaining" may be vague since (as you said) it may imply a broader scope beyond this loop.
I'm leaning towards "unfrozenItemsToBeSeen". That's more clearly loop-scoped.
> Perhaps this is a better wording:
> // Since this loop only operates on unfrozen flex items, we can break as
> // soon as we have seen all of them.
WFM.
> Also, the 'item' null checks seems redundant - we must have at least
> that many items (assuming these loops don't manipulate the list).
Yeah, I left that in there as a sanity-check I suppose (and as a remnant of the traditional iterator loop structure). We can move it to an assertion instead of an official loop check, though.
> > (Might also be worth asserting that remainingUnfrozenItems is 0 at the end
> > of each of these loops, too. I'll add that before landing, if you don't
> > object.)
>
> That'd be fine, except perhaps if the loops fit within one page, it might
> not be necessary if we drop the 'item' null-check.
Yup, never mind about this part. I'll demote the item null-check to an assertion (as noted above), which makes unnecessary the count assertion that I was suggesting.
Assignee | ||
Comment 13•11 years ago
|
||
Here's the patch w/ review comments addressed.
I ended up naming the variable "numUnfrozenItemsToBeSeen", which is a bit long, but it at least uses a similar naming-scheme to the variables that we derive it from (mNumItems, mNumFrozenItems), with the "ToBeSeen" suffix indicating that it's a just-for-now tally of remaining items to walk through.
I'll give this a Try run, and then land if that goes well.
Attachment #8417114 -
Flags: review+
Assignee | ||
Comment 14•11 years ago
|
||
Attachment #8417114 -
Attachment is obsolete: true
Assignee | ||
Comment 15•11 years ago
|
||
Assignee | ||
Updated•11 years ago
|
Flags: in-testsuite-
Assignee | ||
Comment 16•11 years ago
|
||
Comment 17•11 years ago
|
||
Status: ASSIGNED → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla32
You need to log in
before you can comment on or make changes to this bug.
Description
•