From 7126a43e9e1cea50d3534b50d4554f4a18cd6e14 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Oct 2021 12:14:49 -0700 Subject: [Wasm GC] Take advantage of immutable struct fields in effects.h (#4240) This is the easy part of using immutability more: Just note immutable fields as such when we read from them, and then a write to a struct does not interfere with such reads. That is, only a read from a mutable field can notice the effect of a write. --- src/ir/effects.h | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/ir/effects.h b/src/ir/effects.h index 3ccffb6f5..7074df755 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -79,7 +79,8 @@ public: bool writesTable = false; // TODO: More specific type-based alias analysis, and not just at the // struct/array level. - bool readsStruct = false; + bool readsMutableStruct = false; + bool readsImmutableStruct = false; bool writesStruct = false; bool readsArray = false; bool writesArray = false; @@ -132,7 +133,12 @@ public: } bool accessesMemory() const { return calls || readsMemory || writesMemory; } bool accessesTable() const { return calls || readsTable || writesTable; } - bool accessesStruct() const { return calls || readsStruct || writesStruct; } + bool accessesMutableStruct() const { + return calls || readsMutableStruct || writesStruct; + } + bool accessesStruct() const { + return accessesMutableStruct() || readsImmutableStruct; + } bool accessesArray() const { return calls || readsArray || writesArray; } // Check whether this may transfer control flow to somewhere outside of this // expression (aside from just flowing out normally). That includes a break @@ -151,8 +157,9 @@ public: writesStruct || writesArray || isAtomic || calls; } bool readsGlobalState() const { - return globalsRead.size() || readsMemory || readsTable || readsStruct || - readsArray || isAtomic || calls; + return globalsRead.size() || readsMemory || readsTable || + readsMutableStruct || readsImmutableStruct || readsArray || + isAtomic || calls; } bool hasNonTrapSideEffects() const { @@ -203,8 +210,8 @@ public: ((other.writesMemory || other.calls) && accessesMemory()) || ((writesTable || calls) && other.accessesTable()) || ((other.writesTable || other.calls) && accessesTable()) || - ((writesStruct || calls) && other.accessesStruct()) || - ((other.writesStruct || other.calls) && accessesStruct()) || + ((writesStruct || calls) && other.accessesMutableStruct()) || + ((other.writesStruct || other.calls) && accessesMutableStruct()) || ((writesArray || calls) && other.accessesArray()) || ((other.writesArray || other.calls) && accessesArray()) || (danglingPop || other.danglingPop)) { @@ -268,7 +275,8 @@ public: writesMemory = writesMemory || other.writesMemory; readsTable = readsTable || other.readsTable; writesTable = writesTable || other.writesTable; - readsStruct = readsStruct || other.readsStruct; + readsMutableStruct = readsMutableStruct || other.readsMutableStruct; + readsImmutableStruct = readsImmutableStruct || other.readsImmutableStruct; writesStruct = writesStruct || other.writesStruct; readsArray = readsArray || other.readsArray; writesArray = writesArray || other.writesArray; @@ -650,7 +658,17 @@ private: void visitRttSub(RttSub* curr) {} void visitStructNew(StructNew* curr) {} void visitStructGet(StructGet* curr) { - parent.readsStruct = true; + if (curr->ref->type == Type::unreachable) { + return; + } + if (curr->ref->type.getHeapType() + .getStruct() + .fields[curr->index] + .mutable_ == Mutable) { + parent.readsMutableStruct = true; + } else { + parent.readsImmutableStruct = true; + } // traps when the arg is null if (curr->ref->type.isNullable()) { parent.implicitTrap = true; -- cgit v1.2.3