Skip to content

Commit

Permalink
Bug 1309445 - Convert FrameConstructionItemList::mItems to use mozill…
Browse files Browse the repository at this point in the history
…a::LinkedList. r=dholbert

The major change to the Iterator is due to the fact that the end of a
LinkedList is represented by nullptr.

Also delete the type conversion functions which are no longer needed.

MozReview-Commit-ID: 2lYtFW9pSon
  • Loading branch information
aethanyc committed Oct 18, 2016
1 parent dad363f commit b9287ed
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 60 deletions.
36 changes: 21 additions & 15 deletions layout/base/nsCSSFrameConstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12785,10 +12785,10 @@ Iterator::AppendItemToList(FrameConstructionItemList& aTargetList)
NS_ASSERTION(&aTargetList != &mList, "Unexpected call");
NS_PRECONDITION(!IsDone(), "should not be done");

FrameConstructionItem* item = ToItem(mCurrent);
FrameConstructionItem* item = mCurrent;
Next();
PR_REMOVE_LINK(item);
PR_APPEND_LINK(item, &aTargetList.mItems);
item->remove();
aTargetList.mItems.insertBack(item);

mList.AdjustCountsForItem(item, -1);
aTargetList.AdjustCountsForItem(item, 1);
Expand All @@ -12800,7 +12800,7 @@ Iterator::AppendItemsToList(const Iterator& aEnd,
FrameConstructionItemList& aTargetList)
{
NS_ASSERTION(&aTargetList != &mList, "Unexpected call");
NS_PRECONDITION(mEnd == aEnd.mEnd, "end iterator for some other list?");
NS_PRECONDITION(&mList == &aEnd.mList, "End iterator for some other list?");

// We can't just move our guts to the other list if it already has
// some information or if we're not moving our entire list.
Expand All @@ -12812,10 +12812,12 @@ Iterator::AppendItemsToList(const Iterator& aEnd,
return;
}

// move over the list of items
PR_INSERT_AFTER(&aTargetList.mItems, &mList.mItems);
// Need to init when we remove to makd ~FrameConstructionItemList work right.
PR_REMOVE_AND_INIT_LINK(&mList.mItems);
// Move our entire list of items into the empty target list.
// XXX: If LinkedList supports move assignment, we could use
// aTargetList.mItems = Move(mList.mItems);
aTargetList.mItems.~LinkedList<FrameConstructionItem>();
new (&aTargetList.mItems) LinkedList<FrameConstructionItem>(
Move(mList.mItems));

// Copy over the various counters
aTargetList.mInlineCount = mList.mInlineCount;
Expand All @@ -12833,33 +12835,37 @@ Iterator::AppendItemsToList(const Iterator& aEnd,
new (&mList) FrameConstructionItemList();

// Point ourselves to aEnd, as advertised
mCurrent = mEnd = &mList.mItems;
SetToEnd();
NS_POSTCONDITION(*this == aEnd, "How did that happen?");
}

void
nsCSSFrameConstructor::FrameConstructionItemList::
Iterator::InsertItem(FrameConstructionItem* aItem)
{
// Just insert the item before us. There's no magic here.
PR_INSERT_BEFORE(aItem, mCurrent);
if (IsDone()) {
mList.mItems.insertBack(aItem);
} else {
// Just insert the item before us. There's no magic here.
mCurrent->setPrevious(aItem);
}
mList.AdjustCountsForItem(aItem, 1);

NS_POSTCONDITION(PR_NEXT_LINK(aItem) == mCurrent, "How did that happen?");
NS_POSTCONDITION(aItem->getNext() == mCurrent, "How did that happen?");
}

void
nsCSSFrameConstructor::FrameConstructionItemList::
Iterator::DeleteItemsTo(const Iterator& aEnd)
{
NS_PRECONDITION(mEnd == aEnd.mEnd, "end iterator for some other list?");
NS_PRECONDITION(&mList == &aEnd.mList, "End iterator for some other list?");
NS_PRECONDITION(*this != aEnd, "Shouldn't be at aEnd yet");

do {
NS_ASSERTION(!IsDone(), "Ran off end of list?");
FrameConstructionItem* item = ToItem(mCurrent);
FrameConstructionItem* item = mCurrent;
Next();
PR_REMOVE_LINK(item);
item->remove();
mList.AdjustCountsForItem(item, -1);
delete item;
} while (*this != aEnd);
Expand Down
69 changes: 24 additions & 45 deletions layout/base/nsCSSFrameConstructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define nsCSSFrameConstructor_h___

#include "mozilla/Attributes.h"
#include "mozilla/LinkedList.h"
#include "mozilla/RestyleManagerBase.h"
#include "mozilla/RestyleManagerHandle.h"

Expand Down Expand Up @@ -785,7 +786,7 @@ class nsCSSFrameConstructor : public nsFrameManager
uint32_t aDataLength);

/* A class representing a list of FrameConstructionItems */
class FrameConstructionItemList {
class FrameConstructionItemList final {
public:
FrameConstructionItemList() :
mInlineCount(0),
Expand All @@ -797,21 +798,14 @@ class nsCSSFrameConstructor : public nsFrameManager
mParentHasNoXBLChildren(false),
mTriedConstructingFrames(false)
{
PR_INIT_CLIST(&mItems);
memset(mDesiredParentCounts, 0, sizeof(mDesiredParentCounts));
}

~FrameConstructionItemList() {
PRCList* cur = PR_NEXT_LINK(&mItems);
while (cur != &mItems) {
PRCList* next = PR_NEXT_LINK(cur);
delete ToItem(cur);
cur = next;
while (FrameConstructionItem* item = mItems.popFirst()) {
delete item;
}

// Leaves our mItems pointing to deleted memory in both directions,
// but that's OK at this point.

// Create the undisplayed entries for our mUndisplayedItems, if any, but
// only if we have tried constructing frames for this item list. If we
// haven't, then we're just throwing it away and will probably try again.
Expand All @@ -836,7 +830,7 @@ class nsCSSFrameConstructor : public nsFrameManager
bool HasLineBoundaryAtStart() { return mLineBoundaryAtStart; }
bool HasLineBoundaryAtEnd() { return mLineBoundaryAtEnd; }
bool ParentHasNoXBLChildren() { return mParentHasNoXBLChildren; }
bool IsEmpty() const { return PR_CLIST_IS_EMPTY(&mItems); }
bool IsEmpty() const { return mItems.isEmpty(); }
bool AnyItemsNeedBlockParent() const { return mLineParticipantCount != 0; }
bool AreAllItemsInline() const { return mInlineCount == mItemCount; }
bool AreAllItemsBlock() const { return mBlockCount == mItemCount; }
Expand All @@ -862,7 +856,7 @@ class nsCSSFrameConstructor : public nsFrameManager
aPendingBinding, aStyleContext,
aSuppressWhiteSpaceOptimizations,
aAnonChildren);
PR_APPEND_LINK(item, &mItems);
mItems.insertBack(item);
++mItemCount;
++mDesiredParentCounts[item->DesiredParentType()];
return item;
Expand All @@ -883,7 +877,7 @@ class nsCSSFrameConstructor : public nsFrameManager
aPendingBinding, aStyleContext,
aSuppressWhiteSpaceOptimizations,
aAnonChildren);
PR_INSERT_LINK(item, &mItems);
mItems.insertFront(item);
++mItemCount;
++mDesiredParentCounts[item->DesiredParentType()];
return item;
Expand All @@ -898,31 +892,26 @@ class nsCSSFrameConstructor : public nsFrameManager
void BlockItemAdded() { ++mBlockCount; }
void LineParticipantItemAdded() { ++mLineParticipantCount; }

class Iterator;
friend class Iterator;

class Iterator {
public:
explicit Iterator(FrameConstructionItemList& list) :
mCurrent(PR_NEXT_LINK(&list.mItems)),
mEnd(&list.mItems),
mList(list)
explicit Iterator(FrameConstructionItemList& aList)
: mCurrent(aList.mItems.getFirst())
, mList(aList)
{}
Iterator(const Iterator& aOther) :
mCurrent(aOther.mCurrent),
mEnd(aOther.mEnd),
mList(aOther.mList)
{}

bool operator==(const Iterator& aOther) const {
NS_ASSERTION(mEnd == aOther.mEnd, "Iterators for different lists?");
MOZ_ASSERT(&mList == &aOther.mList, "Iterators for different lists?");
return mCurrent == aOther.mCurrent;
}
bool operator!=(const Iterator& aOther) const {
return !(*this == aOther);
}
Iterator& operator=(const Iterator& aOther) {
NS_ASSERTION(mEnd == aOther.mEnd, "Iterators for different lists?");
MOZ_ASSERT(&mList == &aOther.mList, "Iterators for different lists?");
mCurrent = aOther.mCurrent;
return *this;
}
Expand All @@ -931,31 +920,27 @@ class nsCSSFrameConstructor : public nsFrameManager
return &mList;
}

operator FrameConstructionItem& () {
return item();
}

FrameConstructionItem& item() {
MOZ_ASSERT(!IsDone(), "Should have checked IsDone()!");
return *FrameConstructionItemList::ToItem(mCurrent);
return *mCurrent;
}

const FrameConstructionItem& item() const {
MOZ_ASSERT(!IsDone(), "Should have checked IsDone()!");
return *FrameConstructionItemList::ToItem(mCurrent);
return *mCurrent;
}

bool IsDone() const { return mCurrent == mEnd; }
bool AtStart() const { return mCurrent == PR_NEXT_LINK(mEnd); }
bool IsDone() const { return mCurrent == nullptr; }
bool AtStart() const { return mCurrent == mList.mItems.getFirst(); }
void Next() {
NS_ASSERTION(!IsDone(), "Should have checked IsDone()!");
mCurrent = PR_NEXT_LINK(mCurrent);
mCurrent = mCurrent->getNext();
}
void Prev() {
NS_ASSERTION(!AtStart(), "Should have checked AtStart()!");
mCurrent = PR_PREV_LINK(mCurrent);
mCurrent = mCurrent ? mCurrent->getPrevious() : mList.mItems.getLast();
}
void SetToEnd() { mCurrent = mEnd; }
void SetToEnd() { mCurrent = nullptr; }

// Skip over all items that want the given parent type. Return whether
// the iterator is done after doing that. The iterator must not be done
Expand Down Expand Up @@ -993,7 +978,7 @@ class nsCSSFrameConstructor : public nsFrameManager

// Remove the item pointed to by this iterator from its current list and
// Append it to aTargetList. This iterator is advanced to point to the
// next item in its list. aIter must not be done. aOther must not be
// next item in its list. aIter must not be done. aTargetList must not be
// the list this iterator is iterating over..
void AppendItemToList(FrameConstructionItemList& aTargetList);

Expand Down Expand Up @@ -1021,16 +1006,11 @@ class nsCSSFrameConstructor : public nsFrameManager
void DeleteItemsTo(const Iterator& aEnd);

private:
PRCList* mCurrent;
PRCList* mEnd;
FrameConstructionItem* mCurrent;
FrameConstructionItemList& mList;
};

private:
static FrameConstructionItem* ToItem(PRCList* item) {
return static_cast<FrameConstructionItem*>(item);
}

struct UndisplayedItem {
UndisplayedItem(nsIContent* aContent, nsStyleContext* aStyleContext) :
mContent(aContent), mStyleContext(aStyleContext)
Expand All @@ -1044,7 +1024,7 @@ class nsCSSFrameConstructor : public nsFrameManager
// should be either +1 or -1 depending on which is happening.
void AdjustCountsForItem(FrameConstructionItem* aItem, int32_t aDelta);

PRCList mItems;
mozilla::LinkedList<FrameConstructionItem> mItems;
uint32_t mInlineCount;
uint32_t mBlockCount;
uint32_t mLineParticipantCount;
Expand All @@ -1070,9 +1050,8 @@ class nsCSSFrameConstructor : public nsFrameManager
* constructed. This contains all the information needed to construct the
* frame other than the parent frame and whatever would be stored in the
* frame constructor state. */
struct FrameConstructionItem : public PRCList {
// No need to PR_INIT_CLIST in the constructor because the only
// place that creates us immediately appends us.
struct FrameConstructionItem final
: public mozilla::LinkedListElement<FrameConstructionItem> {
FrameConstructionItem(const FrameConstructionData* aFCData,
nsIContent* aContent,
nsIAtom* aTag,
Expand Down

0 comments on commit b9287ed

Please sign in to comment.