From 7984f03acb3f8f4ff8674618bdda7fb4ea9eb40e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 09:02:39 -0700 Subject: [PATCH 01/39] yolo --- src/wasm-interpreter.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 701a89199fe..bcca9409e16 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -29,8 +29,10 @@ #include #include "fp16.h" +#include "ir/iteration.h" #include "ir/intrinsics.h" #include "ir/module-utils.h" +#include "ir/properties.h" #include "support/bits.h" #include "support/safe_integer.h" #include "support/stdckdint.h" @@ -240,6 +242,8 @@ class ExpressionRunner : public OverriddenVisitor { protected: RelaxedBehavior relaxedBehavior = RelaxedBehavior::NonConstant; + std::vector valueStack; + public: ExpressionRunner(Module* module = nullptr, Index maxDepth = NO_LIMIT, @@ -255,6 +259,17 @@ class ExpressionRunner : public OverriddenVisitor { if (maxDepth != NO_LIMIT && depth > maxDepth) { hostLimit("interpreter recursion limit"); } + if (!Properties::isControlFlow(curr)) { + // Visit the children and add them to the value stack. (Control flow + // expressions handle things manually.) + for (auto* child : ChildIterator(curr)) { + Flow flow = visit(child); + if (flow.breaking()) { + return flow; + } + valueStack.push_back(flow.values); + } + } auto ret = OverriddenVisitor::visit(curr); if (!ret.breaking()) { Type type = ret.getType(); From 9685d6ec16492d228a8da104f8950b3ecbec3e51 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 09:03:22 -0700 Subject: [PATCH 02/39] script --- a.py | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 a.py diff --git a/a.py b/a.py new file mode 100644 index 00000000000..3d0459c10e4 --- /dev/null +++ b/a.py @@ -0,0 +1,4 @@ +import os, sys +import subprocess + + From 93ea61cef668f63c99f6c35eb6d831d785ade1c6 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 09:04:42 -0700 Subject: [PATCH 03/39] script --- a.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/a.py b/a.py index 3d0459c10e4..afc3a862f74 100644 --- a/a.py +++ b/a.py @@ -1,4 +1,8 @@ import os, sys import subprocess +diff = subprocess.check_output(['git', 'diff']) +if diff: + print('cannot run since diff exists') + sys.exit(1) From ba18f371b5422fa754b0f497d89fcfd743a7da3e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 09:05:16 -0700 Subject: [PATCH 04/39] script --- a.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/a.py b/a.py index afc3a862f74..388e22b9399 100644 --- a/a.py +++ b/a.py @@ -6,3 +6,6 @@ print('cannot run since diff exists') sys.exit(1) +for line in open('src/wasm-interpreter.h').readlines(): + print(line) + From 7093708ce0489f974eaac31ad70fbc5a35e6aff5 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 09:07:46 -0700 Subject: [PATCH 05/39] work --- a.py | 8 +++++++- src/wasm-interpreter.h | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/a.py b/a.py index 388e22b9399..5229f4c686d 100644 --- a/a.py +++ b/a.py @@ -1,11 +1,17 @@ import os, sys import subprocess -diff = subprocess.check_output(['git', 'diff']) +diff = subprocess.check_output(['git', 'diff', 'src/']) if diff: print('cannot run since diff exists') sys.exit(1) for line in open('src/wasm-interpreter.h').readlines(): print(line) + # look for + # Flow flow = visit(expression); + # or + # Flow flow = self()->visit(expression); + if ' = visit(' in line or ' = self()->visit(' in line: + Flow flow = self()->visit(expression); diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index bcca9409e16..b8aa5b2aebd 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -244,6 +244,13 @@ class ExpressionRunner : public OverriddenVisitor { std::vector valueStack; + Literals pop() { + assert(!valueStack.empty()); + auto ret = valueStack.back(); + valueStack.pop_back(); + return ret; + } + public: ExpressionRunner(Module* module = nullptr, Index maxDepth = NO_LIMIT, From 53c3657ff663da865ae342d10a4779b8ee433b36 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 09:11:30 -0700 Subject: [PATCH 06/39] work --- a.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/a.py b/a.py index 5229f4c686d..b05b0afb433 100644 --- a/a.py +++ b/a.py @@ -6,12 +6,18 @@ print('cannot run since diff exists') sys.exit(1) +new = [] + for line in open('src/wasm-interpreter.h').readlines(): - print(line) # look for # Flow flow = visit(expression); # or # Flow flow = self()->visit(expression); if ' = visit(' in line or ' = self()->visit(' in line: - Flow flow = self()->visit(expression); + print(line.rstrip()) + parts = line.split(' ') + eq_index = parts.index('=') + + new.append(line) +open('src/wasm-interpreter.h', 'w').write(''.join(new)) From 09fbf0032b53721fc50b8508ad2194f40c4413df Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 09:12:20 -0700 Subject: [PATCH 07/39] work --- a.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/a.py b/a.py index b05b0afb433..1502dd11fcb 100644 --- a/a.py +++ b/a.py @@ -7,8 +7,10 @@ sys.exit(1) new = [] - -for line in open('src/wasm-interpreter.h').readlines(): +lines = open('src/wasm-interpreter.h').readlines() +i = 0 +while i < len(lines): + line = lines[i] # look for # Flow flow = visit(expression); # or @@ -19,5 +21,6 @@ eq_index = parts.index('=') new.append(line) + i += 1 open('src/wasm-interpreter.h', 'w').write(''.join(new)) From 8d8022a01e8b8136ecc027fbbaf0f4faf5b20011 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 09:13:49 -0700 Subject: [PATCH 08/39] work --- a.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/a.py b/a.py index 1502dd11fcb..b0dbc2d7f02 100644 --- a/a.py +++ b/a.py @@ -18,7 +18,8 @@ if ' = visit(' in line or ' = self()->visit(' in line: print(line.rstrip()) parts = line.split(' ') - eq_index = parts.index('=') + parts[-1] = 'pop();' + line = ' '.join(parts) + '\n' new.append(line) i += 1 From 4db30300529f307a47f8d7a95abe11b8e33287d9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 09:17:22 -0700 Subject: [PATCH 09/39] work --- a.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/a.py b/a.py index b0dbc2d7f02..aba4da44274 100644 --- a/a.py +++ b/a.py @@ -17,9 +17,23 @@ # Flow flow = self()->visit(expression); if ' = visit(' in line or ' = self()->visit(' in line: print(line.rstrip()) - parts = line.split(' ') - parts[-1] = 'pop();' - line = ' '.join(parts) + '\n' + # next, we should see + # + # if (flow.breaking()) { + # return flow; + # } + # + next = lines[i + 1] + if '.breaking()) {' in next: + next = lines[i + 2] + if 'return ' in next: + next = lines[i + 3] + if '}' in next: + # success! turn it all into a pop + parts = line.split(' ') + parts[-1] = 'pop();' + line = ' '.join(parts) + '\n' + i += 3 new.append(line) i += 1 From 1d2f536df68f415ecf9453b262af48636dc95615 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 09:19:12 -0700 Subject: [PATCH 10/39] weird --- src/wasm-interpreter.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index b8aa5b2aebd..a7318fb06ec 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -242,9 +242,10 @@ class ExpressionRunner : public OverriddenVisitor { protected: RelaxedBehavior relaxedBehavior = RelaxedBehavior::NonConstant; - std::vector valueStack; + // TODO: Literals here and not Flows + std::vector valueStack; - Literals pop() { + Flow pop() { assert(!valueStack.empty()); auto ret = valueStack.back(); valueStack.pop_back(); @@ -274,7 +275,7 @@ class ExpressionRunner : public OverriddenVisitor { if (flow.breaking()) { return flow; } - valueStack.push_back(flow.values); + valueStack.push_back(flow); } } auto ret = OverriddenVisitor::visit(curr); From f81efad7e92fd07b5fb11e107a9b8d933b6485e8 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 09:23:40 -0700 Subject: [PATCH 11/39] TRY.maybe.revert --- src/wasm-interpreter.h | 736 +++++++++-------------------------------- 1 file changed, 149 insertions(+), 587 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index a7318fb06ec..956c0dfd46a 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -183,11 +183,8 @@ class ExpressionRunner : public OverriddenVisitor { Flow generateArguments(const ExpressionList& operands, Literals& arguments) { NOTE_ENTER_("generateArguments"); arguments.reserve(operands.size()); - for (auto expression : operands) { - Flow flow = self()->visit(expression); - if (flow.breaking()) { - return flow; - } + for (Index i = 0; i < operands.size(); i++) { + Flow flow = pop(); NOTE_EVAL1(flow.values); arguments.push_back(flow.getSingleValue()); } @@ -267,7 +264,7 @@ class ExpressionRunner : public OverriddenVisitor { if (maxDepth != NO_LIMIT && depth > maxDepth) { hostLimit("interpreter recursion limit"); } - if (!Properties::isControlFlow(curr)) { + if (!Properties::isControlFlowStructure(curr)) { // Visit the children and add them to the value stack. (Control flow // expressions handle things manually.) for (auto* child : ChildIterator(curr)) { @@ -375,16 +372,10 @@ class ExpressionRunner : public OverriddenVisitor { bool condition = true; Flow flow; if (curr->value) { - flow = visit(curr->value); - if (flow.breaking()) { - return flow; - } + flow = pop(); } if (curr->condition) { - Flow conditionFlow = visit(curr->condition); - if (conditionFlow.breaking()) { - return conditionFlow; - } + Flow conditionFlow = pop(); condition = conditionFlow.getSingleValue().getInteger() != 0; if (!condition) { return flow; @@ -398,16 +389,10 @@ class ExpressionRunner : public OverriddenVisitor { Flow flow; Literals values; if (curr->value) { - flow = visit(curr->value); - if (flow.breaking()) { - return flow; - } + flow = pop(); values = flow.values; } - flow = visit(curr->condition); - if (flow.breaking()) { - return flow; - } + flow = pop(); int64_t index = flow.getSingleValue().getInteger(); Name target = curr->default_; if (index >= 0 && (size_t)index < curr->targets.size()) { @@ -429,10 +414,7 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitUnary(Unary* curr) { NOTE_ENTER("Unary"); - Flow flow = visit(curr->value); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); Literal value = flow.getSingleValue(); NOTE_EVAL1(value); switch (curr->op) { @@ -712,15 +694,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitBinary(Binary* curr) { NOTE_ENTER("Binary"); - Flow flow = visit(curr->left); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); Literal left = flow.getSingleValue(); - flow = visit(curr->right); - if (flow.breaking()) { - return flow; - } + flow = pop(); Literal right = flow.getSingleValue(); NOTE_EVAL2(left, right); assert(curr->left->type.isConcrete() ? left.type == curr->left->type @@ -1205,10 +1181,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitSIMDExtract(SIMDExtract* curr) { NOTE_ENTER("SIMDExtract"); - Flow flow = self()->visit(curr->vec); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); Literal vec = flow.getSingleValue(); switch (curr->op) { case ExtractLaneSVecI8x16: @@ -1234,15 +1207,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitSIMDReplace(SIMDReplace* curr) { NOTE_ENTER("SIMDReplace"); - Flow flow = self()->visit(curr->vec); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); Literal vec = flow.getSingleValue(); - flow = self()->visit(curr->value); - if (flow.breaking()) { - return flow; - } + flow = pop(); Literal value = flow.getSingleValue(); switch (curr->op) { case ReplaceLaneVecI8x16: @@ -1264,34 +1231,19 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitSIMDShuffle(SIMDShuffle* curr) { NOTE_ENTER("SIMDShuffle"); - Flow flow = self()->visit(curr->left); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); Literal left = flow.getSingleValue(); - flow = self()->visit(curr->right); - if (flow.breaking()) { - return flow; - } + flow = pop(); Literal right = flow.getSingleValue(); return left.shuffleV8x16(right, curr->mask); } Flow visitSIMDTernary(SIMDTernary* curr) { NOTE_ENTER("SIMDBitselect"); - Flow flow = self()->visit(curr->a); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); Literal a = flow.getSingleValue(); - flow = self()->visit(curr->b); - if (flow.breaking()) { - return flow; - } + flow = pop(); Literal b = flow.getSingleValue(); - flow = self()->visit(curr->c); - if (flow.breaking()) { - return flow; - } + flow = pop(); Literal c = flow.getSingleValue(); switch (curr->op) { case Bitselect: @@ -1341,15 +1293,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitSIMDShift(SIMDShift* curr) { NOTE_ENTER("SIMDShift"); - Flow flow = self()->visit(curr->vec); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); Literal vec = flow.getSingleValue(); - flow = self()->visit(curr->shift); - if (flow.breaking()) { - return flow; - } + flow = pop(); Literal shift = flow.getSingleValue(); switch (curr->op) { case ShlVecI8x16: @@ -1381,37 +1327,22 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitSelect(Select* curr) { NOTE_ENTER("Select"); - Flow ifTrue = visit(curr->ifTrue); - if (ifTrue.breaking()) { - return ifTrue; - } - Flow ifFalse = visit(curr->ifFalse); - if (ifFalse.breaking()) { - return ifFalse; - } - Flow condition = visit(curr->condition); - if (condition.breaking()) { - return condition; - } + Flow ifTrue = pop(); + Flow ifFalse = pop(); + Flow condition = pop(); NOTE_EVAL1(condition.getSingleValue()); return condition.getSingleValue().geti32() ? ifTrue : ifFalse; // ;-) } Flow visitDrop(Drop* curr) { NOTE_ENTER("Drop"); - Flow value = visit(curr->value); - if (value.breaking()) { - return value; - } + Flow value = pop(); return Flow(); } Flow visitReturn(Return* curr) { NOTE_ENTER("Return"); Flow flow; if (curr->value) { - flow = visit(curr->value); - if (flow.breaking()) { - return flow; - } + flow = pop(); NOTE_EVAL1(flow.getSingleValue()); } flow.breakTo = RETURN_FLOW; @@ -1507,10 +1438,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitTupleExtract(TupleExtract* curr) { NOTE_ENTER("tuple.extract"); - Flow flow = visit(curr->tuple); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); assert(flow.values.size() > curr->index); return Flow(flow.values[curr->index]); } @@ -1547,10 +1475,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitRefIsNull(RefIsNull* curr) { NOTE_ENTER("RefIsNull"); - Flow flow = visit(curr->value); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); const auto& value = flow.getSingleValue(); NOTE_EVAL1(value); return Literal(int32_t(value.isNull())); @@ -1562,15 +1487,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitRefEq(RefEq* curr) { NOTE_ENTER("RefEq"); - Flow flow = visit(curr->left); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); auto left = flow.getSingleValue(); - flow = visit(curr->right); - if (flow.breaking()) { - return flow; - } + flow = pop(); auto right = flow.getSingleValue(); NOTE_EVAL2(left, right); return Literal(int32_t(left == right)); @@ -1599,10 +1518,7 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitRethrow(Rethrow* curr) { WASM_UNREACHABLE("unimp"); } Flow visitThrowRef(ThrowRef* curr) { NOTE_ENTER("ThrowRef"); - Flow flow = visit(curr->exnref); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); const auto& exnref = flow.getSingleValue(); NOTE_EVAL1(exnref); if (exnref.isNull()) { @@ -1614,10 +1530,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitRefI31(RefI31* curr) { NOTE_ENTER("RefI31"); - Flow flow = visit(curr->value); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); const auto& value = flow.getSingleValue(); NOTE_EVAL1(value); return Literal::makeI31(value.geti32(), @@ -1625,10 +1538,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitI31Get(I31Get* curr) { NOTE_ENTER("I31Get"); - Flow flow = visit(curr->i31); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); const auto& value = flow.getSingleValue(); NOTE_EVAL1(value); if (value.isNull()) { @@ -1662,10 +1572,7 @@ class ExpressionRunner : public OverriddenVisitor { }; template Cast doCast(T* curr) { - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return typename Cast::Breaking{ref}; - } + Flow ref = pop(); Literal val = ref.getSingleValue(); Type castType = curr->getCastType(); if (Type::isSubType(val.type, castType)) { @@ -1675,14 +1582,8 @@ class ExpressionRunner : public OverriddenVisitor { } } template Cast doDescCast(T* curr) { - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return typename Cast::Breaking{ref}; - } - Flow desc = self()->visit(curr->desc); - if (desc.breaking()) { - return typename Cast::Breaking{desc}; - } + Flow ref = pop(); + Flow desc = pop(); auto expected = desc.getSingleValue().getGCData(); if (!expected) { trap("null descriptor"); @@ -1732,10 +1633,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitRefGetDesc(RefGetDesc* curr) { NOTE_ENTER("RefGetDesc"); - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return ref; - } + Flow ref = pop(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1772,10 +1670,7 @@ class ExpressionRunner : public OverriddenVisitor { case BrOnNull: case BrOnNonNull: { // Otherwise we are just checking for null. - Flow flow = visit(curr->ref); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); const auto& value = flow.getSingleValue(); NOTE_EVAL1(value); if (curr->op == BrOnNull) { @@ -1802,17 +1697,11 @@ class ExpressionRunner : public OverriddenVisitor { if (curr->type == Type::unreachable) { // We cannot proceed to compute the heap type, as there isn't one. Just // find why we are unreachable, and stop there. - for (auto* operand : curr->operands) { - auto value = self()->visit(operand); - if (value.breaking()) { - return value; - } + for (Index i = 0; i < curr->operands.size(); i++) { + auto value = pop(); } if (curr->desc) { - auto value = self()->visit(curr->desc); - if (value.breaking()) { - return value; - } + auto value = pop(); } WASM_UNREACHABLE("unreachable but no unreachable child"); } @@ -1824,20 +1713,14 @@ class ExpressionRunner : public OverriddenVisitor { if (curr->isWithDefault()) { data[i] = Literal::makeZero(field.type); } else { - auto value = self()->visit(curr->operands[i]); - if (value.breaking()) { - return value; - } + auto value = pop(); data[i] = truncateForPacking(value.getSingleValue(), field); } } if (!curr->desc) { return makeGCData(std::move(data), curr->type); } - auto desc = self()->visit(curr->desc); - if (desc.breaking()) { - return desc; - } + auto desc = pop(); if (desc.getSingleValue().isNull()) { trap("null descriptor"); } @@ -1845,10 +1728,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitStructGet(StructGet* curr) { NOTE_ENTER("StructGet"); - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return ref; - } + Flow ref = pop(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1858,14 +1738,8 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitStructSet(StructSet* curr) { NOTE_ENTER("StructSet"); - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return ref; - } - Flow value = self()->visit(curr->value); - if (value.breaking()) { - return value; - } + Flow ref = pop(); + Flow value = pop(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1878,14 +1752,8 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitStructRMW(StructRMW* curr) { NOTE_ENTER("StructRMW"); - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return ref; - } - Flow value = self()->visit(curr->value); - if (value.breaking()) { - return value; - } + Flow ref = pop(); + Flow value = pop(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1918,18 +1786,9 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitStructCmpxchg(StructCmpxchg* curr) { NOTE_ENTER("StructCmpxchg"); - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return ref; - } - Flow expected = self()->visit(curr->expected); - if (expected.breaking()) { - return expected; - } - Flow replacement = self()->visit(curr->replacement); - if (replacement.breaking()) { - return replacement; - } + Flow ref = pop(); + Flow expected = pop(); + Flow replacement = pop(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1952,15 +1811,9 @@ class ExpressionRunner : public OverriddenVisitor { NOTE_ENTER("ArrayNew"); Flow init; if (!curr->isWithDefault()) { - init = self()->visit(curr->init); - if (init.breaking()) { - return init; - } - } - auto size = self()->visit(curr->size); - if (size.breaking()) { - return size; + init = pop(); } + auto size = pop(); if (curr->type == Type::unreachable) { // We cannot proceed to compute the heap type, as there isn't one. Just // visit the unreachable child, and stop there. @@ -2001,10 +1854,7 @@ class ExpressionRunner : public OverriddenVisitor { // We cannot proceed to compute the heap type, as there isn't one. Just // find why we are unreachable, and stop there. for (auto* value : curr->values) { - auto result = self()->visit(value); - if (result.breaking()) { - return result; - } + auto result = pop(); } WASM_UNREACHABLE("unreachable but no unreachable child"); } @@ -2012,24 +1862,15 @@ class ExpressionRunner : public OverriddenVisitor { auto field = heapType.getArray().element; Literals data(num); for (Index i = 0; i < num; i++) { - auto value = self()->visit(curr->values[i]); - if (value.breaking()) { - return value; - } + auto value = pop(); data[i] = truncateForPacking(value.getSingleValue(), field); } return makeGCData(std::move(data), curr->type); } Flow visitArrayGet(ArrayGet* curr) { NOTE_ENTER("ArrayGet"); - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return ref; - } - Flow index = self()->visit(curr->index); - if (index.breaking()) { - return index; - } + Flow ref = pop(); + Flow index = pop(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -2043,18 +1884,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitArraySet(ArraySet* curr) { NOTE_ENTER("ArraySet"); - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return ref; - } - Flow index = self()->visit(curr->index); - if (index.breaking()) { - return index; - } - Flow value = self()->visit(curr->value); - if (value.breaking()) { - return value; - } + Flow ref = pop(); + Flow index = pop(); + Flow value = pop(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -2069,10 +1901,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitArrayLen(ArrayLen* curr) { NOTE_ENTER("ArrayLen"); - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return ref; - } + Flow ref = pop(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -2081,26 +1910,11 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitArrayCopy(ArrayCopy* curr) { NOTE_ENTER("ArrayCopy"); - Flow destRef = self()->visit(curr->destRef); - if (destRef.breaking()) { - return destRef; - } - Flow destIndex = self()->visit(curr->destIndex); - if (destIndex.breaking()) { - return destIndex; - } - Flow srcRef = self()->visit(curr->srcRef); - if (srcRef.breaking()) { - return srcRef; - } - Flow srcIndex = self()->visit(curr->srcIndex); - if (srcIndex.breaking()) { - return srcIndex; - } - Flow length = self()->visit(curr->length); - if (length.breaking()) { - return length; - } + Flow destRef = pop(); + Flow destIndex = pop(); + Flow srcRef = pop(); + Flow srcIndex = pop(); + Flow length = pop(); auto destData = destRef.getSingleValue().getGCData(); if (!destData) { trap("null ref"); @@ -2130,22 +1944,10 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitArrayFill(ArrayFill* curr) { NOTE_ENTER("ArrayFill"); - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return ref; - } - Flow index = self()->visit(curr->index); - if (index.breaking()) { - return index; - } - Flow value = self()->visit(curr->value); - if (value.breaking()) { - return value; - } - Flow size = self()->visit(curr->size); - if (size.breaking()) { - return size; - } + Flow ref = pop(); + Flow index = pop(); + Flow value = pop(); + Flow size = pop(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -2171,18 +1973,9 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitArrayInitElem(ArrayInitElem* curr) { WASM_UNREACHABLE("unimp"); } Flow visitArrayRMW(ArrayRMW* curr) { NOTE_ENTER("ArrayRMW"); - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return ref; - } - Flow index = self()->visit(curr->index); - if (index.breaking()) { - return index; - } - Flow value = self()->visit(curr->value); - if (value.breaking()) { - return value; - } + Flow ref = pop(); + Flow index = pop(); + Flow value = pop(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -2216,22 +2009,10 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitArrayCmpxchg(ArrayCmpxchg* curr) { NOTE_ENTER("ArrayCmpxchg"); - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return ref; - } - Flow index = self()->visit(curr->index); - if (index.breaking()) { - return index; - } - Flow expected = self()->visit(curr->expected); - if (expected.breaking()) { - return expected; - } - Flow replacement = self()->visit(curr->replacement); - if (replacement.breaking()) { - return replacement; - } + Flow ref = pop(); + Flow index = pop(); + Flow expected = pop(); + Flow replacement = pop(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -2246,10 +2027,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitRefAs(RefAs* curr) { NOTE_ENTER("RefAs"); - Flow flow = visit(curr->value); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); const auto& value = flow.getSingleValue(); NOTE_EVAL1(value); switch (curr->op) { @@ -2266,20 +2044,11 @@ class ExpressionRunner : public OverriddenVisitor { WASM_UNREACHABLE("unimplemented ref.as_*"); } Flow visitStringNew(StringNew* curr) { - Flow ptr = visit(curr->ref); - if (ptr.breaking()) { - return ptr; - } + Flow ptr = pop(); switch (curr->op) { case StringNewWTF16Array: { - Flow start = visit(curr->start); - if (start.breaking()) { - return start; - } - Flow end = visit(curr->end); - if (end.breaking()) { - return end; - } + Flow start = pop(); + Flow end = pop(); auto ptrData = ptr.getSingleValue().getGCData(); if (!ptrData) { trap("null ref"); @@ -2323,10 +2092,7 @@ class ExpressionRunner : public OverriddenVisitor { return Flow(NONCONSTANT_FLOW); } - Flow flow = visit(curr->ref); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); auto value = flow.getSingleValue(); auto data = value.getGCData(); if (!data) { @@ -2337,15 +2103,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitStringConcat(StringConcat* curr) { NOTE_ENTER("StringConcat"); - Flow flow = visit(curr->left); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); auto left = flow.getSingleValue(); - flow = visit(curr->right); - if (flow.breaking()) { - return flow; - } + flow = pop(); auto right = flow.getSingleValue(); NOTE_EVAL2(left, right); auto leftData = left.getGCData(); @@ -2376,18 +2136,9 @@ class ExpressionRunner : public OverriddenVisitor { return Flow(NONCONSTANT_FLOW); } - Flow str = visit(curr->str); - if (str.breaking()) { - return str; - } - Flow array = visit(curr->array); - if (array.breaking()) { - return array; - } - Flow start = visit(curr->start); - if (start.breaking()) { - return start; - } + Flow str = pop(); + Flow array = pop(); + Flow start = pop(); auto strData = str.getSingleValue().getGCData(); auto arrayData = array.getSingleValue().getGCData(); @@ -2411,15 +2162,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitStringEq(StringEq* curr) { NOTE_ENTER("StringEq"); - Flow flow = visit(curr->left); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); auto left = flow.getSingleValue(); - flow = visit(curr->right); - if (flow.breaking()) { - return flow; - } + flow = pop(); auto right = flow.getSingleValue(); NOTE_EVAL2(left, right); auto leftData = left.getGCData(); @@ -2476,23 +2221,14 @@ class ExpressionRunner : public OverriddenVisitor { return Literal(result); } Flow visitStringTest(StringTest* curr) { - Flow flow = visit(curr->ref); - if (flow.breaking()) { - return flow; - } + Flow flow = pop(); auto value = flow.getSingleValue(); return Literal((uint32_t)value.isString()); } Flow visitStringWTF16Get(StringWTF16Get* curr) { NOTE_ENTER("StringWTF16Get"); - Flow ref = visit(curr->ref); - if (ref.breaking()) { - return ref; - } - Flow pos = visit(curr->pos); - if (pos.breaking()) { - return pos; - } + Flow ref = pop(); + Flow pos = pop(); auto refValue = ref.getSingleValue(); auto data = refValue.getGCData(); if (!data) { @@ -2507,18 +2243,9 @@ class ExpressionRunner : public OverriddenVisitor { return Literal(values[i].geti32()); } Flow visitStringSliceWTF(StringSliceWTF* curr) { - Flow ref = visit(curr->ref); - if (ref.breaking()) { - return ref; - } - Flow start = visit(curr->start); - if (start.breaking()) { - return start; - } - Flow end = visit(curr->end); - if (end.breaking()) { - return end; - } + Flow ref = pop(); + Flow start = pop(); + Flow end = pop(); auto refData = ref.getSingleValue().getGCData(); if (!refData) { @@ -3488,10 +3215,7 @@ class ModuleRunnerBase : public ExpressionRunner { if (flow.breaking()) { return flow; } - Flow target = self()->visit(curr->target); - if (target.breaking()) { - return target; - } + Flow target = self()->pop(); auto index = target.getSingleValue().getUnsigned(); auto info = getTableInstanceInfo(curr->table); @@ -3522,10 +3246,7 @@ class ModuleRunnerBase : public ExpressionRunner { if (flow.breaking()) { return flow; } - Flow target = self()->visit(curr->target); - if (target.breaking()) { - return target; - } + Flow target = self()->pop(); auto targetRef = target.getSingleValue(); if (targetRef.isNull()) { trap("null target in call_ref"); @@ -3547,24 +3268,15 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitTableGet(TableGet* curr) { NOTE_ENTER("TableGet"); - Flow index = self()->visit(curr->index); - if (index.breaking()) { - return index; - } + Flow index = self()->pop(); auto info = getTableInstanceInfo(curr->table); auto address = index.getSingleValue().getUnsigned(); return info.interface()->tableLoad(info.name, address); } Flow visitTableSet(TableSet* curr) { NOTE_ENTER("TableSet"); - Flow index = self()->visit(curr->index); - if (index.breaking()) { - return index; - } - Flow value = self()->visit(curr->value); - if (value.breaking()) { - return value; - } + Flow index = self()->pop(); + Flow value = self()->pop(); auto info = getTableInstanceInfo(curr->table); auto address = index.getSingleValue().getUnsigned(); info.interface()->tableStore(info.name, address, value.getSingleValue()); @@ -3581,14 +3293,8 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitTableGrow(TableGrow* curr) { NOTE_ENTER("TableGrow"); - Flow valueFlow = self()->visit(curr->value); - if (valueFlow.breaking()) { - return valueFlow; - } - Flow deltaFlow = self()->visit(curr->delta); - if (deltaFlow.breaking()) { - return deltaFlow; - } + Flow valueFlow = self()->pop(); + Flow deltaFlow = self()->pop(); auto info = getTableInstanceInfo(curr->table); uint64_t tableSize = info.interface()->tableSize(info.name); @@ -3615,18 +3321,9 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitTableFill(TableFill* curr) { NOTE_ENTER("TableFill"); - Flow destFlow = self()->visit(curr->dest); - if (destFlow.breaking()) { - return destFlow; - } - Flow valueFlow = self()->visit(curr->value); - if (valueFlow.breaking()) { - return valueFlow; - } - Flow sizeFlow = self()->visit(curr->size); - if (sizeFlow.breaking()) { - return sizeFlow; - } + Flow destFlow = self()->pop(); + Flow valueFlow = self()->pop(); + Flow sizeFlow = self()->pop(); auto info = getTableInstanceInfo(curr->table); auto dest = destFlow.getSingleValue().getUnsigned(); @@ -3646,18 +3343,9 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitTableCopy(TableCopy* curr) { NOTE_ENTER("TableCopy"); - Flow dest = self()->visit(curr->dest); - if (dest.breaking()) { - return dest; - } - Flow source = self()->visit(curr->source); - if (source.breaking()) { - return source; - } - Flow size = self()->visit(curr->size); - if (size.breaking()) { - return size; - } + Flow dest = self()->pop(); + Flow source = self()->pop(); + Flow size = self()->pop(); NOTE_EVAL1(dest); NOTE_EVAL1(source); NOTE_EVAL1(size); @@ -3697,18 +3385,9 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitTableInit(TableInit* curr) { NOTE_ENTER("TableInit"); - Flow dest = self()->visit(curr->dest); - if (dest.breaking()) { - return dest; - } - Flow offset = self()->visit(curr->offset); - if (offset.breaking()) { - return offset; - } - Flow size = self()->visit(curr->size); - if (size.breaking()) { - return size; - } + Flow dest = self()->pop(); + Flow offset = self()->pop(); + Flow size = self()->pop(); NOTE_EVAL1(dest); NOTE_EVAL1(offset); NOTE_EVAL1(size); @@ -3759,10 +3438,7 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitLocalSet(LocalSet* curr) { NOTE_ENTER("LocalSet"); auto index = curr->index; - Flow flow = self()->visit(curr->value); - if (flow.breaking()) { - return flow; - } + Flow flow = self()->pop(); NOTE_EVAL1(index); NOTE_EVAL1(flow.getSingleValue()); assert(curr->isTee() ? Type::isSubType(flow.getType(), curr->type) : true); @@ -3779,10 +3455,7 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitGlobalSet(GlobalSet* curr) { NOTE_ENTER("GlobalSet"); auto name = curr->name; - Flow flow = self()->visit(curr->value); - if (flow.breaking()) { - return flow; - } + Flow flow = self()->pop(); NOTE_EVAL1(name); NOTE_EVAL1(flow.getSingleValue()); @@ -3792,10 +3465,7 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitLoad(Load* curr) { NOTE_ENTER("Load"); - Flow flow = self()->visit(curr->ptr); - if (flow.breaking()) { - return flow; - } + Flow flow = self()->pop(); NOTE_EVAL1(flow); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); @@ -3811,14 +3481,8 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitStore(Store* curr) { NOTE_ENTER("Store"); - Flow ptr = self()->visit(curr->ptr); - if (ptr.breaking()) { - return ptr; - } - Flow value = self()->visit(curr->value); - if (value.breaking()) { - return value; - } + Flow ptr = self()->pop(); + Flow value = self()->pop(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto addr = @@ -3834,14 +3498,8 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitAtomicRMW(AtomicRMW* curr) { NOTE_ENTER("AtomicRMW"); - Flow ptr = self()->visit(curr->ptr); - if (ptr.breaking()) { - return ptr; - } - auto value = self()->visit(curr->value); - if (value.breaking()) { - return value; - } + Flow ptr = self()->pop(); + auto value = self()->pop(); NOTE_EVAL1(ptr); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); @@ -3878,19 +3536,10 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitAtomicCmpxchg(AtomicCmpxchg* curr) { NOTE_ENTER("AtomicCmpxchg"); - Flow ptr = self()->visit(curr->ptr); - if (ptr.breaking()) { - return ptr; - } + Flow ptr = self()->pop(); NOTE_EVAL1(ptr); - auto expected = self()->visit(curr->expected); - if (expected.breaking()) { - return expected; - } - auto replacement = self()->visit(curr->replacement); - if (replacement.breaking()) { - return replacement; - } + auto expected = self()->pop(); + auto replacement = self()->pop(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto addr = @@ -3910,10 +3559,7 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitAtomicWait(AtomicWait* curr) { NOTE_ENTER("AtomicWait"); - Flow ptr = self()->visit(curr->ptr); - if (ptr.breaking()) { - return ptr; - } + Flow ptr = self()->pop(); NOTE_EVAL1(ptr); auto expected = self()->visit(curr->expected); NOTE_EVAL1(expected); @@ -3948,10 +3594,7 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitAtomicNotify(AtomicNotify* curr) { NOTE_ENTER("AtomicNotify"); - Flow ptr = self()->visit(curr->ptr); - if (ptr.breaking()) { - return ptr; - } + Flow ptr = self()->pop(); NOTE_EVAL1(ptr); auto count = self()->visit(curr->notifyCount); NOTE_EVAL1(count); @@ -4016,17 +3659,11 @@ class ModuleRunnerBase : public ExpressionRunner { WASM_UNREACHABLE("invalid op"); } load.finalize(); - Flow flow = self()->visit(&load); - if (flow.breaking()) { - return flow; - } + Flow flow = self()->pop(); return (flow.getSingleValue().*splat)(); } Flow visitSIMDLoadExtend(SIMDLoad* curr) { - Flow flow = self()->visit(curr->ptr); - if (flow.breaking()) { - return flow; - } + Flow flow = self()->pop(); NOTE_EVAL1(flow); Address src(flow.getSingleValue().getUnsigned()); auto info = getMemoryInstanceInfo(curr->memory); @@ -4083,10 +3720,7 @@ class ModuleRunnerBase : public ExpressionRunner { WASM_UNREACHABLE("invalid op"); } Flow visitSIMDLoadZero(SIMDLoad* curr) { - Flow flow = self()->visit(curr->ptr); - if (flow.breaking()) { - return flow; - } + Flow flow = self()->pop(); NOTE_EVAL1(flow); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); @@ -4104,15 +3738,9 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { NOTE_ENTER("SIMDLoadStoreLane"); - Flow ptrFlow = self()->visit(curr->ptr); - if (ptrFlow.breaking()) { - return ptrFlow; - } + Flow ptrFlow = self()->pop(); NOTE_EVAL1(ptrFlow); - Flow vecFlow = self()->visit(curr->vec); - if (vecFlow.breaking()) { - return vecFlow; - } + Flow vecFlow = self()->pop(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); Address addr = info.instance->getFinalAddress( @@ -4183,10 +3811,7 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitMemoryGrow(MemoryGrow* curr) { NOTE_ENTER("MemoryGrow"); - Flow flow = self()->visit(curr->delta); - if (flow.breaking()) { - return flow; - } + Flow flow = self()->pop(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto* memory = info.instance->wasm.getMemory(info.name); @@ -4222,18 +3847,9 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitMemoryInit(MemoryInit* curr) { NOTE_ENTER("MemoryInit"); - Flow dest = self()->visit(curr->dest); - if (dest.breaking()) { - return dest; - } - Flow offset = self()->visit(curr->offset); - if (offset.breaking()) { - return offset; - } - Flow size = self()->visit(curr->size); - if (size.breaking()) { - return size; - } + Flow dest = self()->pop(); + Flow offset = self()->pop(); + Flow size = self()->pop(); NOTE_EVAL1(dest); NOTE_EVAL1(offset); NOTE_EVAL1(size); @@ -4271,18 +3887,9 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitMemoryCopy(MemoryCopy* curr) { NOTE_ENTER("MemoryCopy"); - Flow dest = self()->visit(curr->dest); - if (dest.breaking()) { - return dest; - } - Flow source = self()->visit(curr->source); - if (source.breaking()) { - return source; - } - Flow size = self()->visit(curr->size); - if (size.breaking()) { - return size; - } + Flow dest = self()->pop(); + Flow source = self()->pop(); + Flow size = self()->pop(); NOTE_EVAL1(dest); NOTE_EVAL1(source); NOTE_EVAL1(size); @@ -4325,18 +3932,9 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitMemoryFill(MemoryFill* curr) { NOTE_ENTER("MemoryFill"); - Flow dest = self()->visit(curr->dest); - if (dest.breaking()) { - return dest; - } - Flow value = self()->visit(curr->value); - if (value.breaking()) { - return value; - } - Flow size = self()->visit(curr->size); - if (size.breaking()) { - return size; - } + Flow dest = self()->pop(); + Flow value = self()->pop(); + Flow size = self()->pop(); NOTE_EVAL1(dest); NOTE_EVAL1(value); NOTE_EVAL1(size); @@ -4362,14 +3960,8 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitArrayNewData(ArrayNewData* curr) { NOTE_ENTER("ArrayNewData"); - auto offsetFlow = self()->visit(curr->offset); - if (offsetFlow.breaking()) { - return offsetFlow; - } - auto sizeFlow = self()->visit(curr->size); - if (sizeFlow.breaking()) { - return sizeFlow; - } + auto offsetFlow = self()->pop(); + auto sizeFlow = self()->pop(); uint64_t offset = offsetFlow.getSingleValue().getUnsigned(); uint64_t size = sizeFlow.getSingleValue().getUnsigned(); @@ -4403,14 +3995,8 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitArrayNewElem(ArrayNewElem* curr) { NOTE_ENTER("ArrayNewElem"); - auto offsetFlow = self()->visit(curr->offset); - if (offsetFlow.breaking()) { - return offsetFlow; - } - auto sizeFlow = self()->visit(curr->size); - if (sizeFlow.breaking()) { - return sizeFlow; - } + auto offsetFlow = self()->pop(); + auto sizeFlow = self()->pop(); uint64_t offset = offsetFlow.getSingleValue().getUnsigned(); uint64_t size = sizeFlow.getSingleValue().getUnsigned(); @@ -4434,22 +4020,10 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitArrayInitData(ArrayInitData* curr) { NOTE_ENTER("ArrayInit"); - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return ref; - } - Flow index = self()->visit(curr->index); - if (index.breaking()) { - return index; - } - Flow offset = self()->visit(curr->offset); - if (offset.breaking()) { - return offset; - } - Flow size = self()->visit(curr->size); - if (size.breaking()) { - return size; - } + Flow ref = self()->pop(); + Flow index = self()->pop(); + Flow offset = self()->pop(); + Flow size = self()->pop(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -4483,22 +4057,10 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitArrayInitElem(ArrayInitElem* curr) { NOTE_ENTER("ArrayInit"); - Flow ref = self()->visit(curr->ref); - if (ref.breaking()) { - return ref; - } - Flow index = self()->visit(curr->index); - if (index.breaking()) { - return index; - } - Flow offset = self()->visit(curr->offset); - if (offset.breaking()) { - return offset; - } - Flow size = self()->visit(curr->size); - if (size.breaking()) { - return size; - } + Flow ref = self()->pop(); + Flow index = self()->pop(); + Flow offset = self()->pop(); + Flow size = self()->pop(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); From 1d6fc388d11729eabf37e9fcf7aa2927d05a2c6b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 09:37:24 -0700 Subject: [PATCH 12/39] FIX --- src/wasm-interpreter.h | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 956c0dfd46a..cac5caf07b3 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1694,17 +1694,10 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitStructNew(StructNew* curr) { NOTE_ENTER("StructNew"); - if (curr->type == Type::unreachable) { - // We cannot proceed to compute the heap type, as there isn't one. Just - // find why we are unreachable, and stop there. - for (Index i = 0; i < curr->operands.size(); i++) { - auto value = pop(); - } - if (curr->desc) { - auto value = pop(); - } - WASM_UNREACHABLE("unreachable but no unreachable child"); - } + // If we are unreachable then we cannot proceed to compute the heap type, + // below, as there isn't one. But if we are unreachable then we should not + // get here, as the child would break in visit(). + assert(curr->type != Type::unreachable); auto heapType = curr->type.getHeapType(); const auto& fields = heapType.getStruct().fields; Literals data(fields.size()); @@ -1850,14 +1843,10 @@ class ExpressionRunner : public OverriddenVisitor { if (num >= DataLimit) { hostLimit("allocation failure"); } - if (curr->type == Type::unreachable) { - // We cannot proceed to compute the heap type, as there isn't one. Just - // find why we are unreachable, and stop there. - for (auto* value : curr->values) { - auto result = pop(); - } - WASM_UNREACHABLE("unreachable but no unreachable child"); - } + // If we are unreachable then we cannot proceed to compute the heap type, + // below, as there isn't one. But if we are unreachable then we should not + // get here, as the child would break in visit(). + assert(curr->type != Type::unreachable); auto heapType = curr->type.getHeapType(); auto field = heapType.getArray().element; Literals data(num); From 0da3cfaf01488d00d0933afa710e59e78f306f4d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 11:38:00 -0700 Subject: [PATCH 13/39] order.debug --- src/wasm-interpreter.h | 74 +++++++++++++---------------------- src/wasm/wasm-interpreter.cpp | 17 -------- 2 files changed, 27 insertions(+), 64 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index cac5caf07b3..58760ff0896 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1,3 +1,4 @@ +#define WASM_INTERPRETER_DEBUG 1 /* * Copyright 2015 WebAssembly Community Group participants * @@ -25,6 +26,7 @@ #include #include +#include #include #include @@ -114,54 +116,12 @@ class Flow { } }; -// Debugging helpers -#ifdef WASM_INTERPRETER_DEBUG -class Indenter { - static int indentLevel; - - const char* entryName; - -public: - Indenter(const char* entry); - ~Indenter(); - - static void print(); -}; - -#define NOTE_ENTER(x) \ - Indenter _int_blah(x); \ - { \ - Indenter::print(); \ - std::cout << "visit " << x << " : " << curr << "\n"; \ - } -#define NOTE_ENTER_(x) \ - Indenter _int_blah(x); \ - { \ - Indenter::print(); \ - std::cout << "visit " << x << "\n"; \ - } -#define NOTE_NAME(p0) \ - { \ - Indenter::print(); \ - std::cout << "name " << '(' << Name(p0) << ")\n"; \ - } -#define NOTE_EVAL1(p0) \ - { \ - Indenter::print(); \ - std::cout << "eval " #p0 " (" << p0 << ")\n"; \ - } -#define NOTE_EVAL2(p0, p1) \ - { \ - Indenter::print(); \ - std::cout << "eval " #p0 " (" << p0 << "), " #p1 " (" << p1 << ")\n"; \ - } -#else // WASM_INTERPRETER_DEBUG +// Debugging helpers XXX remove #define NOTE_ENTER(x) #define NOTE_ENTER_(x) #define NOTE_NAME(p0) #define NOTE_EVAL1(p0) #define NOTE_EVAL2(p0, p1) -#endif // WASM_INTERPRETER_DEBUG // Execute an expression template @@ -240,12 +200,26 @@ class ExpressionRunner : public OverriddenVisitor { RelaxedBehavior relaxedBehavior = RelaxedBehavior::NonConstant; // TODO: Literals here and not Flows - std::vector valueStack; + std::queue valueStack; + +#if WASM_INTERPRETER_DEBUG + std::string indent() { + std::string ret; + for (Index i = 0; i < depth; i++) { + ret += ' '; + } + return ret; + } +#endif + Flow pop() { assert(!valueStack.empty()); - auto ret = valueStack.back(); - valueStack.pop_back(); + auto ret = valueStack.front(); +#if WASM_INTERPRETER_DEBUG + std::cout << indent() << "popping " << ret << '\n'; +#endif + valueStack.pop(); return ret; } @@ -260,6 +234,9 @@ class ExpressionRunner : public OverriddenVisitor { void setRelaxedBehavior(RelaxedBehavior value) { relaxedBehavior = value; } Flow visit(Expression* curr) { +#if WASM_INTERPRETER_DEBUG + std::cout << indent() << "visit(" << getExpressionName(curr) << ")\n"; +#endif depth++; if (maxDepth != NO_LIMIT && depth > maxDepth) { hostLimit("interpreter recursion limit"); @@ -272,7 +249,10 @@ class ExpressionRunner : public OverriddenVisitor { if (flow.breaking()) { return flow; } - valueStack.push_back(flow); +#if WASM_INTERPRETER_DEBUG + std::cout << indent() << " visited child, adding to value stack " << flow << '\n'; +#endif + valueStack.push(flow); } } auto ret = OverriddenVisitor::visit(curr); diff --git a/src/wasm/wasm-interpreter.cpp b/src/wasm/wasm-interpreter.cpp index cd6c232b5fb..37ac05556ac 100644 --- a/src/wasm/wasm-interpreter.cpp +++ b/src/wasm/wasm-interpreter.cpp @@ -2,23 +2,6 @@ namespace wasm { -#ifdef WASM_INTERPRETER_DEBUG -int Indenter::indentLevel = 0; - -Indenter::Indenter(const char* entry) : entryName(entry) { ++indentLevel; } -Indenter::~Indenter() { - print(); - std::cout << "exit " << entryName << '\n'; - --indentLevel; -} -void Indenter::print() { - std::cout << indentLevel << ':'; - for (int i = 0; i <= indentLevel; ++i) { - std::cout << ' '; - } -} -#endif // WASM_INTERPRETER_DEBUG - std::ostream& operator<<(std::ostream& o, const WasmException& exn) { auto exnData = exn.exn.getExnData(); return o << exnData->tag << " " << exnData->payload; From 87b74e71ef19f66133d0488e73c260bd398f20ca Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 12:06:47 -0700 Subject: [PATCH 14/39] fix --- src/wasm-interpreter.h | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 58760ff0896..cad4762e4e9 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -24,9 +24,9 @@ #ifndef wasm_wasm_interpreter_h #define wasm_wasm_interpreter_h +#include #include #include -#include #include #include @@ -200,7 +200,7 @@ class ExpressionRunner : public OverriddenVisitor { RelaxedBehavior relaxedBehavior = RelaxedBehavior::NonConstant; // TODO: Literals here and not Flows - std::queue valueStack; + std::vector valueStack; #if WASM_INTERPRETER_DEBUG std::string indent() { @@ -215,11 +215,11 @@ class ExpressionRunner : public OverriddenVisitor { Flow pop() { assert(!valueStack.empty()); - auto ret = valueStack.front(); + auto ret = valueStack.back(); #if WASM_INTERPRETER_DEBUG std::cout << indent() << "popping " << ret << '\n'; #endif - valueStack.pop(); + valueStack.pop_back(); return ret; } @@ -244,15 +244,34 @@ class ExpressionRunner : public OverriddenVisitor { if (!Properties::isControlFlowStructure(curr)) { // Visit the children and add them to the value stack. (Control flow // expressions handle things manually.) + auto sizeBefore = valueStack.size(); for (auto* child : ChildIterator(curr)) { Flow flow = visit(child); if (flow.breaking()) { return flow; } -#if WASM_INTERPRETER_DEBUG - std::cout << indent() << " visited child, adding to value stack " << flow << '\n'; -#endif - valueStack.push(flow); + valueStack.push_back(flow); + } + // Reverse the children, so that pops written in the natural order in the + // visit*() methods pop the right things. That is, if we have + // + // (foo + // (bar) + // (quux) + // ) + // + // Then we first process bar, then quux, leaving quux last on the stack. + // But we want to write, in visitFoo(), + // + // auto bar = pop(); + // auto quux = pop(); + // + // (otherwise, we could reverse the order in the visit*() methods, but at + // the cost of readability). + auto sizeAfter = valueStack.size(); + if (sizeAfter >= sizeBefore + 2) { + std::reverse(valueStack.begin() + sizeBefore, + valueStack.begin() + sizeAfter); } } auto ret = OverriddenVisitor::visit(curr); @@ -270,6 +289,9 @@ class ExpressionRunner : public OverriddenVisitor { } } depth--; +#if WASM_INTERPRETER_DEBUG + std::cout << indent() << "=> returning: " << ret << '\n'; +#endif return ret; } From 7c407294b36d2cb298a64a75fb021d9285898a3a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 12:35:42 -0700 Subject: [PATCH 15/39] nicer --- src/wasm-interpreter.h | 297 +++++++++++++++++++++-------------------- 1 file changed, 149 insertions(+), 148 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index cad4762e4e9..a5b22997a21 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1,4 +1,4 @@ -#define WASM_INTERPRETER_DEBUG 1 +//#define WASM_INTERPRETER_DEBUG 1 /* * Copyright 2015 WebAssembly Community Group participants * @@ -144,7 +144,7 @@ class ExpressionRunner : public OverriddenVisitor { NOTE_ENTER_("generateArguments"); arguments.reserve(operands.size()); for (Index i = 0; i < operands.size(); i++) { - Flow flow = pop(); + Flow flow = getChild(); NOTE_EVAL1(flow.values); arguments.push_back(flow.getSingleValue()); } @@ -212,8 +212,9 @@ class ExpressionRunner : public OverriddenVisitor { } #endif - - Flow pop() { + // Get a child value. This returns values in the natural order, the same as in + // the wat and in wasm.h. + Flow getChild() { assert(!valueStack.empty()); auto ret = valueStack.back(); #if WASM_INTERPRETER_DEBUG @@ -263,8 +264,8 @@ class ExpressionRunner : public OverriddenVisitor { // Then we first process bar, then quux, leaving quux last on the stack. // But we want to write, in visitFoo(), // - // auto bar = pop(); - // auto quux = pop(); + // auto bar = getChild(); + // auto quux = getChild(); // // (otherwise, we could reverse the order in the visit*() methods, but at // the cost of readability). @@ -374,10 +375,10 @@ class ExpressionRunner : public OverriddenVisitor { bool condition = true; Flow flow; if (curr->value) { - flow = pop(); + flow = getChild(); } if (curr->condition) { - Flow conditionFlow = pop(); + Flow conditionFlow = getChild(); condition = conditionFlow.getSingleValue().getInteger() != 0; if (!condition) { return flow; @@ -391,10 +392,10 @@ class ExpressionRunner : public OverriddenVisitor { Flow flow; Literals values; if (curr->value) { - flow = pop(); + flow = getChild(); values = flow.values; } - flow = pop(); + flow = getChild(); int64_t index = flow.getSingleValue().getInteger(); Name target = curr->default_; if (index >= 0 && (size_t)index < curr->targets.size()) { @@ -416,7 +417,7 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitUnary(Unary* curr) { NOTE_ENTER("Unary"); - Flow flow = pop(); + Flow flow = getChild(); Literal value = flow.getSingleValue(); NOTE_EVAL1(value); switch (curr->op) { @@ -696,9 +697,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitBinary(Binary* curr) { NOTE_ENTER("Binary"); - Flow flow = pop(); + Flow flow = getChild(); Literal left = flow.getSingleValue(); - flow = pop(); + flow = getChild(); Literal right = flow.getSingleValue(); NOTE_EVAL2(left, right); assert(curr->left->type.isConcrete() ? left.type == curr->left->type @@ -1183,7 +1184,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitSIMDExtract(SIMDExtract* curr) { NOTE_ENTER("SIMDExtract"); - Flow flow = pop(); + Flow flow = getChild(); Literal vec = flow.getSingleValue(); switch (curr->op) { case ExtractLaneSVecI8x16: @@ -1209,9 +1210,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitSIMDReplace(SIMDReplace* curr) { NOTE_ENTER("SIMDReplace"); - Flow flow = pop(); + Flow flow = getChild(); Literal vec = flow.getSingleValue(); - flow = pop(); + flow = getChild(); Literal value = flow.getSingleValue(); switch (curr->op) { case ReplaceLaneVecI8x16: @@ -1233,19 +1234,19 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitSIMDShuffle(SIMDShuffle* curr) { NOTE_ENTER("SIMDShuffle"); - Flow flow = pop(); + Flow flow = getChild(); Literal left = flow.getSingleValue(); - flow = pop(); + flow = getChild(); Literal right = flow.getSingleValue(); return left.shuffleV8x16(right, curr->mask); } Flow visitSIMDTernary(SIMDTernary* curr) { NOTE_ENTER("SIMDBitselect"); - Flow flow = pop(); + Flow flow = getChild(); Literal a = flow.getSingleValue(); - flow = pop(); + flow = getChild(); Literal b = flow.getSingleValue(); - flow = pop(); + flow = getChild(); Literal c = flow.getSingleValue(); switch (curr->op) { case Bitselect: @@ -1295,9 +1296,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitSIMDShift(SIMDShift* curr) { NOTE_ENTER("SIMDShift"); - Flow flow = pop(); + Flow flow = getChild(); Literal vec = flow.getSingleValue(); - flow = pop(); + flow = getChild(); Literal shift = flow.getSingleValue(); switch (curr->op) { case ShlVecI8x16: @@ -1329,22 +1330,22 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitSelect(Select* curr) { NOTE_ENTER("Select"); - Flow ifTrue = pop(); - Flow ifFalse = pop(); - Flow condition = pop(); + Flow ifTrue = getChild(); + Flow ifFalse = getChild(); + Flow condition = getChild(); NOTE_EVAL1(condition.getSingleValue()); return condition.getSingleValue().geti32() ? ifTrue : ifFalse; // ;-) } Flow visitDrop(Drop* curr) { NOTE_ENTER("Drop"); - Flow value = pop(); + Flow value = getChild(); return Flow(); } Flow visitReturn(Return* curr) { NOTE_ENTER("Return"); Flow flow; if (curr->value) { - flow = pop(); + flow = getChild(); NOTE_EVAL1(flow.getSingleValue()); } flow.breakTo = RETURN_FLOW; @@ -1440,7 +1441,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitTupleExtract(TupleExtract* curr) { NOTE_ENTER("tuple.extract"); - Flow flow = pop(); + Flow flow = getChild(); assert(flow.values.size() > curr->index); return Flow(flow.values[curr->index]); } @@ -1477,7 +1478,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitRefIsNull(RefIsNull* curr) { NOTE_ENTER("RefIsNull"); - Flow flow = pop(); + Flow flow = getChild(); const auto& value = flow.getSingleValue(); NOTE_EVAL1(value); return Literal(int32_t(value.isNull())); @@ -1489,9 +1490,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitRefEq(RefEq* curr) { NOTE_ENTER("RefEq"); - Flow flow = pop(); + Flow flow = getChild(); auto left = flow.getSingleValue(); - flow = pop(); + flow = getChild(); auto right = flow.getSingleValue(); NOTE_EVAL2(left, right); return Literal(int32_t(left == right)); @@ -1520,7 +1521,7 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitRethrow(Rethrow* curr) { WASM_UNREACHABLE("unimp"); } Flow visitThrowRef(ThrowRef* curr) { NOTE_ENTER("ThrowRef"); - Flow flow = pop(); + Flow flow = getChild(); const auto& exnref = flow.getSingleValue(); NOTE_EVAL1(exnref); if (exnref.isNull()) { @@ -1532,7 +1533,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitRefI31(RefI31* curr) { NOTE_ENTER("RefI31"); - Flow flow = pop(); + Flow flow = getChild(); const auto& value = flow.getSingleValue(); NOTE_EVAL1(value); return Literal::makeI31(value.geti32(), @@ -1540,7 +1541,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitI31Get(I31Get* curr) { NOTE_ENTER("I31Get"); - Flow flow = pop(); + Flow flow = getChild(); const auto& value = flow.getSingleValue(); NOTE_EVAL1(value); if (value.isNull()) { @@ -1574,7 +1575,7 @@ class ExpressionRunner : public OverriddenVisitor { }; template Cast doCast(T* curr) { - Flow ref = pop(); + Flow ref = getChild(); Literal val = ref.getSingleValue(); Type castType = curr->getCastType(); if (Type::isSubType(val.type, castType)) { @@ -1584,8 +1585,8 @@ class ExpressionRunner : public OverriddenVisitor { } } template Cast doDescCast(T* curr) { - Flow ref = pop(); - Flow desc = pop(); + Flow ref = getChild(); + Flow desc = getChild(); auto expected = desc.getSingleValue().getGCData(); if (!expected) { trap("null descriptor"); @@ -1635,7 +1636,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitRefGetDesc(RefGetDesc* curr) { NOTE_ENTER("RefGetDesc"); - Flow ref = pop(); + Flow ref = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1672,7 +1673,7 @@ class ExpressionRunner : public OverriddenVisitor { case BrOnNull: case BrOnNonNull: { // Otherwise we are just checking for null. - Flow flow = pop(); + Flow flow = getChild(); const auto& value = flow.getSingleValue(); NOTE_EVAL1(value); if (curr->op == BrOnNull) { @@ -1708,14 +1709,14 @@ class ExpressionRunner : public OverriddenVisitor { if (curr->isWithDefault()) { data[i] = Literal::makeZero(field.type); } else { - auto value = pop(); + auto value = getChild(); data[i] = truncateForPacking(value.getSingleValue(), field); } } if (!curr->desc) { return makeGCData(std::move(data), curr->type); } - auto desc = pop(); + auto desc = getChild(); if (desc.getSingleValue().isNull()) { trap("null descriptor"); } @@ -1723,7 +1724,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitStructGet(StructGet* curr) { NOTE_ENTER("StructGet"); - Flow ref = pop(); + Flow ref = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1733,8 +1734,8 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitStructSet(StructSet* curr) { NOTE_ENTER("StructSet"); - Flow ref = pop(); - Flow value = pop(); + Flow ref = getChild(); + Flow value = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1747,8 +1748,8 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitStructRMW(StructRMW* curr) { NOTE_ENTER("StructRMW"); - Flow ref = pop(); - Flow value = pop(); + Flow ref = getChild(); + Flow value = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1781,9 +1782,9 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitStructCmpxchg(StructCmpxchg* curr) { NOTE_ENTER("StructCmpxchg"); - Flow ref = pop(); - Flow expected = pop(); - Flow replacement = pop(); + Flow ref = getChild(); + Flow expected = getChild(); + Flow replacement = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1806,9 +1807,9 @@ class ExpressionRunner : public OverriddenVisitor { NOTE_ENTER("ArrayNew"); Flow init; if (!curr->isWithDefault()) { - init = pop(); + init = getChild(); } - auto size = pop(); + auto size = getChild(); if (curr->type == Type::unreachable) { // We cannot proceed to compute the heap type, as there isn't one. Just // visit the unreachable child, and stop there. @@ -1853,15 +1854,15 @@ class ExpressionRunner : public OverriddenVisitor { auto field = heapType.getArray().element; Literals data(num); for (Index i = 0; i < num; i++) { - auto value = pop(); + auto value = getChild(); data[i] = truncateForPacking(value.getSingleValue(), field); } return makeGCData(std::move(data), curr->type); } Flow visitArrayGet(ArrayGet* curr) { NOTE_ENTER("ArrayGet"); - Flow ref = pop(); - Flow index = pop(); + Flow ref = getChild(); + Flow index = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1875,9 +1876,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitArraySet(ArraySet* curr) { NOTE_ENTER("ArraySet"); - Flow ref = pop(); - Flow index = pop(); - Flow value = pop(); + Flow ref = getChild(); + Flow index = getChild(); + Flow value = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1892,7 +1893,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitArrayLen(ArrayLen* curr) { NOTE_ENTER("ArrayLen"); - Flow ref = pop(); + Flow ref = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1901,11 +1902,11 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitArrayCopy(ArrayCopy* curr) { NOTE_ENTER("ArrayCopy"); - Flow destRef = pop(); - Flow destIndex = pop(); - Flow srcRef = pop(); - Flow srcIndex = pop(); - Flow length = pop(); + Flow destRef = getChild(); + Flow destIndex = getChild(); + Flow srcRef = getChild(); + Flow srcIndex = getChild(); + Flow length = getChild(); auto destData = destRef.getSingleValue().getGCData(); if (!destData) { trap("null ref"); @@ -1935,10 +1936,10 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitArrayFill(ArrayFill* curr) { NOTE_ENTER("ArrayFill"); - Flow ref = pop(); - Flow index = pop(); - Flow value = pop(); - Flow size = pop(); + Flow ref = getChild(); + Flow index = getChild(); + Flow value = getChild(); + Flow size = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -1964,9 +1965,9 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitArrayInitElem(ArrayInitElem* curr) { WASM_UNREACHABLE("unimp"); } Flow visitArrayRMW(ArrayRMW* curr) { NOTE_ENTER("ArrayRMW"); - Flow ref = pop(); - Flow index = pop(); - Flow value = pop(); + Flow ref = getChild(); + Flow index = getChild(); + Flow value = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -2000,10 +2001,10 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitArrayCmpxchg(ArrayCmpxchg* curr) { NOTE_ENTER("ArrayCmpxchg"); - Flow ref = pop(); - Flow index = pop(); - Flow expected = pop(); - Flow replacement = pop(); + Flow ref = getChild(); + Flow index = getChild(); + Flow expected = getChild(); + Flow replacement = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -2018,7 +2019,7 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitRefAs(RefAs* curr) { NOTE_ENTER("RefAs"); - Flow flow = pop(); + Flow flow = getChild(); const auto& value = flow.getSingleValue(); NOTE_EVAL1(value); switch (curr->op) { @@ -2035,11 +2036,11 @@ class ExpressionRunner : public OverriddenVisitor { WASM_UNREACHABLE("unimplemented ref.as_*"); } Flow visitStringNew(StringNew* curr) { - Flow ptr = pop(); + Flow ptr = getChild(); switch (curr->op) { case StringNewWTF16Array: { - Flow start = pop(); - Flow end = pop(); + Flow start = getChild(); + Flow end = getChild(); auto ptrData = ptr.getSingleValue().getGCData(); if (!ptrData) { trap("null ref"); @@ -2083,7 +2084,7 @@ class ExpressionRunner : public OverriddenVisitor { return Flow(NONCONSTANT_FLOW); } - Flow flow = pop(); + Flow flow = getChild(); auto value = flow.getSingleValue(); auto data = value.getGCData(); if (!data) { @@ -2094,9 +2095,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitStringConcat(StringConcat* curr) { NOTE_ENTER("StringConcat"); - Flow flow = pop(); + Flow flow = getChild(); auto left = flow.getSingleValue(); - flow = pop(); + flow = getChild(); auto right = flow.getSingleValue(); NOTE_EVAL2(left, right); auto leftData = left.getGCData(); @@ -2127,9 +2128,9 @@ class ExpressionRunner : public OverriddenVisitor { return Flow(NONCONSTANT_FLOW); } - Flow str = pop(); - Flow array = pop(); - Flow start = pop(); + Flow str = getChild(); + Flow array = getChild(); + Flow start = getChild(); auto strData = str.getSingleValue().getGCData(); auto arrayData = array.getSingleValue().getGCData(); @@ -2153,9 +2154,9 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitStringEq(StringEq* curr) { NOTE_ENTER("StringEq"); - Flow flow = pop(); + Flow flow = getChild(); auto left = flow.getSingleValue(); - flow = pop(); + flow = getChild(); auto right = flow.getSingleValue(); NOTE_EVAL2(left, right); auto leftData = left.getGCData(); @@ -2212,14 +2213,14 @@ class ExpressionRunner : public OverriddenVisitor { return Literal(result); } Flow visitStringTest(StringTest* curr) { - Flow flow = pop(); + Flow flow = getChild(); auto value = flow.getSingleValue(); return Literal((uint32_t)value.isString()); } Flow visitStringWTF16Get(StringWTF16Get* curr) { NOTE_ENTER("StringWTF16Get"); - Flow ref = pop(); - Flow pos = pop(); + Flow ref = getChild(); + Flow pos = getChild(); auto refValue = ref.getSingleValue(); auto data = refValue.getGCData(); if (!data) { @@ -2234,9 +2235,9 @@ class ExpressionRunner : public OverriddenVisitor { return Literal(values[i].geti32()); } Flow visitStringSliceWTF(StringSliceWTF* curr) { - Flow ref = pop(); - Flow start = pop(); - Flow end = pop(); + Flow ref = getChild(); + Flow start = getChild(); + Flow end = getChild(); auto refData = ref.getSingleValue().getGCData(); if (!refData) { @@ -3206,7 +3207,7 @@ class ModuleRunnerBase : public ExpressionRunner { if (flow.breaking()) { return flow; } - Flow target = self()->pop(); + Flow target = self()->getChild(); auto index = target.getSingleValue().getUnsigned(); auto info = getTableInstanceInfo(curr->table); @@ -3237,7 +3238,7 @@ class ModuleRunnerBase : public ExpressionRunner { if (flow.breaking()) { return flow; } - Flow target = self()->pop(); + Flow target = self()->getChild(); auto targetRef = target.getSingleValue(); if (targetRef.isNull()) { trap("null target in call_ref"); @@ -3259,15 +3260,15 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitTableGet(TableGet* curr) { NOTE_ENTER("TableGet"); - Flow index = self()->pop(); + Flow index = self()->getChild(); auto info = getTableInstanceInfo(curr->table); auto address = index.getSingleValue().getUnsigned(); return info.interface()->tableLoad(info.name, address); } Flow visitTableSet(TableSet* curr) { NOTE_ENTER("TableSet"); - Flow index = self()->pop(); - Flow value = self()->pop(); + Flow index = self()->getChild(); + Flow value = self()->getChild(); auto info = getTableInstanceInfo(curr->table); auto address = index.getSingleValue().getUnsigned(); info.interface()->tableStore(info.name, address, value.getSingleValue()); @@ -3284,8 +3285,8 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitTableGrow(TableGrow* curr) { NOTE_ENTER("TableGrow"); - Flow valueFlow = self()->pop(); - Flow deltaFlow = self()->pop(); + Flow valueFlow = self()->getChild(); + Flow deltaFlow = self()->getChild(); auto info = getTableInstanceInfo(curr->table); uint64_t tableSize = info.interface()->tableSize(info.name); @@ -3312,9 +3313,9 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitTableFill(TableFill* curr) { NOTE_ENTER("TableFill"); - Flow destFlow = self()->pop(); - Flow valueFlow = self()->pop(); - Flow sizeFlow = self()->pop(); + Flow destFlow = self()->getChild(); + Flow valueFlow = self()->getChild(); + Flow sizeFlow = self()->getChild(); auto info = getTableInstanceInfo(curr->table); auto dest = destFlow.getSingleValue().getUnsigned(); @@ -3334,9 +3335,9 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitTableCopy(TableCopy* curr) { NOTE_ENTER("TableCopy"); - Flow dest = self()->pop(); - Flow source = self()->pop(); - Flow size = self()->pop(); + Flow dest = self()->getChild(); + Flow source = self()->getChild(); + Flow size = self()->getChild(); NOTE_EVAL1(dest); NOTE_EVAL1(source); NOTE_EVAL1(size); @@ -3376,9 +3377,9 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitTableInit(TableInit* curr) { NOTE_ENTER("TableInit"); - Flow dest = self()->pop(); - Flow offset = self()->pop(); - Flow size = self()->pop(); + Flow dest = self()->getChild(); + Flow offset = self()->getChild(); + Flow size = self()->getChild(); NOTE_EVAL1(dest); NOTE_EVAL1(offset); NOTE_EVAL1(size); @@ -3429,7 +3430,7 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitLocalSet(LocalSet* curr) { NOTE_ENTER("LocalSet"); auto index = curr->index; - Flow flow = self()->pop(); + Flow flow = self()->getChild(); NOTE_EVAL1(index); NOTE_EVAL1(flow.getSingleValue()); assert(curr->isTee() ? Type::isSubType(flow.getType(), curr->type) : true); @@ -3446,7 +3447,7 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitGlobalSet(GlobalSet* curr) { NOTE_ENTER("GlobalSet"); auto name = curr->name; - Flow flow = self()->pop(); + Flow flow = self()->getChild(); NOTE_EVAL1(name); NOTE_EVAL1(flow.getSingleValue()); @@ -3456,7 +3457,7 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitLoad(Load* curr) { NOTE_ENTER("Load"); - Flow flow = self()->pop(); + Flow flow = self()->getChild(); NOTE_EVAL1(flow); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); @@ -3472,8 +3473,8 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitStore(Store* curr) { NOTE_ENTER("Store"); - Flow ptr = self()->pop(); - Flow value = self()->pop(); + Flow ptr = self()->getChild(); + Flow value = self()->getChild(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto addr = @@ -3489,8 +3490,8 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitAtomicRMW(AtomicRMW* curr) { NOTE_ENTER("AtomicRMW"); - Flow ptr = self()->pop(); - auto value = self()->pop(); + Flow ptr = self()->getChild(); + auto value = self()->getChild(); NOTE_EVAL1(ptr); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); @@ -3527,10 +3528,10 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitAtomicCmpxchg(AtomicCmpxchg* curr) { NOTE_ENTER("AtomicCmpxchg"); - Flow ptr = self()->pop(); + Flow ptr = self()->getChild(); NOTE_EVAL1(ptr); - auto expected = self()->pop(); - auto replacement = self()->pop(); + auto expected = self()->getChild(); + auto replacement = self()->getChild(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto addr = @@ -3550,7 +3551,7 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitAtomicWait(AtomicWait* curr) { NOTE_ENTER("AtomicWait"); - Flow ptr = self()->pop(); + Flow ptr = self()->getChild(); NOTE_EVAL1(ptr); auto expected = self()->visit(curr->expected); NOTE_EVAL1(expected); @@ -3585,7 +3586,7 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitAtomicNotify(AtomicNotify* curr) { NOTE_ENTER("AtomicNotify"); - Flow ptr = self()->pop(); + Flow ptr = self()->getChild(); NOTE_EVAL1(ptr); auto count = self()->visit(curr->notifyCount); NOTE_EVAL1(count); @@ -3650,11 +3651,11 @@ class ModuleRunnerBase : public ExpressionRunner { WASM_UNREACHABLE("invalid op"); } load.finalize(); - Flow flow = self()->pop(); + Flow flow = self()->getChild(); return (flow.getSingleValue().*splat)(); } Flow visitSIMDLoadExtend(SIMDLoad* curr) { - Flow flow = self()->pop(); + Flow flow = self()->getChild(); NOTE_EVAL1(flow); Address src(flow.getSingleValue().getUnsigned()); auto info = getMemoryInstanceInfo(curr->memory); @@ -3711,7 +3712,7 @@ class ModuleRunnerBase : public ExpressionRunner { WASM_UNREACHABLE("invalid op"); } Flow visitSIMDLoadZero(SIMDLoad* curr) { - Flow flow = self()->pop(); + Flow flow = self()->getChild(); NOTE_EVAL1(flow); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); @@ -3729,9 +3730,9 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { NOTE_ENTER("SIMDLoadStoreLane"); - Flow ptrFlow = self()->pop(); + Flow ptrFlow = self()->getChild(); NOTE_EVAL1(ptrFlow); - Flow vecFlow = self()->pop(); + Flow vecFlow = self()->getChild(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); Address addr = info.instance->getFinalAddress( @@ -3802,7 +3803,7 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitMemoryGrow(MemoryGrow* curr) { NOTE_ENTER("MemoryGrow"); - Flow flow = self()->pop(); + Flow flow = self()->getChild(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto* memory = info.instance->wasm.getMemory(info.name); @@ -3838,9 +3839,9 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitMemoryInit(MemoryInit* curr) { NOTE_ENTER("MemoryInit"); - Flow dest = self()->pop(); - Flow offset = self()->pop(); - Flow size = self()->pop(); + Flow dest = self()->getChild(); + Flow offset = self()->getChild(); + Flow size = self()->getChild(); NOTE_EVAL1(dest); NOTE_EVAL1(offset); NOTE_EVAL1(size); @@ -3878,9 +3879,9 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitMemoryCopy(MemoryCopy* curr) { NOTE_ENTER("MemoryCopy"); - Flow dest = self()->pop(); - Flow source = self()->pop(); - Flow size = self()->pop(); + Flow dest = self()->getChild(); + Flow source = self()->getChild(); + Flow size = self()->getChild(); NOTE_EVAL1(dest); NOTE_EVAL1(source); NOTE_EVAL1(size); @@ -3923,9 +3924,9 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitMemoryFill(MemoryFill* curr) { NOTE_ENTER("MemoryFill"); - Flow dest = self()->pop(); - Flow value = self()->pop(); - Flow size = self()->pop(); + Flow dest = self()->getChild(); + Flow value = self()->getChild(); + Flow size = self()->getChild(); NOTE_EVAL1(dest); NOTE_EVAL1(value); NOTE_EVAL1(size); @@ -3951,8 +3952,8 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitArrayNewData(ArrayNewData* curr) { NOTE_ENTER("ArrayNewData"); - auto offsetFlow = self()->pop(); - auto sizeFlow = self()->pop(); + auto offsetFlow = self()->getChild(); + auto sizeFlow = self()->getChild(); uint64_t offset = offsetFlow.getSingleValue().getUnsigned(); uint64_t size = sizeFlow.getSingleValue().getUnsigned(); @@ -3986,8 +3987,8 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitArrayNewElem(ArrayNewElem* curr) { NOTE_ENTER("ArrayNewElem"); - auto offsetFlow = self()->pop(); - auto sizeFlow = self()->pop(); + auto offsetFlow = self()->getChild(); + auto sizeFlow = self()->getChild(); uint64_t offset = offsetFlow.getSingleValue().getUnsigned(); uint64_t size = sizeFlow.getSingleValue().getUnsigned(); @@ -4011,10 +4012,10 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitArrayInitData(ArrayInitData* curr) { NOTE_ENTER("ArrayInit"); - Flow ref = self()->pop(); - Flow index = self()->pop(); - Flow offset = self()->pop(); - Flow size = self()->pop(); + Flow ref = self()->getChild(); + Flow index = self()->getChild(); + Flow offset = self()->getChild(); + Flow size = self()->getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); @@ -4048,10 +4049,10 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitArrayInitElem(ArrayInitElem* curr) { NOTE_ENTER("ArrayInit"); - Flow ref = self()->pop(); - Flow index = self()->pop(); - Flow offset = self()->pop(); - Flow size = self()->pop(); + Flow ref = self()->getChild(); + Flow index = self()->getChild(); + Flow offset = self()->getChild(); + Flow size = self()->getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); From 2b1af67b702d0d88ba8b0497aecd0f6d3a08d021 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 13:16:23 -0700 Subject: [PATCH 16/39] fix --- src/wasm-interpreter.h | 37 ++++++++++++------------------------- test/lit/exec/atomic.wast | 8 ++++---- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index a5b22997a21..e05877e5687 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1810,13 +1810,10 @@ class ExpressionRunner : public OverriddenVisitor { init = getChild(); } auto size = getChild(); - if (curr->type == Type::unreachable) { - // We cannot proceed to compute the heap type, as there isn't one. Just - // visit the unreachable child, and stop there. - auto init = self()->visit(curr->init); - assert(init.breaking()); - return init; - } + // If we are unreachable then we cannot proceed to compute the heap type, + // below, as there isn't one. But if we are unreachable then we should not + // get here, as the child would break in visit(). + assert(curr->type != Type::unreachable); auto heapType = curr->type.getHeapType(); const auto& element = heapType.getArray().element; Index num = size.getSingleValue().geti32(); @@ -2357,6 +2354,8 @@ class ConstantExpressionRunner : public ExpressionRunner { // Map remembering concrete global values set in the context of this flow. std::unordered_map globalValues; + SubType* self() { return static_cast(this); } + public: ConstantExpressionRunner(Module* module, Flags flags, @@ -2394,7 +2393,7 @@ class ConstantExpressionRunner : public ExpressionRunner { // If we are evaluating and not replacing the expression, remember the // constant value set, if any, and see if there is a value flowing through // a tee. - auto setFlow = ExpressionRunner::visit(curr->value); + auto setFlow = self()->getChild(); if (!setFlow.breaking()) { setLocalValue(curr->index, setFlow.values); if (curr->type.isConcrete()) { @@ -2413,7 +2412,7 @@ class ConstantExpressionRunner : public ExpressionRunner { auto* global = this->module->getGlobal(curr->name); // Check if the global has an immutable value anyway if (!global->imported() && !global->mutable_) { - return ExpressionRunner::visit(global->init); + return self()->getChild(); } } // Check if a constant value has been set in the context of this runner. @@ -2431,7 +2430,7 @@ class ConstantExpressionRunner : public ExpressionRunner { // If we are evaluating and not replacing the expression, remember the // constant value set, if any, for subsequent gets. assert(this->module->getGlobal(curr->name)->mutable_); - auto setFlow = ExpressionRunner::visit(curr->value); + auto setFlow = self()->getChild(); if (!setFlow.breaking()) { setGlobalValue(curr->name, setFlow.values); return Flow(); @@ -3553,16 +3552,8 @@ class ModuleRunnerBase : public ExpressionRunner { NOTE_ENTER("AtomicWait"); Flow ptr = self()->getChild(); NOTE_EVAL1(ptr); - auto expected = self()->visit(curr->expected); - NOTE_EVAL1(expected); - if (expected.breaking()) { - return expected; - } - auto timeout = self()->visit(curr->timeout); - NOTE_EVAL1(timeout); - if (timeout.breaking()) { - return timeout; - } + auto expected = self()->getChild(); + auto timeout = self()->getChild(); auto bytes = curr->expectedType.getByteSize(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); @@ -3588,11 +3579,7 @@ class ModuleRunnerBase : public ExpressionRunner { NOTE_ENTER("AtomicNotify"); Flow ptr = self()->getChild(); NOTE_EVAL1(ptr); - auto count = self()->visit(curr->notifyCount); - NOTE_EVAL1(count); - if (count.breaking()) { - return count; - } + auto count = self()->getChild(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto addr = diff --git a/test/lit/exec/atomic.wast b/test/lit/exec/atomic.wast index 631bdd53174..4b48470edb6 100644 --- a/test/lit/exec/atomic.wast +++ b/test/lit/exec/atomic.wast @@ -8,13 +8,13 @@ (memory $0 23 256 shared) ;; CHECK: [fuzz-exec] calling wait_and_log - ;; CHECK-NEXT: [LoggingExternalInterface logging 2] + ;; CHECK-NEXT: [LoggingExternalInterface logging 0 0] (func $wait_and_log (export "wait_and_log") (call $log (memory.atomic.wait64 - (i32.const 0) - (i64.const 0) - (i64.const 0) + (i32.const 32) + (i64.const 64) + (i64.const 128) ) ) ) From 7409bca86080f874e4795a0d0c80a96024f1d638 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 13:38:15 -0700 Subject: [PATCH 17/39] revertfix --- src/wasm-interpreter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index e05877e5687..fea9d7f33f7 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -2412,7 +2412,7 @@ class ConstantExpressionRunner : public ExpressionRunner { auto* global = this->module->getGlobal(curr->name); // Check if the global has an immutable value anyway if (!global->imported() && !global->mutable_) { - return self()->getChild(); + return ExpressionRunner::visit(global->init); } } // Check if a constant value has been set in the context of this runner. From d683b380d9b9ab8ecb63713a21540a0811cb8574 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 13:41:06 -0700 Subject: [PATCH 18/39] fix --- test/lit/exec/atomic.wast | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lit/exec/atomic.wast b/test/lit/exec/atomic.wast index 4b48470edb6..a5551a36386 100644 --- a/test/lit/exec/atomic.wast +++ b/test/lit/exec/atomic.wast @@ -8,7 +8,7 @@ (memory $0 23 256 shared) ;; CHECK: [fuzz-exec] calling wait_and_log - ;; CHECK-NEXT: [LoggingExternalInterface logging 0 0] + ;; CHECK-NEXT: [LoggingExternalInterface logging 1] (func $wait_and_log (export "wait_and_log") (call $log (memory.atomic.wait64 From ca5d8cded1b76d34c29fa10bf4d79ec615fc13df Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 13:41:25 -0700 Subject: [PATCH 19/39] undo --- test/lit/exec/atomic.wast | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/lit/exec/atomic.wast b/test/lit/exec/atomic.wast index a5551a36386..631bdd53174 100644 --- a/test/lit/exec/atomic.wast +++ b/test/lit/exec/atomic.wast @@ -8,13 +8,13 @@ (memory $0 23 256 shared) ;; CHECK: [fuzz-exec] calling wait_and_log - ;; CHECK-NEXT: [LoggingExternalInterface logging 1] + ;; CHECK-NEXT: [LoggingExternalInterface logging 2] (func $wait_and_log (export "wait_and_log") (call $log (memory.atomic.wait64 - (i32.const 32) - (i64.const 64) - (i64.const 128) + (i32.const 0) + (i64.const 0) + (i64.const 0) ) ) ) From 675a306cc83135392bc2569342305e6ab089ce31 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 14:15:19 -0700 Subject: [PATCH 20/39] fixen --- src/wasm-interpreter.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index fea9d7f33f7..14c46fce56a 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1,4 +1,4 @@ -//#define WASM_INTERPRETER_DEBUG 1 +#define WASM_INTERPRETER_DEBUG 1 /* * Copyright 2015 WebAssembly Community Group participants * @@ -218,7 +218,7 @@ class ExpressionRunner : public OverriddenVisitor { assert(!valueStack.empty()); auto ret = valueStack.back(); #if WASM_INTERPRETER_DEBUG - std::cout << indent() << "popping " << ret << '\n'; + std::cout << indent() << "getting child " << ret << '\n'; #endif valueStack.pop_back(); return ret; @@ -249,6 +249,10 @@ class ExpressionRunner : public OverriddenVisitor { for (auto* child : ChildIterator(curr)) { Flow flow = visit(child); if (flow.breaking()) { + depth--; +#if WASM_INTERPRETER_DEBUG + std::cout << indent() << "=> breaking: " << flow << '\n'; +#endif return flow; } valueStack.push_back(flow); @@ -301,6 +305,7 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitBlock(Block* curr) { NOTE_ENTER("Block"); +std::cout << indent() << "BLOCK name " << curr->name << '\n'; // special-case Block, because Block nesting (in their first element) can be // incredibly deep std::vector stack; @@ -316,6 +321,7 @@ class ExpressionRunner : public OverriddenVisitor { stack.pop_back(); if (flow.breaking()) { flow.clearIf(curr->name); +std::cout << indent() << " breaking, me" << curr->name << " leaving " << flow << '\n'; continue; } auto& list = curr->list; @@ -327,10 +333,12 @@ class ExpressionRunner : public OverriddenVisitor { flow = visit(list[i]); if (flow.breaking()) { flow.clearIf(curr->name); +std::cout << indent() << "inner breaking, me" << curr->name << " leaving " << flow << '\n'; break; } } } +std::cout << indent() << "BLOCK final flow, me" << curr->name << " leaving " << flow << '\n'; return flow; } Flow visitIf(If* curr) { From 483f5f962ef858d184786ce7d84508a1284f76b8 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 14:29:17 -0700 Subject: [PATCH 21/39] fix --- src/wasm-interpreter.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 14c46fce56a..b8edf53984c 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -249,10 +249,13 @@ class ExpressionRunner : public OverriddenVisitor { for (auto* child : ChildIterator(curr)) { Flow flow = visit(child); if (flow.breaking()) { - depth--; #if WASM_INTERPRETER_DEBUG std::cout << indent() << "=> breaking: " << flow << '\n'; #endif + depth--; + // We don't need to add any values on the stack, as the parent will + // not read them. + valueStack.resize(sizeBefore); return flow; } valueStack.push_back(flow); @@ -4266,6 +4269,9 @@ class ModuleRunnerBase : public ExpressionRunner { << '\n'; #endif + // All values should have been consumed. + assert(self()->valueStack.empty()); + if (flow.breakTo != RETURN_CALL_FLOW) { break; } From 2b8a16e6a85893835bed23834855b26254be9e87 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 14:29:38 -0700 Subject: [PATCH 22/39] clean --- src/wasm-interpreter.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index b8edf53984c..f2c470b1083 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -308,7 +308,6 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitBlock(Block* curr) { NOTE_ENTER("Block"); -std::cout << indent() << "BLOCK name " << curr->name << '\n'; // special-case Block, because Block nesting (in their first element) can be // incredibly deep std::vector stack; @@ -324,7 +323,6 @@ std::cout << indent() << "BLOCK name " << curr->name << '\n'; stack.pop_back(); if (flow.breaking()) { flow.clearIf(curr->name); -std::cout << indent() << " breaking, me" << curr->name << " leaving " << flow << '\n'; continue; } auto& list = curr->list; @@ -336,12 +334,10 @@ std::cout << indent() << " breaking, me" << curr->name << " leaving " << flow << flow = visit(list[i]); if (flow.breaking()) { flow.clearIf(curr->name); -std::cout << indent() << "inner breaking, me" << curr->name << " leaving " << flow << '\n'; break; } } } -std::cout << indent() << "BLOCK final flow, me" << curr->name << " leaving " << flow << '\n'; return flow; } Flow visitIf(If* curr) { From 13c35fec19651121898cc2c61d87033707ba70fb Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 17:22:20 -0700 Subject: [PATCH 23/39] fix --- src/wasm-interpreter.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index f2c470b1083..9e9c9b66ab4 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -2916,7 +2916,10 @@ class ModuleRunnerBase : public ExpressionRunner { if (!export_ || export_->kind != ExternalKind::Function) { externalInterface->trap("callExport not found"); } - return callFunction(*export_->getInternalName(), arguments); + auto ret = callFunction(*export_->getInternalName(), arguments); + // All values should have been consumed. + assert(self()->valueStack.empty()); + return ret; } Literals callExport(Name name) { return callExport(name, Literals()); } @@ -3200,8 +3203,8 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow ret = callFunction(target, arguments); -#ifdef WASM_INTERPRETER_DEBUG - std::cout << "(returned to " << scope->function->name << ")\n"; +#if WASM_INTERPRETER_DEBUG + std::cout << self()->indent() << "(returned to " << scope->function->name << ")\n"; #endif return ret; } @@ -3231,8 +3234,8 @@ class ModuleRunnerBase : public ExpressionRunner { Flow ret = info.interface()->callTable( info.name, index, curr->heapType, arguments, curr->type, *self()); -#ifdef WASM_INTERPRETER_DEBUG - std::cout << "(returned to " << scope->function->name << ")\n"; +#if WASM_INTERPRETER_DEBUG + std::cout << self()->indent() << "(returned to " << scope->function->name << ")\n"; #endif return ret; } @@ -3258,8 +3261,8 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow ret = callFunction(targetRef.getFunc(), arguments); -#ifdef WASM_INTERPRETER_DEBUG - std::cout << "(returned to " << scope->function->name << ")\n"; +#if WASM_INTERPRETER_DEBUG + std::cout << self()->indent() << "(returned to " << scope->function->name << ")\n"; #endif return ret; } @@ -4251,8 +4254,8 @@ class ModuleRunnerBase : public ExpressionRunner { FunctionScope scope(function, arguments, *self()); -#ifdef WASM_INTERPRETER_DEBUG - std::cout << "entering " << function->name << "\n with arguments:\n"; +#if WASM_INTERPRETER_DEBUG + std::cout << self()->indent() << "entering " << function->name << "\n with arguments:\n"; for (unsigned i = 0; i < arguments.size(); ++i) { std::cout << " $" << i << ": " << arguments[i] << '\n'; } @@ -4260,14 +4263,11 @@ class ModuleRunnerBase : public ExpressionRunner { flow = self()->visit(function->body); -#ifdef WASM_INTERPRETER_DEBUG - std::cout << "exiting " << function->name << " with " << flow.values +#if WASM_INTERPRETER_DEBUG + std::cout << self()->indent() << "exiting " << function->name << " with " << flow.values << '\n'; #endif - // All values should have been consumed. - assert(self()->valueStack.empty()); - if (flow.breakTo != RETURN_CALL_FLOW) { break; } From 26d09a7598856cc84415d1a48041c07023571841 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 24 Jul 2025 17:34:54 -0700 Subject: [PATCH 24/39] fix --- src/wasm-interpreter.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 9e9c9b66ab4..14ed74a660d 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -2916,10 +2916,7 @@ class ModuleRunnerBase : public ExpressionRunner { if (!export_ || export_->kind != ExternalKind::Function) { externalInterface->trap("callExport not found"); } - auto ret = callFunction(*export_->getInternalName(), arguments); - // All values should have been consumed. - assert(self()->valueStack.empty()); - return ret; + return callFunction(*export_->getInternalName(), arguments); } Literals callExport(Name name) { return callExport(name, Literals()); } From 2b43ba8043afa7d99450fe88e6b89814a85f8219 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 07:43:39 -0700 Subject: [PATCH 25/39] simpl --- src/wasm-interpreter.h | 82 ++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 14ed74a660d..8290b780b96 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1,4 +1,4 @@ -#define WASM_INTERPRETER_DEBUG 1 +//#define WASM_INTERPRETER_DEBUG 1 /* * Copyright 2015 WebAssembly Community Group participants * @@ -199,9 +199,6 @@ class ExpressionRunner : public OverriddenVisitor { protected: RelaxedBehavior relaxedBehavior = RelaxedBehavior::NonConstant; - // TODO: Literals here and not Flows - std::vector valueStack; - #if WASM_INTERPRETER_DEBUG std::string indent() { std::string ret; @@ -212,15 +209,24 @@ class ExpressionRunner : public OverriddenVisitor { } #endif + // The values we gather from children in visit(), and then give to the + // instruction to execute. + // TODO: Literals here and not Flows + using VisitValues = SmallVector; + + // The current set of visit values, used in getChild. + VisitValues* visitValues = nullptr; + // Get a child value. This returns values in the natural order, the same as in // the wat and in wasm.h. Flow getChild() { - assert(!valueStack.empty()); - auto ret = valueStack.back(); + assert(visitValues); + assert(!visitValues->empty()); + auto ret = visitValues->back(); #if WASM_INTERPRETER_DEBUG std::cout << indent() << "getting child " << ret << '\n'; #endif - valueStack.pop_back(); + visitValues->pop_back(); return ret; } @@ -242,47 +248,47 @@ class ExpressionRunner : public OverriddenVisitor { if (maxDepth != NO_LIMIT && depth > maxDepth) { hostLimit("interpreter recursion limit"); } - if (!Properties::isControlFlowStructure(curr)) { - // Visit the children and add them to the value stack. (Control flow - // expressions handle things manually.) - auto sizeBefore = valueStack.size(); - for (auto* child : ChildIterator(curr)) { + + Flow ret; + if (Properties::isControlFlowStructure(curr)) { + // Handle things manually, each control flow structure has its own logic. + ret = OverriddenVisitor::visit(curr); + } else { + // General instruction handling: Visit the children and add them to the + // set of values, handling all control flow ourselves here, and saving + // the stack of visitValues as we go. + auto* oldVisitValues = visitValues; + VisitValues values; + visitValues = &values; + + // Iterate over the children, placing their values in the list of values. + ChildIterator iter(curr); + auto num = iter.getNumChildren(); + values.resize(num); + // Place the first item at the end, so that getChild() can simply pop. + Index i = num - 1; + for (auto* child : iter) { Flow flow = visit(child); if (flow.breaking()) { #if WASM_INTERPRETER_DEBUG std::cout << indent() << "=> breaking: " << flow << '\n'; #endif depth--; - // We don't need to add any values on the stack, as the parent will - // not read them. - valueStack.resize(sizeBefore); + visitValues = oldVisitValues; return flow; } - valueStack.push_back(flow); - } - // Reverse the children, so that pops written in the natural order in the - // visit*() methods pop the right things. That is, if we have - // - // (foo - // (bar) - // (quux) - // ) - // - // Then we first process bar, then quux, leaving quux last on the stack. - // But we want to write, in visitFoo(), - // - // auto bar = getChild(); - // auto quux = getChild(); - // - // (otherwise, we could reverse the order in the visit*() methods, but at - // the cost of readability). - auto sizeAfter = valueStack.size(); - if (sizeAfter >= sizeBefore + 2) { - std::reverse(valueStack.begin() + sizeBefore, - valueStack.begin() + sizeAfter); + values[i] = flow; + i--; } + + // Execute the instruction, which will start with calls to getChild() + // that read from our VisitValues. + ret = OverriddenVisitor::visit(curr); + + // Restore the parent. + visitValues = oldVisitValues; } - auto ret = OverriddenVisitor::visit(curr); + if (!ret.breaking()) { Type type = ret.getType(); if (type.isConcrete() || curr->type.isConcrete()) { From f6606919446aac70caaa02e62b9d72a98ec89cee Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 07:56:13 -0700 Subject: [PATCH 26/39] tryfix --- src/wasm-interpreter.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 8290b780b96..6aeee1a6b6b 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -4087,9 +4087,12 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitTry(Try* curr) { NOTE_ENTER("Try"); + auto* oldVisitValues = self()->visitValues; try { return self()->visit(curr->body); } catch (const WasmException& e) { + self()->visitValues = oldVisitValues; + // If delegation is in progress and the current try is not the target of // the delegation, don't handle it and just rethrow. if (scope->currDelegateTarget.is()) { @@ -4136,9 +4139,12 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitTryTable(TryTable* curr) { NOTE_ENTER("TryTable"); + auto* oldVisitValues = self()->visitValues; try { return self()->visit(curr->body); } catch (const WasmException& e) { + self()->visitValues = oldVisitValues; + auto exnData = e.exn.getExnData(); for (size_t i = 0; i < curr->catchTags.size(); i++) { auto catchTag = curr->catchTags[i]; From 3d3bb696cd3e7d6f2593d4f2e7a817acd44d41ec Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 08:23:12 -0700 Subject: [PATCH 27/39] chaks --- src/wasm-interpreter.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 6aeee1a6b6b..b7872f71416 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -209,6 +209,7 @@ class ExpressionRunner : public OverriddenVisitor { } #endif +public: // TODO move/change // The values we gather from children in visit(), and then give to the // instruction to execute. // TODO: Literals here and not Flows @@ -258,13 +259,13 @@ class ExpressionRunner : public OverriddenVisitor { // set of values, handling all control flow ourselves here, and saving // the stack of visitValues as we go. auto* oldVisitValues = visitValues; - VisitValues values; - visitValues = &values; + VisitValues currVisitValues; + visitValues = &currVisitValues; // Iterate over the children, placing their values in the list of values. ChildIterator iter(curr); auto num = iter.getNumChildren(); - values.resize(num); + currVisitValues.resize(num); // Place the first item at the end, so that getChild() can simply pop. Index i = num - 1; for (auto* child : iter) { @@ -277,13 +278,14 @@ class ExpressionRunner : public OverriddenVisitor { visitValues = oldVisitValues; return flow; } - values[i] = flow; + currVisitValues[i] = flow; i--; } // Execute the instruction, which will start with calls to getChild() // that read from our VisitValues. ret = OverriddenVisitor::visit(curr); + assert(visitValues->empty()); // Restore the parent. visitValues = oldVisitValues; @@ -3105,6 +3107,7 @@ class ModuleRunnerBase : public ExpressionRunner { class FunctionScope { public: std::vector locals; + typename SubType::VisitValues* visitValues; Function* function; SubType& parent; @@ -3118,6 +3121,7 @@ class ModuleRunnerBase : public ExpressionRunner { parent.scope = this; parent.callDepth++; parent.functionStack.push_back(function->name); + visitValues = parent.visitValues; if (function->getParams().size() != arguments.size()) { std::cerr << "Function `" << function->name << "` expects " @@ -3147,6 +3151,7 @@ class ModuleRunnerBase : public ExpressionRunner { parent.scope = oldScope; parent.callDepth--; parent.functionStack.pop_back(); + parent.visitValues = visitValues; } // The current delegate target, if delegation of an exception is in From 876d246fe3409e481967cc613e42ab8964a69f86 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 08:27:37 -0700 Subject: [PATCH 28/39] typo --- src/ir/iteration.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ir/iteration.h b/src/ir/iteration.h index bfbf3bb6263..00f2a7383e4 100644 --- a/src/ir/iteration.h +++ b/src/ir/iteration.h @@ -32,7 +32,7 @@ namespace wasm { // In general, it is preferable not to use this class and to directly access the // children (using e.g. iff->ifTrue etc.), as that is faster. However, in cases // where speed does not matter, this can be convenient. TODO: reimplement these -// to avoid materializing all the chilren at once. +// to avoid materializing all the children at once. // // ChildIterator - Iterates over all children // From 38f14dbfb4526d66d75760f0640ac0d24f424ad9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 08:32:39 -0700 Subject: [PATCH 29/39] simpl --- src/wasm-interpreter.h | 209 +---------------------------------------- 1 file changed, 1 insertion(+), 208 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index b7872f71416..1c3f2fe42b4 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1,4 +1,4 @@ -//#define WASM_INTERPRETER_DEBUG 1 +#define WASM_INTERPRETER_DEBUG 1 /* * Copyright 2015 WebAssembly Community Group participants * @@ -116,13 +116,6 @@ class Flow { } }; -// Debugging helpers XXX remove -#define NOTE_ENTER(x) -#define NOTE_ENTER_(x) -#define NOTE_NAME(p0) -#define NOTE_EVAL1(p0) -#define NOTE_EVAL2(p0, p1) - // Execute an expression template class ExpressionRunner : public OverriddenVisitor { @@ -141,11 +134,9 @@ class ExpressionRunner : public OverriddenVisitor { Index maxLoopIterations; Flow generateArguments(const ExpressionList& operands, Literals& arguments) { - NOTE_ENTER_("generateArguments"); arguments.reserve(operands.size()); for (Index i = 0; i < operands.size(); i++) { Flow flow = getChild(); - NOTE_EVAL1(flow.values); arguments.push_back(flow.getSingleValue()); } return Flow(); @@ -315,7 +306,6 @@ class ExpressionRunner : public OverriddenVisitor { Module* getModule() { return module; } Flow visitBlock(Block* curr) { - NOTE_ENTER("Block"); // special-case Block, because Block nesting (in their first element) can be // incredibly deep std::vector stack; @@ -349,12 +339,10 @@ class ExpressionRunner : public OverriddenVisitor { return flow; } Flow visitIf(If* curr) { - NOTE_ENTER("If"); Flow flow = visit(curr->condition); if (flow.breaking()) { return flow; } - NOTE_EVAL1(flow.values); if (flow.getSingleValue().geti32()) { Flow flow = visit(curr->ifTrue); if (!flow.breaking() && !curr->ifFalse) { @@ -368,7 +356,6 @@ class ExpressionRunner : public OverriddenVisitor { return Flow(); } Flow visitLoop(Loop* curr) { - NOTE_ENTER("Loop"); Index loopCount = 0; while (1) { Flow flow = visit(curr->body); @@ -386,7 +373,6 @@ class ExpressionRunner : public OverriddenVisitor { } } Flow visitBreak(Break* curr) { - NOTE_ENTER("Break"); bool condition = true; Flow flow; if (curr->value) { @@ -403,7 +389,6 @@ class ExpressionRunner : public OverriddenVisitor { return flow; } Flow visitSwitch(Switch* curr) { - NOTE_ENTER("Switch"); Flow flow; Literals values; if (curr->value) { @@ -422,8 +407,6 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitConst(Const* curr) { - NOTE_ENTER("Const"); - NOTE_EVAL1(curr->value); return Flow(curr->value); // heh } @@ -431,10 +414,8 @@ class ExpressionRunner : public OverriddenVisitor { // delegate to the Literal::* methods, except we handle traps here. Flow visitUnary(Unary* curr) { - NOTE_ENTER("Unary"); Flow flow = getChild(); Literal value = flow.getSingleValue(); - NOTE_EVAL1(value); switch (curr->op) { case ClzInt32: case ClzInt64: @@ -711,12 +692,10 @@ class ExpressionRunner : public OverriddenVisitor { WASM_UNREACHABLE("invalid op"); } Flow visitBinary(Binary* curr) { - NOTE_ENTER("Binary"); Flow flow = getChild(); Literal left = flow.getSingleValue(); flow = getChild(); Literal right = flow.getSingleValue(); - NOTE_EVAL2(left, right); assert(curr->left->type.isConcrete() ? left.type == curr->left->type : true); assert(curr->right->type.isConcrete() ? right.type == curr->right->type @@ -1198,7 +1177,6 @@ class ExpressionRunner : public OverriddenVisitor { WASM_UNREACHABLE("invalid op"); } Flow visitSIMDExtract(SIMDExtract* curr) { - NOTE_ENTER("SIMDExtract"); Flow flow = getChild(); Literal vec = flow.getSingleValue(); switch (curr->op) { @@ -1224,7 +1202,6 @@ class ExpressionRunner : public OverriddenVisitor { WASM_UNREACHABLE("invalid op"); } Flow visitSIMDReplace(SIMDReplace* curr) { - NOTE_ENTER("SIMDReplace"); Flow flow = getChild(); Literal vec = flow.getSingleValue(); flow = getChild(); @@ -1248,7 +1225,6 @@ class ExpressionRunner : public OverriddenVisitor { WASM_UNREACHABLE("invalid op"); } Flow visitSIMDShuffle(SIMDShuffle* curr) { - NOTE_ENTER("SIMDShuffle"); Flow flow = getChild(); Literal left = flow.getSingleValue(); flow = getChild(); @@ -1256,7 +1232,6 @@ class ExpressionRunner : public OverriddenVisitor { return left.shuffleV8x16(right, curr->mask); } Flow visitSIMDTernary(SIMDTernary* curr) { - NOTE_ENTER("SIMDBitselect"); Flow flow = getChild(); Literal a = flow.getSingleValue(); flow = getChild(); @@ -1310,7 +1285,6 @@ class ExpressionRunner : public OverriddenVisitor { WASM_UNREACHABLE("invalid op"); } Flow visitSIMDShift(SIMDShift* curr) { - NOTE_ENTER("SIMDShift"); Flow flow = getChild(); Literal vec = flow.getSingleValue(); flow = getChild(); @@ -1344,34 +1318,27 @@ class ExpressionRunner : public OverriddenVisitor { WASM_UNREACHABLE("invalid op"); } Flow visitSelect(Select* curr) { - NOTE_ENTER("Select"); Flow ifTrue = getChild(); Flow ifFalse = getChild(); Flow condition = getChild(); - NOTE_EVAL1(condition.getSingleValue()); return condition.getSingleValue().geti32() ? ifTrue : ifFalse; // ;-) } Flow visitDrop(Drop* curr) { - NOTE_ENTER("Drop"); Flow value = getChild(); return Flow(); } Flow visitReturn(Return* curr) { - NOTE_ENTER("Return"); Flow flow; if (curr->value) { flow = getChild(); - NOTE_EVAL1(flow.getSingleValue()); } flow.breakTo = RETURN_FLOW; return flow; } Flow visitNop(Nop* curr) { - NOTE_ENTER("Nop"); return Flow(); } Flow visitUnreachable(Unreachable* curr) { - NOTE_ENTER("Unreachable"); trap("unreachable"); WASM_UNREACHABLE("unreachable"); } @@ -1438,11 +1405,9 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitAtomicFence(AtomicFence* curr) { // Wasm currently supports only sequentially consistent atomics, in which // case atomic_fence can be lowered to nothing. - NOTE_ENTER("AtomicFence"); return Flow(); } Flow visitTupleMake(TupleMake* curr) { - NOTE_ENTER("tuple.make"); Literals arguments; Flow flow = generateArguments(curr->operands, arguments); if (flow.breaking()) { @@ -1455,7 +1420,6 @@ class ExpressionRunner : public OverriddenVisitor { return flow; } Flow visitTupleExtract(TupleExtract* curr) { - NOTE_ENTER("tuple.extract"); Flow flow = getChild(); assert(flow.values.size() > curr->index); return Flow(flow.values[curr->index]); @@ -1488,28 +1452,21 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitPop(Pop* curr) { WASM_UNREACHABLE("unimp"); } Flow visitCallRef(CallRef* curr) { WASM_UNREACHABLE("unimp"); } Flow visitRefNull(RefNull* curr) { - NOTE_ENTER("RefNull"); return Literal::makeNull(curr->type.getHeapType()); } Flow visitRefIsNull(RefIsNull* curr) { - NOTE_ENTER("RefIsNull"); Flow flow = getChild(); const auto& value = flow.getSingleValue(); - NOTE_EVAL1(value); return Literal(int32_t(value.isNull())); } Flow visitRefFunc(RefFunc* curr) { - NOTE_ENTER("RefFunc"); - NOTE_NAME(curr->func); return Literal::makeFunc(curr->func, curr->type.getHeapType()); } Flow visitRefEq(RefEq* curr) { - NOTE_ENTER("RefEq"); Flow flow = getChild(); auto left = flow.getSingleValue(); flow = getChild(); auto right = flow.getSingleValue(); - NOTE_EVAL2(left, right); return Literal(int32_t(left == right)); } Flow visitTableGet(TableGet* curr) { WASM_UNREACHABLE("unimp"); } @@ -1523,22 +1480,18 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitTry(Try* curr) { WASM_UNREACHABLE("unimp"); } Flow visitTryTable(TryTable* curr) { WASM_UNREACHABLE("unimp"); } Flow visitThrow(Throw* curr) { - NOTE_ENTER("Throw"); Literals arguments; Flow flow = generateArguments(curr->operands, arguments); if (flow.breaking()) { return flow; } - NOTE_EVAL1(curr->tag); throwException(WasmException{makeExnData(curr->tag, arguments)}); WASM_UNREACHABLE("throw"); } Flow visitRethrow(Rethrow* curr) { WASM_UNREACHABLE("unimp"); } Flow visitThrowRef(ThrowRef* curr) { - NOTE_ENTER("ThrowRef"); Flow flow = getChild(); const auto& exnref = flow.getSingleValue(); - NOTE_EVAL1(exnref); if (exnref.isNull()) { trap("null ref"); } @@ -1547,18 +1500,14 @@ class ExpressionRunner : public OverriddenVisitor { WASM_UNREACHABLE("throw"); } Flow visitRefI31(RefI31* curr) { - NOTE_ENTER("RefI31"); Flow flow = getChild(); const auto& value = flow.getSingleValue(); - NOTE_EVAL1(value); return Literal::makeI31(value.geti32(), curr->type.getHeapType().getShared()); } Flow visitI31Get(I31Get* curr) { - NOTE_ENTER("I31Get"); Flow flow = getChild(); const auto& value = flow.getSingleValue(); - NOTE_EVAL1(value); if (value.isNull()) { trap("null ref"); } @@ -1629,7 +1578,6 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitRefTest(RefTest* curr) { - NOTE_ENTER("RefTest"); auto cast = doCast(curr); if (auto* breaking = cast.getBreaking()) { return *breaking; @@ -1638,7 +1586,6 @@ class ExpressionRunner : public OverriddenVisitor { } } Flow visitRefCast(RefCast* curr) { - NOTE_ENTER("RefCast"); auto cast = curr->desc ? doDescCast(curr) : doCast(curr); if (auto* breaking = cast.getBreaking()) { return *breaking; @@ -1650,7 +1597,6 @@ class ExpressionRunner : public OverriddenVisitor { WASM_UNREACHABLE("unreachable"); } Flow visitRefGetDesc(RefGetDesc* curr) { - NOTE_ENTER("RefGetDesc"); Flow ref = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { @@ -1659,7 +1605,6 @@ class ExpressionRunner : public OverriddenVisitor { return data->desc; } Flow visitBrOn(BrOn* curr) { - NOTE_ENTER("BrOn"); // BrOnCast* uses the casting infrastructure, so handle them first. switch (curr->op) { case BrOnCast: @@ -1690,7 +1635,6 @@ class ExpressionRunner : public OverriddenVisitor { // Otherwise we are just checking for null. Flow flow = getChild(); const auto& value = flow.getSingleValue(); - NOTE_EVAL1(value); if (curr->op == BrOnNull) { // BrOnNull does not propagate the value if it takes the branch. if (value.isNull()) { @@ -1711,7 +1655,6 @@ class ExpressionRunner : public OverriddenVisitor { WASM_UNREACHABLE("unexpected op"); } Flow visitStructNew(StructNew* curr) { - NOTE_ENTER("StructNew"); // If we are unreachable then we cannot proceed to compute the heap type, // below, as there isn't one. But if we are unreachable then we should not // get here, as the child would break in visit(). @@ -1738,7 +1681,6 @@ class ExpressionRunner : public OverriddenVisitor { return makeGCData(std::move(data), curr->type, desc.getSingleValue()); } Flow visitStructGet(StructGet* curr) { - NOTE_ENTER("StructGet"); Flow ref = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { @@ -1748,7 +1690,6 @@ class ExpressionRunner : public OverriddenVisitor { return extendForPacking(data->values[curr->index], field, curr->signed_); } Flow visitStructSet(StructSet* curr) { - NOTE_ENTER("StructSet"); Flow ref = getChild(); Flow value = getChild(); auto data = ref.getSingleValue().getGCData(); @@ -1762,7 +1703,6 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitStructRMW(StructRMW* curr) { - NOTE_ENTER("StructRMW"); Flow ref = getChild(); Flow value = getChild(); auto data = ref.getSingleValue().getGCData(); @@ -1796,7 +1736,6 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitStructCmpxchg(StructCmpxchg* curr) { - NOTE_ENTER("StructCmpxchg"); Flow ref = getChild(); Flow expected = getChild(); Flow replacement = getChild(); @@ -1819,7 +1758,6 @@ class ExpressionRunner : public OverriddenVisitor { static const Index DataLimit = (1 << 30) / sizeof(Literal); Flow visitArrayNew(ArrayNew* curr) { - NOTE_ENTER("ArrayNew"); Flow init; if (!curr->isWithDefault()) { init = getChild(); @@ -1853,7 +1791,6 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitArrayNewData(ArrayNewData* curr) { WASM_UNREACHABLE("unimp"); } Flow visitArrayNewElem(ArrayNewElem* curr) { WASM_UNREACHABLE("unimp"); } Flow visitArrayNewFixed(ArrayNewFixed* curr) { - NOTE_ENTER("ArrayNewFixed"); Index num = curr->values.size(); if (num >= DataLimit) { hostLimit("allocation failure"); @@ -1872,7 +1809,6 @@ class ExpressionRunner : public OverriddenVisitor { return makeGCData(std::move(data), curr->type); } Flow visitArrayGet(ArrayGet* curr) { - NOTE_ENTER("ArrayGet"); Flow ref = getChild(); Flow index = getChild(); auto data = ref.getSingleValue().getGCData(); @@ -1887,7 +1823,6 @@ class ExpressionRunner : public OverriddenVisitor { return extendForPacking(data->values[i], field, curr->signed_); } Flow visitArraySet(ArraySet* curr) { - NOTE_ENTER("ArraySet"); Flow ref = getChild(); Flow index = getChild(); Flow value = getChild(); @@ -1904,7 +1839,6 @@ class ExpressionRunner : public OverriddenVisitor { return Flow(); } Flow visitArrayLen(ArrayLen* curr) { - NOTE_ENTER("ArrayLen"); Flow ref = getChild(); auto data = ref.getSingleValue().getGCData(); if (!data) { @@ -1913,7 +1847,6 @@ class ExpressionRunner : public OverriddenVisitor { return Literal(int32_t(data->values.size())); } Flow visitArrayCopy(ArrayCopy* curr) { - NOTE_ENTER("ArrayCopy"); Flow destRef = getChild(); Flow destIndex = getChild(); Flow srcRef = getChild(); @@ -1947,7 +1880,6 @@ class ExpressionRunner : public OverriddenVisitor { return Flow(); } Flow visitArrayFill(ArrayFill* curr) { - NOTE_ENTER("ArrayFill"); Flow ref = getChild(); Flow index = getChild(); Flow value = getChild(); @@ -1976,7 +1908,6 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitArrayInitData(ArrayInitData* curr) { WASM_UNREACHABLE("unimp"); } Flow visitArrayInitElem(ArrayInitElem* curr) { WASM_UNREACHABLE("unimp"); } Flow visitArrayRMW(ArrayRMW* curr) { - NOTE_ENTER("ArrayRMW"); Flow ref = getChild(); Flow index = getChild(); Flow value = getChild(); @@ -2012,7 +1943,6 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitArrayCmpxchg(ArrayCmpxchg* curr) { - NOTE_ENTER("ArrayCmpxchg"); Flow ref = getChild(); Flow index = getChild(); Flow expected = getChild(); @@ -2030,10 +1960,8 @@ class ExpressionRunner : public OverriddenVisitor { return oldVal; } Flow visitRefAs(RefAs* curr) { - NOTE_ENTER("RefAs"); Flow flow = getChild(); const auto& value = flow.getSingleValue(); - NOTE_EVAL1(value); switch (curr->op) { case RefAsNonNull: if (value.isNull()) { @@ -2106,12 +2034,10 @@ class ExpressionRunner : public OverriddenVisitor { return Literal(int32_t(data->values.size())); } Flow visitStringConcat(StringConcat* curr) { - NOTE_ENTER("StringConcat"); Flow flow = getChild(); auto left = flow.getSingleValue(); flow = getChild(); auto right = flow.getSingleValue(); - NOTE_EVAL2(left, right); auto leftData = left.getGCData(); auto rightData = right.getGCData(); if (!leftData || !rightData) { @@ -2165,12 +2091,10 @@ class ExpressionRunner : public OverriddenVisitor { return Literal(int32_t(strData->values.size())); } Flow visitStringEq(StringEq* curr) { - NOTE_ENTER("StringEq"); Flow flow = getChild(); auto left = flow.getSingleValue(); flow = getChild(); auto right = flow.getSingleValue(); - NOTE_EVAL2(left, right); auto leftData = left.getGCData(); auto rightData = right.getGCData(); int32_t result; @@ -2230,7 +2154,6 @@ class ExpressionRunner : public OverriddenVisitor { return Literal((uint32_t)value.isString()); } Flow visitStringWTF16Get(StringWTF16Get* curr) { - NOTE_ENTER("StringWTF16Get"); Flow ref = getChild(); Flow pos = getChild(); auto refValue = ref.getSingleValue(); @@ -2392,8 +2315,6 @@ class ConstantExpressionRunner : public ExpressionRunner { } Flow visitLocalGet(LocalGet* curr) { - NOTE_ENTER("LocalGet"); - NOTE_EVAL1(curr->index); // Check if a constant value has been set in the context of this runner. auto iter = localValues.find(curr->index); if (iter != localValues.end()) { @@ -2402,8 +2323,6 @@ class ConstantExpressionRunner : public ExpressionRunner { return Flow(NONCONSTANT_FLOW); } Flow visitLocalSet(LocalSet* curr) { - NOTE_ENTER("LocalSet"); - NOTE_EVAL1(curr->index); if (!(flags & FlagValues::PRESERVE_SIDEEFFECTS)) { // If we are evaluating and not replacing the expression, remember the // constant value set, if any, and see if there is a value flowing through @@ -2421,8 +2340,6 @@ class ConstantExpressionRunner : public ExpressionRunner { return Flow(NONCONSTANT_FLOW); } Flow visitGlobalGet(GlobalGet* curr) { - NOTE_ENTER("GlobalGet"); - NOTE_NAME(curr->name); if (this->module != nullptr) { auto* global = this->module->getGlobal(curr->name); // Check if the global has an immutable value anyway @@ -2438,8 +2355,6 @@ class ConstantExpressionRunner : public ExpressionRunner { return Flow(NONCONSTANT_FLOW); } Flow visitGlobalSet(GlobalSet* curr) { - NOTE_ENTER("GlobalSet"); - NOTE_NAME(curr->name); if (!(flags & FlagValues::PRESERVE_SIDEEFFECTS) && this->module != nullptr) { // If we are evaluating and not replacing the expression, remember the @@ -2454,152 +2369,114 @@ class ConstantExpressionRunner : public ExpressionRunner { return Flow(NONCONSTANT_FLOW); } Flow visitCall(Call* curr) { - NOTE_ENTER("Call"); - NOTE_NAME(curr->target); return Flow(NONCONSTANT_FLOW); } Flow visitCallIndirect(CallIndirect* curr) { - NOTE_ENTER("CallIndirect"); return Flow(NONCONSTANT_FLOW); } Flow visitCallRef(CallRef* curr) { - NOTE_ENTER("CallRef"); return Flow(NONCONSTANT_FLOW); } Flow visitTableGet(TableGet* curr) { - NOTE_ENTER("TableGet"); return Flow(NONCONSTANT_FLOW); } Flow visitTableSet(TableSet* curr) { - NOTE_ENTER("TableSet"); return Flow(NONCONSTANT_FLOW); } Flow visitTableSize(TableSize* curr) { - NOTE_ENTER("TableSize"); return Flow(NONCONSTANT_FLOW); } Flow visitTableGrow(TableGrow* curr) { - NOTE_ENTER("TableGrow"); return Flow(NONCONSTANT_FLOW); } Flow visitTableFill(TableFill* curr) { - NOTE_ENTER("TableFill"); return Flow(NONCONSTANT_FLOW); } Flow visitTableCopy(TableCopy* curr) { - NOTE_ENTER("TableCopy"); return Flow(NONCONSTANT_FLOW); } Flow visitTableInit(TableInit* curr) { - NOTE_ENTER("TableInit"); return Flow(NONCONSTANT_FLOW); } Flow visitElemDrop(ElemDrop* curr) { - NOTE_ENTER("ElemDrop"); return Flow(NONCONSTANT_FLOW); } Flow visitLoad(Load* curr) { - NOTE_ENTER("Load"); return Flow(NONCONSTANT_FLOW); } Flow visitStore(Store* curr) { - NOTE_ENTER("Store"); return Flow(NONCONSTANT_FLOW); } Flow visitMemorySize(MemorySize* curr) { - NOTE_ENTER("MemorySize"); return Flow(NONCONSTANT_FLOW); } Flow visitMemoryGrow(MemoryGrow* curr) { - NOTE_ENTER("MemoryGrow"); return Flow(NONCONSTANT_FLOW); } Flow visitMemoryInit(MemoryInit* curr) { - NOTE_ENTER("MemoryInit"); return Flow(NONCONSTANT_FLOW); } Flow visitDataDrop(DataDrop* curr) { - NOTE_ENTER("DataDrop"); return Flow(NONCONSTANT_FLOW); } Flow visitMemoryCopy(MemoryCopy* curr) { - NOTE_ENTER("MemoryCopy"); return Flow(NONCONSTANT_FLOW); } Flow visitMemoryFill(MemoryFill* curr) { - NOTE_ENTER("MemoryFill"); return Flow(NONCONSTANT_FLOW); } Flow visitAtomicRMW(AtomicRMW* curr) { - NOTE_ENTER("AtomicRMW"); return Flow(NONCONSTANT_FLOW); } Flow visitAtomicCmpxchg(AtomicCmpxchg* curr) { - NOTE_ENTER("AtomicCmpxchg"); return Flow(NONCONSTANT_FLOW); } Flow visitAtomicWait(AtomicWait* curr) { - NOTE_ENTER("AtomicWait"); return Flow(NONCONSTANT_FLOW); } Flow visitAtomicNotify(AtomicNotify* curr) { - NOTE_ENTER("AtomicNotify"); return Flow(NONCONSTANT_FLOW); } Flow visitSIMDLoad(SIMDLoad* curr) { - NOTE_ENTER("SIMDLoad"); return Flow(NONCONSTANT_FLOW); } Flow visitSIMDLoadSplat(SIMDLoad* curr) { - NOTE_ENTER("SIMDLoadSplat"); return Flow(NONCONSTANT_FLOW); } Flow visitSIMDLoadExtend(SIMDLoad* curr) { - NOTE_ENTER("SIMDLoadExtend"); return Flow(NONCONSTANT_FLOW); } Flow visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { - NOTE_ENTER("SIMDLoadStoreLane"); return Flow(NONCONSTANT_FLOW); } Flow visitArrayNewData(ArrayNewData* curr) { - NOTE_ENTER("ArrayNewData"); return Flow(NONCONSTANT_FLOW); } Flow visitArrayNewElem(ArrayNewElem* curr) { - NOTE_ENTER("ArrayNewElem"); return Flow(NONCONSTANT_FLOW); } Flow visitArrayCopy(ArrayCopy* curr) { - NOTE_ENTER("ArrayCopy"); return Flow(NONCONSTANT_FLOW); } Flow visitArrayFill(ArrayFill* curr) { - NOTE_ENTER("ArrayFill"); return Flow(NONCONSTANT_FLOW); } Flow visitArrayInitData(ArrayInitData* curr) { - NOTE_ENTER("ArrayInitData"); return Flow(NONCONSTANT_FLOW); } Flow visitArrayInitElem(ArrayInitElem* curr) { - NOTE_ENTER("ArrayInitElem"); return Flow(NONCONSTANT_FLOW); } Flow visitPop(Pop* curr) { - NOTE_ENTER("Pop"); return Flow(NONCONSTANT_FLOW); } Flow visitTry(Try* curr) { - NOTE_ENTER("Try"); return Flow(NONCONSTANT_FLOW); } Flow visitTryTable(TryTable* curr) { - NOTE_ENTER("TryTable"); return Flow(NONCONSTANT_FLOW); } Flow visitRethrow(Rethrow* curr) { - NOTE_ENTER("Rethrow"); return Flow(NONCONSTANT_FLOW); } Flow visitRefAs(RefAs* curr) { @@ -2610,27 +2487,21 @@ class ConstantExpressionRunner : public ExpressionRunner { return ExpressionRunner::visitRefAs(curr); } Flow visitContNew(ContNew* curr) { - NOTE_ENTER("ContNew"); return Flow(NONCONSTANT_FLOW); } Flow visitContBind(ContBind* curr) { - NOTE_ENTER("ContBind"); return Flow(NONCONSTANT_FLOW); } Flow visitSuspend(Suspend* curr) { - NOTE_ENTER("Suspend"); return Flow(NONCONSTANT_FLOW); } Flow visitResume(Resume* curr) { - NOTE_ENTER("Resume"); return Flow(NONCONSTANT_FLOW); } Flow visitResumeThrow(ResumeThrow* curr) { - NOTE_ENTER("ResumeThrow"); return Flow(NONCONSTANT_FLOW); } Flow visitStackSwitch(StackSwitch* curr) { - NOTE_ENTER("StackSwitch"); return Flow(NONCONSTANT_FLOW); } @@ -3185,8 +3056,6 @@ class ModuleRunnerBase : public ExpressionRunner { public: Flow visitCall(Call* curr) { - NOTE_ENTER("Call"); - NOTE_NAME(curr->target); Name target = curr->target; Literals arguments; Flow flow = self()->generateArguments(curr->operands, arguments); @@ -3218,7 +3087,6 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitCallIndirect(CallIndirect* curr) { - NOTE_ENTER("CallIndirect"); Literals arguments; Flow flow = self()->generateArguments(curr->operands, arguments); if (flow.breaking()) { @@ -3249,7 +3117,6 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitCallRef(CallRef* curr) { - NOTE_ENTER("CallRef"); Literals arguments; Flow flow = self()->generateArguments(curr->operands, arguments); if (flow.breaking()) { @@ -3276,14 +3143,12 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitTableGet(TableGet* curr) { - NOTE_ENTER("TableGet"); Flow index = self()->getChild(); auto info = getTableInstanceInfo(curr->table); auto address = index.getSingleValue().getUnsigned(); return info.interface()->tableLoad(info.name, address); } Flow visitTableSet(TableSet* curr) { - NOTE_ENTER("TableSet"); Flow index = self()->getChild(); Flow value = self()->getChild(); auto info = getTableInstanceInfo(curr->table); @@ -3293,7 +3158,6 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitTableSize(TableSize* curr) { - NOTE_ENTER("TableSize"); auto info = getTableInstanceInfo(curr->table); auto* table = info.instance->wasm.getTable(info.name); Index tableSize = info.interface()->tableSize(curr->table); @@ -3301,7 +3165,6 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitTableGrow(TableGrow* curr) { - NOTE_ENTER("TableGrow"); Flow valueFlow = self()->getChild(); Flow deltaFlow = self()->getChild(); auto info = getTableInstanceInfo(curr->table); @@ -3329,7 +3192,6 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitTableFill(TableFill* curr) { - NOTE_ENTER("TableFill"); Flow destFlow = self()->getChild(); Flow valueFlow = self()->getChild(); Flow sizeFlow = self()->getChild(); @@ -3351,13 +3213,9 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitTableCopy(TableCopy* curr) { - NOTE_ENTER("TableCopy"); Flow dest = self()->getChild(); Flow source = self()->getChild(); Flow size = self()->getChild(); - NOTE_EVAL1(dest); - NOTE_EVAL1(source); - NOTE_EVAL1(size); Address destVal(dest.getSingleValue().getUnsigned()); Address sourceVal(source.getSingleValue().getUnsigned()); Address sizeVal(size.getSingleValue().getUnsigned()); @@ -3393,13 +3251,9 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitTableInit(TableInit* curr) { - NOTE_ENTER("TableInit"); Flow dest = self()->getChild(); Flow offset = self()->getChild(); Flow size = self()->getChild(); - NOTE_EVAL1(dest); - NOTE_EVAL1(offset); - NOTE_EVAL1(size); auto* segment = wasm.getElementSegment(curr->segment); @@ -3438,44 +3292,31 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitLocalGet(LocalGet* curr) { - NOTE_ENTER("LocalGet"); auto index = curr->index; - NOTE_EVAL1(index); - NOTE_EVAL1(scope->locals[index]); return scope->locals[index]; } Flow visitLocalSet(LocalSet* curr) { - NOTE_ENTER("LocalSet"); auto index = curr->index; Flow flow = self()->getChild(); - NOTE_EVAL1(index); - NOTE_EVAL1(flow.getSingleValue()); assert(curr->isTee() ? Type::isSubType(flow.getType(), curr->type) : true); scope->locals[index] = flow.values; return curr->isTee() ? flow : Flow(); } Flow visitGlobalGet(GlobalGet* curr) { - NOTE_ENTER("GlobalGet"); auto name = curr->name; - NOTE_EVAL1(name); return getGlobal(name); } Flow visitGlobalSet(GlobalSet* curr) { - NOTE_ENTER("GlobalSet"); auto name = curr->name; Flow flow = self()->getChild(); - NOTE_EVAL1(name); - NOTE_EVAL1(flow.getSingleValue()); getGlobal(name) = flow.values; return Flow(); } Flow visitLoad(Load* curr) { - NOTE_ENTER("Load"); Flow flow = self()->getChild(); - NOTE_EVAL1(flow); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto addr = @@ -3484,12 +3325,9 @@ class ModuleRunnerBase : public ExpressionRunner { info.instance->checkAtomicAddress(addr, curr->bytes, memorySize); } auto ret = info.interface()->load(curr, addr, info.name); - NOTE_EVAL1(addr); - NOTE_EVAL1(ret); return ret; } Flow visitStore(Store* curr) { - NOTE_ENTER("Store"); Flow ptr = self()->getChild(); Flow value = self()->getChild(); auto info = getMemoryInstanceInfo(curr->memory); @@ -3499,26 +3337,19 @@ class ModuleRunnerBase : public ExpressionRunner { if (curr->isAtomic) { info.instance->checkAtomicAddress(addr, curr->bytes, memorySize); } - NOTE_EVAL1(addr); - NOTE_EVAL1(value); info.interface()->store(curr, addr, value.getSingleValue(), info.name); return Flow(); } Flow visitAtomicRMW(AtomicRMW* curr) { - NOTE_ENTER("AtomicRMW"); Flow ptr = self()->getChild(); auto value = self()->getChild(); - NOTE_EVAL1(ptr); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto addr = info.instance->getFinalAddress(curr, ptr.getSingleValue(), memorySize); - NOTE_EVAL1(addr); - NOTE_EVAL1(value); auto loaded = info.instance->doAtomicLoad( addr, curr->bytes, curr->type, info.name, memorySize); - NOTE_EVAL1(loaded); auto computed = value.getSingleValue(); switch (curr->op) { case RMWAdd: @@ -3544,9 +3375,7 @@ class ModuleRunnerBase : public ExpressionRunner { return loaded; } Flow visitAtomicCmpxchg(AtomicCmpxchg* curr) { - NOTE_ENTER("AtomicCmpxchg"); Flow ptr = self()->getChild(); - NOTE_EVAL1(ptr); auto expected = self()->getChild(); auto replacement = self()->getChild(); auto info = getMemoryInstanceInfo(curr->memory); @@ -3554,12 +3383,8 @@ class ModuleRunnerBase : public ExpressionRunner { auto addr = info.instance->getFinalAddress(curr, ptr.getSingleValue(), memorySize); expected = Flow(wrapToSmallerSize(expected.getSingleValue(), curr->bytes)); - NOTE_EVAL1(addr); - NOTE_EVAL1(expected); - NOTE_EVAL1(replacement); auto loaded = info.instance->doAtomicLoad( addr, curr->bytes, curr->type, info.name, memorySize); - NOTE_EVAL1(loaded); if (loaded == expected.getSingleValue()) { info.instance->doAtomicStore( addr, curr->bytes, replacement.getSingleValue(), info.name, memorySize); @@ -3567,9 +3392,7 @@ class ModuleRunnerBase : public ExpressionRunner { return loaded; } Flow visitAtomicWait(AtomicWait* curr) { - NOTE_ENTER("AtomicWait"); Flow ptr = self()->getChild(); - NOTE_EVAL1(ptr); auto expected = self()->getChild(); auto timeout = self()->getChild(); auto bytes = curr->expectedType.getByteSize(); @@ -3579,7 +3402,6 @@ class ModuleRunnerBase : public ExpressionRunner { curr, ptr.getSingleValue(), bytes, memorySize); auto loaded = info.instance->doAtomicLoad( addr, bytes, curr->expectedType, info.name, memorySize); - NOTE_EVAL1(loaded); if (loaded != expected.getSingleValue()) { return Literal(int32_t(1)); // not equal } @@ -3594,9 +3416,7 @@ class ModuleRunnerBase : public ExpressionRunner { return Literal(int32_t(2)); // Timed out } Flow visitAtomicNotify(AtomicNotify* curr) { - NOTE_ENTER("AtomicNotify"); Flow ptr = self()->getChild(); - NOTE_EVAL1(ptr); auto count = self()->getChild(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); @@ -3607,7 +3427,6 @@ class ModuleRunnerBase : public ExpressionRunner { return Literal(int32_t(0)); // none woken up } Flow visitSIMDLoad(SIMDLoad* curr) { - NOTE_ENTER("SIMDLoad"); switch (curr->op) { case Load8SplatVec128: case Load16SplatVec128: @@ -3661,7 +3480,6 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitSIMDLoadExtend(SIMDLoad* curr) { Flow flow = self()->getChild(); - NOTE_EVAL1(flow); Address src(flow.getSingleValue().getUnsigned()); auto info = getMemoryInstanceInfo(curr->memory); auto loadLane = [&](Address addr) { @@ -3718,7 +3536,6 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitSIMDLoadZero(SIMDLoad* curr) { Flow flow = self()->getChild(); - NOTE_EVAL1(flow); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); Address src = info.instance->getFinalAddress( @@ -3734,9 +3551,7 @@ class ModuleRunnerBase : public ExpressionRunner { } } Flow visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { - NOTE_ENTER("SIMDLoadStoreLane"); Flow ptrFlow = self()->getChild(); - NOTE_EVAL1(ptrFlow); Flow vecFlow = self()->getChild(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); @@ -3800,14 +3615,12 @@ class ModuleRunnerBase : public ExpressionRunner { WASM_UNREACHABLE("unexpected op"); } Flow visitMemorySize(MemorySize* curr) { - NOTE_ENTER("MemorySize"); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto* memory = info.instance->wasm.getMemory(info.name); return Literal::makeFromInt64(memorySize, memory->addressType); } Flow visitMemoryGrow(MemoryGrow* curr) { - NOTE_ENTER("MemoryGrow"); Flow flow = self()->getChild(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); @@ -3843,13 +3656,9 @@ class ModuleRunnerBase : public ExpressionRunner { return ret; } Flow visitMemoryInit(MemoryInit* curr) { - NOTE_ENTER("MemoryInit"); Flow dest = self()->getChild(); Flow offset = self()->getChild(); Flow size = self()->getChild(); - NOTE_EVAL1(dest); - NOTE_EVAL1(offset); - NOTE_EVAL1(size); auto* segment = wasm.getDataSegment(curr->segment); @@ -3878,18 +3687,13 @@ class ModuleRunnerBase : public ExpressionRunner { return {}; } Flow visitDataDrop(DataDrop* curr) { - NOTE_ENTER("DataDrop"); droppedDataSegments.insert(curr->segment); return {}; } Flow visitMemoryCopy(MemoryCopy* curr) { - NOTE_ENTER("MemoryCopy"); Flow dest = self()->getChild(); Flow source = self()->getChild(); Flow size = self()->getChild(); - NOTE_EVAL1(dest); - NOTE_EVAL1(source); - NOTE_EVAL1(size); Address destVal(dest.getSingleValue().getUnsigned()); Address sourceVal(source.getSingleValue().getUnsigned()); Address sizeVal(size.getSingleValue().getUnsigned()); @@ -3928,13 +3732,9 @@ class ModuleRunnerBase : public ExpressionRunner { return {}; } Flow visitMemoryFill(MemoryFill* curr) { - NOTE_ENTER("MemoryFill"); Flow dest = self()->getChild(); Flow value = self()->getChild(); Flow size = self()->getChild(); - NOTE_EVAL1(dest); - NOTE_EVAL1(value); - NOTE_EVAL1(size); Address destVal(dest.getSingleValue().getUnsigned()); Address sizeVal(size.getSingleValue().getUnsigned()); @@ -3956,7 +3756,6 @@ class ModuleRunnerBase : public ExpressionRunner { return {}; } Flow visitArrayNewData(ArrayNewData* curr) { - NOTE_ENTER("ArrayNewData"); auto offsetFlow = self()->getChild(); auto sizeFlow = self()->getChild(); @@ -3991,7 +3790,6 @@ class ModuleRunnerBase : public ExpressionRunner { return self()->makeGCData(std::move(contents), curr->type); } Flow visitArrayNewElem(ArrayNewElem* curr) { - NOTE_ENTER("ArrayNewElem"); auto offsetFlow = self()->getChild(); auto sizeFlow = self()->getChild(); @@ -4016,7 +3814,6 @@ class ModuleRunnerBase : public ExpressionRunner { return self()->makeGCData(std::move(contents), curr->type); } Flow visitArrayInitData(ArrayInitData* curr) { - NOTE_ENTER("ArrayInit"); Flow ref = self()->getChild(); Flow index = self()->getChild(); Flow offset = self()->getChild(); @@ -4053,7 +3850,6 @@ class ModuleRunnerBase : public ExpressionRunner { return {}; } Flow visitArrayInitElem(ArrayInitElem* curr) { - NOTE_ENTER("ArrayInit"); Flow ref = self()->getChild(); Flow index = self()->getChild(); Flow offset = self()->getChild(); @@ -4091,7 +3887,6 @@ class ModuleRunnerBase : public ExpressionRunner { return {}; } Flow visitTry(Try* curr) { - NOTE_ENTER("Try"); auto* oldVisitValues = self()->visitValues; try { return self()->visit(curr->body); @@ -4143,7 +3938,6 @@ class ModuleRunnerBase : public ExpressionRunner { } } Flow visitTryTable(TryTable* curr) { - NOTE_ENTER("TryTable"); auto* oldVisitValues = self()->visitValues; try { return self()->visit(curr->body); @@ -4180,7 +3974,6 @@ class ModuleRunnerBase : public ExpressionRunner { WASM_UNREACHABLE("rethrow"); } Flow visitPop(Pop* curr) { - NOTE_ENTER("Pop"); assert(!multiValues.empty()); auto ret = multiValues.back(); assert(Type::isSubType(ret.getType(), curr->type)); From 7b08621fd74a55b50ab5782f217faffec46c8763 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 08:49:39 -0700 Subject: [PATCH 30/39] fix --- src/wasm-interpreter.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 1c3f2fe42b4..530c85fe49d 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -276,7 +276,10 @@ class ExpressionRunner : public OverriddenVisitor { // Execute the instruction, which will start with calls to getChild() // that read from our VisitValues. ret = OverriddenVisitor::visit(curr); - assert(visitValues->empty()); + if (ret.breakTo != NONCONSTANT_FLOW) { + // This executed, so the values must have been fully read. + assert(visitValues->empty()); + } // Restore the parent. visitValues = oldVisitValues; From e2740d44947f10a970534ed42c267bc931471f4c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 09:11:29 -0700 Subject: [PATCH 31/39] fix --- src/wasm-interpreter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 530c85fe49d..41926c284ea 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1,4 +1,4 @@ -#define WASM_INTERPRETER_DEBUG 1 +//#define WASM_INTERPRETER_DEBUG 1 /* * Copyright 2015 WebAssembly Community Group participants * @@ -3478,7 +3478,7 @@ class ModuleRunnerBase : public ExpressionRunner { WASM_UNREACHABLE("invalid op"); } load.finalize(); - Flow flow = self()->getChild(); + Flow flow = visitLoad(&load); return (flow.getSingleValue().*splat)(); } Flow visitSIMDLoadExtend(SIMDLoad* curr) { From be17df40b9527b4612876c38da88a9b40e5c18ef Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 09:17:47 -0700 Subject: [PATCH 32/39] format --- src/wasm-interpreter.h | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 41926c284ea..388a5328d4e 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -31,8 +31,8 @@ #include #include "fp16.h" -#include "ir/iteration.h" #include "ir/intrinsics.h" +#include "ir/iteration.h" #include "ir/module-utils.h" #include "ir/properties.h" #include "support/bits.h" @@ -3084,7 +3084,8 @@ class ModuleRunnerBase : public ExpressionRunner { Flow ret = callFunction(target, arguments); #if WASM_INTERPRETER_DEBUG - std::cout << self()->indent() << "(returned to " << scope->function->name << ")\n"; + std::cout << self()->indent() << "(returned to " << scope->function->name + << ")\n"; #endif return ret; } @@ -3114,7 +3115,8 @@ class ModuleRunnerBase : public ExpressionRunner { Flow ret = info.interface()->callTable( info.name, index, curr->heapType, arguments, curr->type, *self()); #if WASM_INTERPRETER_DEBUG - std::cout << self()->indent() << "(returned to " << scope->function->name << ")\n"; + std::cout << self()->indent() << "(returned to " << scope->function->name + << ")\n"; #endif return ret; } @@ -3140,7 +3142,8 @@ class ModuleRunnerBase : public ExpressionRunner { Flow ret = callFunction(targetRef.getFunc(), arguments); #if WASM_INTERPRETER_DEBUG - std::cout << self()->indent() << "(returned to " << scope->function->name << ")\n"; + std::cout << self()->indent() << "(returned to " << scope->function->name + << ")\n"; #endif return ret; } @@ -4065,7 +4068,8 @@ class ModuleRunnerBase : public ExpressionRunner { FunctionScope scope(function, arguments, *self()); #if WASM_INTERPRETER_DEBUG - std::cout << self()->indent() << "entering " << function->name << "\n with arguments:\n"; + std::cout << self()->indent() << "entering " << function->name + << "\n with arguments:\n"; for (unsigned i = 0; i < arguments.size(); ++i) { std::cout << " $" << i << ": " << arguments[i] << '\n'; } @@ -4074,8 +4078,8 @@ class ModuleRunnerBase : public ExpressionRunner { flow = self()->visit(function->body); #if WASM_INTERPRETER_DEBUG - std::cout << self()->indent() << "exiting " << function->name << " with " << flow.values - << '\n'; + std::cout << self()->indent() << "exiting " << function->name << " with " + << flow.values << '\n'; #endif if (flow.breakTo != RETURN_CALL_FLOW) { From e36ac6881c7e01affee4e30f4abd0a5b2f6259df Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 10:20:03 -0700 Subject: [PATCH 33/39] clean --- a.py | 41 ----------------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 a.py diff --git a/a.py b/a.py deleted file mode 100644 index aba4da44274..00000000000 --- a/a.py +++ /dev/null @@ -1,41 +0,0 @@ -import os, sys -import subprocess - -diff = subprocess.check_output(['git', 'diff', 'src/']) -if diff: - print('cannot run since diff exists') - sys.exit(1) - -new = [] -lines = open('src/wasm-interpreter.h').readlines() -i = 0 -while i < len(lines): - line = lines[i] - # look for - # Flow flow = visit(expression); - # or - # Flow flow = self()->visit(expression); - if ' = visit(' in line or ' = self()->visit(' in line: - print(line.rstrip()) - # next, we should see - # - # if (flow.breaking()) { - # return flow; - # } - # - next = lines[i + 1] - if '.breaking()) {' in next: - next = lines[i + 2] - if 'return ' in next: - next = lines[i + 3] - if '}' in next: - # success! turn it all into a pop - parts = line.split(' ') - parts[-1] = 'pop();' - line = ' '.join(parts) + '\n' - i += 3 - - new.append(line) - i += 1 - -open('src/wasm-interpreter.h', 'w').write(''.join(new)) From a6884ebd8363cae43dfaf05b429b7726a3ceeb38 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 10:52:47 -0700 Subject: [PATCH 34/39] faster --- src/wasm-interpreter.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 388a5328d4e..2ea7fe1682e 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -204,7 +204,7 @@ class ExpressionRunner : public OverriddenVisitor { // The values we gather from children in visit(), and then give to the // instruction to execute. // TODO: Literals here and not Flows - using VisitValues = SmallVector; + using VisitValues = std::vector; // The current set of visit values, used in getChild. VisitValues* visitValues = nullptr; @@ -2981,7 +2981,6 @@ class ModuleRunnerBase : public ExpressionRunner { class FunctionScope { public: std::vector locals; - typename SubType::VisitValues* visitValues; Function* function; SubType& parent; @@ -2995,7 +2994,6 @@ class ModuleRunnerBase : public ExpressionRunner { parent.scope = this; parent.callDepth++; parent.functionStack.push_back(function->name); - visitValues = parent.visitValues; if (function->getParams().size() != arguments.size()) { std::cerr << "Function `" << function->name << "` expects " @@ -3025,7 +3023,6 @@ class ModuleRunnerBase : public ExpressionRunner { parent.scope = oldScope; parent.callDepth--; parent.functionStack.pop_back(); - parent.visitValues = visitValues; } // The current delegate target, if delegation of an exception is in From e11e69c4562dc3881ef3f4c53cd94a713844b327 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 11:33:58 -0700 Subject: [PATCH 35/39] faster --- src/wasm-interpreter.h | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 2ea7fe1682e..85b6f63f2e3 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -207,18 +207,17 @@ class ExpressionRunner : public OverriddenVisitor { using VisitValues = std::vector; // The current set of visit values, used in getChild. - VisitValues* visitValues = nullptr; + VisitValues visitValues; // Get a child value. This returns values in the natural order, the same as in // the wat and in wasm.h. Flow getChild() { - assert(visitValues); - assert(!visitValues->empty()); - auto ret = visitValues->back(); + assert(!visitValues.empty()); + auto ret = visitValues.back(); #if WASM_INTERPRETER_DEBUG std::cout << indent() << "getting child " << ret << '\n'; #endif - visitValues->pop_back(); + visitValues.pop_back(); return ret; } @@ -249,16 +248,15 @@ class ExpressionRunner : public OverriddenVisitor { // General instruction handling: Visit the children and add them to the // set of values, handling all control flow ourselves here, and saving // the stack of visitValues as we go. - auto* oldVisitValues = visitValues; - VisitValues currVisitValues; - visitValues = &currVisitValues; + auto oldSize = visitValues.size(); // Iterate over the children, placing their values in the list of values. ChildIterator iter(curr); auto num = iter.getNumChildren(); - currVisitValues.resize(num); + auto newSize = oldSize + num; + visitValues.resize(newSize); // Place the first item at the end, so that getChild() can simply pop. - Index i = num - 1; + Index i = newSize - 1; for (auto* child : iter) { Flow flow = visit(child); if (flow.breaking()) { @@ -266,23 +264,19 @@ class ExpressionRunner : public OverriddenVisitor { std::cout << indent() << "=> breaking: " << flow << '\n'; #endif depth--; - visitValues = oldVisitValues; + visitValues.resize(oldSize); return flow; } - currVisitValues[i] = flow; + visitValues[i] = flow; i--; } // Execute the instruction, which will start with calls to getChild() // that read from our VisitValues. ret = OverriddenVisitor::visit(curr); - if (ret.breakTo != NONCONSTANT_FLOW) { - // This executed, so the values must have been fully read. - assert(visitValues->empty()); - } // Restore the parent. - visitValues = oldVisitValues; + visitValues.resize(oldSize); } if (!ret.breaking()) { @@ -3890,11 +3884,11 @@ class ModuleRunnerBase : public ExpressionRunner { return {}; } Flow visitTry(Try* curr) { - auto* oldVisitValues = self()->visitValues; + auto oldVisitValuesSize = self()->visitValues.size(); try { return self()->visit(curr->body); } catch (const WasmException& e) { - self()->visitValues = oldVisitValues; + self()->visitValues.resize(oldVisitValuesSize); // If delegation is in progress and the current try is not the target of // the delegation, don't handle it and just rethrow. @@ -3941,11 +3935,11 @@ class ModuleRunnerBase : public ExpressionRunner { } } Flow visitTryTable(TryTable* curr) { - auto* oldVisitValues = self()->visitValues; + auto oldVisitValuesSize = self()->visitValues.size(); try { return self()->visit(curr->body); } catch (const WasmException& e) { - self()->visitValues = oldVisitValues; + self()->visitValues.resize(oldVisitValuesSize); auto exnData = e.exn.getExnData(); for (size_t i = 0; i < curr->catchTags.size(); i++) { From 317967da92b2041efb287f750a1af45f84ced784 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 11:42:25 -0700 Subject: [PATCH 36/39] faster --- src/wasm-interpreter.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 85b6f63f2e3..898a9940396 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -203,8 +203,7 @@ class ExpressionRunner : public OverriddenVisitor { public: // TODO move/change // The values we gather from children in visit(), and then give to the // instruction to execute. - // TODO: Literals here and not Flows - using VisitValues = std::vector; + using VisitValues = std::vector; // The current set of visit values, used in getChild. VisitValues visitValues; @@ -267,7 +266,7 @@ class ExpressionRunner : public OverriddenVisitor { visitValues.resize(oldSize); return flow; } - visitValues[i] = flow; + visitValues[i] = std::move(flow.values); i--; } From a823f1447e09c2a19c515fd1d42aacc1c4d2bbfe Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 11:58:59 -0700 Subject: [PATCH 37/39] SIMPL? --- src/wasm-interpreter.h | 124 +++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 60 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 898a9940396..60e862981aa 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -210,7 +210,7 @@ class ExpressionRunner : public OverriddenVisitor { // Get a child value. This returns values in the natural order, the same as in // the wat and in wasm.h. - Flow getChild() { + Literals getChild() { assert(!visitValues.empty()); auto ret = visitValues.back(); #if WASM_INTERPRETER_DEBUG @@ -220,6 +220,17 @@ class ExpressionRunner : public OverriddenVisitor { return ret; } + // Get a single child value, returning a Literal rather than Literals. + Literal getSingleChild() { + assert(!visitValues.empty()); + auto ret = visitValues.back()[0]; +#if WASM_INTERPRETER_DEBUG + std::cout << indent() << "getting single child " << ret << '\n'; +#endif + visitValues.pop_back(); + return ret; + } + public: ExpressionRunner(Module* module = nullptr, Index maxDepth = NO_LIMIT, @@ -369,14 +380,12 @@ class ExpressionRunner : public OverriddenVisitor { } } Flow visitBreak(Break* curr) { - bool condition = true; Flow flow; if (curr->value) { flow = getChild(); } if (curr->condition) { - Flow conditionFlow = getChild(); - condition = conditionFlow.getSingleValue().getInteger() != 0; + auto condition = getSingleChild().getInteger() != 0; if (!condition) { return flow; } @@ -1663,18 +1672,17 @@ class ExpressionRunner : public OverriddenVisitor { if (curr->isWithDefault()) { data[i] = Literal::makeZero(field.type); } else { - auto value = getChild(); - data[i] = truncateForPacking(value.getSingleValue(), field); + data[i] = truncateForPacking(getSingleChild(), field); } } if (!curr->desc) { return makeGCData(std::move(data), curr->type); } - auto desc = getChild(); - if (desc.getSingleValue().isNull()) { + auto desc = getSingleChild(); + if (desc.isNull()) { trap("null descriptor"); } - return makeGCData(std::move(data), curr->type, desc.getSingleValue()); + return makeGCData(std::move(data), curr->type, desc); } Flow visitStructGet(StructGet* curr) { Flow ref = getChild(); @@ -1754,18 +1762,18 @@ class ExpressionRunner : public OverriddenVisitor { static const Index DataLimit = (1 << 30) / sizeof(Literal); Flow visitArrayNew(ArrayNew* curr) { - Flow init; + Literal init; if (!curr->isWithDefault()) { - init = getChild(); + init = getSingleChild(); } - auto size = getChild(); + auto size = getSingleChild(); // If we are unreachable then we cannot proceed to compute the heap type, // below, as there isn't one. But if we are unreachable then we should not // get here, as the child would break in visit(). assert(curr->type != Type::unreachable); auto heapType = curr->type.getHeapType(); const auto& element = heapType.getArray().element; - Index num = size.getSingleValue().geti32(); + Index num = size.geti32(); if (num >= DataLimit) { hostLimit("allocation failure"); } @@ -1777,7 +1785,7 @@ class ExpressionRunner : public OverriddenVisitor { } } else { auto field = curr->type.getHeapType().getArray().element; - auto value = truncateForPacking(init.getSingleValue(), field); + auto value = truncateForPacking(init, field); for (Index i = 0; i < num; i++) { data[i] = value; } @@ -1799,8 +1807,8 @@ class ExpressionRunner : public OverriddenVisitor { auto field = heapType.getArray().element; Literals data(num); for (Index i = 0; i < num; i++) { - auto value = getChild(); - data[i] = truncateForPacking(value.getSingleValue(), field); + auto value = getSingleChild(); + data[i] = truncateForPacking(value, field); } return makeGCData(std::move(data), curr->type); } @@ -2324,14 +2332,12 @@ class ConstantExpressionRunner : public ExpressionRunner { // constant value set, if any, and see if there is a value flowing through // a tee. auto setFlow = self()->getChild(); - if (!setFlow.breaking()) { - setLocalValue(curr->index, setFlow.values); - if (curr->type.isConcrete()) { - assert(curr->isTee()); - return setFlow; - } - return Flow(); + setLocalValue(curr->index, setFlow); + if (curr->type.isConcrete()) { + assert(curr->isTee()); + return setFlow; } + return Flow(); } return Flow(NONCONSTANT_FLOW); } @@ -2357,10 +2363,8 @@ class ConstantExpressionRunner : public ExpressionRunner { // constant value set, if any, for subsequent gets. assert(this->module->getGlobal(curr->name)->mutable_); auto setFlow = self()->getChild(); - if (!setFlow.breaking()) { - setGlobalValue(curr->name, setFlow.values); - return Flow(); - } + setGlobalValue(curr->name, setFlow); + return Flow(); } return Flow(NONCONSTANT_FLOW); } @@ -3338,30 +3342,30 @@ class ModuleRunnerBase : public ExpressionRunner { } Flow visitAtomicRMW(AtomicRMW* curr) { - Flow ptr = self()->getChild(); - auto value = self()->getChild(); + auto ptr = self()->getSingleChild(); + auto value = self()->getSingleChild(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto addr = - info.instance->getFinalAddress(curr, ptr.getSingleValue(), memorySize); + info.instance->getFinalAddress(curr, ptr, memorySize); auto loaded = info.instance->doAtomicLoad( addr, curr->bytes, curr->type, info.name, memorySize); - auto computed = value.getSingleValue(); + Literal computed; switch (curr->op) { case RMWAdd: - computed = loaded.add(computed); + computed = loaded.add(value); break; case RMWSub: - computed = loaded.sub(computed); + computed = loaded.sub(value); break; case RMWAnd: - computed = loaded.and_(computed); + computed = loaded.and_(value); break; case RMWOr: - computed = loaded.or_(computed); + computed = loaded.or_(value); break; case RMWXor: - computed = loaded.xor_(computed); + computed = loaded.xor_(value); break; case RMWXchg: break; @@ -3371,34 +3375,34 @@ class ModuleRunnerBase : public ExpressionRunner { return loaded; } Flow visitAtomicCmpxchg(AtomicCmpxchg* curr) { - Flow ptr = self()->getChild(); - auto expected = self()->getChild(); - auto replacement = self()->getChild(); + auto ptr = self()->getSingleChild(); + auto expected = self()->getSingleChild(); + auto replacement = self()->getSingleChild(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto addr = - info.instance->getFinalAddress(curr, ptr.getSingleValue(), memorySize); - expected = Flow(wrapToSmallerSize(expected.getSingleValue(), curr->bytes)); + info.instance->getFinalAddress(curr, ptr, memorySize); + expected = wrapToSmallerSize(expected, curr->bytes); auto loaded = info.instance->doAtomicLoad( addr, curr->bytes, curr->type, info.name, memorySize); - if (loaded == expected.getSingleValue()) { + if (loaded == expected) { info.instance->doAtomicStore( - addr, curr->bytes, replacement.getSingleValue(), info.name, memorySize); + addr, curr->bytes, replacement, info.name, memorySize); } return loaded; } Flow visitAtomicWait(AtomicWait* curr) { - Flow ptr = self()->getChild(); - auto expected = self()->getChild(); - auto timeout = self()->getChild(); + auto ptr = self()->getSingleChild(); + auto expected = self()->getSingleChild(); + auto timeout = self()->getSingleChild(); auto bytes = curr->expectedType.getByteSize(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto addr = info.instance->getFinalAddress( - curr, ptr.getSingleValue(), bytes, memorySize); + curr, ptr, bytes, memorySize); auto loaded = info.instance->doAtomicLoad( addr, bytes, curr->expectedType, info.name, memorySize); - if (loaded != expected.getSingleValue()) { + if (loaded != expected) { return Literal(int32_t(1)); // not equal } // TODO: Add threads support. For now, report a host limit here, as there @@ -3406,18 +3410,18 @@ class ModuleRunnerBase : public ExpressionRunner { // we'd hang if there is no timeout, and even if there is a timeout // then we can hang for a long time if it is in a loop. The only // timeout value we allow here for now is 0. - if (timeout.getSingleValue().getInteger() != 0) { + if (timeout.getInteger() != 0) { hostLimit("threads support"); } return Literal(int32_t(2)); // Timed out } Flow visitAtomicNotify(AtomicNotify* curr) { - Flow ptr = self()->getChild(); - auto count = self()->getChild(); + auto ptr = self()->getSingleChild(); + auto count = self()->getSingleChild(); auto info = getMemoryInstanceInfo(curr->memory); auto memorySize = info.instance->getMemorySize(info.name); auto addr = - info.instance->getFinalAddress(curr, ptr.getSingleValue(), 4, memorySize); + info.instance->getFinalAddress(curr, ptr, 4, memorySize); // Just check TODO actual threads support info.instance->checkAtomicAddress(addr, 4, memorySize); return Literal(int32_t(0)); // none woken up @@ -3752,11 +3756,11 @@ class ModuleRunnerBase : public ExpressionRunner { return {}; } Flow visitArrayNewData(ArrayNewData* curr) { - auto offsetFlow = self()->getChild(); - auto sizeFlow = self()->getChild(); + auto offsetFlow = self()->getSingleChild(); + auto sizeFlow = self()->getSingleChild(); - uint64_t offset = offsetFlow.getSingleValue().getUnsigned(); - uint64_t size = sizeFlow.getSingleValue().getUnsigned(); + uint64_t offset = offsetFlow.getUnsigned(); + uint64_t size = sizeFlow.getUnsigned(); auto heapType = curr->type.getHeapType(); const auto& element = heapType.getArray().element; @@ -3786,11 +3790,11 @@ class ModuleRunnerBase : public ExpressionRunner { return self()->makeGCData(std::move(contents), curr->type); } Flow visitArrayNewElem(ArrayNewElem* curr) { - auto offsetFlow = self()->getChild(); - auto sizeFlow = self()->getChild(); + auto offsetFlow = self()->getSingleChild(); + auto sizeFlow = self()->getSingleChild(); - uint64_t offset = offsetFlow.getSingleValue().getUnsigned(); - uint64_t size = sizeFlow.getSingleValue().getUnsigned(); + uint64_t offset = offsetFlow.getUnsigned(); + uint64_t size = sizeFlow.getUnsigned(); Literals contents; From 8e244046bd4d62763535badec3c7732b3bba10f2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 12:03:17 -0700 Subject: [PATCH 38/39] simpler --- src/wasm-interpreter.h | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 60e862981aa..559a6fc2bea 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -133,13 +133,11 @@ class ExpressionRunner : public OverriddenVisitor { // Maximum iterations before giving up on a loop. Index maxLoopIterations; - Flow generateArguments(const ExpressionList& operands, Literals& arguments) { + void generateArguments(const ExpressionList& operands, Literals& arguments) { arguments.reserve(operands.size()); for (Index i = 0; i < operands.size(); i++) { - Flow flow = getChild(); - arguments.push_back(flow.getSingleValue()); + arguments.push_back(getSingleChild()); } - return Flow(); } // This small function is mainly useful to put all GCData allocations in a @@ -1414,15 +1412,13 @@ class ExpressionRunner : public OverriddenVisitor { } Flow visitTupleMake(TupleMake* curr) { Literals arguments; - Flow flow = generateArguments(curr->operands, arguments); - if (flow.breaking()) { - return flow; - } + generateArguments(curr->operands, arguments); +#ifndef NDEBUG for (auto arg : arguments) { assert(arg.type.isConcrete()); - flow.values.push_back(arg); } - return flow; +#endif + return arguments; } Flow visitTupleExtract(TupleExtract* curr) { Flow flow = getChild(); @@ -1486,10 +1482,7 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitTryTable(TryTable* curr) { WASM_UNREACHABLE("unimp"); } Flow visitThrow(Throw* curr) { Literals arguments; - Flow flow = generateArguments(curr->operands, arguments); - if (flow.breaking()) { - return flow; - } + generateArguments(curr->operands, arguments); throwException(WasmException{makeExnData(curr->tag, arguments)}); WASM_UNREACHABLE("throw"); } @@ -3055,10 +3048,7 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitCall(Call* curr) { Name target = curr->target; Literals arguments; - Flow flow = self()->generateArguments(curr->operands, arguments); - if (flow.breaking()) { - return flow; - } + self()->generateArguments(curr->operands, arguments); auto* func = wasm.getFunction(curr->target); auto funcType = func->type; if (Intrinsics(*self()->getModule()).isCallWithoutEffects(func)) { @@ -3086,10 +3076,7 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitCallIndirect(CallIndirect* curr) { Literals arguments; - Flow flow = self()->generateArguments(curr->operands, arguments); - if (flow.breaking()) { - return flow; - } + self()->generateArguments(curr->operands, arguments); Flow target = self()->getChild(); auto index = target.getSingleValue().getUnsigned(); @@ -3117,10 +3104,7 @@ class ModuleRunnerBase : public ExpressionRunner { Flow visitCallRef(CallRef* curr) { Literals arguments; - Flow flow = self()->generateArguments(curr->operands, arguments); - if (flow.breaking()) { - return flow; - } + self()->generateArguments(curr->operands, arguments); Flow target = self()->getChild(); auto targetRef = target.getSingleValue(); if (targetRef.isNull()) { From f26e8a7c3f97dc2ae381ca33d0135ada3931eb8c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 25 Jul 2025 12:06:44 -0700 Subject: [PATCH 39/39] common --- src/wasm-interpreter.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 559a6fc2bea..02ccbbc5df4 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -417,8 +417,7 @@ class ExpressionRunner : public OverriddenVisitor { // delegate to the Literal::* methods, except we handle traps here. Flow visitUnary(Unary* curr) { - Flow flow = getChild(); - Literal value = flow.getSingleValue(); + auto value = getSingleChild(); switch (curr->op) { case ClzInt32: case ClzInt64: @@ -695,10 +694,8 @@ class ExpressionRunner : public OverriddenVisitor { WASM_UNREACHABLE("invalid op"); } Flow visitBinary(Binary* curr) { - Flow flow = getChild(); - Literal left = flow.getSingleValue(); - flow = getChild(); - Literal right = flow.getSingleValue(); + auto left = getSingleChild(); + auto right = getSingleChild(); assert(curr->left->type.isConcrete() ? left.type == curr->left->type : true); assert(curr->right->type.isConcrete() ? right.type == curr->right->type