@@ -219,6 +219,9 @@ class EffectAnalyzer {
219219 return mutableGlobalsRead.size () || readsMemory || readsTable ||
220220 readsMutableStruct || readsArray || isAtomic || calls;
221221 }
222+ bool accessesGlobalState () const {
223+ return readsMutableGlobalState () || writesGlobalState ();
224+ }
222225
223226 bool hasNonTrapSideEffects () const {
224227 return localsWritten.size () > 0 || danglingPop || writesGlobalState () ||
@@ -305,10 +308,10 @@ class EffectAnalyzer {
305308 (danglingPop || other.danglingPop )) {
306309 return true ;
307310 }
308- // All atomics are sequentially consistent for now, and ordered wrt other
309- // memory references .
310- if ((isAtomic && other.accessesMemory ()) ||
311- (other.isAtomic && accessesMemory ())) {
311+ // We model all atomics as sequentially consistent for now. They are ordered
312+ // wrt other loads and stores from anything, not just memories .
313+ if ((isAtomic && other.accessesGlobalState ()) ||
314+ (other.isAtomic && accessesGlobalState ())) {
312315 return true ;
313316 }
314317 for (auto local : localsWritten) {
@@ -611,24 +614,26 @@ class EffectAnalyzer {
611614 }
612615 void visitLoad (Load* curr) {
613616 parent.readsMemory = true ;
614- parent.isAtomic |= curr->isAtomic ();
617+ parent.isAtomic |=
618+ curr->isAtomic () && parent.module .getMemory (curr->memory )->shared ;
615619 parent.implicitTrap = true ;
616620 }
617621 void visitStore (Store* curr) {
618622 parent.writesMemory = true ;
619- parent.isAtomic |= curr->isAtomic ();
623+ parent.isAtomic |=
624+ curr->isAtomic () && parent.module .getMemory (curr->memory )->shared ;
620625 parent.implicitTrap = true ;
621626 }
622627 void visitAtomicRMW (AtomicRMW* curr) {
623628 parent.readsMemory = true ;
624629 parent.writesMemory = true ;
625- parent.isAtomic = true ;
630+ parent.isAtomic |= parent. module . getMemory (curr-> memory )-> shared ;
626631 parent.implicitTrap = true ;
627632 }
628633 void visitAtomicCmpxchg (AtomicCmpxchg* curr) {
629634 parent.readsMemory = true ;
630635 parent.writesMemory = true ;
631- parent.isAtomic = true ;
636+ parent.isAtomic |= parent. module . getMemory (curr-> memory )-> shared ;
632637 parent.implicitTrap = true ;
633638 }
634639 void visitAtomicWait (AtomicWait* curr) {
@@ -754,8 +759,9 @@ class EffectAnalyzer {
754759 // memory.size accesses the size of the memory, and thus can be modeled as
755760 // reading memory
756761 parent.readsMemory = true ;
757- // Atomics are sequentially consistent with memory.size.
758- parent.isAtomic = true ;
762+ // Synchronizes when memory.grow on other threads, but only when operating
763+ // on shared memories.
764+ parent.isAtomic |= parent.module .getMemory (curr->memory )->shared ;
759765 }
760766 void visitMemoryGrow (MemoryGrow* curr) {
761767 // TODO: find out if calls is necessary here
@@ -765,8 +771,9 @@ class EffectAnalyzer {
765771 // addresses, and just a read operation in the failure case
766772 parent.readsMemory = true ;
767773 parent.writesMemory = true ;
768- // Atomics are also sequentially consistent with memory.grow.
769- parent.isAtomic = true ;
774+ // Synchronizes with memory.size on other threads, but only when operating
775+ // on shared memories.
776+ parent.isAtomic |= parent.module .getMemory (curr->memory )->shared ;
770777 }
771778 void visitRefNull (RefNull* curr) {}
772779 void visitRefIsNull (RefIsNull* curr) {}
@@ -910,18 +917,8 @@ class EffectAnalyzer {
910917 if (curr->ref ->type .isNullable ()) {
911918 parent.implicitTrap = true ;
912919 }
913- switch (curr->order ) {
914- case MemoryOrder::Unordered:
915- break ;
916- case MemoryOrder::SeqCst:
917- // Synchronizes with other threads.
918- parent.isAtomic = true ;
919- break ;
920- case MemoryOrder::AcqRel:
921- // Only synchronizes if other threads can read the field.
922- parent.isAtomic = curr->ref ->type .getHeapType ().isShared ();
923- break ;
924- }
920+ parent.isAtomic |=
921+ curr->isAtomic () && curr->ref ->type .getHeapType ().isShared ();
925922 }
926923 void visitStructSet (StructSet* curr) {
927924 if (curr->ref ->type .isNull ()) {
@@ -933,9 +930,8 @@ class EffectAnalyzer {
933930 if (curr->ref ->type .isNullable ()) {
934931 parent.implicitTrap = true ;
935932 }
936- if (curr->order != MemoryOrder::Unordered) {
937- parent.isAtomic = true ;
938- }
933+ parent.isAtomic |=
934+ curr->isAtomic () && curr->ref ->type .getHeapType ().isShared ();
939935 }
940936 void visitStructRMW (StructRMW* curr) {
941937 if (curr->ref ->type .isNull ()) {
@@ -1037,6 +1033,8 @@ class EffectAnalyzer {
10371033 parent.readsArray = true ;
10381034 // traps when the arg is null or the index out of bounds
10391035 parent.implicitTrap = true ;
1036+ parent.isAtomic |=
1037+ curr->isAtomic () && curr->ref ->type .getHeapType ().isShared ();
10401038 }
10411039 void visitArraySet (ArraySet* curr) {
10421040 if (curr->ref ->type .isNull ()) {
@@ -1046,6 +1044,8 @@ class EffectAnalyzer {
10461044 parent.writesArray = true ;
10471045 // traps when the arg is null or the index out of bounds
10481046 parent.implicitTrap = true ;
1047+ parent.isAtomic |=
1048+ curr->isAtomic () && curr->ref ->type .getHeapType ().isShared ();
10491049 }
10501050 void visitArrayLen (ArrayLen* curr) {
10511051 if (curr->ref ->type .isNull ()) {
0 commit comments