Skip to content

Commit 15bfc21

Browse files
Alexander Guryanovcaiiiycuk
Alexander Guryanov
authored andcommitted
refactoring: using Parents to count catch blocks
1 parent 0bd8519 commit 15bfc21

File tree

1 file changed

+42
-74
lines changed

1 file changed

+42
-74
lines changed

src/passes/Asyncify.cpp

+42-74
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,6 @@
170170
// calls, so that you know when to start an asynchronous operation and
171171
// when to propagate results back.
172172
//
173-
// * asyncify_get_catch_counter(): call this to get the current value of the
174-
// internal "__asyncify_catch_counter" variable (only when assertions
175-
// or ignore mode are enabled).
176-
//
177173
// These four functions are exported so that you can call them from the
178174
// outside. If you want to manage things from inside the wasm, then you
179175
// couldn't have called them before they were created by this pass. To work
@@ -251,8 +247,9 @@
251247
//
252248
// --pass-arg=asyncify-ignore-unwind-from-catch
253249
//
254-
// This enables extra check before unwind, if it called from within catch
255-
// block then it silently ignored (-fwasm-exceptions support)
250+
// This enables additional check to be performed before unwinding. In
251+
// cases where the unwind operation is triggered from the catch block,
252+
// it will be silently ignored (-fwasm-exceptions support)
256253
//
257254
// --pass-arg=asyncify-verbose
258255
//
@@ -330,6 +327,7 @@
330327
#include "ir/memory-utils.h"
331328
#include "ir/module-utils.h"
332329
#include "ir/names.h"
330+
#include "ir/parents.h"
333331
#include "ir/utils.h"
334332
#include "pass.h"
335333
#include "support/file.h"
@@ -1154,15 +1152,17 @@ struct AsyncifyFlow : public Pass {
11541152
} else if (doesCall(curr)) {
11551153
results.push_back(makeCallSupport(curr));
11561154
continue;
1157-
} else if (auto* iTry = curr->dynCast<Try>()) {
1155+
} else if (auto* try_ = curr->dynCast<Try>()) {
11581156
if (item.phase == Work::Scan) {
11591157
work.push_back(Work{curr, Work::Finish});
1160-
work.push_back(Work{iTry->body, Work::Scan});
1158+
work.push_back(Work{try_->body, Work::Scan});
1159+
// catchBodies are ignored because we assume that pause/resume will
1160+
// not happen inside them
11611161
continue;
11621162
}
1163-
iTry->body = results.back();
1163+
try_->body = results.back();
11641164
results.pop_back();
1165-
results.push_back(iTry);
1165+
results.push_back(try_);
11661166
continue;
11671167
}
11681168
// We must handle all control flow above, and all things that can change
@@ -1244,7 +1244,8 @@ struct AsyncifyFlow : public Pass {
12441244
}
12451245
};
12461246

1247-
// Add catch block counters to verify that unwind is not called from catch block
1247+
// Add catch block counters to verify that unwind is not called from catch
1248+
// block.
12481249
struct AsyncifyAddCatchCounters : public Pass {
12491250
bool isFunctionParallel() override { return true; }
12501251

@@ -1269,80 +1270,43 @@ struct AsyncifyAddCatchCounters : public Pass {
12691270
makeBinary(SubInt32,
12701271
makeGlobalGet(ASYNCIFY_CATCH_COUNTER, Type::i32),
12711272
makeConst(int32_t(amount))));
1272-
};
1273-
};
1274-
CountersBuilder builder(*module_);
1275-
BranchUtils::BranchTargets branchTargets(func->body);
1276-
1277-
// with this walker we will assign count of enclosing catch block to
1278-
// each expression
1279-
// ... - 0
1280-
// catch
1281-
// ... - 1
1282-
// catch
1283-
// ... - 2
1284-
std::unordered_map<Expression*, int> expressionCatchCount;
1285-
struct NestedLevelWalker
1286-
: public PostWalker<NestedLevelWalker,
1287-
UnifiedExpressionVisitor<NestedLevelWalker>> {
1288-
std::unordered_map<Expression*, int>* expressionCatchCount;
1289-
int catchCount = 0;
1290-
1291-
static void doStartCatch(NestedLevelWalker* self, Expression** currp) {
1292-
self->catchCount++;
1293-
}
1294-
1295-
static void doEndCatch(NestedLevelWalker* self, Expression** currp) {
1296-
self->catchCount--;
1297-
}
1298-
1299-
static void scan(NestedLevelWalker* self, Expression** currp) {
1300-
auto curr = *currp;
1301-
if (curr->_id == Expression::Id::TryId) {
1302-
self->expressionCatchCount->insert(
1303-
std::make_pair<>(curr, self->catchCount));
1304-
auto& catchBodies = curr->cast<Try>()->catchBodies;
1305-
for (Index i = 0; i < catchBodies.size(); i++) {
1306-
self->expressionCatchCount->insert(
1307-
std::make_pair<>(catchBodies[i], self->catchCount));
1308-
self->pushTask(doEndCatch, currp);
1309-
self->pushTask(NestedLevelWalker::scan, &catchBodies[i]);
1310-
self->pushTask(doStartCatch, currp);
1311-
}
1312-
self->pushTask(NestedLevelWalker::scan, &curr->cast<Try>()->body);
1313-
return;
1314-
}
1315-
1316-
PostWalker<NestedLevelWalker,
1317-
UnifiedExpressionVisitor<NestedLevelWalker>>::scan(self,
1318-
currp);
1319-
}
1320-
1321-
void visitExpression(Expression* curr) {
1322-
expressionCatchCount->insert(std::make_pair<>(curr, catchCount));
13231273
}
13241274
};
1325-
NestedLevelWalker nestedLevelWalker;
1326-
nestedLevelWalker.expressionCatchCount = &expressionCatchCount;
1327-
nestedLevelWalker.walk(func->body);
13281275

13291276
// with this walker we will handle those changes of counter:
1330-
// - entering into catch (= pop) +1
1331-
// - return -1
1332-
// - break -1
1333-
// - exiting from catch -1
1277+
// - entering top-level catch (= pop) +1
1278+
// - entering nested catch (= pop) 0 (ignored)
1279+
//
1280+
// - return inside top-level/nested catch -1
1281+
// - return outside top-level/nested catch 0 (ignored)
1282+
//
1283+
// - break target outside of top-level catch -1
1284+
// - break target inside of top-level catch 0 (ignored)
1285+
// - break outside top-level/nested catch 0 (ignored)
1286+
//
1287+
// - exiting from top-level catch -1
1288+
// - exiting from nested catch 0 (ignored)
13341289
struct AddCountersWalker : public PostWalker<AddCountersWalker> {
13351290
Function* func;
13361291
CountersBuilder* builder;
13371292
BranchUtils::BranchTargets* branchTargets;
1338-
std::unordered_map<Expression*, int>* expressionCatchCount;
1293+
Parents* parents;
13391294
int finallyNum = 0;
13401295
int popNum = 0;
13411296

13421297
int getCatchCount(Expression* expression) {
1343-
auto it = expressionCatchCount->find(expression);
1344-
assert(it != expressionCatchCount->end());
1345-
return it->second;
1298+
int catchCount = 0;
1299+
while (expression != func->body) {
1300+
auto parent = parents->getParent(expression);
1301+
if (auto* try_ = parent->dynCast<Try>()) {
1302+
if (try_->body != expression) {
1303+
catchCount++;
1304+
}
1305+
}
1306+
expression = parent;
1307+
}
1308+
1309+
return catchCount;
13461310
}
13471311

13481312
// Each catch block except catch_all should have pop instruction
@@ -1461,11 +1425,15 @@ struct AsyncifyAddCatchCounters : public Pass {
14611425
}
14621426
};
14631427

1428+
Parents parents(func->body);
1429+
CountersBuilder builder(*module_);
1430+
BranchUtils::BranchTargets branchTargets(func->body);
1431+
14641432
AddCountersWalker addCountersWalker;
14651433
addCountersWalker.func = func;
14661434
addCountersWalker.builder = &builder;
14671435
addCountersWalker.branchTargets = &branchTargets;
1468-
addCountersWalker.expressionCatchCount = &expressionCatchCount;
1436+
addCountersWalker.parents = &parents;
14691437
addCountersWalker.walk(func->body);
14701438

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

0 commit comments

Comments
 (0)