Repository navigation
Conversation
| // G1/Serial/Parallel relocate objects at safepoints. A sampled Java thread | ||
| // cannot reach a safepoint while its signal handler is reading these oops. | ||
| // Concurrently relocating collectors require load barriers not provided here. |
There was a problem hiding this comment.
Can the profiling signal land on a thread with frozen stack and already in safepoint?
Or is this structurally impossible?
There was a problem hiding this comment.
yes it can, it is not structurally excluded. There is a protection in FrozenStackWalker::append: it rejects any thread state other than _thread_in_Java before reading heap objects. HotSpot switches to _thread_blocked before waiting at the safepoint, so those samples skip frozen-frame recovery and retain truncated=true. For accepted samples, the PC must also belong to interpreted or compiled Java code, excluding freeze/thaw runtime execution.
CI Test ResultsRun: #39931432227 | Commit:
Status Overview
Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled ❌ Failing tests
Retried 3 of 32 cells. Failed Jobs
Summary: Total: 32 | Passed: 29 | Failed: 3 Updated: 2026-10-23 10:03:29 UTC |
…nto paul.fournillon/recover-frozen-virtual-thread-callers
Reliability & Chaos Results✅ All reliability & chaos checks passed Pipeline: https://gitlab.ddbuild.io/DataDog/java-profiler/-/pipelines/146813861 |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
Nested continuation transitions can make frozen-stack recovery append suspended child callers instead of parent callers and incorrectly report the trace as complete.
🤖 Bits Code Review · Commit 746acbe
| // carrier Thread.cont, including when the current Java thread is virtual. | ||
| uintptr_t continuation = readOop(carrier, layout.carrier_cont); | ||
| for (unsigned int i = 0; i < continuation_depth && continuation != 0; i++) { | ||
| continuation = readOop(continuation, layout.cont_parent); |
There was a problem hiding this comment.
Match recovered chunks to the crossed continuation boundary
When a partially thawed parent resumes a nested continuation, Continuation.run publishes the child in Thread.cont before enterSpecial and restores the parent only after it returns. Samples in those Java intervals pass the recovery guards, but the first native return barrier belongs to the parent. Reading Thread.cont therefore selects the child's chunks, potentially appending suspended child frames, omitting parent callers, and clearing truncation. Match recovery to the crossed native continuation boundary, or reject recovery during these transitions. Correctly identifying that boundary requires broader changes, so no localized suggestion is provided.
React: 👍 useful · 👎 wrong · 😕 unclear · 👀 right, but not acting on it
What each reaction means
- 👍 Useful: correct, and you're fixing it or will.
- 👎 Wrong: the finding is incorrect, for example the bug can't happen or the code was misread.
- 😕 Unclear: you can't tell what it means or why it matters.
- 👀 Right, not acting: correct, but intended, out of scope for this PR, a known risk, or too minor.
🤖 Bits Code Review · Open Bits AI session
…nto paul.fournillon/recover-frozen-virtual-thread-callers
This comment has been minimized.
This comment has been minimized.
…nto paul.fournillon/recover-frozen-virtual-thread-callers
What does this PR do?:
Recover older Java callers from HotSpot heap stack chunks when a mounted virtual thread reaches a continuation return barrier. Append interpreted and compiled frames, including inlined callers and parent chunks, to the existing trace buffer before stopping at the continuation root (
cstack=vm) or walking the carrier (cstack=vmx). For deoptimized compiled frames, recover the saved original return PC before decoding inline scopes.Extend regression coverage for both walking modes, CPU and wall sampling, parent chunks, mounted-frame deoptimization, depth limits, native calls, unsupported recovery, and platform-thread/fully thawed controls.
Motivation:
HotSpot can thaw only part of a virtual thread's stack after remounting it. The remaining Java callers stay in heap chunks and are absent from a walk of the carrier's native stack. #877 correctly marks that omission as truncated; this change restores those callers where recovery is supported.
Additional Notes:
paul.fournillon/fix-frozen-virtual-thread-truncation). Retarget tomainafter that dependency merges.break_cont_carrier_spwithout encountering a return barrier; this PR does not claim to fix it.How to test the change?:
./.claude/commands/build-and-summarize spotlessApply :ddprof-test:testDebug \ '-Ptests=*Frozen*' -Pskip-gtest -PkeepJFRs --max-workers=2vmandvmx: the physical caller is retained but its inline callers are omitted. It passes with original-PC recovery on Linux arm64 JDK 21/27 and macOS arm64 JDK 25/27../.claude/commands/build-and-summarize :ddprof-lib:gtestDebug_frozenDeoptimization_ut.spotlessApplyandgit diff --checkpass. The combined frozen-stack Java regression run passes 18 tests with two conditional GC skips.For Datadog employees: