This is with the Obama test case, and 8 stylo threads. This may be harmless/intended, but it caught my eye: max-live: 438,912 in 6,858 blocks tot-alloc: 438,912 in 6,858 blocks (avg size 64.00) deaths: 6,858, at avg age 50,573,815,834 (58.09% of prog lifetime) What's interesting is that the max-live and tot-alloc numbers are the same. That implies that this allocation point (stack) allocated blocks without freeing them as it went, and only freed them after all allocations had finished. And they stayed alive for 58% of the process lifetime, which seems a lot if styling is only one of several processing stages for showing a web page.
So, ensure_element_data creates the heap-allocated style data that hangs off the DOM elements. Those should stick around until the DOM elements are destroyed, or at least removed from the DOM tree. Does this profile include closing that tab? You can also try explicitly document a document.body.remove() call in the web console and seeing if that corresponds with all this memory being freed. Does max-live give a count of bytes or of allocations? The latter would make sense, the former wouldn't. There are ~15k elements on the obama testcase.