commit 1cfeb8b82e98d171cd1dbab03e8d8d216f2b82ef
parent 19d3fc64145c543ce42f73957f532d179660262e
Author: André Bargull <andre.bargull@gmail.com>
Date: Tue, 11 Nov 2025 12:29:35 +0000
Bug 1998451: Improve performance of codegen tests. r=bvisness
Changes:
- Add `stripencoding` to remove the instruction encoding of the input.
This makes the `expected` RegExp simpler, which improves performance
and avoids catastrophic backtracking when the input doesn't match the
output (at least for x86/x64 encoding tests).
- Improve `strip` function to perform only a single `substring` operation.
Differential Revision: https://phabricator.services.mozilla.com/D271435
Diffstat:
6 files changed, 28 insertions(+), 38 deletions(-)
diff --git a/js/src/jit-test/lib/adhoc-multiplatform-test.js b/js/src/jit-test/lib/adhoc-multiplatform-test.js
@@ -94,7 +94,7 @@ const archOptions =
ldr x29, \\[sp\\]`
},
arm: {
- encoding: `${HEX}{8} ${HEX}{8}`,
+ encoding: `${HEX}{8}\\s+${HEX}{8}`,
// The move from r9 to fp is writing the callee's wasm instance into
// the frame for debug checks -- see WasmFrame.h.
prefix: `str fp, \\[sp, #-4\\]!
@@ -223,37 +223,17 @@ function codegenTestMultiplatform_adhoc(module_text, export_name,
if (!options.no_suffix) {
expected = expected + '\n' + suffix;
}
- if (genArm) {
- // For obscure reasons, the arm(32) disassembler prints the
- // instruction word twice. Rather than forcing all expected lines to
- // do the same, we detect any line starting with 8 hex digits followed
- // by a space, and duplicate them so as to match the
- // disassembler's output.
- let newExpected = "";
- let pattern = /^[0-9a-fA-F]{8} /;
- for (line of expected.split(/\n+/)) {
- // Remove whitespace at the start of the line. This could happen
- // for continuation lines in backtick-style expected strings.
- while (line.match(/^\s/)) {
- line = line.slice(1);
- }
- if (line.match(pattern)) {
- line = line.slice(0,9) + line;
- }
- newExpected = newExpected + line + "\n";
- }
- expected = newExpected;
- }
- expected = fixlines(expected, encoding);
+ expected = fixlines(expected);
// Compile the test case and collect disassembly output.
let ins = wasmEvalText(module_text, {}, options.features);
if (options.instanceBox)
options.instanceBox.value = ins;
let output = wasmDis(ins.exports[export_name], {tier:"ion", asString:true});
+ let output_simple = stripencoding(output, encoding);
// Check for success, print diagnostics
- let output_matches_expected = output.match(new RegExp(expected)) != null;
+ let output_matches_expected = output_simple.match(new RegExp(expected)) != null;
if (!output_matches_expected) {
print("---- adhoc-tier1-test.js: TEST FAILED ----");
}
diff --git a/js/src/jit-test/lib/codegen-arm64-test.js b/js/src/jit-test/lib/codegen-arm64-test.js
@@ -33,9 +33,10 @@ function codegenTestARM64_adhoc(module_text, export_name, expected, options = {}
expected = arm64_prefix + '\n' + expected;
if (!options.no_suffix)
expected = expected + '\n' + arm64_suffix;
- expected = fixlines(expected, `${HEX}{8}`);
+ expected = fixlines(expected);
- const output_matches_expected = output.match(new RegExp(expected)) != null;
+ const output_simple = stripencoding(output, `${HEX}{8}`);
+ const output_matches_expected = output_simple.match(new RegExp(expected)) != null;
if (!output_matches_expected) {
print("---- codegen-arm64-test.js: TEST FAILED ----");
}
diff --git a/js/src/jit-test/lib/codegen-test-common.js b/js/src/jit-test/lib/codegen-test-common.js
@@ -11,21 +11,28 @@ function wrap(options, funcs) {
return `(module ${funcs})`;
}
-function fixlines(s, insEncoding) {
+function fixlines(s) {
return s.split(/\n+/)
.map(strip)
.filter(x => x.length > 0)
- .map(x => `(?:0x)?${HEX}+ ${insEncoding} ${x}`)
.map(spaces)
.join('\n');
}
+function stripencoding(s, insEncoding) {
+ var encoding = RegExp(`^(?:0x)?${HEX}+\\s+${insEncoding}\\s+(.*)$`);
+ return s.split('\n')
+ .map(x => x.match(encoding)?.[1] ?? x)
+ .join('\n');
+}
+
function strip(s) {
- while (s.length > 0 && isspace(s.charAt(0)))
- s = s.substring(1);
- while (s.length > 0 && isspace(s.charAt(s.length-1)))
- s = s.substring(0, s.length-1);
- return s;
+ var start = 0, end = s.length;
+ while (start < s.length && isspace(s.charAt(start)))
+ start++;
+ while (end > start && isspace(s.charAt(end - 1)))
+ end--;
+ return s.substring(start, end);
}
function striplines(s) {
diff --git a/js/src/jit-test/lib/codegen-x64-test.js b/js/src/jit-test/lib/codegen-x64-test.js
@@ -163,9 +163,10 @@ function codegenTestX64_adhoc(module_text, export_name, expected, options = {})
if (!options.no_suffix)
expected = expected + '\n' + x64_suffix;
const expected_pretty = striplines(expected);
- expected = fixlines(expected, `(?:${HEX}{2} )*`);
+ expected = fixlines(expected);
- const success = output.match(new RegExp(expected)) != null;
+ const output_simple = stripencoding(output, `(?:${HEX}{2} )*`);
+ const success = output_simple.match(new RegExp(expected)) != null;
if (options.log || !success) {
print("Module text:")
print(module_text);
diff --git a/js/src/jit-test/lib/codegen-x86-test.js b/js/src/jit-test/lib/codegen-x86-test.js
@@ -57,9 +57,10 @@ function codegenTestX86_adhoc(module_text, export_name, expected, options = {})
expected = x86_prefix + '\n' + expected;
if (!options.no_suffix)
expected = expected + '\n' + x86_suffix;
- expected = fixlines(expected, `(?:${HEX}{2} )*`);
+ expected = fixlines(expected);
- const output_matches_expected = output.match(new RegExp(expected)) != null;
+ const output_simple = stripencoding(output, `(?:${HEX}{2} )*`);
+ const output_matches_expected = output_simple.match(new RegExp(expected)) != null;
if (!output_matches_expected) {
print("---- codegen-x86-test.js: TEST FAILED ----");
}
diff --git a/js/src/jit-test/tests/wasm/binop-x64-ion-codegen.js b/js/src/jit-test/tests/wasm/binop-x64-ion-codegen.js
@@ -383,7 +383,7 @@ for ( [pAnyCmp, pAnySel, cmpArgL, cmovArgL ] of
)`,
'f',
// On Linux we have an extra move
- (getBuildConfiguration("windows") ? '' : '48 89 .. mov %r.+, %r.+\n') +
+ (getBuildConfiguration("windows") ? '' : 'mov %r.+, %r.+\n') +
// 'q*' because the disassembler shows 'q' only for the memory cases
`mov %r.+, %r.+
cmpq* ${cmpArgL}, %r.+