Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Various tailcall test improvements #26818

Merged
merged 16 commits into from
Sep 25, 2019
Merged

Conversation

jakobbotsch
Copy link
Member

@jakobbotsch jakobbotsch commented Sep 21, 2019

Add tests that test

  • Tail calls to functions with small return values
  • Tail calls to functions with retbuf
  • Tail calls to functions with multi-reg returned structs
  • Tail calls to functions with void returns
  • Tail calls to abstract methods
  • Tail calls to interface methods
  • tail. calli sequences
  • Tail calls to struct instance methods
  • Tail calls involving refs
  • Tail calls involving byrefs
  • Tail calls involving generics

Remove some illegal tests that pass the address of variables on the local stack frame to a tail. call.

I have also made some changes to the tailcall return address hijacking test:

  • On Linux x64, this test might not be forced to use helper because the struct ForceHelper is passed by value. I have added another arg to one of the tailcall helper functions that fixes this.
  • I have changed the test to use fewer resources
  • I am experimentally enabling it on ARM32

My new tests should fail on platforms without helper-based tailcalls and the hijacking one might also fail on ARM32/x64 Linux now. I will disable them once I see the CI results.

These tests pass address of local stack frame to tail. prefixed calls.
* Tail calls to functions with small return values
* Tail calls to functions with retbuf
* Tail calls to functions with multi-reg returned structs
* Tail calls to functions with void returns
* Tail calls to abstract methods
* Tail calls to interface methods
* tail. calli sequences
* Tail calls to struct instance methods
* Tail calls involving refs
* Tail calls involving byrefs
* Tail calls involving generics
* Force this test to use helper on AMD64 too
* Instead of 3 tailcallers and 1 collector, just use 1 collector and 1
tailcaller. Additionally, run it for only 30 iterations of 1 second
sleeps. This should allow it to run for AMD64 and ARM32 in CI too.
@jakobbotsch
Copy link
Member Author

It looks like the new test is running into #26311 on x64 Windows. I will have to disable it on all platforms except x86 Windows.

@jakobbotsch
Copy link
Member Author

jakobbotsch commented Sep 23, 2019

It was strange to me that the issue in my previous comment was not more widespread since F# users should be running into it for many interface calls in tailcall position. I found out that this failure is a regression -- my new test works fine in .NET core 3.0 preview 8. After some bisecting I have tracked it down to #20643. I will leave it up to someone else whether we should try a targeted fix for it or wait for it to be fixed with #26418 considering that it is a regression.

cc @jashook

@jakobbotsch
Copy link
Member Author

Here is a smaller F# example that access violates with master on x64 Windows:

open System
open System.Runtime.CompilerServices

type IFoo =
    abstract member TailCallee : int -> Guid -> int

[<MethodImpl(MethodImplOptions.NoInlining)>]
let TailCaller (foo : IFoo) =
    foo.TailCallee 0 (new Guid())

type Bar() =
    interface IFoo with
        member this.TailCallee _ _ = 0

[<EntryPoint>]
let main argv = TailCaller (new Bar())

@jashook
Copy link

jashook commented Sep 23, 2019

@jakobbotsch this regression happens because we used to fast tail call, but we make the decision to not after #20643?

@jakobbotsch
Copy link
Member Author

@jashook Both are slow tail calls. If I had to take a wild guess it would be related to the resetting of the arg info here:

coreclr/src/jit/morph.cpp

Lines 8309 to 8316 in f8f0c55

if (!canFastTailCall)
{
fgMorphTailCall(call, pfnCopyArgs);
// Force re-evaluating the argInfo. fgMorphTailCall will modify the
// argument list, invalidating the argInfo.
call->fgArgInfo = nullptr;
}

But I have not at all tried to diagnose it, so it is a wild guess.

@jakobbotsch
Copy link
Member Author

This should be good to go @jkotas.

tests/issues.targets Outdated Show resolved Hide resolved
@jakobbotsch
Copy link
Member Author

jakobbotsch commented Sep 24, 2019

  1. Added the .cs file for the new test
  2. Made TailcallVerifyWithPrefix pinvoke printf on Unix and Sleep on Windows. Clarified that it is now disabled because of no implicit/helper-based tailcalls where it is disabled. I will reenable it on the new supported platforms in [WIP] Implement portable tailcall helpers #26418.
  3. Removed all the dead code from TailcallVerifyWithPrefixTest

Copy link

@jashook jashook left a comment

Choose a reason for hiding this comment

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

lgtm minus two nits

tests/issues.targets Outdated Show resolved Hide resolved
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using InlineIL;
Copy link

Choose a reason for hiding this comment

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

Do you mind also adding a small readme into this folder explaining that this file is not used by testing, it is here to help regenerate the IL test.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added a comment to the top of the file

@jashook
Copy link

jashook commented Sep 25, 2019

Also, feel free to merge after the changes. This has passed CI. No reason to run them again.

@jakobbotsch
Copy link
Member Author

Also, feel free to merge after the changes.

I don't have access to. 😄

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants