Skip to content

Commit bc7e5d1

Browse files
Alexander Guryanovcaiiiycuk
Alexander Guryanov
authored andcommitted
refactoring: using Parents to count catch blocks
1 parent b909ada commit bc7e5d1

File tree

1 file changed

+43
-79
lines changed

1 file changed

+43
-79
lines changed

src/passes/Asyncify.cpp

+43-79
Original file line numberDiff line numberDiff line change
@@ -171,15 +171,7 @@
171171
// calls, so that you know when to start an asynchronous operation and
172172
// when to propagate results back.
173173
//
174-
// * asyncify_get_catch_counter(): call this to get the current value of the
175-
// internal "__asyncify_catch_counter" variable (only when assertions
176-
// or ignore mode are enabled).
177-
//
178-
// * asyncify_get_catch_counter(): call this to get the current value of the
179-
// internal "__asyncify_catch_counter" variable (only when assertions
180-
// or ignore mode are enabled).
181-
//
182-
// These six functions are exported so that you can call them from the
174+
// These five functions are exported so that you can call them from the
183175
// outside. If you want to manage things from inside the wasm, then you
184176
// couldn't have called them before they were created by this pass. To work
185177
// around that, you can create imports to asyncify.start_unwind,
@@ -256,8 +248,9 @@
256248
//
257249
// --pass-arg=asyncify-ignore-unwind-from-catch
258250
//
259-
// This enables extra check before unwind, if it called from within catch
260-
// block then it silently ignored (-fwasm-exceptions support)
251+
// This enables additional check to be performed before unwinding. In
252+
// cases where the unwind operation is triggered from the catch block,
253+
// it will be silently ignored (-fwasm-exceptions support)
261254
//
262255
// --pass-arg=asyncify-verbose
263256
//
@@ -335,6 +328,7 @@
335328
#include "ir/memory-utils.h"
336329
#include "ir/module-utils.h"
337330
#include "ir/names.h"
331+
#include "ir/parents.h"
338332
#include "ir/utils.h"
339333
#include "pass.h"
340334
#include "support/file.h"
@@ -1166,15 +1160,17 @@ struct AsyncifyFlow : public Pass {
11661160
// here as well.
11671161
results.push_back(makeCallSupport(curr));
11681162
continue;
1169-
} else if (auto* iTry = curr->dynCast<Try>()) {
1163+
} else if (auto* try_ = curr->dynCast<Try>()) {
11701164
if (item.phase == Work::Scan) {
11711165
work.push_back(Work{curr, Work::Finish});
1172-
work.push_back(Work{iTry->body, Work::Scan});
1166+
work.push_back(Work{try_->body, Work::Scan});
1167+
// catchBodies are ignored because we assume that pause/resume will
1168+
// not happen inside them
11731169
continue;
11741170
}
1175-
iTry->body = results.back();
1171+
try_->body = results.back();
11761172
results.pop_back();
1177-
results.push_back(iTry);
1173+
results.push_back(try_);
11781174
continue;
11791175
}
11801176
// We must handle all control flow above, and all things that can change
@@ -1256,7 +1252,8 @@ struct AsyncifyFlow : public Pass {
12561252
}
12571253
};
12581254

1259-
// Add catch block counters to verify that unwind is not called from catch block
1255+
// Add catch block counters to verify that unwind is not called from catch
1256+
// block.
12601257
struct AsyncifyAddCatchCounters : public Pass {
12611258
bool isFunctionParallel() override { return true; }
12621259

@@ -1281,80 +1278,43 @@ struct AsyncifyAddCatchCounters : public Pass {
12811278
makeBinary(SubInt32,
12821279
makeGlobalGet(ASYNCIFY_CATCH_COUNTER, Type::i32),
12831280
makeConst(int32_t(amount))));
1284-
};
1285-
};
1286-
CountersBuilder builder(*module_);
1287-
BranchUtils::BranchTargets branchTargets(func->body);
1288-
1289-
// with this walker we will assign count of enclosing catch block to
1290-
// each expression
1291-
// ... - 0
1292-
// catch
1293-
// ... - 1
1294-
// catch
1295-
// ... - 2
1296-
std::unordered_map<Expression*, int> expressionCatchCount;
1297-
struct NestedLevelWalker
1298-
: public PostWalker<NestedLevelWalker,
1299-
UnifiedExpressionVisitor<NestedLevelWalker>> {
1300-
std::unordered_map<Expression*, int>* expressionCatchCount;
1301-
int catchCount = 0;
1302-
1303-
static void doStartCatch(NestedLevelWalker* self, Expression** currp) {
1304-
self->catchCount++;
1305-
}
1306-
1307-
static void doEndCatch(NestedLevelWalker* self, Expression** currp) {
1308-
self->catchCount--;
1309-
}
1310-
1311-
static void scan(NestedLevelWalker* self, Expression** currp) {
1312-
auto curr = *currp;
1313-
if (curr->_id == Expression::Id::TryId) {
1314-
self->expressionCatchCount->insert(
1315-
std::make_pair<>(curr, self->catchCount));
1316-
auto& catchBodies = curr->cast<Try>()->catchBodies;
1317-
for (Index i = 0; i < catchBodies.size(); i++) {
1318-
self->expressionCatchCount->insert(
1319-
std::make_pair<>(catchBodies[i], self->catchCount));
1320-
self->pushTask(doEndCatch, currp);
1321-
self->pushTask(NestedLevelWalker::scan, &catchBodies[i]);
1322-
self->pushTask(doStartCatch, currp);
1323-
}
1324-
self->pushTask(NestedLevelWalker::scan, &curr->cast<Try>()->body);
1325-
return;
1326-
}
1327-
1328-
PostWalker<NestedLevelWalker,
1329-
UnifiedExpressionVisitor<NestedLevelWalker>>::scan(self,
1330-
currp);
1331-
}
1332-
1333-
void visitExpression(Expression* curr) {
1334-
expressionCatchCount->insert(std::make_pair<>(curr, catchCount));
13351281
}
13361282
};
1337-
NestedLevelWalker nestedLevelWalker;
1338-
nestedLevelWalker.expressionCatchCount = &expressionCatchCount;
1339-
nestedLevelWalker.walk(func->body);
13401283

13411284
// with this walker we will handle those changes of counter:
1342-
// - entering into catch (= pop) +1
1343-
// - return -1
1344-
// - break -1
1345-
// - exiting from catch -1
1285+
// - entering top-level catch (= pop) +1
1286+
// - entering nested catch (= pop) 0 (ignored)
1287+
//
1288+
// - return inside top-level/nested catch -1
1289+
// - return outside top-level/nested catch 0 (ignored)
1290+
//
1291+
// - break target outside of top-level catch -1
1292+
// - break target inside of top-level catch 0 (ignored)
1293+
// - break outside top-level/nested catch 0 (ignored)
1294+
//
1295+
// - exiting from top-level catch -1
1296+
// - exiting from nested catch 0 (ignored)
13461297
struct AddCountersWalker : public PostWalker<AddCountersWalker> {
13471298
Function* func;
13481299
CountersBuilder* builder;
13491300
BranchUtils::BranchTargets* branchTargets;
1350-
std::unordered_map<Expression*, int>* expressionCatchCount;
1301+
Parents* parents;
13511302
int finallyNum = 0;
13521303
int popNum = 0;
13531304

13541305
int getCatchCount(Expression* expression) {
1355-
auto it = expressionCatchCount->find(expression);
1356-
assert(it != expressionCatchCount->end());
1357-
return it->second;
1306+
int catchCount = 0;
1307+
while (expression != func->body) {
1308+
auto parent = parents->getParent(expression);
1309+
if (auto* try_ = parent->dynCast<Try>()) {
1310+
if (try_->body != expression) {
1311+
catchCount++;
1312+
}
1313+
}
1314+
expression = parent;
1315+
}
1316+
1317+
return catchCount;
13581318
}
13591319

13601320
// Each catch block except catch_all should have pop instruction
@@ -1473,11 +1433,15 @@ struct AsyncifyAddCatchCounters : public Pass {
14731433
}
14741434
};
14751435

1436+
Parents parents(func->body);
1437+
CountersBuilder builder(*module_);
1438+
BranchUtils::BranchTargets branchTargets(func->body);
1439+
14761440
AddCountersWalker addCountersWalker;
14771441
addCountersWalker.func = func;
14781442
addCountersWalker.builder = &builder;
14791443
addCountersWalker.branchTargets = &branchTargets;
1480-
addCountersWalker.expressionCatchCount = &expressionCatchCount;
1444+
addCountersWalker.parents = &parents;
14811445
addCountersWalker.walk(func->body);
14821446

14831447
EHUtils::handleBlockNestedPops(func, *module_);

0 commit comments

Comments
 (0)