write real jit unwind handling on aarch64 windows
Categories
(Core :: JavaScript Engine: JIT, enhancement, P3)
Tracking
()
Tracking | Status | |
---|---|---|
firefox66 | --- | fixed |
People
(Reporter: froydnj, Assigned: away)
References
(Blocks 1 open bug)
Details
Attachments
(1 file)
Updated•6 years ago
|
![]() |
||
Comment 1•6 years ago
|
||
![]() |
Reporter | |
Comment 2•6 years ago
|
||
![]() |
||
Comment 3•6 years ago
|
||
Comment 6•6 years ago
|
||
![]() |
||
Comment 8•6 years ago
|
||
Comment 10•6 years ago
|
||
Updated•6 years ago
|
![]() |
Assignee | |
Comment 12•6 years ago
|
||
I think I've found a path that can make this work. From comment 7:
- An RtlInstallFunctionTableCallback that, when called, returns a
RUNTIME_FUNCTION that does an analogous thing to the x86_64 code.
I was worried that the 1M size limit in the xdata record would prevent the RUNTIME_FUNCTION from being able to say that it applies to the code that just crashed.
It turns out this is not a problem because the length field is not checked at all. I can set it to zero and it still works. This tells me that Windows is doing its address bookkeeping entirely based on the parameters to RtlInstallFunctionTableCallback, which are large enough to cover our JIT regions.
So we can bake a single generic RUNTIME_FUNCTION into the first page of the region, and the callback can just return a pointer to it. It's a little more indirect than the x86_64 one, but it doesn't have to worry about an EndAddress field.
Locally I made JIT code be super crashy (by reverting bug 1501269) and got the exception to flow all the way to breakpad with a successful report at Socorro. (I also disabled E10S to work around bug 1517729.)
Before review I want to do some more testing to make sure this doesn't blow things up horribly.
![]() |
Assignee | |
Comment 13•6 years ago
|
||
For lack of arm64 test coverage, I applied comment 12 to x86_64 as well, and sent it through try. Green: https://treeherder.mozilla.org/#/jobs?repo=try&group_state=expanded&revision=ad91e236b6be95b99e48320d4f271b3968b904d3
Back on arm64, I confirmed that this setup doesn't cause Breakpad to get wrongly invoked when someone calls RtlVirtualUnwind with UNW_FLAG_NHANDLER, which was one of my concerns in comment 7.
Luke: what do you think about landing the RtlInstallFunctionTableCallback approach for both arm64 and x86_64, so that the x86_64 install base could tell us if something's wrong? Otherwise I'm worried that if there's a subtle problem, it'll go undetected due to the currently-low install base of arm64.
Oh, and just to double-check: the JIT regions live basically forever, right? I ask because there's no such thing as RtlUninstallFunctionTableCallback.
![]() |
||
Comment 14•6 years ago
•
|
||
I think that's a great idea to improve symmetry and testing between x86_64 / arm64, so yes.
The JIT region almost lives forever; technically the code is realized when JS_ShutDown() is called:
We already don't do this if there are any live JSRuntimes (as a hack to paper over leaking situations). I'm not sure what would go wrong if we simply never released the machine code. It's not like we support a sequence of init->shutdown->init->shutdown (libraryInitState asserts this, even) or we'll need the memory for something else after shutdown. Jan, can you think any reason we need to release the executable code region?
![]() |
Assignee | |
Comment 15•6 years ago
|
||
Comment 16•6 years ago
|
||
(In reply to Luke Wagner [:luke] from comment #14)
We already don't do this if there are any live JSRuntimes (as a hack to paper over leaking situations). I'm not sure what would go wrong if we simply never released the machine code. It's not like we support a sequence of init->shutdown->init->shutdown (libraryInitState asserts this, even) or we'll need the memory for something else after shutdown. Jan, can you think any reason we need to release the executable code region?
Not releasing would be OK I think (as long as leak checking tools don't complain). At that point the pages should be just reserved, not committed.
However we should keep the asserts on that path. We could rename ReleaseProcessExecutableMemory for that and add a comment there documenting why we're doing it this way.
![]() |
Assignee | |
Comment 17•6 years ago
|
||
I feel uneasy about changing those lifetimes, mostly out of unfamiliarity with the code.
What if we made the function table callback more aware of what's going on? Instead of using the allocation region as the callback's Context parameter, we could give it the ProcessExecutableMemory object. The callback could then test initialized().
Comment 18•6 years ago
|
||
Comment 19•6 years ago
|
||
bugherder |
Description
•