R12 — the Ghidra seam is an interface, and its P-code vocabulary cannot flatten - #34
Merged
Merged
Conversation
…annot flatten
Starting the r2il-machine-semantic-contract-v1 arc (lance-graph PR #1027)
from the GHIDRA end while a sibling session drives W0-W4. Two findings,
pointing the same way. Nothing swapped, nothing minted, no layout touched.
1. THE SEAM IS AN INTERFACE, and no core fork is required:
Language (INTERFACE)
.parse(...) -> InstructionPrototype (INTERFACE)
.getPcode(...) -> PcodeOp[]
InstructionDB.getPcode() only delegates. InstructionPrototype has
exactly two implementations, and SleighLanguage constructs the real
one at exactly one site (SleighLanguage.java:392). Instruction is
itself an interface with an InstructionStub already in tree.
This had been flagged twice this session as unverified. It gates the
whole Java half; the answer is favourable.
2. GHIDRA'S P-CODE VOCABULARY CANNOT BE CARRIED AS VALUE CLASSES — its
identity can. R12 transcribes the field shapes from Varnode.java:51-54
and PcodeOp.java:102-105 and runs them through R2/R4's harness on the
JEP 401 EA build, with -XX:+PrintFlatArrayLayout so the VM reports
element sizes rather than the program asserting them:
VarnodePayload(int,int,long) 16 B -> not flat
PcodeOpPayload(int,long) 12 B -> not flat
VarnodeRef/PcodeOpRef/InstructionRef(long) -> flat, element size 8
Those payload rows are the OPTIMISTIC bound — every reference deleted.
The real Varnode holds an Address; the real PcodeOp holds a
SequenceNumber, a Varnode[] and a Varnode, so a 2-input PcodeOp is
FIVE heap objects.
Verdict: the W5 facade ADDRESSES the vocabulary rather than carrying
it — which needs nothing new. It is the same result LaneId/Ordinal/
MaskId already rely on, and the same reason RowRange (16 B) does not
flatten.
Unanticipated, recorded so it is not lost: an 8-byte VarnodeNarrow
(u8 space, u8 size, 48-bit offset) ALSO flattens, so 8 bytes can carry a
varnode's real content rather than a pointer to it. Bounded by exactly
one condition, a 48-bit offset — a W0/W1 address-space question, not a
Valhalla one. Named as an option, deliberately NOT proposed as the
design: pre-empting W1's tenant carving from this side is what the
plan's own R1 rule forbids one layer up.
lgj-abi 134 lib tests still green (nothing in this commit touches it).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCfrD5y19cvFc4AoyydXYv
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_d37b5c12-6fc6-470c-880b-effc7b88e2d7) |
AdaWorldAPI
marked this pull request as ready for review
August 25, 2026 17:11
This was referenced Aug 25, 2026
AdaWorldAPI
pushed a commit
that referenced
this pull request
Aug 27, 2026
PR_ARC_INVENTORY had entries for #1-#12, #14, #16, #18, #20 and #32, and nothing else. Missing: #13, #22-#31, #33-#41 — twenty PRs. (#15/#17/#19/#21 are also absent and correctly so: each is itself an arc-entry-only PR, exempt under the termination clause.) #32's own entry still read "(draft, opened …)" with no merge sha. Corrects this branch's first count, which said nineteen and read the gap as starting at #21. Both were wrong — it is twenty, and it starts at #13. The first count was a range subtraction over a file with holes; the enumeration is what found the difference. Method, which is the point rather than an aside: each entry drafted from that PR's own body and diff, five parallel agents over four PRs each, none permitted to work from a later session's recall. Every backfilled entry's Confidence bullet ends "Backfilled 2026-08-27 from the PR body and diff, not written at merge time", so reconstructed entries are distinguishable from ones written at merge time; several state which claims are the PR body's own and were not re-verified. Every cited sha, date and merge-vs- squash label machine-checked against git. Four things the backfill turned up, each recorded in the entry it belongs to: #25's body asserts "no code, no reproducer changes" and its own diff contradicts it; #39 left its lgj_hop doc comment describing the pre-change design; #34's banked evidence file did not identify its own JDK; and #41 is on main while its own title reads [DO NOT MERGE AS-IS], recorded as unresolved disposition rather than an endorsement. ISS-LGJ-ARC-INVENTORY-STOPPED-AT-32 moves to RESOLVED with the corrected count and the standing rule restated: the entry goes in at open, in the PR's own commit. The backfill is the repair, not the process. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DCfrD5y19cvFc4AoyydXYv
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.
Starting the
r2il-machine-semantic-contract-v1arc (lance-graph #1027, merged) from the Ghidra end, while a sibling session drives W0–W4. Measurement + source trace only: nothing swapped, nothing minted, no layout touched.1. The seam is an interface — no core fork required
This was flagged twice this session as unverified, and it gates the entire Java half. Traced:
InstructionDB.getPcode()(:608-628) does nothing but delegate toproto.getPcode(...).InstructionPrototypehas exactly two implementations —SleighInstructionPrototypeandInvalidPrototype.SleighLanguageconstructs the real one at exactly one site (SleighLanguage.java:392).Instructionis itself an interface, with anInstructionStubalready in tree.So a third implementation is the insertion point. The answer is favourable.
2. Ghidra's P-code vocabulary cannot be carried as value classes — its identity can
R12, field shapes transcribed from
Varnode.java:51-54andPcodeOp.java:102-105(not invented), run through R2/R4's harness on the JEP 401 EA build with-XX:+PrintFlatArrayLayoutso the VM reports element sizes rather than the program asserting them:VarnodePayload(int,int,long)— 16 BPcodeOpPayload(int,long)— 12 BVarnodeNarrow— 8 B packed contentNULL_FREE_ATOMIC_FLAT)VarnodeRef(long)NULL_FREE_NON_ATOMIC_FLAT)PcodeOpRef(long)InstructionRef(long)The two
*Payloadrows are the optimistic lower bound — every reference deleted. The realVarnodeadditionally holds anAddress; the realPcodeOpholds aSequenceNumber, aVarnode[]and aVarnode. So a 2-inputPcodeOpis five heap objects: the op, its sequence number, the input array, and oneVarnodeper operand. That is ONE ROW IS NOT ONE JAVA OBJECT at its worst — one instruction becomes a small object graph.Verdict: the W5 facade ADDRESSES the vocabulary rather than carrying it. And that needs nothing new — it is the same result
LaneId/Ordinal/MaskIdalready rely on, and the same reasonRowRange(16 B) does not flatten. W5's central question is answered before W5 starts.The finding the plan did not anticipate
VarnodeNarrow—spaceId:u8,size:u8, 48-bit offset — also flattens. So 8 bytes is enough to carry a varnode's real content, not merely a pointer to it: a descriptor that reads space and size with no lane round-trip. It is bounded by exactly one condition — a 48-bit offset — and whether that suffices is a W0/W1 address-space question, not a Valhalla one.Recorded as an option so it is not lost; deliberately not proposed as the design. Pre-empting W1's tenant carving from this side is precisely what the plan's own R1 rule ("no private object graph then serialize") forbids one layer up.
Also worth noting: the single-
longrefs come backNON_ATOMIC_FLATwhile the multi-fieldVarnodeNarrowisATOMIC_FLAT. Both flatten at element size 8; only the tearing guarantee differs.What this deliberately does not do
No
InstructionPrototypeimplementation, no facade types, no descriptor mint. Those wait on W1's tenant spec — this establishes only what is true regardless of what W1 decides.Gates
lgj-abi134 lib tests green (nothing here touches it). R12 compiles and runs on/opt/jdks/jdk-27(JEP 401 EA); the run is banked verbatim inR12-observed.txt, including the VM's ownPrintFlatArrayLayoutoutput.🤖 Generated with Claude Code
https://claude.ai/code/session_01DCfrD5y19cvFc4AoyydXYv
Generated by Claude Code