-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Closed
Labels
area-VM-coreclrbacklog-cleanup-candidateAn inactive issue that has been marked for automated closure.An inactive issue that has been marked for automated closure.questionAnswer questions and provide assistance, not an issue with source code or documentation.Answer questions and provide assistance, not an issue with source code or documentation.
Milestone
Description
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

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?
HFadeel, jnm2, YuriiPovkh and deep-outcome
Metadata
Metadata
Assignees
Labels
area-VM-coreclrbacklog-cleanup-candidateAn inactive issue that has been marked for automated closure.An inactive issue that has been marked for automated closure.questionAnswer questions and provide assistance, not an issue with source code or documentation.Answer questions and provide assistance, not an issue with source code or documentation.