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

[Question] Can Virtual Stub Dispatch be "inlined"? #8819

Open
benaadams opened this Issue Jan 5, 2017 · 1 comment

Comments

Projects
None yet
3 participants
@benaadams
Collaborator

benaadams commented Jan 5, 2017

Investigation of dispatch costs

There are 3 states for an interface callsite

1. 0 attached methods : Unresolved  -> Lookup stub
2. 1 attached method  : Monomorphic -> Dispatch stub
3. N attached methods : Megamorphic -> Resolve stub

For a monomorphic interface call it always goes via a stub to do dispatch; which is roughly the same cost as 2 chained non-inlined direct calls:

                      Method |          Mean |     StdDev | Scaled |          RPS |
---------------------------- |-------------- |----------- |------- |------------- |
     -> InterfaceMonomorphic | 1,276.6333 ns | 16.6153 ns |   1.00 |   783,310.26 |
      InterfacePolymorphicX2 | 1,444.7386 ns | 25.2325 ns |   1.13 |   692,166.75 |
     InterfaceMegamorphicX33 | 1,428.9762 ns | 13.8861 ns |   1.12 |   699,801.72 |

InterfaceUnsafeCastConstTest |   830.3120 ns |  9.8983 ns |   0.65 | 1,204,366.58 |
  InterfaceUnsafeCastVarTest | 1,198.1936 ns | 16.6743 ns |   0.94 |   834,589.69 |

  -> DirectViaCastIndirected | 1,136.0911 ns | 19.6327 ns |   0.89 |   880,211.12 |
     DirectViaCastNotInlined |   679.2567 ns |  9.4285 ns |   0.53 | 1,472,197.44 |
        DirectViaCastInlined |   192.5118 ns |  5.2530 ns |   0.15 | 5,194,485.75 |

Which is in line with the BoTR Virtual Stub Dispatch where the call site; calls stub; which calls method
Figure 1

For 1 resolved type (monomorphic) it looks roughly like this (excuse the pseudo-code)

function CallInterface()
{
    VirtualStub dispatch = callsite_dispatch;
    dispatch.Invoke(obj.methodTable);
}

class DispatchStub : VirtualStub
{
    Type expectedMT;
    PCODE implTarget;
    PCODE failTarget;

    Invoke(MethodTable methodTable)
    {
        if (expectedMT == methodTable)
        {
             this->implTarget();
        }
        else
        {
            this->failTarget();
        }
    }
}

However if the LookupStub and ResolveStubs returned 0 as MT then the DispatchStub could be turned into a regular POCO and the call inlined?

function CallInterface()
{
    var dispatch = callsite_dispatch;
    var expectedMT = dispatch->expectedMT;
    if (expectedMT == 0 || expectedMT == obj.methodTable)
    {
         dispatch->implTarget();
    }
    else
    {
        dispatch->failTarget();
    }
}

class DispatchStub : VirtualStub
{
    Type expectedMT;
    PCODE implTarget;
    PCODE failTarget;
}
class LookupStub : VirtualStub
{
    Type expectedMT = 0;
    PCODE implTarget => Invoke();
    PCODE failTarget ...;
}
class ResolveStub : VirtualStub
{
    Type expectedMT = 0;
    PCODE implTarget => Invoke();
    PCODE failTarget ...;
}

Comparable examples

Inline caches in Smalltalk, Java, Javascript

Question

Would there be any benefit to this change?

@benaadams benaadams changed the title from [Question] Can Virtual Stub Dispatch be inlined? to [Question] Can Virtual Stub Dispatch be "inlined"? Jan 5, 2017

@gkhanna79

This comment has been minimized.

Show comment
Hide comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment