Skip to content
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

Allow RyuJIT to refer to frozen RuntimeType instances #94342

Merged
merged 2 commits into from
Nov 6, 2023

Conversation

MichalStrehovsky
Copy link
Member

With #93440 it became possible to place RuntimeType instances in the frozen region. This adds support for generating frozen RuntimeType instances within the compiler. We give these to RyuJIT whenever it asks for them.

  • New FrozenObjectNode descendant that represents a RuntimeType instance. We have two flavors - one wraps constructed and the other wraps necessary MethodTables (we have a need for freezing both kinds to keep our ability to optimize RuntimeTypes used in comparisons only).
  • We hand out references to these whenever RyuJIT needs them.
  • At MethodTable emission time, we check whether a frozen RuntimeType for this MethodTable was generated. If so, we pre-populate MethodTable’s WritableData section with a reloc to the RuntimeType. Otherwise we use null as usual.
  • At runtime for GetTypeFromEEType, if WritableData is non-null, we just return that. Otherwise we create a pinned RuntimeType instance and write it into WritableData. In the future, we should allocate this on a frozen heap.

Old codegen for Console.WriteLine(typeof(Program)):

sub         rsp,28h
lea         rcx,[repro_Program::`vftable' (07FF7D03154E0h)]
call        S_P_CoreLib_Internal_Runtime_CompilerHelpers_LdTokenHelpers__GetRuntimeType (07FF7D0253290h)
mov         rcx,rax
call        System_Console_System_Console__WriteLine_11 (07FF7D0262AC0h)
nop
add         rsp,28h
ret

New codegen:

sub         rsp,28h
lea         rcx,[__RuntimeType_repro_Program (07FF7A218EC50h)]
call        System_Console_System_Console__WriteLine_11 (07FF7A20F2680h)
nop
add         rsp,28h
ret

I’ll do cctor preinitialization in a subsequent PR to keep things short. Contributes to #91704.

Cc @dotnet/ilc-contrib

With dotnet#93440 it became possible to place `RuntimeType` instances in the frozen region. This adds support for generating frozen `RuntimeType` instances within the compiler. We give these to RyuJIT whenever it asks for them.

* New `FrozenObjectNode` descendant that represents a `RuntimeType` instance. We have two flavors - one wraps constructed and the other wraps necessary `MethodTable`s (we have a need for freezing both kinds to keep our ability to optimize `RuntimeTypes` used in comparisons only).
* We hand out references to these whenever RyuJIT needs them.
* At `MethodTable` emission time, we check whether a frozen `RuntimeType` for this `MethodTable` was generated. If so, we pre-populate `MethodTable`’s `WritableData` section with a reloc to the `RuntimeType`. Otherwise we use null as usual.
* At runtime for `GetTypeFromEEType`, if `WritableData` is non-null, we just return that. Otherwise we create a pinned `RuntimeType` instance and write it into `WritableData`. In the future, we should allocate this on a frozen heap.

Old codegen for `Console.WriteLine(typeof(Program))`:

```asm
sub         rsp,28h
lea         rcx,[repro_Program::`vftable' (07FF7D03154E0h)]
call        S_P_CoreLib_Internal_Runtime_CompilerHelpers_LdTokenHelpers__GetRuntimeType (07FF7D0253290h)
mov         rcx,rax
call        System_Console_System_Console__WriteLine_11 (07FF7D0262AC0h)
nop
add         rsp,28h
ret
```

New codegen:

```asm
sub         rsp,28h
lea         rcx,[__RuntimeType_repro_Program (07FF7A218EC50h)]
call        System_Console_System_Console__WriteLine_11 (07FF7A20F2680h)
nop
add         rsp,28h
ret
```

I’ll do cctor preinitialization in a subsequent PR to keep things short.
Contributes to dotnet#91704.
@ghost
Copy link

ghost commented Nov 3, 2023

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas
See info in area-owners.md if you want to be subscribed.

Issue Details

With #93440 it became possible to place RuntimeType instances in the frozen region. This adds support for generating frozen RuntimeType instances within the compiler. We give these to RyuJIT whenever it asks for them.

  • New FrozenObjectNode descendant that represents a RuntimeType instance. We have two flavors - one wraps constructed and the other wraps necessary MethodTables (we have a need for freezing both kinds to keep our ability to optimize RuntimeTypes used in comparisons only).
  • We hand out references to these whenever RyuJIT needs them.
  • At MethodTable emission time, we check whether a frozen RuntimeType for this MethodTable was generated. If so, we pre-populate MethodTable’s WritableData section with a reloc to the RuntimeType. Otherwise we use null as usual.
  • At runtime for GetTypeFromEEType, if WritableData is non-null, we just return that. Otherwise we create a pinned RuntimeType instance and write it into WritableData. In the future, we should allocate this on a frozen heap.

Old codegen for Console.WriteLine(typeof(Program)):

sub         rsp,28h
lea         rcx,[repro_Program::`vftable' (07FF7D03154E0h)]
call        S_P_CoreLib_Internal_Runtime_CompilerHelpers_LdTokenHelpers__GetRuntimeType (07FF7D0253290h)
mov         rcx,rax
call        System_Console_System_Console__WriteLine_11 (07FF7D0262AC0h)
nop
add         rsp,28h
ret

New codegen:

sub         rsp,28h
lea         rcx,[__RuntimeType_repro_Program (07FF7A218EC50h)]
call        System_Console_System_Console__WriteLine_11 (07FF7A20F2680h)
nop
add         rsp,28h
ret

I’ll do cctor preinitialization in a subsequent PR to keep things short. Contributes to #91704.

Cc @dotnet/ilc-contrib

Author: MichalStrehovsky
Assignees: MichalStrehovsky
Labels:

area-NativeAOT-coreclr

Milestone: -

Comment on lines 34 to 35
ref RuntimeType? type = ref Unsafe.AsRef<RuntimeType?>(pMT->WritableData);
return type ?? GetTypeFromMethodTableSlow(pMT, ref type);
Copy link
Member

@jkotas jkotas Nov 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ref RuntimeType? type = ref Unsafe.AsRef<RuntimeType?>(pMT->WritableData);
return type ?? GetTypeFromMethodTableSlow(pMT, ref type);
return Unsafe.AsRef<RuntimeType?>(pMT->WritableData) ?? GetTypeFromMethodTableSlow(pMT);

We should fetch the writetable data again in the slow method to minimize size of the aggressively inlined code.

{
UnsafeGCHandle tempHandle = UnsafeGCHandle.Alloc(new RuntimeType(pMT));
// TODO: instead of fragmenting the frozen object heap, we should have our own allocator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added check-box for this to #91704

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@EgorBo
Copy link
Member

EgorBo commented Nov 4, 2023

Nice! is this expected to be pre-initializeable now? (I checked your branch and it is not)

public class MyClass
{
    public static readonly Type type = typeof(int);
}

@MichalStrehovsky
Copy link
Member Author

Nice! is this expected to be pre-initializeable now? (I checked your branch and it is not)

public class MyClass
{
    public static readonly Type type = typeof(int);
}

"I’ll do cctor preinitialization in a subsequent PR to keep things short." at the bottom of top-post.

@MichalStrehovsky
Copy link
Member Author

/azp run runtime-nativeaot-outerloop

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@MichalStrehovsky MichalStrehovsky merged commit f1871f3 into dotnet:main Nov 6, 2023
119 of 126 checks passed
@MichalStrehovsky MichalStrehovsky deleted the frozenruntimetype branch November 6, 2023 11:53
@ghost ghost locked as resolved and limited conversation to collaborators Dec 6, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants