dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.29k stars 4.74k forks source link

Extra calls in Asm #109688

Open 1zaboy opened 2 days ago

1zaboy commented 2 days ago

Description

I have method

    public static void RecordError(Exception exception)
    {
    }

And I have code witch call RecordError

                try
                {
                     ...
                }
                catch (Exception ex)
                {
                    O.RecordError(ex);
                }

But when I build it and check Asm, I see call [Test.O:RecordError(System.Exception)] in asm

Since the method does not contain any code, its call could be removed.

I use .net 8 and Disasmo for see asm

Reproduction Steps

See Description

Expected behavior

not call method

Actual behavior

call method

Regression?

No response

Known Workarounds

-

Configuration

.net 8

<PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
</PropertyGroup>

Other information

No response

EgorBo commented 2 days ago

Can you attach the full snippet? If O could be null then it's not legal to drop exception handling.

dotnet-policy-service[bot] commented 2 days ago

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

1zaboy commented 2 days ago

@EgorBo Hi, here is my code. And the asm I get.

public static class OpenTlemetry {    
public static void RecordError(Exception exception)
    {

    }
}
                try
                {
                    Console.WriteLine("Activity started.");
                    throw new Exception("My Error");
                }
                catch (Exception ex)
                {
                    OpenTlemetry.RecordError(ex);
                }

            Console.WriteLine("Tracing completed.");
; Assembly listing for method Program:Main() (FullOpts)
; Emitting BLENDED_CODE for X64 with AVX512 - Windows
; FullOpts code
; optimized code
; rbp based frame
; fully interruptible
; No PGO data

G_M000_IG01:                ;; offset=0x0000
       push     rbp
       push     rbx
       sub      rsp, 40
       lea      rbp, [rsp+0x30]
       mov      qword ptr [rbp-0x10], rsp

G_M000_IG02:                ;; offset=0x000F
       mov      ecx, 1
       mov      rdx, 0x7FF85AEA8A28
       call     CORINFO_HELP_STRCNS
       mov      rcx, rax
       call     [System.Console:WriteLine(System.String)]
       mov      rcx, 0x7FF85AC3EB38
       call     CORINFO_HELP_NEWSFAST
       mov      rbx, rax
       mov      ecx, 37
       mov      rdx, 0x7FF85AEA8A28
       call     CORINFO_HELP_STRCNS
       mov      rdx, rax
       mov      rcx, rbx
       call     [System.Exception:.ctor(System.String):this]
       mov      rcx, rbx
       call     CORINFO_HELP_THROW
       int3     

G_M000_IG03:                ;; offset=0x0067
       mov      rcx, 0x21D00008538
       call     [System.Console:WriteLine(System.String)]
       nop      

G_M000_IG04:                ;; offset=0x0078
       add      rsp, 40
       pop      rbx
       pop      rbp
       ret      

G_M000_IG05:                ;; offset=0x007F
       push     rbp
       push     rbx
       sub      rsp, 40
       mov      rbp, qword ptr [rcx+0x20]
       mov      qword ptr [rsp+0x20], rbp
       lea      rbp, [rbp+0x30]

G_M000_IG06:                ;; offset=0x0092
       mov      rcx, rdx
       call     [TestOpenT.OpenTlemetry:RecordError(System.Exception)]
       lea      rax, G_M000_IG03

G_M000_IG07:                ;; offset=0x00A2
       add      rsp, 40
       pop      rbx
       pop      rbp
       ret      

; Total bytes of code 169
EgorBo commented 2 days ago

Inliner is very conservative around calls in catch blocks as it assumes such blocks are rarely hit. Is this a performance issue for you? It might makes sense to relax the inliner to be a bit less conservative for such empty calls, though.

1zaboy commented 2 days ago

@EgorBo I try to make a telemetry system with compile-level disabling. (#if #ifend) I made assumptions that methods that do not make sense or have no code will not be added to the final working file. I understand that this is not critical. But for such cases I expected the code to be completely excluded from the final working file.

timcassell commented 2 days ago

As a workaround, you could attribute the function with [Conditional("DO_NOT_DEFINE_ME")].