From d8ea2fcc205b37279932d66403c04ffe90ec63a1 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Wed, 27 Mar 2024 20:32:03 -0700 Subject: [PATCH] Remove the TRAVERSE_CALLS option in the ConstantExpressionRunner The implementation of calls with this option was incorrect because it cleared the locals before evaluating the call arguments. The likely explanation for why this was never noticed is that there are no users of this option, especially since it is exposed in the C and JS APIs but not used internally. Rather than try to fix the implementation, just remove the option. --- CHANGELOG.md | 1 + src/binaryen-c.cpp | 4 --- src/binaryen-c.h | 6 ---- src/js/binaryen.js-post.js | 1 - src/wasm-interpreter.h | 33 ---------------------- test/binaryen.js/expressionrunner.js | 35 +----------------------- test/binaryen.js/expressionrunner.js.txt | 1 - 7 files changed, 2 insertions(+), 79 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4b81c71013..80d55213061 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ Current Trunk to configure which features to enable in the parser. - The build-time option to use legacy WasmGC opcodes is removed. - The strings in `string.const` instructions must now be valid WTF-8. + - The `TraverseCalls` flag for `ExpressionRunner` is removed. v117 ---- diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 402dce5537b..a348760782d 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -6322,10 +6322,6 @@ ExpressionRunnerFlags ExpressionRunnerFlagsPreserveSideeffects() { return CExpressionRunner::FlagValues::PRESERVE_SIDEEFFECTS; } -ExpressionRunnerFlags ExpressionRunnerFlagsTraverseCalls() { - return CExpressionRunner::FlagValues::TRAVERSE_CALLS; -} - ExpressionRunnerRef ExpressionRunnerCreate(BinaryenModuleRef module, ExpressionRunnerFlags flags, BinaryenIndex maxDepth, diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 42bd4591573..bc63e963ae1 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -3495,12 +3495,6 @@ BINARYEN_API ExpressionRunnerFlags ExpressionRunnerFlagsDefault(); // so subsequent code keeps functioning. BINARYEN_API ExpressionRunnerFlags ExpressionRunnerFlagsPreserveSideeffects(); -// Traverse through function calls, attempting to compute their concrete value. -// Must not be used in function-parallel scenarios, where the called function -// might be concurrently modified, leading to undefined behavior. Traversing -// another function reuses all of this runner's flags. -BINARYEN_API ExpressionRunnerFlags ExpressionRunnerFlagsTraverseCalls(); - // Creates an ExpressionRunner instance BINARYEN_API ExpressionRunnerRef ExpressionRunnerCreate(BinaryenModuleRef module, diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 125bbf01ed4..1461420bb61 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -638,7 +638,6 @@ function initializeConstants() { Module['ExpressionRunner']['Flags'] = { 'Default': Module['_ExpressionRunnerFlagsDefault'](), 'PreserveSideeffects': Module['_ExpressionRunnerFlagsPreserveSideeffects'](), - 'TraverseCalls': Module['_ExpressionRunnerFlagsTraverseCalls']() }; } diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 377eb94652c..8da80afc907 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -2211,10 +2211,6 @@ class ConstantExpressionRunner : public ExpressionRunner { // the expression if it also sets a local, which must be preserved in this // scenario so subsequent code keeps functioning. PRESERVE_SIDEEFFECTS = 1 << 0, - // Traverse through function calls, attempting to compute their concrete - // value. Must not be used in function-parallel scenarios, where the called - // function might be concurrently modified, leading to undefined behavior. - TRAVERSE_CALLS = 1 << 1 }; // Flags indicating special requirements, for example whether we are just @@ -2322,35 +2318,6 @@ class ConstantExpressionRunner : public ExpressionRunner { Flow visitCall(Call* curr) { NOTE_ENTER("Call"); NOTE_NAME(curr->target); - // Traverse into functions using the same mode, which we can also do - // when replacing as long as the function does not have any side effects. - // Might yield something useful for simple functions like `clamp`, sometimes - // even if arguments are only partially constant or not constant at all. - if ((flags & FlagValues::TRAVERSE_CALLS) != 0 && this->module != nullptr) { - auto* func = this->module->getFunction(curr->target); - if (!func->imported()) { - if (func->getResults().isConcrete()) { - auto numOperands = curr->operands.size(); - assert(numOperands == func->getNumParams()); - auto prevLocalValues = localValues; - localValues.clear(); - for (Index i = 0; i < numOperands; ++i) { - auto argFlow = ExpressionRunner::visit(curr->operands[i]); - if (!argFlow.breaking()) { - assert(argFlow.values.isConcrete()); - localValues[i] = argFlow.values; - } - } - auto retFlow = ExpressionRunner::visit(func->body); - localValues = prevLocalValues; - if (retFlow.breakTo == RETURN_FLOW) { - return Flow(retFlow.values); - } else if (!retFlow.breaking()) { - return retFlow; - } - } - } - } return Flow(NONCONSTANT_FLOW); } Flow visitCallIndirect(CallIndirect* curr) { diff --git a/test/binaryen.js/expressionrunner.js b/test/binaryen.js/expressionrunner.js index 7071f950d24..9535b3eeca7 100644 --- a/test/binaryen.js/expressionrunner.js +++ b/test/binaryen.js/expressionrunner.js @@ -1,7 +1,6 @@ var Flags = binaryen.ExpressionRunner.Flags; console.log("// ExpressionRunner.Flags.Default = " + Flags.Default); console.log("// ExpressionRunner.Flags.PreserveSideeffects = " + Flags.PreserveSideeffects); -console.log("// ExpressionRunner.Flags.TraverseCalls = " + Flags.TraverseCalls); function assertDeepEqual(x, y) { if (typeof x === "object") { @@ -139,39 +138,7 @@ assertDeepEqual( } ); -// Should traverse into (simple) functions if requested -runner = new binaryen.ExpressionRunner(module, Flags.TraverseCalls); -module.addFunction("add", binaryen.createType([ binaryen.i32, binaryen.i32 ]), binaryen.i32, [], - module.block(null, [ - module.i32.add( - module.local.get(0, binaryen.i32), - module.local.get(1, binaryen.i32) - ) - ], binaryen.i32) -); -assert(runner.setLocalValue(0, module.i32.const(1))); -expr = runner.runAndDispose( - module.i32.add( - module.i32.add( - module.local.get(0, binaryen.i32), - module.call("add", [ - module.i32.const(2), - module.i32.const(4) - ], binaryen.i32) - ), - module.local.get(0, binaryen.i32) - ) -); -assertDeepEqual( - binaryen.getExpressionInfo(expr), - { - id: binaryen.ExpressionIds.Const, - type: binaryen.i32, - value: 8 - } -); - -// Should not attempt to traverse into functions if not explicitly set +// Should not attempt to traverse into functions runner = new binaryen.ExpressionRunner(module); expr = runner.runAndDispose( module.i32.add( diff --git a/test/binaryen.js/expressionrunner.js.txt b/test/binaryen.js/expressionrunner.js.txt index 7d686bd2881..50a46843c4b 100644 --- a/test/binaryen.js/expressionrunner.js.txt +++ b/test/binaryen.js/expressionrunner.js.txt @@ -1,3 +1,2 @@ // ExpressionRunner.Flags.Default = 0 // ExpressionRunner.Flags.PreserveSideeffects = 1 -// ExpressionRunner.Flags.TraverseCalls = 2