Closed Bug 190735 Opened 22 years ago Closed 14 years ago

deCOMtaminate nsIFrame

Categories

(Core :: Layout, defect, P3)

defect

Tracking

()

RESOLVED FIXED

People

(Reporter: roc, Unassigned)

References

(Blocks 3 open bugs)

Details

(Keywords: perf, Whiteboard: [fix])

Attachments

(7 files, 3 obsolete files)

80.62 KB, patch
Details | Diff | Splinter Review
17.52 KB, patch
dbaron
: review+
dbaron
: superreview+
Details | Diff | Splinter Review
5.85 KB, patch
roc
: review+
Details | Diff | Splinter Review
166.65 KB, patch
Details | Diff | Splinter Review
104.93 KB, patch
Details | Diff | Splinter Review
276.47 KB, patch
Details | Diff | Splinter Review
194.61 KB, patch
bzbarsky
: review+
bzbarsky
: superreview+
Details | Diff | Splinter Review
I have a patch and a strategy for deCOMifying nsIFrame. I will explain in a moment.
I'm going to attach a patch that whacks nsIFrame (and to some extent, nsFrame) so that it supports both COM-style and non-COM-style interfaces for every function that is actually used. We can land this patch immediately (well, once 1.4 opens) and start using the clean interfaces immediately. We can also incrementally convert existing code from the COM-style to the non-COM-style --- both callers of methods and implementors (overriders) of methods. This patch is also hopefully of a reviewable size. I hope the subsequent conversion can be done with a blanket r+sr. Once the conversion is complete we can remove the legacy methods, and we can also remove the non-COM wrappers. Here's an example of what I've done. Existing code: NS_IMETHOD CanContinueTextRun(PRBool* aResult) = 0; becomes virtual PRBool _CanContinueTextRun() { PRBool r; CanContinueTextRun(&r); return r; } NS_IMETHOD CanContinueTextRun(PRBool* aResult) { *aResult = _CanContinueTextRun(); return NS_OK; } This changes no behaviour at all. _CanContinueTextRun isn't called anywhere (yet), and CanContinueTextRun is overridden in nsFrame. But going forward it allows two things: We can convert calls to CanContinueTextRun to _CanContinueTextRun, and they will work. Once all virtual call sites are converted, we can convert the implementors (starting at the leaves of the class hierarchy) to override the new method instead of the old one. Once we're done, we can delete CanContinueTextRun, make _CanContinueTextRun() in nsIFrame pure virtual, and use a script to rename _CanContinueTextRun to CanContinueTextRun globally. This wasn't necessary everywhere, a lot of the new methods have been given their final "real" name (methods that are only implemented in nsFrame, or which I renamed to a better name anyway). The reason we have to use _CanContinueTextRun instead of just overloading CanContinueTextRun is because of a stupid feature of C++. The problem is that subclasses which override CanContinueTextRun(PRBool*) would actually hide CanContinueTextRun() from the base class, making it inaccessible in the subclass. This also produces lots of warnings. While whacking nsIFrame I have done the following things: -- removed nsresult almost everywhere. In almost all cases the result was never checked, or it was checked but nothing intelligent was or could be done about a failure, or implementations always returned NS_OK, or the result was better indicated with a special return value (typically null). -- Replaced nsIPresShell references with nsIPresContext, with the idea of helping an eventual merge of nsIPresShell into nsIPresContext -- renamed methods where I thought the names were poor -- converted out parameters to real results whenever possible -- made all remaining out parameters be pointers, not references. bz and I agree that having to put "&" in your parameter list at a call site helps show that that parameter is an out parameter (C# does something similar with "ref" for its out parameters). -- removed methods that no-one was using or that should be somewhere else (e.g., moved down into nsTextFrame) (of course the COM-style legacy methods are still there, for now) -- made all references to nsISupports-derived objects be pointers, not C++ references --- especially nsIRenderingContext. This is for consistency. -- made methods nonvirtual if they were only implemented in nsFrame One thing I did not do was to stop nsIFrame inheriting from nsISupports. This seems quite difficult because in various places frames are passed around as nsISupports (e.g., frame tree iterators).
I had to add some 'virtual's back in to fix linking problems. Too bad editor likes to monkey around with nsIFrame :-(.
Quick comments from a totally partial skim: 1) already_AddRefed<nsIStyleContext> GetStyleContext() {} That should prevent the need for that comment about it being already addrefed too. ;) 2) Any reasons not to use the MoveTo() and SizeTo() functions on mRect instead of setting its x, y, etc manually in the SetPosition and SetSize methods?
already_AddRefed... neat OK, I'll use MoveTo/SizeTo.
*** Bug 187924 has been marked as a duplicate of this bug. ***
Attached patch improved patch (obsolete) — Splinter Review
Takes account of bz's comments. Makes some functions non-virtual and adds ...External versions for those modules outside layout that can't link to them.
Attachment #112715 - Attachment is obsolete: true
Changes SetFrameState/GetFrameState to AddStateBits/RemoveStateBits/GetStateBits. adds nsresult to Init() because some initializations really can fail and we need to detect them.
Attachment #113102 - Attachment is obsolete: true
Attachment #113155 - Flags: superreview?(bzbarsky)
Attachment #113155 - Flags: review?(dbaron)
- * Destroy() for each child) + * Destruct() for each child) oops? You could use a comment about the _ convention. (That's the migration plan, right? I could certainly use the comment to remind me exactly how it's used.) I think bryner may have beaten you to changing GetStyleContext. Have you had a chance to merge? I'm not crazy about virtual functions defined inline. Any better ideas? More later...
> oops? yep > You could use a comment about the _ convention. (That's the migration plan, > right? I could certainly use the comment to remind me exactly how it's used.) Yep. > I think bryner may have beaten you to changing GetStyleContext. Have you had > a chance to merge? No. I don't carry patches in my tree. I'll merge when I iterate this patch for you. > I'm not crazy about virtual functions defined inline. Any better ideas? Well, it's just a convenience. I could easily move them to nsFrame (leaving them as nsIFrame::Blah), it would just be slightly more code to write. Anything in particular make you disapprove of the practice?
roc, is this a priority for 1.4a? Or is it ok to start this in 1.4b? (just trying to prioritize reviews....)
This isn't going to make 1.4a. Either we will decide it's low risk enough for 1.4b, or we'll push it to 1.5. The only review I want from you is for the transparent windows bug 113232 :-).
Comment on attachment 113155 [details] [diff] [review] another iteration >+typedef PRInt32 nsPaintResult; Documentation? What are possible values? What do they mean? >+/** >+ */ >+struct nsContentRange { Documentation? What is this struct used for? >+ * This method *can* fail. For example, frames for IFRAMEs and other complex >+ * objects can fail to initialize due to resource limits. >+ * > * @param aContent the content object associated with the frame > * @param aGeometricParent the geometric parent frame > * @param aContentParent the content parent frame There is no aContentParent an hasn't been in a while... Remove that line? >- * Destroy() for each child) >+ * Destruct() for each child) What's "Destruct()"? >+ virtual void _SetInitialChildList(nsIPresContext* aPresContext, >+ nsIAtom* aListName, >+ nsIFrame* aChildList) { >+ SetInitialChildList(aPresContext, aListName, aChildList); >+ } Hmmm... Are we sure we want to give no feedback on using an unrecognized aListName? (Not that anyone checks the return value of SetInitialChildList right now....) >- NS_IMETHOD AppendFrames(nsIPresContext* aPresContext, >+ virtual void _AppendFrames(nsIPresContext* aPresContext, Same here. And this is mis-indented. >+ virtual void _InsertFrames(nsIPresContext* aPresContext, >+ virtual void _RemoveFrame(nsIPresContext* aPresContext, >+ virtual void _ReplaceFrame(nsIPresContext* aPresContext, And here. >+ already_AddRefed<nsIContent> GetContent() const { NS_IF_ADDREF(mContent); return mContent; >+ nsIContent* GetContentUnrefed() const { return mContent; } Any reason to have both? Why not just have |nsIContent* GetContent() { return mContent; }|? Same question for GetStyleContext/GetStyleContextUnrefed. >+ * The indicies must be consecutive and implementations MUST return >+ * nsnull if asked for an index that is out of range. "indices". >+ virtual already_AddRefed<nsIAtom> _GetAdditionalChildListName(PRInt32 aIndex) const { Does this return nsnull if aIndex is out of some range? >+ * @return an indication of the layers that need to be painted by this frame I assume this will become clear in the future? ;) It could use some documentation explaining what one would use the return value for.... >+ virtual nsPaintResult _Paint(nsIPresContext* aPresContext, Will failures (can there be any?) be indicated via the nsPaintResult? >+ virtual nsReflowStatus _Reflow(nsIPresContext* aPresContext, Same here.... Some things still do Init()-like stuff on initial reflow and could fail.... Or do we want to enforce Reflow() not failing and move all such stuff to Init() ? >+ already_AddRefed<nsIAtom> GetType() const { >+ virtual nsIAtom* GetTypeUnrefed() const { Again, why have both? >+ NS_IMETHOD Destroy(nsIPresContext* aPresContext) { >+ _Destroy(aPresContext); >+ return NS_OK; >+ } This bothers me.... _Destroy just calls Destroy(), no? So you're depending on all subclasses overriding this.... Is that a good thing to depend on? Same applies to lots of the legacy stuff. >Index: layout/base/public/nsIPresContext.h >+ // deCOMtaminated methods >+ nsIPresShell* GetShellUnrefed() { return mShell; } >+ nsIPresShell* GetShell() { NS_IF_ADDREF(mShell); return mShell; } already_AddRefed for that second one, please. Again, why do we need both? I guess we should add a comment saying that nsIPresContext is not a real interface either? Otherwise someone will try to "fix" the presence of members in the interface.... >Index: layout/base/public/nsIPresShell.h >+ nsIPresContext* GetPresContext() { already_AddRefed. >+ nsIPresContext* GetPresContextUnrefed(); And again, do we need both? In nsFrame.cpp: >- NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS, >- ("WillReflow: oldState=%x", mState)); Why remove that? >Index: layout/html/base/src/nsFrame.h >+ NS_IMETHOD SetParent(const nsIFrame* aParent) { >+ mParent = (nsIFrame*)aParent; Can we make mParent const? If not, imo SetParent should not take a const. >+nsIPresContext* >+PresShell::GetPresContextUnrefed() Just call it GetPresContext; the fact that it's unrefed is clear from the return type -- if it addrefed, it would return already_AddRefed Looks pretty sweet, Robert. ;)
> Documentation? What are possible values? What do they mean? OK > Documentation? What is this struct used for? Used to get/set a range of content children. I'll add a comment. > here is no aContentParent an hasn't been in a while... Remove that line? Yeah > What's "Destruct()"? A mistake. Should be Destroy(). > Hmmm... Are we sure we want to give no feedback on using an unrecognized > aListName? > > (Not that anyone checks the return value of SetInitialChildList right now....) We should assert in the method. This is not something we really want to probe for at runtime --- and if we really have to probe for some reason, we can explicitly scan the child list names to see if the list we want is there. I'll bet money we never want to do that. As a general rule, I'm not returning a result if either a) no-one currently checks it or b) it always currently returns NS_OK. Especially for these private interfaces, I think we cry wolf when we pretend things can fail that really can't (or where the failure is really just a coding bug that should be fixed and therefore should be an assertion). It just means we end up ignoring results willy-nilly and end up ignoring the ones that matter, too. (For public interfaces the situation is a bit different because "can fail/cannot fail" may be exposing too much of the implementation to clients.) > Any reason to have both? Why not just have |nsIContent* GetContent() { return > mContent; }|? Mainly because our getters usually do return an already-addrefed object. I'd like to remain consistent with that. > Does this return nsnull if aIndex is out of some range? Yeah. I'll add a comment. > I assume this will become clear in the future? ;) Yeah. This is really a forward-looking comment anticipating a scheme for dynamically discovering which layers need to be painted to reduce the number of passes over the frame tree during painting. I should probably just remove it for now. > Will failures (can there be any?) be indicated via the nsPaintResult? No, I don't think we'll be indicating Paint failure. > Same here.... Some things still do Init()-like stuff on initial reflow and > could fail.... Or do we want to enforce Reflow() not failing and move all such > stuff to Init() ? IIRC we don't currently handle Reflow failures anywhere. What would you do, anyway? > This bothers me.... _Destroy just calls Destroy(), no? So you're > depending on all subclasses overriding this.... Is that a good thing to > depend on? Not in the long term, but this is a necessary part of the migration strategy. The strategy is: change all virtual call sites of Destroy() to call _Destroy(); then change all implementations of Destroy() to override _Destroy() and call ParentClass::_Destroy()*; then remove the Destroy() stub from nsIFrame; then rename _Destroy to Destroy everywhere. The first two steps can be done incrementally. * This step has to be done to all children of a class C before it is done to C itself. Probably in practice we'll start by focusing on the virtual call sites and fix most of them before we start fixing up the implementation signatures. > already_AddRefed for that second one, please. Sure. > I guess we should add a comment saying that nsIPresContext is not a real > interface either? Yeah > Why remove that? Oops. I'll put it back. > Can we make mParent const? If not, imo SetParent should not take a const. It probably should not take a const.
> Mainly because our getters usually do return an already-addrefed object. I'd > like to remain consistent with that. Why? For out params that's a necessary convention, because you can't tell what the callee did to you nsIFoo**. But here, if you're assigning into an nsCOMPtr you don't care what the method returns (because use of already_AddRefed will not leak in that situation, and neither will a raw ptr return). If you're assigning into a raw ptr, the already_AddRefed version will simply fail to compile, and you have to call .get() on it, indicating that you know you're taking over the ref. So the already_AddRefed annotation resolves the callee ambiguity that has to be resolved by a convention in the out param case... I'd just make all those methods return weak ptrs; if the caller wants to take a strong ref by assigning into an nsCOMPtr, he will. Just my $0.02.
I also agree with bz about returning weak pointers where possible.
Comment on attachment 113155 [details] [diff] [review] another iteration I'm willing to say r=dbaron if you produce a patch with bz's comments addressed. I've looked at this a bit in the past and I think we should just move forward rather than slowing everything down with too much review. (And I also want this to land so I can combine the two templatized global GetStyleData functions into one that has both parameters templatized so that we don't need .get() when using it.)
Good ... For the next week at least I have to focus on cleaning up the fallout from all my 1.4a landings so I'm not quite sure when I'll get back to this.
Attachment #113155 - Flags: superreview?(bzbarsky)
OK, as I see it there is a possible problem with RemoveFrame/ReplaceFrame. Consider the case when I have |nsIFrame *aFrame|. This frame has a parent but is _not_ in that parent's child list yet (it's in the middle of being constructed). I try to get rid of that frame. The problem is, I don't _know_ whether it's in the parent's child list, since the same code can be hit from elsewhere. So after I call RemoveFrame or ReplaceFrame I have no way to tell whether I'm supposed to be calling Destroy() on the frame... We could say that RemoveFrame and ReplaceFrame should not be called on frames that are not kids of that parent. Then we need a way to find out whether a frame is a kid of that parent.... (Fwiw, this is an issue for CantRenderReplacedElement, sorta. I've hacked around it for now, and I hope to rewrite CantRenderReplacedElement such that it ceases being an issue, but it could come up in other contexts.... I'm not saying those methods _need_ to return nsresult, but they should be asserting otherwise and we should look at what places trigger those asserts.)
OK, I'll add results for Remove/ReplaceFrame. I'm trying to decide how to handle prescontexts. Since this patch likely won't land until 1.5 anyway, I think I'll try to put a prescontext pointer in nsDocument, and let frames get it from there. We'll have something like this in nsIFrame: virtual nsIPrescontext* GetPresContext() { GetContent()->GetDocument()->GetPresContext(); } which should turn into 3 loads if we do those helper functions right. This will require extra code to make printing work right which resets the prescontext on the document.
As long as we're careful not to call that stuff as content is being removed from the document (think removeChild)....
Comment on attachment 113155 [details] [diff] [review] another iteration Need another rev of this patch
Attachment #113155 - Flags: review?(dbaron)
Since this patch seems to be rotting, I'm tempted to help with this. (I've already done GetStyleData, at least to some extent.) I'd be more inclined to break it up into pieces by function (e.g., ContentStatesChanged, GetView/HasView) rather than by class (as attachment 113155 [details] [diff] [review] seems to do). Or were you (Robert) planning to revive this patch soon?
I'd like to get rid of the aPresContext parameters in this pass too. What do you think is the best way to do that? Can we just stick an mPresContext in nsFrame for now?
I think I'd rather not combine too many things into one patch, and I'm also a bit hesitant about any strategy that involves lots of "temporary" code, having seen temporary code that's still around from 1999. I'd rather do the aPresContext removal somewhat separately and probably all at once. (If not all at once, then at least in groups of related methods that call each other, such as "reflow methods", "painting methods", etc. Otherwise we'd change an |aPresContext| to a |GetPresContext()| in one pass and remove it in the next pass, since many of the methods take pres context parameters only to pass to something else that takes a pres context.) However, initial steps could be done to remove it from (1) things like nsFrameManager that can have an mPresContext member variable independently of frames and (2) from all the nsIFrame methods that then don't need it. I'd rather not leave code in the tree for a while that leaves us with the costs of both ways (the memory use of the mPresContext on all frames plus the code to pass aPresContext from place to place) and the benefits of neither.
For reflow methods we can stick an mPresContext in the reflow state.
Keywords: perf
Blocks: 203448
We can already do something just like comment 21 (and probably even more null-safe), by getting the pres context from the rule node from the style context from the frame. (Same number of steps as the proposal in comment 21.) If that sounds reasonable, I'll do a patch (with a little deCOMification of the necessary functions) and put it in a dependent bug...
Hey yeah! That rules! aPresContext BEGONE!
Here's just a subset of the deCOMtamination that might be ready for checkin. It just adds some non-COM accessor methods where that's easy, and removes aPresContext parameters from a few of the methods that are only implemented in nsFrame. Those methods get wrappers so no other client code has to change right away. If we check this in, then I would suggest just going mad and fixing all callers to the obsolete methods, and removing those methods, without further review.
Attachment #126101 - Flags: superreview?(dbaron)
Attachment #126101 - Flags: review?(dbaron)
Hmm. Maybe methods like GetClosestView, GetParentWithView, and AnyAncestorVisible should be moved to nsLayoutUtils. This would be a good time to do it. Any thoughts?
What would be the benefits of doing so?
It would make nsIFrame look more like "an interface to frames" rather than "algorithms which involve frames". Maybe this is a distinction not worth making.
Yeah, ok. That makes sense.
Comment on attachment 126101 [details] [diff] [review] checkin-able subset >+ nsRect GetRect() const { return mRect; } How about: const nsRect& GetRect() const { return mRect; } (which shouldn't be slower for any uses (since clients can always copy into their own nsRect, and could be faster for clients that assign to |const nsRect&| or just use members directly) and maybe even a non-const version instead of |SetRect|? >+ nsFrameState GetFrameState() { return mState; } >+ void SetFrameState(nsFrameState aNewState) { mState = aNewState; } How about using what you had in the previous patch instead of this, which was: + nsFrameState GetStateBits() { return mState; } + void AddStateBits(nsFrameState aBits) { mState |= aBits; } + void RemoveStateBits(nsFrameState aBits) { mState &= ~aBits; } I liked that better. Could you also rename the new-style version of |GetParentWithView| to |GetAncestorWithView|? >-NS_IMETHODIMP nsFrame::GetParentWithView(nsIPresContext* aPresContext, >- nsIFrame** aParent) const >+nsIFrame* nsIFrame::GetParentWithView() const > { >- NS_PRECONDITION(nsnull != aParent, "null OUT parameter pointer"); >- > nsIFrame* parent; >- for (parent = mParent; nsnull != parent; parent->GetParent(&parent)) { >+ for (parent = mParent; nsnull != parent; parent = parent->GetParent()) { Could you call the variable something other than |parent| (maybe |f|), and declare it inside the for-loop expression? > /* virtual */ PRBool >-nsIFrame::AreAncestorViewsVisible(nsIPresContext* aPresContext) >+nsIFrame::AreAncestorViewsVisible() const > { >- for (nsIView* view = GetClosestView(aPresContext); >+ for (nsIView* view = GetClosestView(); > view; view->GetParent(view)) { If these lines now fit under 80 chars, could you recombine? >-NS_IMETHODIMP nsFrame::GetWindow(nsIPresContext* aPresContext, >- nsIWidget** aWindow) const >+nsIWidget* nsIFrame::GetWindow() const > { >- NS_PRECONDITION(nsnull != aWindow, "null OUT parameter pointer"); >- > nsIFrame* frame; Could you make this a |const nsIFrame*| and move it into the for-loop's expression? > nsIWidget* window = nsnull; >- for (frame = (nsIFrame*)this; nsnull != frame; frame->GetParentWithView(aPresContext, &frame)) { >+ for (frame = (nsIFrame*)this; nsnull != frame; frame = frame->GetParentWithView()) { and skip the cast, and the "nsnull !=", and if that doesn't get it under 80 chars, break the line? With those changes, r+sr=dbaron.
Attachment #126101 - Flags: superreview?(dbaron)
Attachment #126101 - Flags: superreview+
Attachment #126101 - Flags: review?(dbaron)
Attachment #126101 - Flags: review+
> (which shouldn't be slower for any uses (since clients can always copy into > their own nsRect, and could be faster for clients that assign to |const > nsRect&| or just use members directly) I think it's slightly cleaner to return the *current* rect than to return a reference to a rect that will change if the frame changes size or position, but OK. > and maybe even a non-const version > instead of |SetRect|? I think I'll pass on this one. We might conceivably want to be able to track actual changes to the rect. > I liked that better. Hmm, sure, so do I actually :-). > Could you also rename the new-style version of |GetParentWithView| to > |GetAncestorWithView|? Sure > Could you call the variable something other than |parent| (maybe |f|), Sure > and declare it inside the for-loop expression? Isn't that deprecated because of different compiler interpretations of the scope? I'll do it anyway since it won't matter here. > If these lines now fit under 80 chars, could you recombine? Sure > Could you make this a |const nsIFrame*| Sure > and move it into the for-loop's expression? OK > and skip the cast, and the "nsnull !=", and if that doesn't get it under 80 > chars, break the line? Sure. Thanks!
> I think it's slightly cleaner to return the *current* rect than to return a > reference to a rect that will change if the frame changes size or position, but > OK. But if that's what someone wants, wouldn't the |const nsRect&| syntax raise a red flag? (Maybe not, though, since it could be seen as binding a temporary to a reference.) (I never learned the rules for how many times the copy-constructor gets called in the various use cases for your version...)
> But if that's what someone wants, wouldn't the |const nsRect&| syntax raise a > red flag? Probably someone would just copy manually with nsRect r = frame->GetRect(). I'm just saying that the copy semantics is the cleaner default. > I never learned the rules for how many times the copy-constructor gets called > in the various use cases for your version... Since it's inline, I don't think it really matters; the compiler should always be able to get away with just one copy (or less; only the fields which are used need to be copied).
After bug 206682, I have very little faith in the ability of compilers to optimize code the way I think they ought to.
I asked scc about this a while ago and he claimed that nsRect r = frame->GetRect(); (as I've defined it) could be treated as equivalent to frame->GetRect(&r); so we should be OK. After checking this in, shall I just go ahead and check in updates of callers to the new methods? Or do you want review of those changes?
I checked in the patch with nsRect GetRect(). Changing it to const nsRect& in the future will be easy if that's necessary.
After I check in a few more changes this afternoon, I'll have finished layout/html/base/src. I'll move on to layout/html/forms/src. A few observations: -- Lots more interfaces should be deCOMtaminated... -- Lots of nsCOMPtrs can be converted to weak pointers. I think this is responsible for a lot of the code size savings. -- The code size saving in gcc is often 2x the size saved in VC++ ... this implies something very sad about gcc code generation. -- We should document when methods can never return null (e.g., nsIPresContext::GetViewManager, nsIView::GetViewManager, nsIFrame::GetParent() for non-viewport frames) and eliminate unncessary null checks. They uglify the code and probably create unnecessary and costly alternative exit paths. -- Some frames have an mPresContext member, which should be removed.
OK, now I've done everything under view/, layout/html/, and layout/base/. Next up, layout/xul/, layout/svg/ and layout/mathml/.
This fixes a few mistakes (with the last of them, I'm not sure whether it was intended -- but I do want to look at the code some more) in the first third or so of what roc's checked in under my rubber-stamp review, and also cleans up a few things I noticed while reviewing.
Should I stop using the rubberstamp and go back to normal review?
This contains all the changes to layout/xul, which are the last changes under layout/. Shall I check this in under rubber-stamp or do you want to review them first?
I reviewed it myself, caught a couple of errors, and checked it in.
I just checked in the changes for content/.
Here's the final patch that cleans up the last uses of the deprecated methods and removes the deprecated methods. This patch involves changes to platform-specific code (and may reveal places that my build doesn't build where I missed some changes), so it's the riskiest of the lot. However, there is really nothing interesting going on here so unless I hear otherwise I'll check it in under rubber-stamp and watch Tinderbox carefully.
Comment on attachment 127609 [details] [diff] [review] review "comments" on part of what I rubber-stamped oh, for some reason I thought we'd already checked this in. I can check this in too if you like.
Attachment #127609 - Flags: superreview?(roc)
Attachment #127609 - Flags: superreview+
Attachment #127609 - Flags: review?(roc)
Attachment #127609 - Flags: review+
Checked in both of those patches and fixed bustage. woohoo.
FYI, I'm now working up a patch to convert GetFrameType to NS_IMETHOD_(nsIAtom*) GetType();
Attached patch fix GetFrameType() -> GetType (obsolete) — Splinter Review
As promised. This is a simple one; the signature changes in nsIFrame.h to "virtual nsIAtom* GetType()" and everything else follows from that.
Comment on attachment 133872 [details] [diff] [review] fix GetFrameType() -> GetType Boris, another giant cleanup patch for you to review. Note: if you just rubber-stamp it, I won't tell :-)
Attachment #133872 - Flags: superreview?(bzbarsky)
Attachment #133872 - Flags: review?(bzbarsky)
Comment on attachment 133872 [details] [diff] [review] fix GetFrameType() -> GetType >Index: layout/base/src/nsFrameTraversal.cpp >+ nsIAtom* atom = grandParent->GetType(); >+ if ( atom ) > { > #ifdef DEBUG_skamio How about moving the if (atom) check inside the ifdef? And hoisting the code that runs in opt builds out of the body of this if? >Index: layout/base/src/nsLayoutUtils.cpp > } >- >+ > if (aContent && aFrame->GetContent() != aContent) { Let the whitespace be. ;) >Index: layout/html/base/src/nsFrame.cpp >@@ -3264,16 +3262,13 @@ nsFrame::GetNextPrevLineFromeBlockFrame( >- nsIAtom *resultFrameType; >- if(NS_SUCCEEDED(resultFrame->GetFrameType(&resultFrameType)) && resultFrameType) >- { >- if (resultFrameType == nsLayoutAtoms::tableOuterFrame) >+ if (resultFrame->GetType() == nsLayoutAtoms::tableOuterFrame) That code needs to get outdented, right? Please do that. >Index: layout/html/base/src/nsHTMLReflowState.cpp >- if (IS_TABLE_CELL(fType.get())) { >+ if (IS_TABLE_CELL(parentReflowState->frame->GetType())) { IS_TABLE_CELL is a macro that uses the type more than once... you may want to store the type in a temporary here as before. >@@ -1656,15 +1642,13 @@ static void > CheckResetTableDerivedComputedWidth(nsHTMLReflowState& aState, >+ if (!IS_TABLE_CELL(aState.parentReflowState->frame->GetType())) { Again. >Index: layout/html/style/src/nsCSSFrameConstructor.cpp > GetOuterTableFrame(nsIFrame* aParentFrame) > { >+ if (nsLayoutAtoms::tableOuterFrame == aParentFrame->GetType()) { >+ return aParentFrame; > } > else { >- parent = aParentFrame->GetParent(); >+ return aParentFrame->GetParent(); else after return... >@@ -10947,24 +10877,19 @@ nsCSSFrameConstructor::CreateContinuingF >+ if (IS_TABLE_CELL(cellFrame->GetType())) { IS_TABLE_CELL again. >Index: layout/html/table/src/nsCellMap.cpp >@@ -1342,23 +1342,19 @@ PRBool nsCellMap::CellsSpanOut(nsIPresCo >+ if (IS_TABLE_CELL(cellFrame->GetType())) { >@@ -1487,18 +1483,15 @@ nsCellMap::ExpandWithRows(nsIPresContext >+ if (IS_TABLE_CELL(cFrame->GetType())) { >@@ -1898,18 +1891,15 @@ nsCellMap::RebuildConsideringRows(nsIPre >+ if (IS_TABLE_CELL(cFrame->GetType())) { Again, all three times. >Index: layout/html/table/src/nsTableCellFrame.cpp >@@ -98,15 +98,13 @@ nsTableCellFrame::~nsTableCellFrame() >+ if (IS_TABLE_CELL(childFrame->GetType())) { And here. >Index: layout/html/table/src/nsTableFrame.cpp >@@ -473,15 +470,13 @@ nsTableFrame::IsPercentageBase(PRBool& a >+ if (IS_TABLE_CELL(aFrame->GetType())) { And here. >@@ -1206,15 +1191,13 @@ void nsTableFrame::RemoveRows(nsIPresCon >+ if (IS_TABLE_CELL(kidFrame->GetType())) { Again. >@@ -7051,15 +7005,13 @@ nsReflowTimer* GetFrameTimer(nsIFrame* a >+ if (IS_TABLE_CELL(parentFrame->GetType())) { And here. > void nsTableFrame::DebugReflowDone(nsIFrame* aFrame) >+ if (IS_TABLE_CELL(aFrame->GetType())) { And here. >Index: layout/html/table/src/nsTableRowFrame.cpp >@@ -224,15 +224,13 @@ nsTableRowFrame::AppendFrames(nsIPresCon >+ if (IS_TABLE_CELL(childFrame->GetType())) { >@@ -259,15 +257,13 @@ nsTableRowFrame::InsertFrames(nsIPresCon >+ if (IS_TABLE_CELL(childFrame->GetType())) { >@@ -294,15 +290,13 @@ nsTableRowFrame::RemoveFrame(nsIPresCont >+ if (IS_TABLE_CELL(aOldFrame->GetType())) { > nsTableRowFrame::GetFirstCell() >+ if (IS_TABLE_CELL(childFrame->GetType())) { >@@ -379,15 +369,13 @@ nsTableRowFrame::DidResize(nsIPresContex >+ if (IS_TABLE_CELL(childFrame->GetType())) { >@@ -515,15 +503,13 @@ nsTableRowFrame::CalcHeight(const nsHTML >+ if (IS_TABLE_CELL(kidFrame->GetType())) { >@@ -1502,15 +1487,13 @@ nsTableRowFrame::InsertCellFrame(nsTable >+ if (!IS_TABLE_CELL(child->GetType())) { And here, all seven times. >Index: layout/mathml/base/src/nsMathMLmoFrame.cpp >+nsMathMLmoFrame::GetType() const Bunch of else-after-return stuff in here.... r+sr=bzbarsky with those nits picked (I could go either way on the IS_TABLE_CELL thing, so it's your call).
Attachment #133872 - Flags: superreview?(bzbarsky)
Attachment #133872 - Flags: superreview+
Attachment #133872 - Flags: review?(bzbarsky)
Attachment #133872 - Flags: review+
Maybe IS_TABLE_CELL should be a function instead, with an nsIFrame* parameter? Then decisions on what to inline could be made without changing callers.
Yeah, that's the other option. That'd be nice, in fact.
> How about moving the if (atom) check inside the ifdef? > And hoisting the code that runs in opt builds out of the body of this if? Good idea > That code needs to get outdented, right? Please do that. OK > else after return... OK > IS_TABLE_CELL is a macro that uses the type more than once... you may want to > store the type in a temporary here as before. I think the right thing to do is to make IS_TABLE_CELL an inline function. (Why ever use a macro when an inline function will do?) However, I'll have it just take the frame type as a parameter as it does now. That way, any call sites that already have the type available can just pass it in.
Attached patch fixSplinter Review
Basically the same as before, but I added bz's comments, and see the final change to nsLayoutAtoms.h. Making IS_TABLE_CELL be a simple static inline function, no name change, is a bit cheezy but it should cause no problems.
Attachment #133872 - Attachment is obsolete: true
Checked in the patch. Satisfying Tp decrease.
I'm working on converting FirstChild and GetAdditionalChildListName. They become virtual nsIFrame* GetFirstChild(nsIAtom* aListName); virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex); The existing FirstChild documents a special error code to distinguish between an empty child list and a child list that the frame doesn't support ... but so far, I haven't found anything that actually cares. One can always figure out if the frame supports a particular child list by iterating with GetAdditionalChildListName.
Comment on attachment 134972 [details] [diff] [review] patch as described hey bz, another giant patch for you :-).
Attachment #134972 - Flags: superreview?(bz-vacation)
Attachment #134972 - Flags: review?(bz-vacation)
It'll take me a few days; I have prior review commitments that I'm already way behind on...
Comment on attachment 134972 [details] [diff] [review] patch as described >Index: layout/html/base/src/nsBlockFrame.cpp >+nsBlockFrame::GetFirstChild(nsIAtom* aListName) const This function has lots of else-after-returns now.. Is that necessary? >Index: layout/html/base/src/nsContainerFrame.cpp >+nsContainerFrame::GetFirstChild(nsIAtom* aListName) const Same. >+nsContainerFrame::GetAdditionalChildListName(PRInt32 aIndex) const Same. >Index: layout/html/base/src/nsFrame.cpp > #define HUGE_DISTANCE 999999 //some HUGE number that will always fail first comparison I know you didn't write this, but how about changing this to PR_INT32_MAX as long as you're here? >@@ -3000,22 +2990,18 @@ nsFrame::SetSelected(nsIPresContext* aPr >+ nsIFrame* kid = GetFirstChild(nsnull); >+ while (nsnull != kid) { while (kid) { >- result = frame->FirstChild(aPresContext, nsnull,&frame); >+ frame = frame->GetFirstChild(nsnull); > if (frame && NS_SUCCEEDED(result)) > { > result = frame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator), > getter_AddRefs(iter)); Again, not your code but how about |iter = do_QueryInterface(frame);| ? >Index: layout/html/base/src/nsHTMLContainerFrame.cpp >@@ -376,27 +374,24 @@ ReparentFrameViewTo(nsIPresContext* aPre >+ nsIFrame* childFrame = aFrame->GetFirstChild(listName); > for (; childFrame; childFrame = childFrame->GetNextSibling()) { Any reason to not move the childFrame initialization into the first clause of the for() ? >Index: layout/html/base/src/nsInlineFrame.cpp >@@ -687,15 +687,13 @@ void MarkPercentAwareFrame(nsIPresContex > SetContainsPercentAwareChild(aInline); // if a child container is effected, so am I Again not your code, but "affected".... I've made it to the beginning of nsComboboxControlFrame.cpp; more later.
Sure, I can fix all those.
I'm going to try to get this review done before freeze, but I'm not sure I can pull it off. :(
It won't kill me if you don't get to it before freeze.
Comment on attachment 133907 [details] [diff] [review] fix This have added two "might be used uninitialized" warnings on brad TBox: +layout/html/base/src/nsHTMLReflowState.cpp:1709 + `nsIAtom*fType' might be used uninitialized in this function ++layout/html/base/src/nsPresShell.cpp:4344 + `nsIAtom*frameType' might be used uninitialized in this function
> ++layout/html/base/src/nsPresShell.cpp:4344 > + `nsIAtom*frameType' might be used uninitialized in this function This warning is completely bogus as a trivial analysis of the code shows (frameType not initialized implies aFrame is null implies there are no accesses to frameType at all). The other warning is also bogus, but that's not nearly as obvious (same kind of issue -- the access is protected by an if() condition that, if satisfied, would have forced the variable being set earlier; just much further apart). Here it may make sense to init fType to null....
Comment on attachment 134972 [details] [diff] [review] patch as described >Index: layout/html/tests/TestInlineFrame.cpp >- for (FirstChild(f); nsnull != f; f->GetNextSibling(f)) { >+ for (GetFirstChild(f); nsnull != f; f->GetNextSibling(f)) { That's not the same FirstChild()... Though I doubt this code builds either way. >Index: layout/xul/base/src/nsBoxObject.cpp I assume we still need mPresShell in that file, even with this change? But see comment on mPresContext following. >Index: layout/xul/base/src/nsMenuBarFrame.cpp Similar here with mPresContext? We should probably file a separate bug to move all mPresContext-using frames over to getting it off the style context.... >Index: layout/xul/base/src/nsMenuFrame.cpp >+nsMenuFrame::GetFirstChild(nsIAtom* aListName) const else-after-return in this method. >Index: layout/xul/base/src/nsPopupBoxObject.cpp More mPresShell stuff here (separate bug, as above). r+sr=bzbarsky with that.
Attachment #134972 - Flags: superreview?(bz-vacation)
Attachment #134972 - Flags: superreview+
Attachment #134972 - Flags: review?(bz-vacation)
Attachment #134972 - Flags: review+
Thanks for that. Certainly all frames can lose their mPresContext members. I'll file a bug for that. I'll look into removing mPresShell and file a bug if necessary.
I checked this in (after fixing up considerable rot). It seems to have reduced Tp a little bit. A bit surprising considering the trivialness of the change, but perhaps it means more nsIFrame* locals can be held in registers.
Comment on attachment 134972 [details] [diff] [review] patch as described This checking have added two "may be uninitialized" warnings to brad TBox: +layout/base/src/nsFrameTraversal.cpp:409 + `nsIFrame*result' might be used uninitialized in this function + +layout/base/src/nsFrameTraversal.cpp:749 + `nsIFrame*result' might be used uninitialized in this function +
I checked in a fix for those warnings.
This adding 3 other (actual !) warnings in <http://tinderbox.mozilla.org/SeaMonkey/warn1073661540.19272.html>: { evaughan 1. layout/xul/base/src/nsBox.cpp:806 (See build log excerpt) Unused variable `nsIPresContext*presContext' 804 nsBox::CollapseChild(nsBoxLayoutState& aState, nsIFrame* aFrame, PRBool aHide) 805 { 806 nsIPresContext* presContext = aState.GetPresContext(); 807 808 // shrink the view karnaze 14. layout/html/table/src/nsTableRowGroupFrame.cpp:1561 (See build log excerpt) Unused variable `nsresult rv' 1559 { 1560 nsTableFrame* tableFrame = nsnull; 1561 nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame); 1562 if (!tableFrame) return 0; roc+ 2. layout/xul/base/src/nsSplitterFrame.cpp:652 (See build log excerpt) Unused variable `nsIFrame*thumbFrame' 650 nsSplitterFrameInner::AddListener(nsIPresContext* aPresContext) 651 { 652 nsIFrame* thumbFrame = mOuter->GetFirstChild(nsnull); 653 654 nsCOMPtr<nsIDOMEventReceiver> } The formers are old code, newly reported; The later is new code. Hints: line removal, (void) xxx, variable use... Thanks.
Robert, do you know any usage of ::ReplaceFrame other than to be called from ReplaceFrame?
I believe whatever LXR says.
Depends on: 396185
QA Contact: ian → layout
Blocks: deCOM
Should this bug still be open, five years later, with the new QueryFrame scheme that we have?
Assignee: roc → nobody
I'm going to claim this is fixed, more work can be done in followups.
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
Comment on attachment 128431 [details] [diff] [review] layout/xul changes > } else if (aAttribute == nsXULAtoms::acceltext) { > // someone reset the accelText attribute, so clear the bit that says *we* set it >- nsFrameState state; >- GetFrameState(&state); >- SetFrameState(state & ~NS_STATE_ACCELTEXT_IS_DERIVED); >+ AddStateBits(NS_STATE_ACCELTEXT_IS_DERIVED); This should be RemoveStateBits, no?
(In reply to comment #82) > >- SetFrameState(state & ~NS_STATE_ACCELTEXT_IS_DERIVED); > >+ AddStateBits(NS_STATE_ACCELTEXT_IS_DERIVED); > This should be RemoveStateBits, no? Obviously :-< That was checked in in http://bonsai.mozilla.org/cvslog.cgi?file=mozilla/layout/xul/base/src/nsMenuFrame.cpp&mark=1.251#1.252 (MOZILLA_1_5b_RELEASE, etc) Then code was modified in http://hg.mozilla.org/mozilla-central/rev/e4e653196488 Bug 583957, lazy menuframe update, r=enndeakin, sr=neil, a=dbaron (FIREFOX_4_0b4_BUILD1) That's bug 592424 ;->
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: