-
Notifications
You must be signed in to change notification settings - Fork 5k
JIT: fix issue in cloning loops with trys in handlers #113586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2680,8 +2680,8 @@ BasicBlock* Compiler::fgCloneTryRegion(BasicBlock* tryEntry, CloneTryInfo& info, | |
if (bbIsTryBeg(block)) | ||
{ | ||
assert(added); | ||
JITDUMP("==> found try entry for EH#%02u nested in handler at " FMT_BB "\n", block->bbNum, | ||
block->getTryIndex()); | ||
JITDUMP("==> found try entry for EH#%02u nested in handler at " FMT_BB "\n", block->getTryIndex(), | ||
block->bbNum); | ||
regionsToProcess.Push(block->getTryIndex()); | ||
} | ||
} | ||
|
@@ -2761,6 +2761,12 @@ BasicBlock* Compiler::fgCloneTryRegion(BasicBlock* tryEntry, CloneTryInfo& info, | |
assert(insertBeforeIndex == enclosingTryIndex); | ||
} | ||
|
||
if (insertBeforeIndex != compHndBBtabCount) | ||
{ | ||
JITDUMP("Existing EH region(s) EH#%02u...EH#%02u will become EH#%02u...EH#%02u\n", insertBeforeIndex, | ||
compHndBBtabCount - 1, insertBeforeIndex + regionCount, compHndBBtabCount + regionCount - 1); | ||
} | ||
|
||
// Once we call fgTryAddEHTableEntries with deferCloning = false, | ||
// all the EH indicies at or above insertBeforeIndex will shift, | ||
// and the EH table may reallocate. | ||
|
@@ -2860,7 +2866,7 @@ BasicBlock* Compiler::fgCloneTryRegion(BasicBlock* tryEntry, CloneTryInfo& info, | |
// | ||
if (ebd->ebdEnclosingTryIndex != EHblkDsc::NO_ENCLOSING_INDEX) | ||
{ | ||
if (XTnum < clonedOutermostRegionIndex) | ||
if (ebd->ebdEnclosingTryIndex < clonedOutermostRegionIndex) | ||
{ | ||
ebd->ebdEnclosingTryIndex += (unsigned short)indexShift; | ||
} | ||
|
@@ -2873,7 +2879,7 @@ BasicBlock* Compiler::fgCloneTryRegion(BasicBlock* tryEntry, CloneTryInfo& info, | |
|
||
if (ebd->ebdEnclosingHndIndex != EHblkDsc::NO_ENCLOSING_INDEX) | ||
{ | ||
if (XTnum < clonedOutermostRegionIndex) | ||
if (ebd->ebdEnclosingHndIndex < clonedOutermostRegionIndex) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Second part of fix. |
||
{ | ||
ebd->ebdEnclosingHndIndex += (unsigned short)indexShift; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
// g - giant finally (TF will remain try finally) | ||
// p - regions are serial, not nested | ||
// TFi - try finally with what follows in the finally | ||
// I - inlining | ||
// | ||
// x: we currently cannot clone loops where the try is the first thing | ||
// as the header and preheader are different regions | ||
|
@@ -1127,5 +1128,142 @@ public static int Sum_TFiTFxL(int[] data, int n) | |
|
||
return sum; | ||
} | ||
|
||
[Fact] | ||
public static int Test_LTFiTF() => Sum_LTFiTF(data, n) - 130; | ||
|
||
public static int Sum_LTFiTF(int[] data, int n) | ||
{ | ||
int sum = 0; | ||
|
||
for (int i = 0; i < n; i++) | ||
{ | ||
sum += data[i]; | ||
try | ||
{ | ||
SideEffect(); | ||
} | ||
finally | ||
{ | ||
try | ||
{ | ||
SideEffect(); | ||
} | ||
finally | ||
{ | ||
sum += 1; | ||
} | ||
|
||
sum += 1; | ||
} | ||
} | ||
|
||
return sum; | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static int SomeEH() | ||
{ | ||
int sum = 0; | ||
|
||
try | ||
{ | ||
SideEffect(); | ||
} | ||
finally | ||
{ | ||
try | ||
{ | ||
SideEffect(); | ||
} | ||
finally | ||
{ | ||
sum += 1; | ||
} | ||
|
||
sum += 1; | ||
} | ||
|
||
return sum; | ||
} | ||
|
||
[Fact] | ||
public static int Test_LITFiTF() => Sum_LITFiTF(data, n) - 130; | ||
|
||
public static int Sum_LITFiTF(int[] data, int n) | ||
{ | ||
int sum = 0; | ||
|
||
for (int i = 0; i < n; i++) | ||
{ | ||
sum += data[i]; | ||
sum += SomeEH(); | ||
} | ||
|
||
return sum; | ||
} | ||
|
||
[Fact] | ||
public static int Test_TFLTFiTF() => Sum_TFLTFiTF(data, n) - 131; | ||
|
||
public static int Sum_TFLTFiTF(int[] data, int n) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test case has the EH arrangement that triggers the bug. A try with a loop with a try / finally with a try in the finally. |
||
{ | ||
int sum = 0; | ||
|
||
try | ||
{ | ||
for (int i = 0; i < n; i++) | ||
{ | ||
sum += data[i]; | ||
try | ||
{ | ||
SideEffect(); | ||
} | ||
finally | ||
{ | ||
try | ||
{ | ||
SideEffect(); | ||
} | ||
finally | ||
{ | ||
sum += 1; | ||
} | ||
|
||
sum += 1; | ||
} | ||
} | ||
} | ||
finally | ||
{ | ||
SideEffect(); | ||
sum += 1; | ||
} | ||
return sum; | ||
} | ||
|
||
// [Fact] | ||
public static int Test_TFLITFiTF() => Sum_TFLITFiTF(data, n) - 131; | ||
|
||
public static int Sum_TFLITFiTF(int[] data, int n) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a case like the above but requires inlining to create the proper loop/EH structure; it's what I ran into testing #112998. |
||
{ | ||
int sum = 0; | ||
|
||
try | ||
{ | ||
for (int i = 0; i < n; i++) | ||
{ | ||
sum += data[i]; | ||
sum += SomeEH(); | ||
} | ||
} | ||
finally | ||
{ | ||
SideEffect(); | ||
sum += 1; | ||
} | ||
|
||
return sum; | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the actual fix, we only want to adjust indices within the span of regions we've cloned.