runtime icon indicating copy to clipboard operation
runtime copied to clipboard

[mono][jit] Resolve constrained static virtual calls in gshared methods.

Open vargaz opened this issue 3 years ago • 4 comments

Mostly fixes https://github.com/dotnet/runtime/issues/75801.

Some restrictions still remain, mostly methods with generic arguments like INegator`1<T>:NegateIfNeeded<Vector128<T>>.

vargaz avatar Sep 19 '22 14:09 vargaz

/azp run runtime-wasm

vargaz avatar Sep 19 '22 20:09 vargaz

Azure Pipelines successfully started running 1 pipeline(s).

azure-pipelines[bot] avatar Sep 19 '22 20:09 azure-pipelines[bot]

/azp run runtime-wasm

vargaz avatar Sep 20 '22 03:09 vargaz

Azure Pipelines successfully started running 1 pipeline(s).

azure-pipelines[bot] avatar Sep 20 '22 03:09 azure-pipelines[bot]

This approach is not going to work, for example:

public class Tests
{
        private interface INegator<T> where T : struct
        {
            static abstract bool NegateIfNeeded(bool equals);
        }

        private readonly struct DontNegate<T> : INegator<T> where T : struct
        {
            public static bool NegateIfNeeded(bool equals) {
                Console.WriteLine (typeof (T));
                Console.WriteLine (typeof (T));
                Console.WriteLine (typeof (T));
                Console.WriteLine (typeof (T));
                return equals;
            }
        }

        private readonly struct Negate<T> : INegator<T> where T : struct
        {
            public static bool NegateIfNeeded(bool equals) => !equals;
        }

    private static int IndexOfValueType<TValue, TNegator>()
            where TValue : struct, INumber<TValue>
            where TNegator : struct, INegator<TValue>
    {
        for (int j = 0; j < 1000; ++j) {
            for (int i = 0; i < 100000; ++i)
                TNegator.NegateIfNeeded (true);
        }
        return 0;
    }

The AOT compiler will compile IndexOfValueType(TValue_BYTE, TNegator_INST). The IL sequence for the call is:

constrained. !!TNegator
call       bool class Tests/INegator`1<!!TValue>::NegateIfNeeded(bool)

This PR will resolve the called method to: Tests/DontNegate`1<T_BYTE>:NegateIfNeeded (bool) where T_BYTE is the inner type variable of TNegator_INST. The problem is that this type variable is not part of the calling method so at runtime, when we try to inflate Tests/DontNegate`1<T_BYTE>:NegateIfNeeded (bool) with the real type arguments (byte, Negate<byte>), it won't be inflated so we end up calling an open method.

vargaz avatar Sep 22 '22 05:09 vargaz

Closing in favor of: https://github.com/dotnet/runtime/pull/76033

vargaz avatar Sep 22 '22 19:09 vargaz