Rather than searching from the beginning (old end) of the cache,
LiveSameFrameCache::find can search from the young end of the cache, popping
invalid stack entries as it goes.
This means that the number of entries searched is related to the number of
cached frames popped since the last stack capture, not the total number of
entries in the cache.
This also removes the need for iterators, iterator arithmetic, or any random
access to the stack; the function simply uses the vector's 'back', 'popBack',
'empty', and 'clear' methods.
MozReview-Commit-ID: DCFt0uhiqql
When capturing frames in an activation that had both 1) an async parent stack
established by AutoSetAsyncStackForNewCalls and 2) SavedFrames cached in the
activation's LiveSavedFramesCache, SavedStacks::insertFrames would supplant the
SavedFrame chain from the cache with the async parent stack, causing frames to
be dropped.
The code also looked for frames in the wrong activation's LiveSavedFramesCache.
The code assumed that only the parent of a frame whose hasCachedSavedFrame flag
is set could be retrieved from the cache; this was pessimistic, as we can
compare the cached and actual pc's, and potentially provide cache hits for the
youngest frame with a flag set.
MozReview-Commit-ID: 8tXTI43pjYr
I botched another patch in this series because I was confused about when zero
meant "no limit" and when it actually just meant zero, so I figured I'd fix this.
MozReview-Commit-ID: 5vgzKGSKL8F
A jit::BaselineFrame is followed in memory by a jit::JitFrameLayout; as the
stack grows downwards, the JitFrameLayout is pushed first, "followed" by the
BaselineFrame at lower addresses, and finally by locals and the operand stack.
A BaselineFrame* points, naturally, at the BaselineFrame structure, but we use
the address of the JitFrameLayout as the address for a physical Ion frame -
actually, a pointer to its base class, jit::CommonFrameLayout. This means that,
if OSR replaces a BaselineFrame with an Ion frame, then walking the stack with a
FrameIter will see an Ion frame where a BaselineFrame used to appear, and the
LiveSavedFrameCache::FramePtr we'll construct from that FrameIter will be
different.
If the LiveSavedFrameCache wants to assert that frames with their bits set
indeed appear in the cache, then we'd better clear the flag whenever we OSR the
frame. But this is a pity; it's still the same frame, representing the same
function activation.
Meanwhile, both BaselineFrame and CommonFrameLayout have their own
hasCachedSavedFrame flags, which is confusing.
This patch changes FramePtr to use a jit::CommonFrameLayout* for both Baseline
frames and physical Ion frames, so OSR does not change the frame's address, and
use CommonFrameLayout's hasCachedSavedFrame flag for both types, so that OSR
need not take any explicit steps to propagate the cached flag to the new frame.
MozReview-Commit-ID: rOMjUXlwIQ
Some variants of AbstractFramePtr have a cached saved frame flag, and others
don't, but the whole point of LiveSavedFrameCache::FramePtr is that it
represents a frame that does have a flag.
Rather than one variant of FramePtr that is an AbstractFramePtr (restricted to
certain variants), flatten out the two enums into one, and make FramePtr the
sole authority on which sorts of frames we have, and how to access their flags.
This means there is no need for hasCachedSavedFrame accessors on
AbstractFramePtr, just on the individual concrete frame types.
MozReview-Commit-ID: BRVdfqOqBsG
This obviates dynamic checks in find about the state of the iterator, since
they're covered by the fact that we were able to obtain a FramePtr at all.
This does mean that we have to pass the pc separately. But that's symmetrical
with the insert method, so it's okay.
MozReview-Commit-ID: FgsDjHB2il4
Instead of using FrameIter::hasCachedSavedFrame, the code should instead try to
construct a FramePtr via LiveSavedFrameCache::getFramePtr, which returns a
Maybe<FramePtr>. If that is Some, then we know the frame at hand actually has a
flag, and we can test and set it.
Since the existing FrameIter::hasCachedSavedFrame screens out all wasm frames,
we change LiveSavedFrameCache::getFramePtr to do the same. However, the existing
behavior was incorrect, since wasm::DebugFrame does carry the flag; we'll fix
that in a later patch.
FrameIter::hasCachedSavedFrame asserted that jsJitFrame().isIonScripted(); this
is tested by isPhysicalIonFrame(), so that case is already covered.
MozReview-Commit-ID: 92wCc71s4nU
By design, the LiveSavedFrameCache holds the addresses of both live and dead
stack frames. This change wraps those addresses in an opaque type that can only
be compared for equality with other such values, and provides no interface to
retrieve the underlying pointer, ensuring statically that we will not
accidentally use a cache key to access memory.
MozReview-Commit-ID: 9Wom5gFVQls
For the "js" crate, disable the "regex" feature to reduce binary size.
For the "u2fhid" crate, it's used only in examples. Make it a dev-dependency
so it won't be part of the Firefox build.
MozReview-Commit-ID: DY9indMqrRw
When capturing the JavaScript stack as a chain of SavedFrames, the
hasCachedSavedFrame flag on a frame indicates that the frame has an entry in
the LiveSavedFrameCache, which may hand us the SavedFrame for a previously
captured remainder of the stack, letting us stop the stack walk early.
The LiveSavedFrameCache uses AbstractFramePtr and jit::CommonFrameLayout* values
as keys. A RematerializedFrame uses an AbstractFramePtr as its key, but the
BaselineFrame we build from it has a jit::CommonFrameLayout* as its key; the two
keys are unequal. It's valuable to be able to assert that, if a frame has its
hasCachedSavedFrame flag set, then it must have an entry in the cache; to allow
that, converting a RematerializedFrame to a BaselineFrame must clear the flag,
since the BaselineFrame's key is not present.
We could instead fix up the cache entry's key, and carry over the flag, but it's
simpler to just let the cache get repopulated as needed.
MozReview-Commit-ID: 612daDJ1R4w
In JSFunction, u.wasm.native_ member must have the same type and offset as
u.native.func_. This is better accomplished by simply using func_ for both.
Further, u.wasm.jitEntry_ must alias u.native.extra.asmJSFuncIndex_. This is
better accomplished simply by making them both members of the same union.
This leaves u.wasm empty, so it can be deleted. Two static assertions about
member offsets can be removed.
MozReview-Commit-ID: 8ukNaFysWvD