From f3c28b72555527f1e15f17d3876d3b30c54478e5 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 22 Apr 2020 08:01:35 +0200 Subject: [PATCH 1/5] Handle drops of unknown local/global values in ExpressionRunner --- src/ir/effects.h | 19 +++++++++++---- src/wasm-interpreter.h | 15 ++++++++++++ test/binaryen.js/expressionrunner.js | 22 +++++++++++++++++ test/binaryen.js/expressionrunner.js.txt | 14 +++++++++++ test/passes/dae-optimizing.txt | 30 ++++-------------------- test/passes/precompute_all-features.txt | 7 +----- 6 files changed, 70 insertions(+), 37 deletions(-) diff --git a/src/ir/effects.h b/src/ir/effects.h index 4f3af012fe3..6a21fe6c2dc 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -27,15 +27,22 @@ namespace wasm { struct EffectAnalyzer : public PostWalker> { - EffectAnalyzer(const PassOptions& passOptions, + EffectAnalyzer(bool ignoreImplicitTraps, + bool debugInfo, FeatureSet features, Expression* ast = nullptr) - : ignoreImplicitTraps(passOptions.ignoreImplicitTraps), - debugInfo(passOptions.debugInfo), features(features) { + : ignoreImplicitTraps(ignoreImplicitTraps), debugInfo(debugInfo), + features(features) { if (ast) { analyze(ast); } } + EffectAnalyzer(const PassOptions& passOptions, + FeatureSet features, + Expression* ast = nullptr) + : EffectAnalyzer( + passOptions.ignoreImplicitTraps, passOptions.debugInfo, features, ast) { + } bool ignoreImplicitTraps; bool debugInfo; @@ -400,7 +407,8 @@ struct EffectAnalyzer implicitTrap = true; break; } - default: {} + default: { + } } } } @@ -418,7 +426,8 @@ struct EffectAnalyzer implicitTrap = true; break; } - default: {} + default: { + } } } } diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 6432eee79da..378b28ced7e 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1132,6 +1132,21 @@ class ExpressionRunner : public OverriddenVisitor { NOTE_ENTER("Drop"); Flow value = visit(curr->value); if (value.breaking()) { + // Handle the case where a local or global value might not be known, even + // though we do not need to know in order to perform the drop if there are + // no other relevant side-effects. + if (value.breakTo == NONCONSTANT_FLOW && module != nullptr) { + EffectAnalyzer effects(false, false, module->features, curr->value); + effects.localsRead.clear(); + effects.globalsRead.clear(); + if (!(flags & FlagValues::PRESERVE_SIDEEFFECTS)) { + effects.localsWritten.clear(); + effects.globalsWritten.clear(); + } + if (!effects.hasAnything()) { + return Flow(); + } + } return value; } return Flow(); diff --git a/test/binaryen.js/expressionrunner.js b/test/binaryen.js/expressionrunner.js index 35117c45393..4ef1231d280 100644 --- a/test/binaryen.js/expressionrunner.js +++ b/test/binaryen.js/expressionrunner.js @@ -204,5 +204,27 @@ expr = runner.runAndDispose( ); assert(expr === 0); +// Should skip over dropped expressions without side-effects +runner = new binaryen.ExpressionRunner(module); +expr = runner.runAndDispose( + module.block(null, [ + module.drop( + module.i32.add( + module.local.get(0), + module.i32.const(5) + ) + ), + module.i32.const(9) + ], binaryen.i32) +); +assertDeepEqual( + binaryen.getExpressionInfo(expr), + { + id: binaryen.ExpressionIds.Const, + type: binaryen.i32, + value: 9 + } +); + module.dispose(); binaryen.setAPITracing(false); diff --git a/test/binaryen.js/expressionrunner.js.txt b/test/binaryen.js/expressionrunner.js.txt index 4d74c9febbf..6c1fcce72b2 100644 --- a/test/binaryen.js/expressionrunner.js.txt +++ b/test/binaryen.js/expressionrunner.js.txt @@ -147,6 +147,20 @@ int main() { expressions[62] = BinaryenBreak(the_module, "theLoop", expressions[0], expressions[0]); expressions[63] = BinaryenLoop(the_module, "theLoop", expressions[62]); ExpressionRunnerRunAndDispose(expressionRunners[11], expressions[63]); + expressionRunners[12] = ExpressionRunnerCreate(the_module, 0, 0, 0); + expressions[64] = BinaryenLocalGet(the_module, 0, BinaryenTypeNone()); + expressions[65] = BinaryenConst(the_module, BinaryenLiteralInt32(5)); + expressions[66] = BinaryenBinary(the_module, 0, expressions[64], expressions[65]); + expressions[67] = BinaryenDrop(the_module, expressions[66]); + expressions[68] = BinaryenConst(the_module, BinaryenLiteralInt32(9)); + { + BinaryenExpressionRef children[] = { expressions[67], expressions[68] }; + expressions[69] = BinaryenBlock(the_module, NULL, children, 2, BinaryenTypeInt32()); + } + expressions[70] = ExpressionRunnerRunAndDispose(expressionRunners[12], expressions[69]); + BinaryenExpressionGetId(expressions[70]); + BinaryenExpressionGetType(expressions[70]); + BinaryenConstGetValueI32(expressions[70]); BinaryenModuleDispose(the_module); types.clear(); expressions.clear(); diff --git a/test/passes/dae-optimizing.txt b/test/passes/dae-optimizing.txt index 3ae2fb25e8d..d03066c8a37 100644 --- a/test/passes/dae-optimizing.txt +++ b/test/passes/dae-optimizing.txt @@ -4,32 +4,10 @@ (type $none_=>_f32 (func (result f32))) (global $global$0 (mut i32) (i32.const 10)) (func $0 (result i32) - (local $0 i32) - (local $1 i32) - (drop - (if (result f32) - (local.tee $0 - (i32.const 33554432) - ) - (loop $label$2 (result f32) - (if - (global.get $global$0) - (return - (local.get $0) - ) - ) - (local.set $0 - (local.get $1) - ) - (local.set $1 - (i32.const 0) - ) - (br_if $label$2 - (local.get $0) - ) - (f32.const 1) - ) - (call $1) + (if + (global.get $global$0) + (return + (i32.const 33554432) ) ) (i32.const -11) diff --git a/test/passes/precompute_all-features.txt b/test/passes/precompute_all-features.txt index 9c7f4eab164..a1892a0f152 100644 --- a/test/passes/precompute_all-features.txt +++ b/test/passes/precompute_all-features.txt @@ -15,12 +15,7 @@ (i32.const 2300) ) (nop) - (drop - (i32.add - (i32.const 1) - (local.get $x) - ) - ) + (nop) (nop) (nop) (nop) From 4bd783f3e5a24e728845e993e9832dfa5fbf5156 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 22 Apr 2020 08:33:27 +0200 Subject: [PATCH 2/5] improve tests --- test/binaryen.js/expressionrunner.js | 45 ++++++++++++++++++++++-- test/binaryen.js/expressionrunner.js.txt | 35 +++++++++++++++++- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/test/binaryen.js/expressionrunner.js b/test/binaryen.js/expressionrunner.js index 4ef1231d280..a9359912e80 100644 --- a/test/binaryen.js/expressionrunner.js +++ b/test/binaryen.js/expressionrunner.js @@ -204,13 +204,13 @@ expr = runner.runAndDispose( ); assert(expr === 0); -// Should skip over dropped expressions without side-effects +// Should skip over dropped expressions if all we don't know is a local value runner = new binaryen.ExpressionRunner(module); expr = runner.runAndDispose( module.block(null, [ module.drop( module.i32.add( - module.local.get(0), + module.local.get(0, binaryen.i32), // here module.i32.const(5) ) ), @@ -226,5 +226,46 @@ assertDeepEqual( } ); +// Like above, but must preserve relevant side-effects if requested +runner = new binaryen.ExpressionRunner(module, Flags.PreserveSideeffects); +expr = runner.runAndDispose( + module.block(null, [ + module.drop( + module.block(null, [ + module.local.set(0, // here + module.i32.const(5) + ), + module.local.get(1, binaryen.i32) + ], binaryen.i32) + ), + module.i32.const(10) + ], binaryen.i32) +); +assert(expr === 0); + +// Like above, but sets are ok to drop if not preserving side-effects +runner = new binaryen.ExpressionRunner(module); +expr = runner.runAndDispose( + module.block(null, [ + module.drop( + module.block(null, [ + module.local.set(0, // here + module.i32.const(5) + ), + module.local.get(1, binaryen.i32) + ], binaryen.i32) + ), + module.i32.const(10) + ], binaryen.i32) +); +assertDeepEqual( + binaryen.getExpressionInfo(expr), + { + id: binaryen.ExpressionIds.Const, + type: binaryen.i32, + value: 10 + } +); + module.dispose(); binaryen.setAPITracing(false); diff --git a/test/binaryen.js/expressionrunner.js.txt b/test/binaryen.js/expressionrunner.js.txt index 6c1fcce72b2..61a82f0a991 100644 --- a/test/binaryen.js/expressionrunner.js.txt +++ b/test/binaryen.js/expressionrunner.js.txt @@ -148,7 +148,7 @@ int main() { expressions[63] = BinaryenLoop(the_module, "theLoop", expressions[62]); ExpressionRunnerRunAndDispose(expressionRunners[11], expressions[63]); expressionRunners[12] = ExpressionRunnerCreate(the_module, 0, 0, 0); - expressions[64] = BinaryenLocalGet(the_module, 0, BinaryenTypeNone()); + expressions[64] = BinaryenLocalGet(the_module, 0, BinaryenTypeInt32()); expressions[65] = BinaryenConst(the_module, BinaryenLiteralInt32(5)); expressions[66] = BinaryenBinary(the_module, 0, expressions[64], expressions[65]); expressions[67] = BinaryenDrop(the_module, expressions[66]); @@ -161,6 +161,39 @@ int main() { BinaryenExpressionGetId(expressions[70]); BinaryenExpressionGetType(expressions[70]); BinaryenConstGetValueI32(expressions[70]); + expressionRunners[13] = ExpressionRunnerCreate(the_module, 1, 0, 0); + expressions[71] = BinaryenConst(the_module, BinaryenLiteralInt32(5)); + expressions[72] = BinaryenLocalSet(the_module, 0, expressions[71]); + expressions[73] = BinaryenLocalGet(the_module, 1, BinaryenTypeInt32()); + { + BinaryenExpressionRef children[] = { expressions[72], expressions[73] }; + expressions[74] = BinaryenBlock(the_module, NULL, children, 2, BinaryenTypeInt32()); + } + expressions[75] = BinaryenDrop(the_module, expressions[74]); + expressions[76] = BinaryenConst(the_module, BinaryenLiteralInt32(10)); + { + BinaryenExpressionRef children[] = { expressions[75], expressions[76] }; + expressions[77] = BinaryenBlock(the_module, NULL, children, 2, BinaryenTypeInt32()); + } + ExpressionRunnerRunAndDispose(expressionRunners[13], expressions[77]); + expressionRunners[14] = ExpressionRunnerCreate(the_module, 0, 0, 0); + expressions[78] = BinaryenConst(the_module, BinaryenLiteralInt32(5)); + expressions[79] = BinaryenLocalSet(the_module, 0, expressions[78]); + expressions[80] = BinaryenLocalGet(the_module, 1, BinaryenTypeInt32()); + { + BinaryenExpressionRef children[] = { expressions[79], expressions[80] }; + expressions[81] = BinaryenBlock(the_module, NULL, children, 2, BinaryenTypeInt32()); + } + expressions[82] = BinaryenDrop(the_module, expressions[81]); + expressions[83] = BinaryenConst(the_module, BinaryenLiteralInt32(10)); + { + BinaryenExpressionRef children[] = { expressions[82], expressions[83] }; + expressions[84] = BinaryenBlock(the_module, NULL, children, 2, BinaryenTypeInt32()); + } + expressions[85] = ExpressionRunnerRunAndDispose(expressionRunners[14], expressions[84]); + BinaryenExpressionGetId(expressions[85]); + BinaryenExpressionGetType(expressions[85]); + BinaryenConstGetValueI32(expressions[85]); BinaryenModuleDispose(the_module); types.clear(); expressions.clear(); From d8a6bfa3d8fe3c699a5a416ef65a80d13d9e613b Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 22 Apr 2020 18:28:39 +0200 Subject: [PATCH 3/5] revert sets --- src/wasm-interpreter.h | 19 ++++++----- test/binaryen.js/expressionrunner.js | 43 +----------------------- test/binaryen.js/expressionrunner.js.txt | 33 ------------------ test/passes/dae-optimizing.txt | 30 ++++++++++++++--- 4 files changed, 37 insertions(+), 88 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 378b28ced7e..a6f05210ed6 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -196,6 +196,9 @@ class ExpressionRunner : public OverriddenVisitor { // Map remembering concrete global values set in the context of this flow. std::unordered_map globalValues; + // Whether an unknown local has been encountered in a sub-expression. + bool seenUnknownLocalGet = false; + Flow generateArguments(const ExpressionList& operands, LiteralList& arguments) { NOTE_ENTER_("generateArguments"); @@ -1130,19 +1133,16 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitDrop(Drop* curr) { NOTE_ENTER("Drop"); + seenUnknownLocalGet = false; Flow value = visit(curr->value); if (value.breaking()) { - // Handle the case where a local or global value might not be known, even - // though we do not need to know in order to perform the drop if there are - // no other relevant side-effects. - if (value.breakTo == NONCONSTANT_FLOW && module != nullptr) { + // Handle the case where all we don't know to perform the drop is a local + // value, which we do not need to know if there are no other side-effects. + // Doesn't apply to globals since these would error when module is given. + if (seenUnknownLocalGet && value.breakTo == NONCONSTANT_FLOW && + module != nullptr) { EffectAnalyzer effects(false, false, module->features, curr->value); effects.localsRead.clear(); - effects.globalsRead.clear(); - if (!(flags & FlagValues::PRESERVE_SIDEEFFECTS)) { - effects.localsWritten.clear(); - effects.globalsWritten.clear(); - } if (!effects.hasAnything()) { return Flow(); } @@ -1269,6 +1269,7 @@ class ExpressionRunner : public OverriddenVisitor { if (iter != localValues.end()) { return Flow(std::move(iter->second)); } + seenUnknownLocalGet = true; return Flow(NONCONSTANT_FLOW); } Flow visitLocalSet(LocalSet* curr) { diff --git a/test/binaryen.js/expressionrunner.js b/test/binaryen.js/expressionrunner.js index a9359912e80..c55c0ae1be3 100644 --- a/test/binaryen.js/expressionrunner.js +++ b/test/binaryen.js/expressionrunner.js @@ -204,7 +204,7 @@ expr = runner.runAndDispose( ); assert(expr === 0); -// Should skip over dropped expressions if all we don't know is a local value +// Should not bail on dropped expressions if all we don't know is a local value runner = new binaryen.ExpressionRunner(module); expr = runner.runAndDispose( module.block(null, [ @@ -226,46 +226,5 @@ assertDeepEqual( } ); -// Like above, but must preserve relevant side-effects if requested -runner = new binaryen.ExpressionRunner(module, Flags.PreserveSideeffects); -expr = runner.runAndDispose( - module.block(null, [ - module.drop( - module.block(null, [ - module.local.set(0, // here - module.i32.const(5) - ), - module.local.get(1, binaryen.i32) - ], binaryen.i32) - ), - module.i32.const(10) - ], binaryen.i32) -); -assert(expr === 0); - -// Like above, but sets are ok to drop if not preserving side-effects -runner = new binaryen.ExpressionRunner(module); -expr = runner.runAndDispose( - module.block(null, [ - module.drop( - module.block(null, [ - module.local.set(0, // here - module.i32.const(5) - ), - module.local.get(1, binaryen.i32) - ], binaryen.i32) - ), - module.i32.const(10) - ], binaryen.i32) -); -assertDeepEqual( - binaryen.getExpressionInfo(expr), - { - id: binaryen.ExpressionIds.Const, - type: binaryen.i32, - value: 10 - } -); - module.dispose(); binaryen.setAPITracing(false); diff --git a/test/binaryen.js/expressionrunner.js.txt b/test/binaryen.js/expressionrunner.js.txt index 61a82f0a991..adb55dc5cbe 100644 --- a/test/binaryen.js/expressionrunner.js.txt +++ b/test/binaryen.js/expressionrunner.js.txt @@ -161,39 +161,6 @@ int main() { BinaryenExpressionGetId(expressions[70]); BinaryenExpressionGetType(expressions[70]); BinaryenConstGetValueI32(expressions[70]); - expressionRunners[13] = ExpressionRunnerCreate(the_module, 1, 0, 0); - expressions[71] = BinaryenConst(the_module, BinaryenLiteralInt32(5)); - expressions[72] = BinaryenLocalSet(the_module, 0, expressions[71]); - expressions[73] = BinaryenLocalGet(the_module, 1, BinaryenTypeInt32()); - { - BinaryenExpressionRef children[] = { expressions[72], expressions[73] }; - expressions[74] = BinaryenBlock(the_module, NULL, children, 2, BinaryenTypeInt32()); - } - expressions[75] = BinaryenDrop(the_module, expressions[74]); - expressions[76] = BinaryenConst(the_module, BinaryenLiteralInt32(10)); - { - BinaryenExpressionRef children[] = { expressions[75], expressions[76] }; - expressions[77] = BinaryenBlock(the_module, NULL, children, 2, BinaryenTypeInt32()); - } - ExpressionRunnerRunAndDispose(expressionRunners[13], expressions[77]); - expressionRunners[14] = ExpressionRunnerCreate(the_module, 0, 0, 0); - expressions[78] = BinaryenConst(the_module, BinaryenLiteralInt32(5)); - expressions[79] = BinaryenLocalSet(the_module, 0, expressions[78]); - expressions[80] = BinaryenLocalGet(the_module, 1, BinaryenTypeInt32()); - { - BinaryenExpressionRef children[] = { expressions[79], expressions[80] }; - expressions[81] = BinaryenBlock(the_module, NULL, children, 2, BinaryenTypeInt32()); - } - expressions[82] = BinaryenDrop(the_module, expressions[81]); - expressions[83] = BinaryenConst(the_module, BinaryenLiteralInt32(10)); - { - BinaryenExpressionRef children[] = { expressions[82], expressions[83] }; - expressions[84] = BinaryenBlock(the_module, NULL, children, 2, BinaryenTypeInt32()); - } - expressions[85] = ExpressionRunnerRunAndDispose(expressionRunners[14], expressions[84]); - BinaryenExpressionGetId(expressions[85]); - BinaryenExpressionGetType(expressions[85]); - BinaryenConstGetValueI32(expressions[85]); BinaryenModuleDispose(the_module); types.clear(); expressions.clear(); diff --git a/test/passes/dae-optimizing.txt b/test/passes/dae-optimizing.txt index d03066c8a37..3ae2fb25e8d 100644 --- a/test/passes/dae-optimizing.txt +++ b/test/passes/dae-optimizing.txt @@ -4,10 +4,32 @@ (type $none_=>_f32 (func (result f32))) (global $global$0 (mut i32) (i32.const 10)) (func $0 (result i32) - (if - (global.get $global$0) - (return - (i32.const 33554432) + (local $0 i32) + (local $1 i32) + (drop + (if (result f32) + (local.tee $0 + (i32.const 33554432) + ) + (loop $label$2 (result f32) + (if + (global.get $global$0) + (return + (local.get $0) + ) + ) + (local.set $0 + (local.get $1) + ) + (local.set $1 + (i32.const 0) + ) + (br_if $label$2 + (local.get $0) + ) + (f32.const 1) + ) + (call $1) ) ) (i32.const -11) From 2ca876685872ef75a48f60011b88a68acde0633e Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 6 May 2020 22:19:25 +0200 Subject: [PATCH 4/5] handle unknown global values --- src/wasm-interpreter.h | 17 ++++++++++------- test/binaryen.js/expressionrunner.js | 6 +++--- test/binaryen.js/expressionrunner.js.txt | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 9419f360b35..a2866277c13 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -196,8 +196,9 @@ class ExpressionRunner : public OverriddenVisitor { // Map remembering concrete global values set in the context of this flow. std::unordered_map globalValues; - // Whether an unknown local has been encountered in a sub-expression. - bool seenUnknownLocalGet = false; + // Whether an unknown value of a local or global has been encountered in a + // sub-expression. + bool seenUnknownValue = false; Flow generateArguments(const ExpressionList& operands, LiteralList& arguments) { @@ -1133,16 +1134,17 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitDrop(Drop* curr) { NOTE_ENTER("Drop"); - seenUnknownLocalGet = false; + seenUnknownValue = false; Flow value = visit(curr->value); if (value.breaking()) { // Handle the case where all we don't know to perform the drop is a local - // value, which we do not need to know if there are no other side-effects. - // Doesn't apply to globals since these would error when module is given. - if (seenUnknownLocalGet && value.breakTo == NONCONSTANT_FLOW && + // or global value, which we do not need to know if there are no other + // side-effects. + if (seenUnknownValue && value.breakTo == NONCONSTANT_FLOW && module != nullptr) { EffectAnalyzer effects(false, false, module->features, curr->value); effects.localsRead.clear(); + effects.globalsRead.clear(); if (!effects.hasAnything()) { return Flow(); } @@ -1269,7 +1271,7 @@ class ExpressionRunner : public OverriddenVisitor { if (iter != localValues.end()) { return Flow(iter->second); } - seenUnknownLocalGet = true; + seenUnknownValue = true; return Flow(NONCONSTANT_FLOW); } Flow visitLocalSet(LocalSet* curr) { @@ -1306,6 +1308,7 @@ class ExpressionRunner : public OverriddenVisitor { if (iter != globalValues.end()) { return Flow(iter->second); } + seenUnknownValue = true; return Flow(NONCONSTANT_FLOW); } Flow visitGlobalSet(GlobalSet* curr) { diff --git a/test/binaryen.js/expressionrunner.js b/test/binaryen.js/expressionrunner.js index c55c0ae1be3..f15c49205d6 100644 --- a/test/binaryen.js/expressionrunner.js +++ b/test/binaryen.js/expressionrunner.js @@ -204,14 +204,14 @@ expr = runner.runAndDispose( ); assert(expr === 0); -// Should not bail on dropped expressions if all we don't know is a local value +// Should not bail on dropped expressions if all we don't know is a value runner = new binaryen.ExpressionRunner(module); expr = runner.runAndDispose( module.block(null, [ module.drop( module.i32.add( - module.local.get(0, binaryen.i32), // here - module.i32.const(5) + module.local.get(0, binaryen.i32), // here + module.global.get("aGlobal", binaryen.i32), // ) ), module.i32.const(9) diff --git a/test/binaryen.js/expressionrunner.js.txt b/test/binaryen.js/expressionrunner.js.txt index adb55dc5cbe..9c10e0e51d8 100644 --- a/test/binaryen.js/expressionrunner.js.txt +++ b/test/binaryen.js/expressionrunner.js.txt @@ -149,7 +149,7 @@ int main() { ExpressionRunnerRunAndDispose(expressionRunners[11], expressions[63]); expressionRunners[12] = ExpressionRunnerCreate(the_module, 0, 0, 0); expressions[64] = BinaryenLocalGet(the_module, 0, BinaryenTypeInt32()); - expressions[65] = BinaryenConst(the_module, BinaryenLiteralInt32(5)); + expressions[65] = BinaryenGlobalGet(the_module, "aGlobal", BinaryenTypeInt32()); expressions[66] = BinaryenBinary(the_module, 0, expressions[64], expressions[65]); expressions[67] = BinaryenDrop(the_module, expressions[66]); expressions[68] = BinaryenConst(the_module, BinaryenLiteralInt32(9)); From 285e481ef3055293f262ce15e7332e421b3722c0 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 6 May 2020 22:40:19 +0200 Subject: [PATCH 5/5] move to ConstantExpressionRunner --- src/wasm-interpreter.h | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 1b16221f65e..07c12f553a9 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -157,10 +157,6 @@ class ExpressionRunner : public OverriddenVisitor { // Maximum iterations before giving up on a loop. Index maxLoopIterations; - // Whether an unknown value of a local or global has been encountered in a - // sub-expression. - bool seenUnknownValue = false; - Flow generateArguments(const ExpressionList& operands, LiteralList& arguments) { NOTE_ENTER_("generateArguments"); @@ -1075,21 +1071,8 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitDrop(Drop* curr) { NOTE_ENTER("Drop"); - seenUnknownValue = false; Flow value = visit(curr->value); if (value.breaking()) { - // Handle the case where all we don't know to perform the drop is a local - // or global value, which we do not need to know if there are no other - // side-effects. - if (seenUnknownValue && value.breakTo == NONCONSTANT_FLOW && - module != nullptr) { - EffectAnalyzer effects(false, false, module->features, curr->value); - effects.localsRead.clear(); - effects.globalsRead.clear(); - if (!effects.hasAnything()) { - return Flow(); - } - } return value; } return Flow(); @@ -1322,6 +1305,10 @@ class ConstantExpressionRunner : public ExpressionRunner { // Map remembering concrete global values set in the context of this flow. std::unordered_map globalValues; + // Whether an unknown value of a local or global has been encountered in a + // sub-expression. + bool seenUnknownValue = false; + public: struct NonconstantException { }; // TODO: use a flow with a special name, as this is likely very slow @@ -1412,6 +1399,27 @@ class ConstantExpressionRunner : public ExpressionRunner { } return Flow(NONCONSTANT_FLOW); } + Flow visitDrop(Drop* curr) { + NOTE_ENTER("Drop"); + seenUnknownValue = false; + Flow value = ExpressionRunner::visit(curr->value); + if (value.breaking()) { + // Handle the case where all we don't know to perform the drop is a local + // or global value, which we do not need to know if there are no other + // side-effects. + if (seenUnknownValue && value.breakTo == NONCONSTANT_FLOW && + module != nullptr) { + EffectAnalyzer effects(false, false, module->features, curr->value); + effects.localsRead.clear(); + effects.globalsRead.clear(); + if (!effects.hasAnything()) { + return Flow(); + } + } + return value; + } + return Flow(); + } Flow visitCall(Call* curr) { NOTE_ENTER("Call"); NOTE_NAME(curr->target);