Closed Bug 1736069 Opened 3 years ago Closed 2 years ago

Crash in [@ webrender::spatial_tree::SceneSpatialTree::add_spatial_node] caused by retained display lists

Categories

(Core :: Graphics: WebRender, defect, P2)

Firefox 95
Desktop
All
defect

Tracking

()

VERIFIED FIXED
100 Branch
Tracking Status
thunderbird_esr91 --- unaffected
firefox-esr78 --- unaffected
firefox-esr91 --- unaffected
firefox93 --- unaffected
firefox94 --- unaffected
firefox95 --- wontfix
firefox96 --- wontfix
firefox97 --- wontfix
firefox98 --- wontfix
firefox99 --- verified
firefox100 + verified

People

(Reporter: calixte, Assigned: mikokm)

References

(Blocks 2 open bugs, Regression)

Details

(Keywords: crash, regression, testcase-wanted)

Crash Data

Attachments

(2 files, 1 obsolete file)

Maybe Fission related. (DOMFissionEnabled=1)

Crash report: https://crash-stats.mozilla.org/report/index/284b2034-ab5c-4299-9559-a486a0211015

Reason: EXCEPTION_BREAKPOINT

Top 10 frames of crashing thread:

0 xul.dll RustMozCrash mozglue/static/rust/wrappers.cpp:17
1 xul.dll mozglue_static::panic_hook mozglue/static/rust/lib.rs:91
2 xul.dll core::ops::function::Fn::call<void  ../c8dfcfe046a7680554bf4eb612bad840e7631c4b/library/core/src/ops/function.rs:227
3 xul.dll std::panicking::rust_panic_with_hook ../c8dfcfe046a7680554bf4eb612bad840e7631c4b//library/std/src/panicking.rs:626
4 xul.dll std::panicking::begin_panic_handler::closure$0 ../c8dfcfe046a7680554bf4eb612bad840e7631c4b//library/std/src/panicking.rs:517
5 xul.dll std::sys_common::backtrace::__rust_end_short_backtrace<std::panicking::begin_panic_handler::closure$0, never$> ../c8dfcfe046a7680554bf4eb612bad840e7631c4b//library/std/src/sys_common/backtrace.rs:141
6 xul.dll std::panicking::begin_panic_handler ../c8dfcfe046a7680554bf4eb612bad840e7631c4b//library/std/src/panicking.rs:515
7 xul.dll core::panicking::panic_fmt ../c8dfcfe046a7680554bf4eb612bad840e7631c4b//library/core/src/panicking.rs:92
8 xul.dll core::panicking::panic ../c8dfcfe046a7680554bf4eb612bad840e7631c4b//library/core/src/panicking.rs:50
9 xul.dll webrender::spatial_tree::SceneSpatialTree::add_spatial_node gfx/wr/webrender/src/spatial_tree.rs:429

There are 6 crashes (from 1 installation) in nightly 95 with buildid 20211014212856. In analyzing the backtrace, the regression may have been introduced by patch [1] to fix bug 1734740.

[1] https://hg.mozilla.org/mozilla-central/rev?node=f664ac371d87

Flags: needinfo?(gwatson)

This is hitting an assert that was deliberately added to try and catch any logic errors in Gecko where more than one spatial node are being assigned the same unique identifier key.

Do we have any repro steps and/or URLs as the low crash rate of this means we'll need to repro to find the edge case that can result in this occurring?

Flags: needinfo?(gwatson)

Hey Glenn. I'm not sure if your question was for Calixte or someone else, but could you needinfo the intended recipient? I'm the engineering REO for Firefox 95 and want to make sure this bug doesn't slip through the cracks. Thanks!

Flags: needinfo?(gwatson)
Flags: needinfo?(gwatson) → needinfo?(cdenizet)

URLs from crash-stats are a private information, so I sent them to :gw by email.

Flags: needinfo?(cdenizet)

Thanks for sending those URLs. Unfortunately I haven't been able to reproduce with any of those, with or without fission enabled. However, it looks like there might be some tier2 intermittent failure bugs that look similar - I'll see if I can reproduce with any of those.

I have added some extra debug info in https://bugzilla.mozilla.org/show_bug.cgi?id=1738141 to hopefully help in tracking this down.

:gw: do you have anymore info on this crash?

Flags: needinfo?(gwatson)

This seems to still be happening, but I haven't seen any intermittent CI failures with the new logs yet (unless I'm looking at the wrong bugzilla bugs, none of them seem to have new intermittent failures mentioned?). I'll kick off some more try runs today and see if I can reproduce with the updated logging information.

Flags: needinfo?(gwatson)
Assignee: nobody → gwatson

From looking through the recent crash reports, most seem to be either:

duplicate key SpatialNodeUid { kind: InternalReferenceFrame, pipeline_id: PipelineId(1, 463) }

or

duplicate key SpatialNodeUid { kind: External { key: SpatialTreeItemKey { key0: 4892765728, key1: 73 } }, pipeline_id: PipelineId(1, 38) }

The second one is somewhat expected given the crashes we're seeing, the first one is not.

It's hard to know without being able to reproduce this (yet), but for the InternalReferenceFrame assert to fire, one possibility is that a display list is being supplied to WR that has two iframe display items which reference the same pipeline_id.

There may be other ways that this assert could occur, but I can't think of any right now.

Am I right in assuming that this should never occur and if it was, it's some kind of fission bug?

Flags: needinfo?(tnikkel)

In normal operation I think that's correct, however when printing we "replicate" frames in fixed pos (nsCSSFrameConstructor::ReplicateFixedFrames), that could possible lead to more than one iframe display item for the same iframe element, and there might be other situations where we do something with duplicating display items, I remember Matt talking about it, but I forget the specifics right now.

Flags: needinfo?(tnikkel)

And a bug in retained display lists could mean we create a new iframe (gecko) display item while the old one is still mistakenly in the display list, but we usually have asserts to catch most of these problems sooner.

Maybe miko can add to this.

Flags: needinfo?(mikokm)

I just came across nsSubDocumentFrame::mRetainedRemoteFrame while reading code for something else, which is used to paint the previous document in an iframe until the next one is ready to paint, some sort of confusion with that could possibly cause this.

I've created https://bugzilla.mozilla.org/show_bug.cgi?id=1741714, a small patch that asserts the same pipeline_id isn't seen twice during a scene build. If we see any crash reports from that patch, we'll at least know that it's the root cause of the crashes here.

OK, so we have some crash reports coming from that new assert now [1].

This confirms that what is being supplied to WR is a display list that has multiple iframe element(s) that reference the same pipeline id, which will be the cause of this assert (in at least one case, there may be another case occurring).

Timothy, any ideas on how we might try repro this, given your comments 10-13? I guess one way might be to try create an iframe that stretches across multiple pages when printing?

[1] https://crash-stats.mozilla.org/signature/?product=Firefox&version=96.0a1&signature=webrender%3A%3Ascene_building%3A%3ASceneBuilder%3A%3Abuild&date=%3E%3D2021-11-21T21%3A05%3A00.000Z&date=%3C2021-11-28T21%3A05%3A00.000Z&_columns=date&_columns=product&_columns=version&_columns=build_id&_columns=platform&_columns=reason&_columns=address&_columns=install_time&_columns=startup_crash&_sort=-date&page=1#reports

Flags: needinfo?(tnikkel)

One thing I could do is change WR so that if it encounters the same iframe display item twice, it skips recursing in to it and adding it a second time.

This would prevent the assert / panic. It might result in some kind of visible artifact that gets reported as a different bug with better repro steps? (though - this scenario has never really been supported in WR, at best you'll get duplicated iframe contents from whichever was the most recently updated display list for that pipeline id, so it's not clear what will actually be seen in this case).

Removing the panic might also make it harder to get a repro case. Thoughts?

See Also: → 1743152
Blocks: wr-stability
See Also: → 1728118

I can finally reproduce the debugging assert - this test case https://bugzilla.mozilla.org/show_bug.cgi?id=1743152 is hitting the seen_pipeline_ids assert. Now to figure out if it's something that's a bug in Gecko we can fix up, or if it's something more fundamental / complex to fix and we need a WR workaround.

The patch in https://bugzilla.mozilla.org/show_bug.cgi?id=1743152#c8 should fix either all, or at least the majority, of these crashes (I think there might be two separate causes of this).

Flags: needinfo?(mikokm)

I think I've answered the needinfo here. Please request again if I'm mistaken.

Flags: needinfo?(tnikkel)
No longer blocks: 1734740
OS: Windows 11 → All
Hardware: Unspecified → Desktop

Looks like we're still seeing these crashes on 96/97, but I guess we're waiting to see what happens when 96 ships next week compared to 95 to see how much of an effect bug 1743152 had?

Looks like the crash volume on 96 is substantially lower than 95, so bug 1743152 made a pretty big difference. Leaving this bug open for the remaining crashes, however.

Has Regression Range: --- → yes

I've found one reliable way to replicate this crash, unfortunately you need to have a cloudflare account.

Steps to reproduce:

  1. Login to cloudflare dashboard
  2. select a domain you have (to enter the domain overview)
  3. select duplicate tab with RMB on tab
    -> crash

alternative to step 3
copy a link from the menu (for example DNS) and paste it to the address bar of a new tab
-> crash

Blocks: gfx-triage

Henri, can you try reproducing this on release Firefox with layout.display-list.retain=false?

Flags: needinfo?(cg+zbmvyynohtmvyyn)

(In reply to Jeff Muizelaar [:jrmuizel] from comment #24)

Henri, can you try reproducing this on release Firefox with layout.display-list.retain=false?

I tried this on 96.0.3 (64-bit), archlinux package version.
With the default setting layout.display-list.retain=true, it crashes reliably

setting layout.display-list.retain=false prevents the crash

If you want, I can try it on mozilla.org binary as well.

Flags: needinfo?(cg+zbmvyynohtmvyyn)

Miko, it looks like retained display lists are to blame.

Flags: needinfo?(mikokm)
Summary: Crash in [@ webrender::spatial_tree::SceneSpatialTree::add_spatial_node] → Crash in [@ webrender::spatial_tree::SceneSpatialTree::add_spatial_node] caused by retained display lists

STR from bug 1755234

  1. Set layout.display-list.retain.sc = False
  2. Optional : Enable cloudflare DOH in Nightly
  3. Create an account on cloudflare. A free account is sufficient, premium not required.
  4. Go to https://dash.cloudflare.com/
  5. Go to Websites-> add a website.
  6. Input "example.org" as your website
  7. Click on "example.org" setup
  8. On the left panel, click on "DNS" . A page will open
  9. Refresh the page by pressing F5

Crash

Assignee: gwatson → nobody

Miko, what do you think about running the STRs in Comment 28 through Pernosco and see what we get?

Hey folks, Harley from Cloudflare here. We're still receiving the occasional crash report from customers on this, but we've been unable to get a reproducable test case up and running locally (even by following the steps outlined above in #28).

From our customers that can reproduce this reliably it does look like the latest Nightly fixes this, but is there anything we can do in the meantime to help debug? If there's a specific suspect DOM structure or state transition we're doing, we'll be more than happy to get an isolated test case together, just let me know.

Flags: needinfo?(mikokm)
Flags: needinfo?(mikokm)

I cannot reproduce this locally on Linux or Windows, with Nightly or with release Firefox.

Flags: needinfo?(mikokm)

Because most of the crashes appear to be on Mac, I also tried Nightly and release Firefox on MacOS 12 - could not reproduce.

(In reply to Miko Mynttinen [:miko] from comment #33)

Because most of the crashes appear to be on Mac, I also tried Nightly and release Firefox on MacOS 12 - could not reproduce.

I can repro the STR with a DPI of 150% (Win11x64, AMD iGPU)

(In reply to Mayank Bansal from comment #34)

(In reply to Miko Mynttinen [:miko] from comment #33)

Because most of the crashes appear to be on Mac, I also tried Nightly and release Firefox on MacOS 12 - could not reproduce.

I can repro the STR with a DPI of 150% (Win11x64, AMD iGPU)

Still could not reproduce.

Keywords: testcase-wanted

Happy to run any debug/instrumented build and collect logs

If it's useful, I have a Win11 AMD iGPU machine.

I'll try to repro.

Assignee: nobody → jgilbert

Setup:

  1. Create an account on cloudflare. A free account is sufficient, premium not required.
  2. Go to https://dash.cloudflare.com/
  3. Go to Websites-> add a website.
  4. Input "example.org" as your website
  5. Choose free tier

Repro:

  1. Set layout.display-list.retain.sc = False
  2. Go to https://dash.cloudflare.com/
  3. On the left panel, click on "DNS" . A page will open
  4. Zoom page to 150% (e.g. shift+ctrl+plus)
  5. Refresh the page by pressing F5
  6. Possibly observe gpu process crash?
  7. about:crashes contains a new crash

This is on my Win11 AMD iGPU machine, on both Release97.0.1, and Nightly99-2022-03-04
Crash on Release97: https://crash-stats.mozilla.org/report/index/7243c118-b72e-40a0-a30c-725a30220304
Crash on Nightly99: https://crash-stats.mozilla.org/report/index/871c502e-da7c-4cba-9ecb-896730220304

@gw: Anything I can do to help, since I can repro? Does zooming allow it to repro for you? I think I only started seeing this after I started zooming.

Flags: needinfo?(gwatson)

Although it triggers an assert in WR, it seems to be caused by (what I'm assuming is) a bug in the gecko DL generation code, possibly related to retained display lists. Might be something that Miko can take a look at?

Flags: needinfo?(gwatson)

Miko, can you pick up the assignment on this, please?

Flags: needinfo?(mikokm)
Assignee: jgilbert → mikokm
Status: NEW → ASSIGNED
Flags: needinfo?(mikokm)
Priority: -- → P3
No longer blocks: gfx-triage

I can reproduce this in Nightly 100.0a1 on Linux/X11, also when using the CloudFlare dashboard. The first time I saw a crash was after expanding the "Security" section (click on ▼) on the navigation panel.

Report: https://crash-stats.mozilla.org/report/index/efc50dde-8bd0-4231-acda-f75620220318

[Tracking Requested - why for this release]: This is a reproducible crash multiple people are hitting in CloudFlare, apparently with enterprise plans.

Changing the priority to P2 as the bug is tracked by a release manager for the current nightly.
See Triage for Bugzilla for more information.
If you disagree, please discuss with a release manager.

Priority: P3 → P2
Attached file display-list.txt (obsolete) —

The problem here is that Gecko generated display list contains display items with duplicate (frame, perFrameKey) pairs.

I think that display list merging gets confused here where both StickyPosition and nsDisplayContainer have identical contents. This implies that either that sticky position style has changed without invalidation (and been replaced with nsDisplayContainer), or that nsDisplayContainer has been added without invalidation.

    StickyPosition p=0x7f4ce19308f0 f=0x7f4ce12e54c8(Block(footer)(1) class:c_da c_cm c_dc c_db c_ej c_j) key=56 z=1 bounds(0,40260,3360,3600) componentAlpha(0,0,0,0) clip() asr(<0x7f4ce121fc40>) clipChain(0x7f4ce117ab58 <0,3780,3360,40110> [0x7f4ce121fc40], 0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  (opaque 0,40260,3360,3600) reuse-state(None) (flags 0x0) (scrolltarget 0)
      CompositorHitTestInfo p=0x7f4ce07ab328 f=0x7f4ce12e54c8(Block(footer)(1) class:c_da c_cm c_dc c_db c_ej c_j) key=25 z=1 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,40110) asr(<0x7f4ce121fc40>) clipChain(0x7f4ce117ab58 <0,3780,3360,40110> [0x7f4ce121fc40], 0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  hitTestInfo(0x1) hitTestArea(0,40260,3360,3600) reuse-state(None)
      BackgroundColor p=0x7f4ce07aa500 f=0x7f4ce12e5590(HTMLButtonControl(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=6 bounds(0,40260,3360,3600) componentAlpha(0,0,0,0) clip(0,3780,3360,40110) asr(<0x7f4ce121fc40>) clipChain(0x7f4ce117ab58 <0,3780,3360,40110> [0x7f4ce121fc40], 0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr]) uniform  (opaque 0,40260,3360,3600) hitTestInfo(0x1) hitTestArea(0,40260,3360,3600) reuse-state(None) (rgba 1,1,1,1) backgroundRect(x=0, y=40260, w=3360, h=3600)
      ButtonBorderBackground p=0x7f4ce07b1970 f=0x7f4ce12e5590(HTMLButtonControl(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=12 bounds(0,40260,3360,3600) componentAlpha(0,0,0,0) clip(0,3780,3360,40110) asr(<0x7f4ce121fc40>) clipChain(0x7f4ce117ab58 <0,3780,3360,40110> [0x7f4ce121fc40], 0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  reuse-state(None)
      CompositorHitTestInfo p=0x7f4ce07ab278 f=0x7f4ce12e5648(Block(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,40110) asr(<0x7f4ce121fc40>) clipChain(0x7f4ce117ab58 <0,3780,3360,40110> [0x7f4ce121fc40], 0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  hitTestInfo(0x1) hitTestArea(0,40260,3360,3600) reuse-state(None)
      CompositorHitTestInfo p=0x7f4ce07ab1c8 f=0x7f4ce12e5710(FlexContainer(div)(0) class:c_r c_bg c_ao c_er c_ec c_c c_j) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,40110) asr(<0x7f4ce121fc40>) clipChain(0x7f4ce117ab58 <0,3780,3360,40110> [0x7f4ce121fc40], 0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  hitTestInfo(0x1) hitTestArea(0,40260,3360,3600) reuse-state(None)
      Border p=0x7f4ce117cee0 f=0x7f4ce12e5710(FlexContainer(div)(0) class:c_r c_bg c_ao c_er c_ec c_c c_j) key=9 bounds(0,40260,3360,60) componentAlpha(0,0,0,0) clip(0,3780,3360,40110) asr(<0x7f4ce121fc40>) clipChain(0x7f4ce117ab58 <0,3780,3360,40110> [0x7f4ce121fc40], 0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  reuse-state(None)
      CompositorHitTestInfo p=0x7f4ce07ab118 f=0x7f4ce12e57c0(FlexContainer(div)(0) class:c_dc c_bg c_r c_s c_c c_ed) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,40110) asr(<0x7f4ce121fc40>) clipChain(0x7f4ce117ab58 <0,3780,3360,40110> [0x7f4ce121fc40], 0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  hitTestInfo(0x1) hitTestArea(0,40320,3360,3540) reuse-state(None)
      nsDisplayTransform p=0x7f4ce1930728 f=0x7f4ce12e5958(SVGOuterSVGAnonChild(svg)(0) class:c_es c_cd c_am c_et) key=73 bounds(1337,41747,685,686) componentAlpha(0,0,0,0) clip(1260,41670,840,840) asr(<0x7f4ce121fc40>) clipChain(0x7f4ce1930440 <1260,41670,840,840> [0x7f4ce121fc40], 0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  reuse-state(None)[ 0.875 0; 0 0.875; 42 1389; ] prerender(no) childrenBuildingRect(x=89, y=89, w=781, h=783)
        SVGWrapper p=0x7f4ce19305e8 f=0x7f4ce12e5958(SVGOuterSVGAnonChild(svg)(0) class:c_es c_cd c_am c_et) key=60 bounds(89,89,781,782) componentAlpha(0,0,0,0) clip() asr(<0x7f4ce121fc40>) clipChain()  reuse-state(None)
          DisplaySVGGeometry p=0x7f4ce1930488 f=0x7f4ce12e5a08(SVGGeometry(path)(0)) key=58 bounds(89,89,434,782) componentAlpha(0,0,0,0) clip() asr(<0x7f4ce121fc40>) clipChain()  reuse-state(None)
          DisplaySVGGeometry p=0x7f4ce1930538 f=0x7f4ce12e5a88(SVGGeometry(path)(1)) key=58 bounds(436,89,434,782) componentAlpha(0,0,0,0) clip() asr(<0x7f4ce121fc40>) clipChain()  reuse-state(None)
    nsDisplayContainer p=0x7f4cdd4f51d8 f=0x7f4ce12e54c8(Block(footer)(1) class:c_da c_cm c_dc c_db c_ej c_j) key=26 z=1 bounds(0,40260,3360,3600) componentAlpha(0,0,0,0) clip() asr() clipChain()  (opaque 0,40260,3360,3600) reuse-state(None)
      CompositorHitTestInfo p=0x7f4ce1178df8 f=0x7f4ce12e54c8(Block(footer)(1) class:c_da c_cm c_dc c_db c_ej c_j) key=25 z=1 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,40080) asr() clipChain(0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  hitTestInfo(0x1) hitTestArea(0,40260,3360,3600) reuse-state(None)
      BackgroundColor p=0x7f4cdd4f4358 f=0x7f4ce12e5590(HTMLButtonControl(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=6 bounds(0,40260,3360,3600) componentAlpha(0,0,0,0) clip(0,3780,3360,40080) asr() clipChain(0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr]) uniform  (opaque 0,40260,3360,3600) hitTestInfo(0x1) hitTestArea(0,40260,3360,3600) reuse-state(None) (rgba 1,1,1,1) backgroundRect(x=0, y=40260, w=3360, h=3600)
      ButtonBorderBackground p=0x7f4cdd4f49b0 f=0x7f4ce12e5590(HTMLButtonControl(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=12 bounds(0,40260,3360,3600) componentAlpha(0,0,0,0) clip(0,3780,3360,40080) asr() clipChain(0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  reuse-state(None)
      CompositorHitTestInfo p=0x7f4ce1178bc0 f=0x7f4ce12e5648(Block(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,40080) asr() clipChain(0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  hitTestInfo(0x1) hitTestArea(0,40260,3360,3600) reuse-state(None)
      CompositorHitTestInfo p=0x7f4ce1178988 f=0x7f4ce12e5710(FlexContainer(div)(0) class:c_r c_bg c_ao c_er c_ec c_c c_j) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,40080) asr() clipChain(0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  hitTestInfo(0x1) hitTestArea(0,40260,3360,3600) reuse-state(None)
      Border p=0x7f4cdd4f3a10 f=0x7f4ce12e5710(FlexContainer(div)(0) class:c_r c_bg c_ao c_er c_ec c_c c_j) key=9 bounds(0,40260,3360,60) componentAlpha(0,0,0,0) clip(0,3780,3360,40080) asr() clipChain(0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  reuse-state(None)
      CompositorHitTestInfo p=0x7f4ce11791b8 f=0x7f4ce12e57c0(FlexContainer(div)(0) class:c_dc c_bg c_r c_s c_c c_ed) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,40080) asr() clipChain(0x7f4cdd4f6cb8 <0,3780,3360,40080> [root asr])  hitTestInfo(0x1) hitTestArea(0,40320,3360,3540) reuse-state(None)
      nsDisplayTransform p=0x7f4cdd4f3ad0 f=0x7f4ce12e5958(SVGOuterSVGAnonChild(svg)(0) class:c_es c_cd c_am c_et) key=73 bounds(1337,41747,685,686) componentAlpha(0,0,0,0) clip(1260,41670,840,840) asr() clipChain(0x7f4cdd4f9008 <1260,41670,840,840> [root asr])  reuse-state(None)[ 0.875 0; 0 0.875; 42 1389; ] prerender(no) childrenBuildingRect(x=89, y=89, w=781, h=783)
        SVGWrapper p=0x7f4cdd4f2980 f=0x7f4ce12e5958(SVGOuterSVGAnonChild(svg)(0) class:c_es c_cd c_am c_et) key=60 bounds(89,89,781,782) componentAlpha(0,0,0,0) clip() asr() clipChain()  reuse-state(None)
          DisplaySVGGeometry p=0x7f4cdd4f2770 f=0x7f4ce12e5a08(SVGGeometry(path)(0)) key=58 bounds(89,89,434,782) componentAlpha(0,0,0,0) clip() asr() clipChain()  reuse-state(None)
          DisplaySVGGeometry p=0x7f4cdd4f28d0 f=0x7f4ce12e5a88(SVGGeometry(path)(1)) key=58 bounds(436,89,434,782) componentAlpha(0,0,0,0) clip() asr() clipChain()  reuse-state(None)

After looking at the previous full display list build, I am leaning towards this being an invalidation issue with sticky position style:

Full display list build:
AsyncZoom p=0x7f38c471ecd8 f=0x7f38c4f941a8(HTMLScroll(html)(-1) class:no-js) key=2 bounds(0,0,56610,49740) componentAlpha(1001,1275,53239,44970) clip(0,0,56610,49740) asr() clipChain(0x7f38c471d170 <0,0,56610,49740> [root asr])  (opaque 0,0,56610,50040) reuse-state(None) (flags 0x0) (scrolltarget 0)
  FixedPosition p=0x7f38c4724738 f=0x7f38c63aeba0(HTMLScroll(aside)(0) class:c_d c_i c_cl c_cm c_h c_cn c_co c_cp c_cq c_cr c_cs c_ct c_cu c_b c_cv c_cw c_c c_cx) key=31 z=1201 bounds(0,3780,3420,45960) componentAlpha(1001,4935,1357,1230) clip(0,0,56610,49740) asr() clipChain(0x7f38c471d170 <0,0,56610,49740> [root asr])  (opaque 0,3780,3420,45960) reuse-state(None) (containerASR ) (scrolltarget 13)
    nsDisplayContainer p=0x7f38c4720d78 f=0x7f38c63894c8(Block(footer)(1) class:c_da c_cm c_dc c_db c_ej c_j) key=26 z=1 bounds(0,46140,3360,3600) componentAlpha(0,0,0,0) clip() asr() clipChain()  (opaque 0,46140,3360,3600) reuse-state(None)
      CompositorHitTestInfo p=0x7f38c4724db8 f=0x7f38c63894c8(Block(footer)(1) class:c_da c_cm c_dc c_db c_ej c_j) key=25 z=1 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None)
      BackgroundColor p=0x7f38c4723c28 f=0x7f38c6389590(HTMLButtonControl(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=6 bounds(0,46140,3360,3600) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr]) uniform  (opaque 0,46140,3360,3600) hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None) (rgba 1,1,1,1) backgroundRect(x=0, y=46140, w=3360, h=3600)
      ButtonBorderBackground p=0x7f38c4723d00 f=0x7f38c6389590(HTMLButtonControl(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=12 bounds(0,46140,3360,3600) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr])  reuse-state(None)
      CompositorHitTestInfo p=0x7f38c4e09878 f=0x7f38c6389648(Block(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None)
      CompositorHitTestInfo p=0x7f38c471e960 f=0x7f38c6389710(FlexContainer(div)(0) class:c_r c_bg c_ao c_er c_ec c_c c_j) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None)
      Border p=0x7f38c4723f18 f=0x7f38c6389710(FlexContainer(div)(0) class:c_r c_bg c_ao c_er c_ec c_c c_j) key=9 bounds(0,46140,3360,60) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr])  reuse-state(None)
      CompositorHitTestInfo p=0x7f38c4721d80 f=0x7f38c63897c0(FlexContainer(div)(0) class:c_dc c_bg c_r c_s c_c c_ed) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46200,3360,3540) reuse-state(None)
      nsDisplayTransform p=0x7f38c4724370 f=0x7f38c6389958(SVGOuterSVGAnonChild(svg)(0) class:c_es c_cd c_am c_et) key=73 bounds(1337,47627,685,686) componentAlpha(0,0,0,0) clip(1260,47550,840,840) asr() clipChain(0x7f38c4724088 <1260,47550,840,840> [root asr])  reuse-state(None)[ 0.875 0; 0 0.875; 42 1585; ] prerender(no) childrenBuildingRect(x=89, y=89, w=781, h=783)
        SVGWrapper p=0x7f38c4724230 f=0x7f38c6389958(SVGOuterSVGAnonChild(svg)(0) class:c_es c_cd c_am c_et) key=60 bounds(89,89,781,782) componentAlpha(0,0,0,0) clip() asr() clipChain()  reuse-state(None)
          DisplaySVGGeometry p=0x7f38c47240d0 f=0x7f38c6389a08(SVGGeometry(path)(0)) key=58 bounds(89,89,434,782) componentAlpha(0,0,0,0) clip() asr() clipChain()  reuse-state(None)
          DisplaySVGGeometry p=0x7f38c4724180 f=0x7f38c6389a88(SVGGeometry(path)(1)) key=58 bounds(436,89,434,782) componentAlpha(0,0,0,0) clip() asr() clipChain()  reuse-state(None)

Modified display list (new items):
AsyncZoom p=0x7f38c471efa8 f=0x7f38c4f941a8(HTMLScroll(html)(-1) class:no-js) key=2 bounds(0,0,56610,49740) componentAlpha(1001,1275,53239,44970) clip(0,0,56610,49740) asr() clipChain(0x7f38c471d170 <0,0,56610,49740> [root asr])  (opaque 0,0,56610,50040) reuse-state(None) (flags 0x0) (scrolltarget 0)
  FixedPosition p=0x7f38c6377400 f=0x7f38c63aeba0(HTMLScroll(aside)(0) class:c_d c_i c_cl c_cm c_h c_cn c_co c_cp c_cq c_cr c_cs c_ct c_cu c_b c_cv c_cw c_c c_cx) key=31 z=1201 bounds(0,3780,3420,45960) componentAlpha(1001,4935,1357,1230) clip(0,0,56610,49740) asr() clipChain(0x7f38c471d170 <0,0,56610,49740> [root asr])  (opaque 0,3780,3420,45960) reuse-state(None) (containerASR ) (scrolltarget 13)
    StickyPosition p=0x7f38c479f450 f=0x7f38c63894c8(Block(footer)(1) class:c_da c_cm c_dc c_db c_ej c_j) key=56 z=1 bounds(0,46140,3360,3600) componentAlpha(0,0,0,0) clip() asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  (opaque 0,46140,3360,3600) reuse-state(None) (flags 0x0) (scrolltarget 0)
      CompositorHitTestInfo p=0x7f38c471d820 f=0x7f38c63894c8(Block(footer)(1) class:c_da c_cm c_dc c_db c_ej c_j) key=25 z=1 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None)
      BackgroundColor p=0x7f38c63780a0 f=0x7f38c6389590(HTMLButtonControl(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=6 bounds(0,46140,3360,3600) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr]) uniform  (opaque 0,46140,3360,3600) hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None) (rgba 1,1,1,1) backgroundRect(x=0, y=46140, w=3360, h=3600)
      ButtonBorderBackground p=0x7f38c479eea8 f=0x7f38c6389590(HTMLButtonControl(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=12 bounds(0,46140,3360,3600) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  reuse-state(None)
      CompositorHitTestInfo p=0x7f38c4e07108 f=0x7f38c6389648(Block(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None)
      CompositorHitTestInfo p=0x7f38c471dc88 f=0x7f38c6389710(FlexContainer(div)(0) class:c_r c_bg c_ao c_er c_ec c_c c_j) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None)
      Border p=0x7f38c63776f8 f=0x7f38c6389710(FlexContainer(div)(0) class:c_r c_bg c_ao c_er c_ec c_c c_j) key=9 bounds(0,46140,3360,60) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  reuse-state(None)
      CompositorHitTestInfo p=0x7f38c471dec0 f=0x7f38c63897c0(FlexContainer(div)(0) class:c_dc c_bg c_r c_s c_c c_ed) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46200,3360,3540) reuse-state(None)
      nsDisplayTransform p=0x7f38c479f288 f=0x7f38c6389958(SVGOuterSVGAnonChild(svg)(0) class:c_es c_cd c_am c_et) key=73 bounds(1337,47627,685,686) componentAlpha(0,0,0,0) clip(1260,47550,840,840) asr(<0x7f38c63aec40>) clipChain(0x7f38c479efa0 <1260,47550,840,840> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  reuse-state(None)[ 0.875 0; 0 0.875; 42 1585; ] prerender(no) childrenBuildingRect(x=89, y=89, w=781, h=783)
        SVGWrapper p=0x7f38c479f148 f=0x7f38c6389958(SVGOuterSVGAnonChild(svg)(0) class:c_es c_cd c_am c_et) key=60 bounds(89,89,781,782) componentAlpha(0,0,0,0) clip() asr(<0x7f38c63aec40>) clipChain()  reuse-state(None)
          DisplaySVGGeometry p=0x7f38c479efe8 f=0x7f38c6389a08(SVGGeometry(path)(0)) key=58 bounds(89,89,434,782) componentAlpha(0,0,0,0) clip() asr(<0x7f38c63aec40>) clipChain()  reuse-state(None)
          DisplaySVGGeometry p=0x7f38c479f098 f=0x7f38c6389a88(SVGGeometry(path)(1)) key=58 bounds(436,89,434,782) componentAlpha(0,0,0,0) clip() asr(<0x7f38c63aec40>) clipChain()  reuse-state(None)

Merged display list:
AsyncZoom p=0x7f38c471ecd8 f=0x7f38c4f941a8(HTMLScroll(html)(-1) class:no-js) key=2 bounds(0,0,56610,49740) componentAlpha(1001,1275,53239,44970) clip(0,0,56610,49740) asr() clipChain(0x7f38c471d170 <0,0,56610,49740> [root asr])  (opaque 0,0,56610,50040) reuse-state(None) (flags 0x0) (scrolltarget 0)
  FixedPosition p=0x7f38c4724738 f=0x7f38c63aeba0(HTMLScroll(aside)(0) class:c_d c_i c_cl c_cm c_h c_cn c_co c_cp c_cq c_cr c_cs c_ct c_cu c_b c_cv c_cw c_c c_cx) key=31 z=1201 bounds(0,3780,3420,45960) componentAlpha(1001,4935,1357,1230) clip(0,0,56610,49740) asr() clipChain(0x7f38c471d170 <0,0,56610,49740> [root asr])  (opaque 0,3780,3420,45960) reuse-state(None) (containerASR ) (scrolltarget 13)
    StickyPosition p=0x7f38c479f450 f=0x7f38c63894c8(Block(footer)(1) class:c_da c_cm c_dc c_db c_ej c_j) key=56 z=1 bounds(0,46140,3360,3600) componentAlpha(0,0,0,0) clip() asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  (opaque 0,46140,3360,3600) reuse-state(None) (flags 0x0) (scrolltarget 0)
      CompositorHitTestInfo p=0x7f38c471d820 f=0x7f38c63894c8(Block(footer)(1) class:c_da c_cm c_dc c_db c_ej c_j) key=25 z=1 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None)
      BackgroundColor p=0x7f38c63780a0 f=0x7f38c6389590(HTMLButtonControl(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=6 bounds(0,46140,3360,3600) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr]) uniform  (opaque 0,46140,3360,3600) hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None) (rgba 1,1,1,1) backgroundRect(x=0, y=46140, w=3360, h=3600)
      ButtonBorderBackground p=0x7f38c479eea8 f=0x7f38c6389590(HTMLButtonControl(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=12 bounds(0,46140,3360,3600) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  reuse-state(None)
      CompositorHitTestInfo p=0x7f38c4e07108 f=0x7f38c6389648(Block(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None)
      CompositorHitTestInfo p=0x7f38c471dc88 f=0x7f38c6389710(FlexContainer(div)(0) class:c_r c_bg c_ao c_er c_ec c_c c_j) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None)
      Border p=0x7f38c63776f8 f=0x7f38c6389710(FlexContainer(div)(0) class:c_r c_bg c_ao c_er c_ec c_c c_j) key=9 bounds(0,46140,3360,60) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  reuse-state(None)
      CompositorHitTestInfo p=0x7f38c471dec0 f=0x7f38c63897c0(FlexContainer(div)(0) class:c_dc c_bg c_r c_s c_c c_ed) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45990) asr(<0x7f38c63aec40>) clipChain(0x7f38c4e06588 <0,3780,3360,45990> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46200,3360,3540) reuse-state(None)
      nsDisplayTransform p=0x7f38c479f288 f=0x7f38c6389958(SVGOuterSVGAnonChild(svg)(0) class:c_es c_cd c_am c_et) key=73 bounds(1337,47627,685,686) componentAlpha(0,0,0,0) clip(1260,47550,840,840) asr(<0x7f38c63aec40>) clipChain(0x7f38c479efa0 <1260,47550,840,840> [0x7f38c63aec40], 0x7f38c4721d38 <0,3780,3360,45960> [root asr])  reuse-state(None)[ 0.875 0; 0 0.875; 42 1585; ] prerender(no) childrenBuildingRect(x=89, y=89, w=781, h=783)
        SVGWrapper p=0x7f38c479f148 f=0x7f38c6389958(SVGOuterSVGAnonChild(svg)(0) class:c_es c_cd c_am c_et) key=60 bounds(89,89,781,782) componentAlpha(0,0,0,0) clip() asr(<0x7f38c63aec40>) clipChain()  reuse-state(None)
          DisplaySVGGeometry p=0x7f38c479efe8 f=0x7f38c6389a08(SVGGeometry(path)(0)) key=58 bounds(89,89,434,782) componentAlpha(0,0,0,0) clip() asr(<0x7f38c63aec40>) clipChain()  reuse-state(None)
          DisplaySVGGeometry p=0x7f38c479f098 f=0x7f38c6389a88(SVGGeometry(path)(1)) key=58 bounds(436,89,434,782) componentAlpha(0,0,0,0) clip() asr(<0x7f38c63aec40>) clipChain()  reuse-state(None)
    nsDisplayContainer p=0x7f38c4720d78 f=0x7f38c63894c8(Block(footer)(1) class:c_da c_cm c_dc c_db c_ej c_j) key=26 z=1 bounds(0,46140,3360,3600) componentAlpha(0,0,0,0) clip() asr() clipChain()  (opaque 0,46140,3360,3600) reuse-state(None)
      CompositorHitTestInfo p=0x7f38c4724db8 f=0x7f38c63894c8(Block(footer)(1) class:c_da c_cm c_dc c_db c_ej c_j) key=25 z=1 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None)
      BackgroundColor p=0x7f38c4723c28 f=0x7f38c6389590(HTMLButtonControl(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=6 bounds(0,46140,3360,3600) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr]) uniform  (opaque 0,46140,3360,3600) hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None) (rgba 1,1,1,1) backgroundRect(x=0, y=46140, w=3360, h=3600)
      ButtonBorderBackground p=0x7f38c4723d00 f=0x7f38c6389590(HTMLButtonControl(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=12 bounds(0,46140,3360,3600) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr])  reuse-state(None)
      CompositorHitTestInfo p=0x7f38c4e09878 f=0x7f38c6389648(Block(button)(0) class:c_cz c_ek c_el c_em c_en c_eo c_ep c_eq c_cv c_b c_j) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None)
      CompositorHitTestInfo p=0x7f38c471e960 f=0x7f38c6389710(FlexContainer(div)(0) class:c_r c_bg c_ao c_er c_ec c_c c_j) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46140,3360,3600) reuse-state(None)
      Border p=0x7f38c4723f18 f=0x7f38c6389710(FlexContainer(div)(0) class:c_r c_bg c_ao c_er c_ec c_c c_j) key=9 bounds(0,46140,3360,60) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr])  reuse-state(None)
      CompositorHitTestInfo p=0x7f38c4721d80 f=0x7f38c63897c0(FlexContainer(div)(0) class:c_dc c_bg c_r c_s c_c c_ed) key=25 bounds(0,0,0,0) componentAlpha(0,0,0,0) clip(0,3780,3360,45960) asr() clipChain(0x7f38c4721d38 <0,3780,3360,45960> [root asr])  hitTestInfo(0x1) hitTestArea(0,46200,3360,3540) reuse-state(None)
      nsDisplayTransform p=0x7f38c4724370 f=0x7f38c6389958(SVGOuterSVGAnonChild(svg)(0) class:c_es c_cd c_am c_et) key=73 bounds(1337,47627,685,686) componentAlpha(0,0,0,0) clip(1260,47550,840,840) asr() clipChain(0x7f38c4724088 <1260,47550,840,840> [root asr])  reuse-state(None)[ 0.875 0; 0 0.875; 42 1585; ] prerender(no) childrenBuildingRect(x=89, y=89, w=781, h=783)
        SVGWrapper p=0x7f38c4724230 f=0x7f38c6389958(SVGOuterSVGAnonChild(svg)(0) class:c_es c_cd c_am c_et) key=60 bounds(89,89,781,782) componentAlpha(0,0,0,0) clip() asr() clipChain()  reuse-state(None)
          DisplaySVGGeometry p=0x7f38c47240d0 f=0x7f38c6389a08(SVGGeometry(path)(0)) key=58 bounds(89,89,434,782) componentAlpha(0,0,0,0) clip() asr() clipChain()  reuse-state(None)
          DisplaySVGGeometry p=0x7f38c4724180 f=0x7f38c6389a88(SVGGeometry(path)(1)) key=58 bounds(436,89,434,782) componentAlpha(0,0,0,0) clip() asr() clipChain()  reuse-state(None)
Attached file dl-log.txt
Attachment #9269084 - Attachment is obsolete: true

It seems likely that the issue is this check that decides whether to build nsDisplayStickyPosition. Display list merging relies on static display list structure and container item changes are only allowed if they invalidate the frame.

What happens here:

  1. Firefox builds a full non-retained display list. During display list building WantAsyncScroll() returns false because GetLayoutScrollRange() is an empty rect. This results in display port not getting set and ScrollFrameHelper::mWillBuildScrollableLayer will be false. nsDisplayStickyPosition is not created.
  2. Some descendent frame of the scrollframe changes the scrollable overflow and that change propagates to the scroll frame without display item invalidation.
  3. During the next partial display list build, the overflow changes GetLayoutScrollRange() to a non-empty rect, the display port is set, and ScrollFrameHelper::mWillBuildScrollableLayer will be true. This creates nsDisplayStickyPosition item and the display list merging gets confused, which results in duplicate display items.

I tried to construct a testcase for this, but I was not able to change scrollable overflow area without causing invalidation of the scroll frame.

See Also: → 1731575
Pushed by mikokm@gmail.com:
https://hg.mozilla.org/integration/autoland/rev/c10609d434ae
Unconditionally create nsDisplayStickyPosition items r=tnikkel
Status: ASSIGNED → RESOLVED
Closed: 2 years ago
Resolution: --- → FIXED
Target Milestone: --- → 100 Branch

:miko it looks like it would be worth getting this out earlier if we backport it to beta.
Would you like to add a beta uplift request?

Flags: needinfo?(mikokm)

Comment on attachment 9269164 [details]
Bug 1736069 - Unconditionally create nsDisplayStickyPosition items r=tnikkel

Beta/Release Uplift Approval Request

  • User impact if declined: Pages with sticky positioned content might render wrong or crash the browser
  • Is this code covered by automated tests?: No
  • Has the fix been verified in Nightly?: Yes
  • Needs manual test from QE?: Yes
  • If yes, steps to reproduce: See comment 39
  • List of other uplifts needed: None
  • Risk to taking this patch: Medium
  • Why is the change risky/not risky? (and alternatives if risky): This patch fixes an obvious bug that causes display list merging to break.

I marked this as medium risk because the root cause of the bug is still unknown and there is no test. However the patch does pass all the current tests and should be easy to backout in case of regressions.

  • String changes made/needed:
Flags: needinfo?(mikokm)
Attachment #9269164 - Flags: approval-mozilla-beta?
Flags: qe-verify+

Comment on attachment 9269164 [details]
Bug 1736069 - Unconditionally create nsDisplayStickyPosition items r=tnikkel

Approved for beta uplift, available on the beta channel with 99RC1. Thanks.

Attachment #9269164 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
QA Whiteboard: [qa-triaged]

Was able to reproduce the crash on Firefox 99.0b8 under macOS 10.15.7 by following the STR from Comment 39.

The crash is no longer reproducible on Firefox 100.0a1 (2022-03-27) and Firefox 99.0b9 (treeherder build). Tests were performed on macOS 10.15.7, Ubuntu 20.04 and Windows 11.

Status: RESOLVED → VERIFIED
Flags: qe-verify+
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: