@@ -1274,32 +1274,37 @@ struct AsyncifyAddCatchCounters : public Pass {
1274
1274
CountersBuilder builder (*module_);
1275
1275
BranchUtils::BranchTargets branchTargets (func->body );
1276
1276
1277
- // with this walker we will find level of "nesting" for each expression
1278
- // ... - +0
1277
+ // with this walker we will assign count of enclosing catch block to
1278
+ // each expression
1279
+ // ... - 0
1279
1280
// catch
1280
- // ... - + 1
1281
+ // ... - 1
1281
1282
// catch
1282
- // ... - + 2
1283
- std::unordered_map<Expression*, int > expressionNestedLevel ;
1283
+ // ... - 2
1284
+ std::unordered_map<Expression*, int > expressionCatchCount ;
1284
1285
struct NestedLevelWalker
1285
1286
: public PostWalker<NestedLevelWalker,
1286
1287
UnifiedExpressionVisitor<NestedLevelWalker>> {
1287
- std::unordered_map<Expression*, int >* expressionNestedLevel ;
1288
- int nestedLevel = 0 ;
1288
+ std::unordered_map<Expression*, int >* expressionCatchCount ;
1289
+ int catchCount = 0 ;
1289
1290
1290
1291
static void doStartCatch (NestedLevelWalker* self, Expression** currp) {
1291
- self->nestedLevel ++;
1292
+ self->catchCount ++;
1292
1293
}
1293
1294
1294
1295
static void doEndCatch (NestedLevelWalker* self, Expression** currp) {
1295
- self->nestedLevel --;
1296
+ self->catchCount --;
1296
1297
}
1297
1298
1298
1299
static void scan (NestedLevelWalker* self, Expression** currp) {
1299
1300
auto curr = *currp;
1300
1301
if (curr->_id == Expression::Id::TryId) {
1302
+ self->expressionCatchCount ->insert (
1303
+ std::make_pair<>(curr, self->catchCount ));
1301
1304
auto & catchBodies = curr->cast <Try>()->catchBodies ;
1302
1305
for (Index i = 0 ; i < catchBodies.size (); i++) {
1306
+ self->expressionCatchCount ->insert (
1307
+ std::make_pair<>(catchBodies[i], self->catchCount ));
1303
1308
self->pushTask (doEndCatch, currp);
1304
1309
self->pushTask (NestedLevelWalker::scan, &catchBodies[i]);
1305
1310
self->pushTask (doStartCatch, currp);
@@ -1314,146 +1319,153 @@ struct AsyncifyAddCatchCounters : public Pass {
1314
1319
}
1315
1320
1316
1321
void visitExpression (Expression* curr) {
1317
- expressionNestedLevel ->insert (std::make_pair<>(curr, nestedLevel ));
1322
+ expressionCatchCount ->insert (std::make_pair<>(curr, catchCount ));
1318
1323
}
1319
1324
};
1320
1325
NestedLevelWalker nestedLevelWalker;
1321
- nestedLevelWalker.expressionNestedLevel = &expressionNestedLevel ;
1326
+ nestedLevelWalker.expressionCatchCount = &expressionCatchCount ;
1322
1327
nestedLevelWalker.walk (func->body );
1323
1328
1324
- // with this walker we will handle those counters :
1329
+ // with this walker we will handle those changes of counter :
1325
1330
// - entering into catch (= pop) +1
1326
- // - return -N (nested catch count up to root)
1327
- // - break -N (nested catch count up to label)
1331
+ // - return -1
1332
+ // - break -1
1328
1333
// - exiting from catch -1
1329
1334
struct AddCountersWalker : public PostWalker <AddCountersWalker> {
1330
1335
Function* func;
1331
1336
CountersBuilder* builder;
1332
1337
BranchUtils::BranchTargets* branchTargets;
1333
- std::unordered_map<Expression*, int >* expressionNestedLevel;
1334
- int labelNum = 0 ;
1338
+ std::unordered_map<Expression*, int >* expressionCatchCount;
1339
+ int finallyNum = 0 ;
1340
+ int popNum = 0 ;
1341
+
1342
+ int getCatchCount (Expression* expression) {
1343
+ auto it = expressionCatchCount->find (expression);
1344
+ assert (it != expressionCatchCount->end ());
1345
+ return it->second ;
1346
+ }
1335
1347
1336
1348
// Each catch block except catch_all should have pop instruction
1337
- // We increment counter each time when pop happens (= entering catch
1338
- // block)
1349
+ // We increment counter each time when we enter top-level catch block
1339
1350
void visitPop (Pop* pop) {
1340
- replaceCurrent (builder->makeSequence (pop, builder->makeInc ()));
1351
+ if (getCatchCount (pop) == 1 ) {
1352
+ auto name =
1353
+ func->name .toString () + " -pop-" + std::to_string (++popNum);
1354
+ replaceCurrent (
1355
+ builder->makeBlock (name, {pop, builder->makeInc ()}, Type::none));
1356
+ }
1341
1357
}
1342
1358
void visitLocalSet (LocalSet* set) {
1343
1359
auto block = set->value ->dynCast <Block>(); // from visitPop above
1344
- if (block) {
1360
+ if (block && block-> name . hasSubstring ( " -pop- " ) ) {
1345
1361
auto pop = block->list [0 ]->dynCast <Pop>();
1346
- if (pop) {
1347
- set->value = pop;
1348
- replaceCurrent (builder->makeSequence (set, builder-> makeInc ()));
1349
- }
1362
+ assert (pop && getCatchCount (pop) == 1 );
1363
+ set->value = pop;
1364
+ replaceCurrent (builder->makeBlock (
1365
+ block-> name , {set, builder-> makeInc ()}, Type::none));
1350
1366
}
1351
1367
}
1352
1368
1353
- // When return happens we decrement counter on amount of nested catch
1354
- // blocks up to root catch
1369
+ // When return happens we decrement counter on 1, because we account
1370
+ // only top-level catch blocks
1355
1371
// catch
1356
1372
// +1
1357
1373
// catch
1358
- // +1
1359
- // ...
1360
- // -2
1374
+ // ;; not counted
1375
+ // -1
1361
1376
// return
1362
1377
// ...
1363
1378
void visitReturn (Return* ret) {
1364
- auto it = expressionNestedLevel->find (ret);
1365
- assert (it != expressionNestedLevel->end ());
1366
- auto nestedLevel = it->second ;
1367
- if (nestedLevel > 0 ) {
1368
- replaceCurrent (
1369
- builder->makeSequence (builder->makeDec (nestedLevel), ret));
1379
+ if (getCatchCount (ret) > 0 ) {
1380
+ replaceCurrent (builder->makeSequence (builder->makeDec (), ret));
1370
1381
}
1371
1382
}
1372
1383
1373
- // When break happens we decrement counter on amount of nested catch
1374
- // blocks up to label
1384
+ // When break happens we decrement counter only if it goes out
1385
+ // from top-level catch block
1375
1386
void visitBreak (Break* br) {
1376
- auto it = expressionNestedLevel->find (br);
1377
- assert (it != expressionNestedLevel->end ());
1378
- auto nestedLevel = it->second ;
1379
-
1380
1387
Expression* target = branchTargets->getTarget (br->name );
1381
1388
assert (target != nullptr );
1382
-
1383
- it = expressionNestedLevel->find (target);
1384
- assert (it != expressionNestedLevel->end ());
1385
-
1386
- auto amount = nestedLevel - it->second ;
1387
- assert (amount >= 0 );
1388
-
1389
- if (amount > 0 ) {
1389
+ if (getCatchCount (br) > 0 && getCatchCount (target) == 0 ) {
1390
1390
if (br->condition == nullptr ) {
1391
- replaceCurrent (builder->makeSequence (builder->makeDec (amount ), br));
1392
- } else {
1393
- auto decIf = builder-> makeIf (
1394
- br->condition ,
1395
- builder->makeSequence (builder->makeDec (amount ), br),
1396
- br-> value );
1391
+ replaceCurrent (builder->makeSequence (builder->makeDec (), br));
1392
+ } else if (br-> value == nullptr ) {
1393
+ auto decIf =
1394
+ builder-> makeIf ( br->condition ,
1395
+ builder->makeSequence (builder->makeDec (), br),
1396
+ nullptr );
1397
1397
br->condition = nullptr ;
1398
1398
replaceCurrent (decIf);
1399
+ } else {
1400
+ Index newLocal = builder->addVar (func, br->value ->type );
1401
+ auto setLocal = builder->makeLocalSet (newLocal, br->value );
1402
+ auto getLocal = builder->makeLocalGet (newLocal, br->value ->type );
1403
+ auto condition = br->condition ;
1404
+ br->condition = nullptr ;
1405
+ br->value = getLocal;
1406
+ auto decIf =
1407
+ builder->makeIf (condition,
1408
+ builder->makeSequence (builder->makeDec (), br),
1409
+ getLocal);
1410
+ replaceCurrent (builder->makeSequence (setLocal, decIf));
1399
1411
}
1400
1412
}
1401
1413
}
1402
1414
1403
- // Replacing each catch block with try/finally and increase counter for
1404
- // catch_all blocks (not handled by visitPop); dec counter at the end
1405
- // of catch block
1406
- // try {fn}-finally-{label}
1415
+ // Replacing each top-level catch block with try/catch_all(finally) and
1416
+ // increase counter for catch_all blocks (not handled by visitPop); dec
1417
+ // counter at the end of catch block try ({fn}-finally-{label})
1407
1418
// +1
1408
1419
// {catch body}
1409
1420
// -1
1410
- // catch
1421
+ // catch_all
1411
1422
// -1
1412
1423
// rethrow {fn}-finally-{label}
1413
1424
void visitTry (Try* curr) {
1414
- for (size_t i = 0 ; i < curr->catchBodies .size (); ++i) {
1415
- curr->catchBodies [i] =
1416
- addCatchCounters (curr->catchBodies [i], i == curr->catchTags .size ());
1425
+ if (getCatchCount (curr) == 0 ) {
1426
+ for (size_t i = 0 ; i < curr->catchBodies .size (); ++i) {
1427
+ curr->catchBodies [i] = addCatchCounters (
1428
+ curr->catchBodies [i], i == curr->catchTags .size ());
1429
+ }
1417
1430
}
1418
1431
}
1419
1432
Expression* addCatchCounters (Expression* expression, bool catchAll) {
1420
- // catch_all case is not covered by PopWalker
1433
+ auto block = expression->dynCast <Block>();
1434
+ if (block == nullptr ) {
1435
+ block = builder->makeBlock (expression);
1436
+ }
1437
+
1438
+ // catch_all case is not covered by visitPop
1421
1439
if (catchAll) {
1422
- auto block = expression->dynCast <Block>();
1423
- assert (block != nullptr );
1424
1440
block->list .insertAt (0 , builder->makeInc ());
1425
1441
}
1426
1442
1427
1443
// dec counters at the end of catch
1428
- if (expression->type == Type::none) {
1429
- if (auto block = expression->dynCast <Block>()) {
1430
- auto last = block->list [block->list .size () - 1 ];
1431
- if (!last->dynCast <Return>()) {
1432
- block->list .push_back (builder->makeDec ());
1433
- block->finalize ();
1434
- }
1435
- } else {
1436
- WASM_UNREACHABLE (" Unexpected expression type" );
1444
+ if (block->type == Type::none) {
1445
+ auto last = block->list [block->list .size () - 1 ];
1446
+ if (!last->dynCast <Return>()) {
1447
+ block->list .push_back (builder->makeDec ());
1448
+ block->finalize ();
1437
1449
}
1438
1450
}
1439
1451
1440
1452
auto name =
1441
- func->name .toString () + " -finally-" + std::to_string (++labelNum );
1453
+ func->name .toString () + " -finally-" + std::to_string (++finallyNum );
1442
1454
return builder->makeTry (
1443
1455
name,
1444
- expression ,
1456
+ block ,
1445
1457
{},
1446
1458
{builder->makeSequence (builder->makeDec (),
1447
1459
builder->makeRethrow (name))},
1448
- expression ->type );
1460
+ block ->type );
1449
1461
}
1450
1462
};
1451
1463
1452
1464
AddCountersWalker addCountersWalker;
1453
1465
addCountersWalker.func = func;
1454
1466
addCountersWalker.builder = &builder;
1455
1467
addCountersWalker.branchTargets = &branchTargets;
1456
- addCountersWalker.expressionNestedLevel = &expressionNestedLevel ;
1468
+ addCountersWalker.expressionCatchCount = &expressionCatchCount ;
1457
1469
addCountersWalker.walk (func->body );
1458
1470
1459
1471
EHUtils::handleBlockNestedPops (func, *module_);
0 commit comments