Skip to content

Commit ef375f3

Browse files
authored
fix(hermes-base): harden switch jump-table normalization
Use opcode-specific switch normalization patterns so only jump-table offsets are ignored during Hermes equivalence checks. Add regression tests proving StringSwitchImm id/default/count and UIntSwitchImm default/min/max remain semantic differences.
1 parent c37ea26 commit ef375f3

2 files changed

Lines changed: 50 additions & 2 deletions

File tree

src/utils/hermes-base.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -650,9 +650,9 @@ export function normalizeDisassemblyLine(
650650
// UIntSwitchImm rX, <jtOffset>, <defaultLabel>, <min>, <max>
651651
// Folding only the first shape let a shifted UIntSwitchImm offset read as a
652652
// real difference and drop an otherwise good delta build.
653-
m = /^(\s*(?:String|UInt)?SwitchImm r\d+, \d+, )\d+(, .*)$/.exec(line);
653+
m = /^(\s*StringSwitchImm r\d+, \d+, )\d+(, L\d+, \d+)$/.exec(line);
654654
if (m) line = `${m[1]}<jt>${m[2]}`;
655-
m = /^(\s*(?:String|UInt)?SwitchImm r\d+, )\d+(, L\d+, .*)$/.exec(line);
655+
m = /^(\s*UIntSwitchImm r\d+, )\d+(, L\d+, \d+, \d+)$/.exec(line);
656656
if (m) line = `${m[1]}<jt>${m[2]}`;
657657
if (/^\s*offset \d+$/.test(line)) line = line.replace(/\d+$/, '<jt>');
658658
return line;
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { describe, expect, test } from 'bun:test';
2+
import { normalizeDisassemblyLine } from '../src/utils/hermes-base';
3+
4+
const normalize = (line: string) =>
5+
normalizeDisassemblyLine(line, new Map<number, string>());
6+
7+
describe('Hermes switch jump-table normalization', () => {
8+
test('normalizes only the StringSwitchImm jump-table offset', () => {
9+
const baseline = normalize(' StringSwitchImm r13, 2, 4024, L146, 150');
10+
expect(baseline).toBe(' StringSwitchImm r13, 2, <jt>, L146, 150');
11+
expect(normalize(' StringSwitchImm r13, 2, 4025, L146, 150')).toBe(
12+
baseline,
13+
);
14+
expect(normalize(' StringSwitchImm r13, 3, 4024, L146, 150')).not.toBe(
15+
baseline,
16+
);
17+
expect(normalize(' StringSwitchImm r13, 2, 4024, L147, 150')).not.toBe(
18+
baseline,
19+
);
20+
expect(normalize(' StringSwitchImm r13, 2, 4024, L146, 151')).not.toBe(
21+
baseline,
22+
);
23+
});
24+
25+
test('normalizes only the UIntSwitchImm jump-table offset', () => {
26+
const baseline = normalize(' UIntSwitchImm r40, 5937, L3, 0, 31');
27+
expect(baseline).toBe(' UIntSwitchImm r40, <jt>, L3, 0, 31');
28+
expect(normalize(' UIntSwitchImm r40, 5938, L3, 0, 31')).toBe(baseline);
29+
expect(normalize(' UIntSwitchImm r40, 5937, L4, 0, 31')).not.toBe(
30+
baseline,
31+
);
32+
expect(normalize(' UIntSwitchImm r40, 5937, L3, 1, 31')).not.toBe(
33+
baseline,
34+
);
35+
expect(normalize(' UIntSwitchImm r40, 5937, L3, 0, 32')).not.toBe(
36+
baseline,
37+
);
38+
});
39+
40+
test('does not fold unsupported or malformed switch shapes', () => {
41+
expect(normalize(' SwitchImm r1, 2, 3, L4, 5')).toBe(
42+
' SwitchImm r1, 2, 3, L4, 5',
43+
);
44+
expect(normalize(' UIntSwitchImm r40, 5937, 3, 0, 31')).toBe(
45+
' UIntSwitchImm r40, 5937, 3, 0, 31',
46+
);
47+
});
48+
});

0 commit comments

Comments
 (0)