Skip to content

Commit 00da10f

Browse files
jakobbotschdavidwrighton
authored andcommitted
Fix incorrect resume BB insertion
In the EH case, we were splitting up the resumption BB and its successor by inserting new resumption BBs. Also add a bunch of logging.
1 parent 9dce32d commit 00da10f

File tree

2 files changed

+42
-16
lines changed

2 files changed

+42
-16
lines changed

src/coreclr/jit/async.cpp

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ void Async2Transformation::Transform(
272272
#ifdef DEBUG
273273
if (m_comp->verbose)
274274
{
275-
printf("Processing call [%06u]\n", Compiler::dspTreeID(call));
275+
printf("Processing call [%06u] in " FMT_BB "\n", Compiler::dspTreeID(call), block->bbNum);
276276
printf(" %zu live LIR edges\n", defs.size());
277277

278278
if (defs.size() > 0)
@@ -397,6 +397,7 @@ void Async2Transformation::Transform(
397397
// (-1 in the tier0 version):
398398
if (m_comp->doesMethodHavePatchpoints() || m_comp->opts.IsOSR())
399399
{
400+
JITDUMP(" Method %s; keeping an IL offset at the beginning of non-GC data\n", m_comp->doesMethodHavePatchpoints() ? "has patchpoints" : "is an OSR method");
400401
dataSize += sizeof(int);
401402
}
402403

@@ -415,6 +416,8 @@ void Async2Transformation::Transform(
415416
returnInGCData = varTypeIsGC(call->gtReturnType);
416417
}
417418

419+
JITDUMP(" Will store return of type %s, size %u in %sGC data\n", call->gtReturnType == TYP_STRUCT ? returnStructLayout->GetClassName() : varTypeName(call->gtReturnType), returnSize, returnInGCData ? "" : "non-");
420+
418421
assert((returnSize > 0) == (call->gtReturnType != TYP_VOID));
419422

420423
// The return value is always stored:
@@ -431,11 +434,16 @@ void Async2Transformation::Transform(
431434
{
432435
returnValDataOffset = dataSize;
433436
dataSize += returnSize;
437+
438+
JITDUMP(" at offset %u\n", returnValDataOffset);
434439
}
435440

436441
unsigned exceptionGCDataIndex = UINT_MAX;
437442
if (block->hasTryIndex())
443+
{
438444
exceptionGCDataIndex = gcRefsCount++;
445+
JITDUMP(" " FMT_BB " is in try region %u; exception will be at GC@+%02u in GC data\n", block->bbNum, exceptionGCDataIndex);
446+
}
439447

440448
for (LiveLocalInfo& inf : m_liveLocals)
441449
{
@@ -518,6 +526,8 @@ void Async2Transformation::Transform(
518526
BasicBlock* remainder = m_comp->fgSplitBlockAfterNode(block, jtrue);
519527
*pRemainder = remainder;
520528

529+
JITDUMP(" Remainder is " FMT_BB "\n", remainder->bbNum);
530+
521531
assert(block->KindIs(BBJ_NONE) && block->NextIs(remainder));
522532

523533
if (m_lastSuspensionBB == nullptr)
@@ -531,6 +541,8 @@ void Async2Transformation::Transform(
531541
retBB->clearHndIndex();
532542
m_lastSuspensionBB = retBB;
533543

544+
JITDUMP(" Created suspension " FMT_BB " for state %u\n", retBB->bbNum, stateNum);
545+
534546
block->SetJumpKindAndTarget(BBJ_COND, retBB DEBUGARG(m_comp));
535547

536548
m_comp->fgAddRefPred(retBB, block);
@@ -733,23 +745,19 @@ void Async2Transformation::Transform(
733745
GenTree* ret = m_comp->gtNewOperNode(GT_RETURN_SUSPEND, TYP_VOID, newContinuation);
734746
LIR::AsRange(retBB).InsertAtEnd(newContinuation, ret);
735747

736-
JITDUMP(" Created suspension BB " FMT_BB "\n", retBB->bbNum);
737-
738-
BasicBlock* prevResumptionBB;
739-
if (m_resumptionBBs.size() == 0)
740-
{
741-
prevResumptionBB = m_comp->fgLastBBInMainFunction();
742-
}
743-
else
748+
if (m_lastResumptionBB == nullptr)
744749
{
745-
prevResumptionBB = m_resumptionBBs[m_resumptionBBs.size() - 1];
750+
m_lastResumptionBB = m_comp->fgLastBBInMainFunction();
746751
}
747752

748-
BasicBlock* resumeBB = m_comp->fgNewBBafter(BBJ_ALWAYS, prevResumptionBB, true, remainder);
753+
BasicBlock* resumeBB = m_comp->fgNewBBafter(BBJ_ALWAYS, m_lastResumptionBB, true, remainder);
749754
resumeBB->bbSetRunRarely();
750755
resumeBB->clearTryIndex();
751756
resumeBB->clearHndIndex();
752757
resumeBB->bbFlags |= BBF_ASYNC_RESUMPTION;
758+
m_lastResumptionBB = resumeBB;
759+
760+
JITDUMP(" Created resumption " FMT_BB " for state %u\n", resumeBB->bbNum, stateNum);
753761

754762
m_comp->fgAddRefPred(remainder, resumeBB);
755763

@@ -876,16 +884,23 @@ void Async2Transformation::Transform(
876884
BasicBlock* storeResultBB = resumeBB;
877885
if (exceptionGCDataIndex != UINT_MAX)
878886
{
887+
JITDUMP(" We need to rethrow an exception\n");
879888
BasicBlock* rethrowExceptionBB = m_comp->fgNewBBinRegion(BBJ_THROW, block, /* jumpDest */ nullptr,
880889
/* runRarely */ true, /* insertAtEnd */ true);
890+
JITDUMP(" Created " FMT_BB " to rethrow exception on resumption\n", rethrowExceptionBB->bbNum);
881891
resumeBB->SetJumpKindAndTarget(BBJ_COND, rethrowExceptionBB DEBUGARG(m_comp));
882892
m_comp->fgAddRefPred(rethrowExceptionBB, resumeBB);
883893
m_comp->fgRemoveRefPred(remainder, resumeBB);
884894

895+
JITDUMP(" Resumption " FMT_BB " becomes BBJ_COND to check for non-null exception\n", resumeBB->bbNum);
896+
885897
storeResultBB = m_comp->fgNewBBafter(BBJ_ALWAYS, resumeBB, true, remainder);
898+
JITDUMP(" Created " FMT_BB " to store result when resuming with no exception\n", storeResultBB->bbNum);
886899
m_comp->fgAddRefPred(remainder, storeResultBB);
887900
m_comp->fgAddRefPred(storeResultBB, resumeBB);
888901

902+
m_lastResumptionBB = storeResultBB;
903+
889904
// Check if we have an exception.
890905
unsigned exceptionLclNum = GetExceptionVar();
891906
GenTree* objectArr = m_comp->gtNewLclvNode(resumeObjectArrLclNum, TYP_REF);
@@ -909,7 +924,7 @@ void Async2Transformation::Transform(
909924
LIR::AsRange(rethrowExceptionBB).InsertAtEnd(LIR::SeqTree(m_comp, rethrowException));
910925

911926
storeResultBB->bbFlags |= BBF_ASYNC_RESUMPTION;
912-
JITDUMP("Added " FMT_BB " to rethrow exception at suspension point\n", rethrowExceptionBB->bbNum);
927+
JITDUMP(" Added " FMT_BB " to rethrow exception at suspension point\n", rethrowExceptionBB->bbNum);
913928
}
914929
}
915930

@@ -1022,7 +1037,6 @@ void Async2Transformation::Transform(
10221037
}
10231038

10241039
m_resumptionBBs.push_back(resumeBB);
1025-
JITDUMP(" Created resumption BB " FMT_BB "\n", resumeBB->bbNum);
10261040
}
10271041

10281042
GenTreeIndir* Async2Transformation::LoadFromOffset(GenTree* base,
@@ -1178,7 +1192,6 @@ void Async2Transformation::LiftLIREdges(BasicBlock* block,
11781192
void Async2Transformation::CreateResumptionSwitch()
11791193
{
11801194
BasicBlock* newEntryBB = m_comp->bbNewBasicBlock(BBJ_NONE);
1181-
JITDUMP("New entry BB: " FMT_BB "\n", newEntryBB->bbNum);
11821195

11831196
if (m_comp->fgFirstBB->hasProfileWeight())
11841197
{
@@ -1189,6 +1202,8 @@ void Async2Transformation::CreateResumptionSwitch()
11891202
FlowEdge* edge = m_comp->fgAddRefPred(m_comp->fgFirstBB, newEntryBB);
11901203
edge->setLikelihood(1);
11911204

1205+
JITDUMP(" Inserting new entry " FMT_BB " before old entry " FMT_BB "\n", newEntryBB->bbNum, m_comp->fgFirstBB->bbNum);
1206+
11921207
m_comp->fgInsertBBbefore(m_comp->fgFirstBB, newEntryBB);
11931208

11941209
// If previous first BB was a scratch BB, then we must add a new scratch BB
@@ -1203,6 +1218,7 @@ void Async2Transformation::CreateResumptionSwitch()
12031218

12041219
if (m_resumptionBBs.size() == 1)
12051220
{
1221+
JITDUMP(" Redirecting entry " FMT_BB " directly to " FMT_BB " as it is the only resumption block\n", newEntryBB->bbNum, m_resumptionBBs[0]->bbNum);
12061222
newEntryBB->SetJumpKindAndTarget(BBJ_COND, m_resumptionBBs[0] DEBUGARG(m_comp));
12071223
m_comp->fgAddRefPred(m_resumptionBBs[0], newEntryBB);
12081224
}
@@ -1212,7 +1228,7 @@ void Async2Transformation::CreateResumptionSwitch()
12121228
condBB->bbSetRunRarely();
12131229
newEntryBB->SetJumpKindAndTarget(BBJ_COND, condBB DEBUGARG(m_comp));
12141230

1215-
JITDUMP("New cond BB: " FMT_BB "\n", condBB->bbNum);
1231+
JITDUMP(" Redirecting entry " FMT_BB " to BBJ_COND " FMT_BB " for resumption with 2 states\n", newEntryBB->bbNum, condBB->bbNum);
12161232

12171233
m_comp->fgAddRefPred(condBB, newEntryBB);
12181234
m_comp->fgAddRefPred(m_resumptionBBs[0], condBB);
@@ -1236,7 +1252,7 @@ void Async2Transformation::CreateResumptionSwitch()
12361252
switchBB->bbSetRunRarely();
12371253
newEntryBB->SetJumpKindAndTarget(BBJ_COND, switchBB DEBUGARG(m_comp));
12381254

1239-
JITDUMP("New switch BB: " FMT_BB "\n", switchBB->bbNum);
1255+
JITDUMP(" Redirecting entry " FMT_BB " to BBJ_SWITCH " FMT_BB " for resumption with %zu states\n", newEntryBB->bbNum, switchBB->bbNum, m_resumptionBBs.size());
12401256

12411257
m_comp->fgAddRefPred(switchBB, newEntryBB);
12421258

@@ -1268,13 +1284,19 @@ void Async2Transformation::CreateResumptionSwitch()
12681284

12691285
if (m_comp->doesMethodHavePatchpoints())
12701286
{
1287+
JITDUMP(" Method has patch points...\n");
12711288
// If we have patchpoints then first check if we need to resume in the OSR version.
12721289
BasicBlock* callHelperBB = m_comp->fgNewBBafter(BBJ_THROW, m_comp->fgLastBBInMainFunction(), false);
12731290
callHelperBB->bbSetRunRarely();
12741291
callHelperBB->clearTryIndex();
12751292
callHelperBB->clearHndIndex();
12761293

1294+
JITDUMP(" Created " FMT_BB " for transitions back into OSR method\n", callHelperBB->bbNum);
1295+
12771296
BasicBlock* checkILOffsetBB = m_comp->fgNewBBbefore(BBJ_COND, newEntryBB->GetJumpDest(), true, callHelperBB);
1297+
1298+
JITDUMP(" Created " FMT_BB " to check whether we should transition immediately to OSR\n", checkILOffsetBB->bbNum);
1299+
12781300
m_comp->fgRemoveRefPred(newEntryBB->GetJumpDest(), newEntryBB);
12791301
newEntryBB->SetJumpDest(checkILOffsetBB);
12801302

@@ -1310,6 +1332,7 @@ void Async2Transformation::CreateResumptionSwitch()
13101332
}
13111333
else if (m_comp->opts.IsOSR())
13121334
{
1335+
JITDUMP(" Method is an OSR function\n");
13131336
// If the tier-0 version resumed and then transitioned to the OSR
13141337
// version by normal means then we will see a non-zero continuation
13151338
// here that belongs to the tier0 method. In that case we should just
@@ -1319,6 +1342,8 @@ void Async2Transformation::CreateResumptionSwitch()
13191342
m_comp->fgRemoveRefPred(newEntryBB->GetJumpDest(), newEntryBB);
13201343
newEntryBB->SetJumpDest(checkILOffsetBB);
13211344

1345+
JITDUMP(" Created " FMT_BB " to check for Tier-0 continuations\n", checkILOffsetBB->bbNum);
1346+
13221347
m_comp->fgAddRefPred(checkILOffsetBB, newEntryBB);
13231348
m_comp->fgAddRefPred(checkILOffsetBB->Next(), checkILOffsetBB);
13241349
m_comp->fgAddRefPred(checkILOffsetBB->GetJumpDest(), checkILOffsetBB);

src/coreclr/jit/async.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class Async2Transformation
3131
unsigned m_resultBaseVar = BAD_VAR_NUM;
3232
unsigned m_exceptionVar = BAD_VAR_NUM;
3333
BasicBlock* m_lastSuspensionBB = nullptr;
34+
BasicBlock* m_lastResumptionBB = nullptr;
3435

3536
void LiftLIREdges(BasicBlock* block,
3637
GenTree* beyond,

0 commit comments

Comments
 (0)