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

Delete support for TLS RVA statics from the Jit #62131

Conversation

SingleAccretion
Copy link
Contributor

@SingleAccretion SingleAccretion commented Nov 29, 2021

This construct is not supported on .NET Core+, so the code in question is dead. Deleting it frees one handle kind (which will be helpful in my future changes), and deletes one path from fgMorphField (which will also be helpful in my future changes).

Fixes #4852.

Part of #58312.

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Nov 29, 2021
@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Nov 29, 2021
@ghost
Copy link

ghost commented Nov 29, 2021

Tagging subscribers to this area: @JulieLeeMSFT
See info in area-owners.md if you want to be subscribed.

Issue Details

This construct is not supported on .NET Core, so the code in question is dead. Deleting it frees one handle kind (which will be helpful in my future changes), and deletes one path from fgMorphField (which will also be helpful in my future changes).

Fixes #4852.

Part of #58312.

Author: SingleAccretion
Assignees: -
Labels:

area-CodeGen-coreclr

Milestone: -

@SingleAccretion SingleAccretion changed the title Delete Tls RVA fields support from the Jit Delete support for TLS RVA statics from the Jit Nov 29, 2021
TLS RVA statics are not supported by CoreCLR, so all
the support for them in the Jit is dead code.
@jkotas
Copy link
Member

jkotas commented Nov 29, 2021

TLS RVA statics have been used by managed C++. Are we sure that managed C++ does not use them anymore?

Note that the issue #4852 filled against these tests is from 2015. The managed C++ was not supported in 2015, but it has changed since then.

@SingleAccretion
Copy link
Contributor Author

SingleAccretion commented Nov 29, 2021

Are we sure that managed C++ does not use them anymore?

That is something for me to investigate before this would be ready for review (or closure).

The first approximation here is that none of the IL tests work if I build/run them, though mysteriously enough they fail with FileNotFoundException, not BadImageException (and if I remove .data tls from them, they do run fine).

Edit: I can get one test to run after all, but now it fails with AV. Hmm.

@jkoritzinsky
Copy link
Member

MSVC's __declspec(thread) isn't supported in C++/CLI, and it looks like (from my experimentation) that C++11's thread_local behaves similarly.

Here's what the field and data declarations for a class-static thread_local (or __declspec(thread) class-static) int with an default value of 42 looks like:

.field static assembly int32 '?i@Unmanaged@@2HA' at D_00021C90
.data D_00021C90 = bytearray (
                 2A 00 00 00)                                     // *...

I think the TLS RVA statics may have only ever been used by Managed C++, which is not supported on .NET 5+. Only C++/CLI is supported on .NET 5+ since it requires a recompilation using the /clr:netcore switch.

@SingleAccretion
Copy link
Contributor Author

I was about to write a comment on how it actually does work 😄.

I tested it is with this (properly /clr:netcore):

__declspec(thread) static int TlsInt = 100;

public ref class CppCliClass
{
public:
    static int GetTlsStatic()
    {
        return TlsInt;
    }

    static void SetTlsStatic(int value)
    {
        TlsInt = value;
    }
};

And it does indeed have the semantics expected of TLS, and produces inline code on x86 (not without first failing on some DEBUG-only asserts, but those are not critical):

// CppCliClass:GetTlsStatic

IN0004: 000000 push     ebp
IN0005: 000001 mov      ebp, esp

G_M10086_IG02:

IN0001: 000003 mov      eax, dword ptr FS:[0x002C]
IN0002: 000009 mov      eax, dword ptr [eax+28]
IN0003: 00000C mov      eax, dword ptr [eax+4]

G_M10086_IG03:

IN0006: 00000F pop      ebp
IN0007: 000010 ret

If you look at the ldasms output, there is no .data tls in there indeed, which is very puzzling because it does survive the roundtripping if you use it on one of the test assemblies.

@jkoritzinsky
Copy link
Member

@SingleAccretion did you make sure to force the TlsInt global variable to generate in managed code instead of in native code? It's possible that it is in the native code segment and as a result uses the native mechanisms to mark it as TLS.

Can you recompile with /clr:pure and see what the IL looks like?

@SingleAccretion
Copy link
Contributor Author

@jkoritzinsky the assembly excerpt is from the Jit compiling the IL for the methods, so, it should be the "real thing".

The methods according to ildasm
  .method public hidebysig static int32  GetTlsStatic() cil managed
  {
    // Code size       6 (0x6)
    .maxstack  1
    IL_0000:  ldsfld     int32 '?A0xfa31f548.TlsInt'
    IL_0005:  ret
  } // end of method CppCliClass::GetTlsStatic

  .method public hidebysig static void  SetTlsStatic(int32 'value') cil managed
  {
    // Code size       7 (0x7)
    .maxstack  1
    IL_0000:  ldarg.0
    IL_0001:  stsfld     int32 '?A0xfa31f548.TlsInt'
    IL_0006:  ret
  } // end of method CppCliClass::SetTlsStatic

Can you recompile with /clr:pure and see what the IL looks like?

Let's see...

@jkoritzinsky
Copy link
Member

Can you also share the IL from ildasm for the field definition?

@SingleAccretion
Copy link
Contributor Author

Just as in your case, it is disassembled as an ordinary .data:

.field static assembly int32 '?A0xfa31f548.TlsInt' at D_0000F77C

.data D_0000F77C = bytearray (
                 64 00 00 00)                                     // d...

@SingleAccretion
Copy link
Contributor Author

Can you recompile with /clr:pure and see what the IL looks like?

Looks like that will not compile: C3389 __declspec(thread) cannot be used with /clr:pure or /clr:safe.

@jkoritzinsky
Copy link
Member

Based on that, I'd say that the TLS support is somehow reliant on native code or native PE features. Not sure exactly how though.

@jkotas
Copy link
Member

jkotas commented Nov 29, 2021

TLS support is somehow reliant on native code or native PE features

Correct. I expect that you can only hit it in mixed mode C++ CLI images. I am not sure whether ilasm can produce images that can hit it.

@SingleAccretion
Copy link
Contributor Author

That is the conclusion I came to as well. I do note that it is Jitted code that gets run, not some kind of native stub, I have verified that by modifying the compiler (making it import the fields in question as constants).

With ilasm-produced images, while they do contain the .tls section with the correct metadata, the TLS index of the image at runtime remains uninitialized, which is why the IL tests AV on execution (the index given to the Jit by getFieldThreadLocalStoreID is bogus).

The C++/CLI-produced images cause the index to be properly initialized, and the code produced for them is functional, on x86. On all other platforms, it crashes as the helper path is not implemented, and the Jit generates call [null].

(Side note: ildasm does not see the .data declarations as .tls simply because the native toolchain puts them in the .rdata section)

So it appears we have this somewhat functioning on x86 for some C++/CLI code, and as such the Jit code needs to be kept. Should we keep the tests though? They will not work unless we somehow fix the TLS index situation (which I imagine is not something we'd want to do). That said, there is not a lot of value in deleting them either...

@jkotas
Copy link
Member

jkotas commented Nov 30, 2021

On all other platforms, it crashes as the helper path is not implemented

It is #42187 (comment)

@SingleAccretion SingleAccretion deleted the Delete-Tls-Rva-Fields-Support branch December 20, 2021 11:19
@ghost ghost locked as resolved and limited conversation to collaborators Jan 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Tests fail with System.BadImageFormatException
3 participants