Skip to content

Commit 75fa6e3

Browse files
committed
Merge branch 'suspends-effect' into directize-resume
2 parents f3f4698 + 64465af commit 75fa6e3

6 files changed

Lines changed: 34 additions & 58 deletions

File tree

src/ir/effects.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ std::ostream& operator<<(std::ostream& o, const EffectAnalyzer& effects) {
9696
if (effects.throws_) {
9797
o << "throws_\n";
9898
}
99-
if (effects.suspends_) {
99+
if (effects.suspends) {
100100
o << "suspends_\n";
101101
}
102102
if (effects.tryDepth) {

src/ir/effects.h

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include "ir/intrinsics.h"
2424
#include "pass.h"
2525
#include "support/name.h"
26-
#include "support/utilities.h"
2726
#include "wasm-traversal.h"
2827
#include "wasm-type.h"
2928
#include "wasm.h"
@@ -44,7 +43,7 @@ class EffectAnalyzer {
4443
readsMutableArray(false), writesArray(false),
4544
readsSharedMutableArray(false), writesSharedArray(false), trap(false),
4645
implicitTrap(false), throws_(false), danglingPop(false),
47-
mayNotReturn(false), hasReturnCallThrow(false), suspends_(false),
46+
mayNotReturn(false), hasReturnCallThrow(false), suspends(false),
4847
module(module), features(module.features) {}
4948

5049
EffectAnalyzer(const PassOptions& passOptions,
@@ -138,7 +137,7 @@ class EffectAnalyzer {
138137
// more here.)
139138
bool hasReturnCallThrow : 1;
140139

141-
bool suspends_ : 1;
140+
bool suspends : 1;
142141

143142
const Module& module;
144143
FeatureSet features;
@@ -230,7 +229,7 @@ class EffectAnalyzer {
230229
return calls || readsSharedMutableArray || writesSharedArray;
231230
}
232231
bool throws() const { return throws_ || !delegateTargets.empty(); }
233-
bool suspends() const { return suspends_; }
232+
234233
// Check whether this may transfer control flow to somewhere outside of this
235234
// expression (aside from just flowing out normally). That includes a break,
236235
// a throw (if the throw is not known to be caught inside this expression;
@@ -240,25 +239,7 @@ class EffectAnalyzer {
240239
// transferred inside the function, but this expression does not know that),
241240
// or a suspension.
242241
bool transfersControlFlow() const {
243-
return branchesOut || throws() || hasExternalBreakTargets() || suspends();
244-
}
245-
246-
// Explicitly marks all global mutable state as clobbered (read and written).
247-
void clobbersGlobalState() {
248-
readsMemory = true;
249-
writesMemory = true;
250-
readsSharedMemory = true;
251-
writesSharedMemory = true;
252-
readsTable = true;
253-
writesTable = true;
254-
readsMutableStruct = true;
255-
writesStruct = true;
256-
readsSharedMutableStruct = true;
257-
writesSharedStruct = true;
258-
readsMutableArray = true;
259-
writesArray = true;
260-
readsSharedMutableArray = true;
261-
writesSharedArray = true;
242+
return branchesOut || suspends || throws() || hasExternalBreakTargets();
262243
}
263244

264245
// Changes something in globally-stored state.
@@ -286,7 +267,7 @@ class EffectAnalyzer {
286267
bool hasNonTrapSideEffects() const {
287268
return localsWritten.size() > 0 || danglingPop || writesGlobalState() ||
288269
throws() || transfersControlFlow() || hasSynchronization() ||
289-
mayNotReturn || suspends();
270+
mayNotReturn;
290271
}
291272

292273
bool hasSideEffects() const { return trap || hasNonTrapSideEffects(); }
@@ -502,7 +483,7 @@ class EffectAnalyzer {
502483
danglingPop = danglingPop || other.danglingPop;
503484
mayNotReturn = mayNotReturn || other.mayNotReturn;
504485
hasReturnCallThrow = hasReturnCallThrow || other.hasReturnCallThrow;
505-
suspends_ = suspends_ || other.suspends_;
486+
suspends = suspends || other.suspends;
506487
readOrder = std::max(readOrder, other.readOrder);
507488
writeOrder = std::max(writeOrder, other.writeOrder);
508489

@@ -1296,8 +1277,8 @@ class EffectAnalyzer {
12961277
void visitSuspend(Suspend* curr) {
12971278
// Suspending transfers control to an enclosing handler and executes
12981279
// arbitrary other code before we may resume here.
1299-
parent.suspends_ = true;
1300-
parent.clobbersGlobalState();
1280+
parent.suspends = true;
1281+
parent.calls = true;
13011282
if (parent.features.hasExceptionHandling() && parent.tryDepth == 0) {
13021283
parent.throws_ = true;
13031284
}
@@ -1397,7 +1378,7 @@ class EffectAnalyzer {
13971378
// If stack switching is enabled and we don't have global effects
13981379
// information, assume that the call target may suspend.
13991380
if (parent.features.hasStackSwitching()) {
1400-
parent.suspends_ = true;
1381+
parent.suspends = true;
14011382
}
14021383
}
14031384
};
@@ -1489,7 +1470,7 @@ class EffectAnalyzer {
14891470
if (danglingPop) {
14901471
effects |= SideEffects::DanglingPop;
14911472
}
1492-
if (suspends_) {
1473+
if (suspends) {
14931474
effects |= SideEffects::Suspends;
14941475
}
14951476
return effects;
@@ -1507,7 +1488,7 @@ class EffectAnalyzer {
15071488
breakTargets.clear();
15081489
throws_ = false;
15091490
delegateTargets.clear();
1510-
suspends_ = false;
1491+
suspends = false;
15111492
assert(!transfersControlFlow());
15121493
}
15131494

src/passes/GlobalEffects.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ std::map<Function*, FuncInfo> analyzeFuncs(Module& module,
143143
// well. If we see something else that throws or suspends, below, then
144144
// we'll note that there.
145145
funcInfo.effects->throws_ = false;
146-
funcInfo.effects->suspends_ = false;
146+
funcInfo.effects->suspends = false;
147147

148148
struct CallScanner
149149
: public PostWalker<CallScanner,
@@ -188,8 +188,8 @@ std::map<Function*, FuncInfo> analyzeFuncs(Module& module,
188188
if (effects.throws_ && funcInfo.effects) {
189189
funcInfo.effects->throws_ = true;
190190
}
191-
if (effects.suspends_ && funcInfo.effects) {
192-
funcInfo.effects->suspends_ = true;
191+
if (effects.suspends && funcInfo.effects) {
192+
funcInfo.effects->suspends = true;
193193
}
194194
}
195195
}

src/passes/OptimizeInstructions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1505,7 +1505,7 @@ struct OptimizeInstructions
15051505
return;
15061506
}
15071507

1508-
if (!target->effects || target->effects->suspends()) {
1508+
if (!target->effects || target->effects->suspends) {
15091509
return;
15101510
}
15111511

test/gtest/effects.cpp

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -54,31 +54,26 @@ TEST_F(EffectAnalyzerTest, Suspend) {
5454
EffectAnalyzer effects(options, wasm, func->body);
5555

5656
// Suspension detection
57-
EXPECT_TRUE(effects.suspends());
57+
EXPECT_TRUE(effects.suspends);
5858
EXPECT_THAT(&effects, Suspends());
5959
EXPECT_TRUE(effects.getSideEffects() & EffectAnalyzer::SideEffects::Suspends);
6060

61-
// Decoupled from call graph edges
62-
EXPECT_FALSE(effects.calls);
63-
EXPECT_THAT(&effects, Not(Calls()));
64-
65-
// Clobbers all global mutable state
66-
EXPECT_TRUE(effects.readsMemory);
67-
EXPECT_TRUE(effects.writesMemory);
68-
EXPECT_TRUE(effects.readsSharedMemory);
69-
EXPECT_TRUE(effects.writesSharedMemory);
70-
EXPECT_TRUE(effects.readsTable);
71-
EXPECT_TRUE(effects.writesTable);
72-
EXPECT_TRUE(effects.readsMutableStruct);
73-
EXPECT_TRUE(effects.writesStruct);
74-
EXPECT_TRUE(effects.readsSharedMutableStruct);
75-
EXPECT_TRUE(effects.writesSharedStruct);
76-
EXPECT_TRUE(effects.readsMutableArray);
77-
EXPECT_TRUE(effects.writesArray);
78-
EXPECT_TRUE(effects.readsSharedMutableArray);
79-
EXPECT_TRUE(effects.writesSharedArray);
61+
// Suspending executes arbitrary other code in the handler before resuming,
62+
// modeled as a call.
63+
EXPECT_TRUE(effects.calls);
64+
EXPECT_THAT(&effects, Calls());
65+
66+
// Accesses all global mutable state via calls
67+
EXPECT_TRUE(effects.accessesMemory());
68+
EXPECT_TRUE(effects.accessesSharedMemory());
69+
EXPECT_TRUE(effects.accessesTable());
70+
EXPECT_TRUE(effects.accessesMutableStruct());
71+
EXPECT_TRUE(effects.accessesSharedMutableStruct());
72+
EXPECT_TRUE(effects.accessesArray());
73+
EXPECT_TRUE(effects.accessesSharedArray());
8074
EXPECT_TRUE(effects.writesGlobalState());
8175
EXPECT_TRUE(effects.readsMutableGlobalState());
76+
EXPECT_TRUE(effects.accessesSharedGlobalState());
8277

8378
// Control flow & side effect queries
8479
EXPECT_TRUE(effects.transfersControlFlow());
@@ -107,12 +102,12 @@ TEST_F(EffectAnalyzerTest, UnknownCall) {
107102
// suspension.
108103
wasm.features.setStackSwitching(true);
109104
EffectAnalyzer effectsWithStackSwitch(options, wasm, caller->body);
110-
EXPECT_TRUE(effectsWithStackSwitch.suspends());
105+
EXPECT_TRUE(effectsWithStackSwitch.suspends);
111106

112107
// With stack switching disabled, calls do not suspend.
113108
wasm.features.setStackSwitching(false);
114109
EffectAnalyzer effectsWithoutStackSwitch(options, wasm, caller->body);
115-
EXPECT_FALSE(effectsWithoutStackSwitch.suspends());
110+
EXPECT_FALSE(effectsWithoutStackSwitch.suspends);
116111
}
117112

118113
} // anonymous namespace

test/gtest/matchers/effects.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ MATCHER(Throws, "") { return arg->throws_; }
4545
MATCHER(DanglingPop, "") { return arg->danglingPop; }
4646
MATCHER(MayNotReturn, "") { return arg->mayNotReturn; }
4747
MATCHER(HasReturnCallThrow, "") { return arg->hasReturnCallThrow; }
48-
MATCHER(Suspends, "") { return arg->suspends(); }
48+
MATCHER(Suspends, "") { return arg->suspends; }
4949

5050
} // namespace wasm
5151

0 commit comments

Comments
 (0)