On Tue, 20 Oct 2026 02:22:01 GMT, Andrei Pangin <[email protected]> wrote:
>> src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp line 614:
>>
>>> 612: while (count < JfrCPUTimeSampleRequest::MAX_NATIVE_FRAMES) {
>>> 613: const address pc = f.pc();
>>> 614: if (pc == nullptr || CodeCache::contains(pc)) {
>>
>> I think the cheap check should be LJF(last java frame). Until we encounter
>> the LJF, everything are native frames. jt->_anchor is the invariant provided
>> by hotspot.
>>
>> for pc check about here:
>> 2. if pc is from interpreter but JVM is not using template interpreter(a
>> corner case), pc is NOT in code cache! However, ucontext points to a java
>> frame, not native frame.
>> 3. Isn't CodeCache.contains() expensive? if we have multiple heaps in
>> CodeCache.
>
> I can't rely on presence of last_java_frame, especially since I want to
> expand native frames support to other thread states in follow-up PRs.
> `CodeCache.contains` is the exact boundary; it's at most 3-4 range checks,
> negligible comparing to other stack walking costs. And Zero Interpreter is
> covered by an existing `last_java_sp` check.
hi, @apangin
I understand we want to pursuit more states. One lesson I learned from ASGCT is
that it is unsafe if we build things based on the status-quo code rather than a
program invariant. Code changes over time.
I have two arguments why we should consider a native stackwalker using the
following invariant:
jt->has_last_Java_frame() && jt->frame_anchor()->walkable()
1. be conservative. Drop those corner cases like JvmtiAgentThread, a java
thread has zero java call yet, in_Java (I don't think check in_Native before is
enough, we need to deploy a Dekker test).
2. Cooperate with the existing stack-walker. Sometimes we also want to stitch
the native part with the second part at safepoint. LFJ is a reasonable joint
point.
If we use LJF invariant, it will work for a mature Java thread that just steps
out of _in_Java and be in a stable _in_Native or _in_VM or _in_blocked. I think
will meet most of demand and it's significant safer.
If we support a java thread just in transitional state, eg. it's constructing
an anchor. We may see some weird interim frame like `JavaFrameAnchor::copy` or
`UpcallLinker::on_entry`, there will be mismatch when we generate stacktrace at
the next safepoint. Even you manage to generate native stacktrace for a java
thread without LJF, it's not easy stitch them.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/32524#discussion_r4331568170