Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,22 @@ public MethodIL GetMethodILWithInlinedSubstitutions(MethodIL method)
if (delta >= 0 && delta < ehRegion.TryLength)
{
if (ehRegion.Kind == ILExceptionRegionKind.Filter)
{
offsetsToVisit.Push(ehRegion.FilterOffset);

// Filter must end with endfilter, so ensure we don't accidentally remove it.
// ECMA-335 dictates that filter block starts at FilterOffset and ends at HandlerOffset.
int expectedEndfilterLocation = ehRegion.HandlerOffset - 2;
bool isValidFilter = expectedEndfilterLocation >= 0
&& (flags[expectedEndfilterLocation] & OpcodeFlags.InstructionStart) != 0
&& methodBytes[expectedEndfilterLocation] == (byte)ILOpcode.prefix1
&& methodBytes[expectedEndfilterLocation + 1] == unchecked((byte)ILOpcode.endfilter);
if (isValidFilter)
{
flags[expectedEndfilterLocation] |= OpcodeFlags.VisibleBasicBlockStart | OpcodeFlags.Mark;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean we will keep the endfilter always (and thus the filter block), or does this preserve the ability to remove the entire filter block?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code runs when we're looking at EH regions associated with a marked instruction. So if the block covered by the filter got trimmed, the filter will be trimmed too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I finally wrapped my head around how this works in the linker, but the implementation in NativeAOT is different... I'll have to spend some time trying to understand it as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The general approach is the same as in ILLinker - seek backwards in the instruction stream and try to come up with a constant value. It doesn't try to reformat the IL after the fact (just nop things out) because RyuJIT is very efficient at getting rid of nops. We don't have to adjust EH regions or recompute branch offsets as a result.

}
}

offsetsToVisit.Push(ehRegion.HandlerOffset);

// RyuJIT is going to look at this basic block even though it's unreachable.
Expand Down