Skip to content

Commit c37ea26

Browse files
sunnylqmclaude
andcommitted
fix(hermes-base): fold UIntSwitchImm jump-table offsets in the equivalence check
The two switch instructions carry the jump-table offset in different operands: StringSwitchImm rX, <id>, <jtOffset>, <defaultLabel>, <count> UIntSwitchImm rX, <jtOffset>, <defaultLabel>, <min>, <max> Only the first shape was folded. Under -pretty-disassemble the default target of a UIntSwitchImm prints as a label (`L3`), so the existing regex — which expects a second number where the label is — never matched, and a jump-table offset that had simply moved with instruction widths read as a real difference. --verifyHermesBase then dropped a perfectly good delta build and fell back to the plain compile, silently, on exactly the bundles where switches are common. Found while benchmarking delta mode on the RN 0.86 example app: the ~300 LOC scenario failed on one line (5937 vs 5938) and lost the delta build, taking its patch from 97.8 KB to 381.0 KB — 3.9x larger. With this fix all three scenarios verify clean (566k-591k instructions compared). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U1e5fWU5jWwgH4ctKwYx5y
1 parent f372289 commit c37ea26

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

src/utils/hermes-base.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -643,10 +643,17 @@ export function normalizeDisassemblyLine(
643643
// wider form. Fold the suffix and the column padding that follows it.
644644
m = /^(\s*)([A-Za-z]+?)(?:LongIndex|Long|Short)?(\s+.*|)$/.exec(line);
645645
if (m) line = `${m[1]}${m[2]}${m[3].replace(/\s+/g, ' ')}`;
646-
// switch jump tables sit after the instructions; their relative offset (and
647-
// the table header hermesc prints for them) moves with instruction widths
646+
// Switch jump tables sit after the instructions; their relative offset (and
647+
// the table header hermesc prints for them) moves with instruction widths.
648+
// The two switch instructions carry that offset in different operands:
649+
// StringSwitchImm rX, <id>, <jtOffset>, <defaultLabel>, <count>
650+
// UIntSwitchImm rX, <jtOffset>, <defaultLabel>, <min>, <max>
651+
// Folding only the first shape let a shifted UIntSwitchImm offset read as a
652+
// real difference and drop an otherwise good delta build.
648653
m = /^(\s*(?:String|UInt)?SwitchImm r\d+, \d+, )\d+(, .*)$/.exec(line);
649654
if (m) line = `${m[1]}<jt>${m[2]}`;
655+
m = /^(\s*(?:String|UInt)?SwitchImm r\d+, )\d+(, L\d+, .*)$/.exec(line);
656+
if (m) line = `${m[1]}<jt>${m[2]}`;
650657
if (/^\s*offset \d+$/.test(line)) line = line.replace(/\d+$/, '<jt>');
651658
return line;
652659
}

tests/hermes-base.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,19 @@ describe('helpers', () => {
461461
strings,
462462
),
463463
).toBe(' StringSwitchImm r13, 2, <jt>, L146, 150');
464+
// UIntSwitchImm carries the jump-table offset one operand earlier
465+
expect(
466+
normalizeDisassemblyLine(
467+
' UIntSwitchImm r40, 5937, L3, 0, 31',
468+
strings,
469+
),
470+
).toBe(' UIntSwitchImm r40, <jt>, L3, 0, 31');
471+
expect(
472+
normalizeDisassemblyLine(
473+
' UIntSwitchImm r40, 5938, L3, 0, 31',
474+
strings,
475+
),
476+
).toBe(' UIntSwitchImm r40, <jt>, L3, 0, 31');
464477
expect(normalizeDisassemblyLine(' offset 4024', strings)).toBe(
465478
' offset <jt>',
466479
);

0 commit comments

Comments
 (0)