Runtime: RyuJIT: Intrinsify GetType().TypeHandle.Value and typeof(T).TypeHandle.Value

Created on 31 May 2016  路  9Comments  路  Source: dotnet/runtime

Sometimes I use IntPtr instead of Type as a key (or part of a complex key) in Dictionary.
Advantages is that it is a value type so I don't keep full blown Type object alive, and GC likes value type fields more than ref ones because less references to follow.

But each time I need to get the value or check if a key exists I have to get Type just to retrieve its handle value.

I suggest intrinsifying these calls:

``` C#
[obj.]GetType().TypeHandle.Value
typeof(T).TypeHandle.Value

### How

In the following code JIT just compares  method table pointer  in the object header to the address of method table of `String` type.

``` C#
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool TestMtCheck(object obj)
{
    return obj.GetType() == typeof(String);
}
 mov rax,7FEF61BDA88h  
 cmp qword ptr [rcx],rax
 sete al  
 movzx eax,al  
 ret  

It could do the same with getting type handle value :

``` C#
[MethodImpl(MethodImplOptions.NoInlining)]
private static IntPtr TestGetHandle(object obj)
{
return obj.GetType().TypeHandle.Value;
}

MethodImpl(MethodImplOptions.NoInlining)]
private static IntPtr TestGetHandle()
{
return typeof(String).TypeHandle.Value;
}

``` ASM
mov rax, qword ptr [rcx]
ret
mov rax, 7FEF61BDA88h  
ret

category:cq
theme:type-intrinsics
skill-level:expert
cost:medium

area-CodeGen-coreclr enhancement optimization tenet-performance

Most helpful comment

There are complications with array type handles and proxy type handles (for remoting on full framework) - the type handle is not equal to methodtable for these.

It may be better to implement fixups for System.Type instead. It would avoid helper call to get to the System.Type. This optimization would be applicable more broadly, and it would make access to the raw handle value cheaper too. I have conversion about it with @cmckinsey @geoffkizer recently.

All 9 comments

And I know about existence of collectible types :)

/cc @RussKeldorph

@jkotas Would JIT be involved in this one?

Yes, this would be JIT work.

There are complications with array type handles and proxy type handles (for remoting on full framework) - the type handle is not equal to methodtable for these.

It may be better to implement fixups for System.Type instead. It would avoid helper call to get to the System.Type. This optimization would be applicable more broadly, and it would make access to the raw handle value cheaper too. I have conversion about it with @cmckinsey @geoffkizer recently.

@jkotas did you ever do any writeup for the fixup idea?

Today, ldtoken is expanded to embedGenericHandle + CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE.

We can add a new method to JIT/EE interface bool expandLdToken(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_GENERICHANDLE_RESULT * pResult) that would allow short-circuiting this if possible. ldtoken would be the lookup returned by bool expandLdToken(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_GENERICHANDLE_RESULT * pResult) and we would save CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE call.

Yesterday I've been working on improving the performance of GC.AllocateUninitializedArray to be able to use it effectively in StringBuilder.

typeof(T[]).TypeHandle.Value (mind the array of T, not just T) used in the following line:

https://github.com/dotnet/coreclr/blob/8bc7fab14d78030914e98b33c70b370d513021f6/src/System.Private.CoreLib/src/System/GC.cs#L679

showed up in the profiles:

obraz

It was just a few %, which itself is not bad. The problem was that this generic code is executed only for value types and having this extra call(s) (.GetRuntimeType and Handle.get_Value) increases the method size and hence prevents from inlining.

I had two cases recently where I could use this. (managed StelemRef and GC.Allocate[Uninitialized]Array API)

I believe the issues with array type handles should not be a problem any more.

Was this page helpful?
0 / 5 - 0 ratings