Skip to content
This repository was archived by the owner on Nov 1, 2020. It is now read-only.
This repository was archived by the owner on Nov 1, 2020. It is now read-only.

Use scanner analysis to aid devirtualization #5019

Description

@MichalStrehovsky

I originally thought this would just be a perf optimization we can do later, but it turns out this is needed for making devirtualization working with our IL scanner at all.

As a refresher - scanning phase in the compiler tries to determine the exact set of methods that we're going to compile so that we can precompute generic dictionary layouts or vtable layouts. There's an essential invariant that says that we're never allowed to end up in a situation where the compilation phase generates more code than the scanning phase.

But consider:

abstract class Base
{
    public abstract void Unreachable();
}

sealed class Derived : Base
{
    public override void Unreachable()
    {
        new Derived();
    }
}

internal class Program
{
    private static void Main(string[] args)
    {
        Derived p = null;
        if (args == null)
            p.Unreachable();
    }
}

In this example, the virtual call to Unreachable doesn't result in scanning any method bodies, since no type with this method in the VTable got ever allocated. Scanner doesn't do devirtualization, because it's an optimization step that the codegen may or may not do. We don't try to predict what the codegen will do. Scanning more things than what we end up compiling is harmless (although it's wasting CPU cycles, so we try hard not to do it).

The simplified devirtualization algorithm we have in CorInfoImpl.cs that RyuJIT uses however will devirtualize the virtual call into a direct call to Derived::Unreachable. Bad things happen as a result.

The devirtualization algorithm needs to take into consideration the information we collected during scanning and abort the devirtualization in this case.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions