feat(agent): implement @Return and @Duration in ClassFileApiBackend#843
Open
jbachorik wants to merge 1 commit into
Open
feat(agent): implement @Return and @Duration in ClassFileApiBackend#843jbachorik wants to merge 1 commit into
jbachorik wants to merge 1 commit into
Conversation
…ackend ClassFileApiBackend (used for Java 26+ class files) previously skipped handlers with @return or @duration parameters. This change adds full support: - @return: dup/dup2 based on TypeKind.slotSize(), store to an allocated local slot, load before INVOKEDYNAMIC. Void methods are silently skipped. - @duration: System.nanoTime() captured at method entry; delta computed at each RETURN point and in a finally-block exception handler (matching the existing ASM instrumentation behavior). Bug fixes applied after chorus review: - emitProbeCall: pre-validate all handler arguments before pushing any onto the stack; an early return mid-loop would leave orphaned stack values and cause a VerifyError on class loading. - emitProbeCall: load the return-value slot using the actual store TypeKind from the ReturnInstruction, not TypeKind.fromDescriptor on the handler descriptor (which would yield REFERENCE for AnyType→Object handlers, mismatching the ISTORE/LSTORE used during capture). - atStart/accept: bind startLabel in accept() alongside entryTsSlot allocation so they are always in sync; an unpairable label in atEnd could leave an unclosed try region. - atEnd: register exceptionCatchAll after binding all three labels; replace stream pipeline with a plain for-loop. Tests cover @return (int, long, void-skip), @duration (normal exit, exception exit), and combined @return+@duration slot-collision check. Tests that require class file version 70 parsing (Java 26+) skip automatically on JDK < 26 via Assumptions.assumeTrue. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This was referenced May 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #837 —
ClassFileApiBackend(used for Java 26+ class files) previously skipped all handlers containing@Returnor@Durationparameters. This PR adds full support for both, matching the behavior of the existing ASM-based backend.@Return: Captures the return value viadup/dup2(based onTypeKind.slotSize()), stores it to an allocated local slot, and loads it before theINVOKEDYNAMICprobe call. Void methods are silently skipped.@Duration: CapturesSystem.nanoTime()at method entry, computes the delta at each normal return point, and also covers exceptional exits via afinally-block exception handler (matching the existing ASM instrumentation behavior).Key correctness constraints respected:
INVOKEDYNAMICdescriptor used verbatim fromom.getTargetDescriptor()— not rebuilt.CodeBuilder.allocateLocal()to avoid slot collisions.VerifyError).TypeKindpassed through to the load site soISTORE+ALOADmismatches are impossible even for@AnyType-typed handler parameters.Test plan
supportsVersionAbove69— ClassFileApiBackend selected for version 70+returnsNullWhenNoProbesMatch— no probes → nullentryProbeInjectedIntoMatchingMethod— INVOKEDYNAMIC injected at method entry (JDK 26+)entryProbeNotInjectedWhenMethodNameMismatches— null for non-matching methodreturnProbeInjectedBeforeReturn— INVOKEDYNAMIC injected before RETURN (JDK 26+)noInjectionForUnsupportedKind— Kind.CALL skippedreturnProbeInjectedWithReturnValueInt— int return value captured in descriptor (JDK 26+)returnProbeInjectedWithReturnValueLong— long (2-slot) return value captured (JDK 26+)returnProbeSkippedForVoidMethod— no INVOKEDYNAMIC + ClassLoader load asserts no VerifyError (JDK 26+)durationProbeInjectedOnNormalReturn— long duration parameter in descriptor (JDK 26+)durationProbeInjectedOnExceptionExit— 2 INVOKEDYNAMIC calls (normal + exception handler) (JDK 26+)returnAndDurationSlotsDoNotCollide— at least 2 distinct store slots (JDK 26+)Tests requiring class file version 70 (Java 26) skip automatically on JDK < 26 via
Assumptions.assumeTrue.🤖 Generated with Claude Code
This change is