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

46239 v2 (no runtime layout changes) #53424

Merged
merged 16 commits into from
Jun 4, 2021

Conversation

trylek
Copy link
Member

@trylek trylek commented May 28, 2021

This is a simplified version of my original fix for 46239 as the full fix including runtime layout cleanup,

#51416

has an enormous bug tail and seems too risky to take relatively late in the release cycle.

Thanks

Tomas

/cc @dotnet/crossgen-contrib

@trylek trylek added this to the 6.0.0 milestone May 28, 2021
@jkotas
Copy link
Member

jkotas commented May 28, 2021

Since we agreed that this is just a stop-gap measure, I think it would better to omit the last commit that introduces a bunch of undesirable dependencies, like making ILVerify depend on interop marshalling.

@trylek
Copy link
Member Author

trylek commented May 28, 2021

@jkotas - Hmm, so am I right to understand that you're suggesting I should basically undo the moves of marshalling-related files originally suggested by Michal and implement the BlittableOrManagedSequential check using a virtual override in ReadyToRunMetadataFieldLayoutAlgorithm?

@MichalStrehovsky
Copy link
Member

@jkotas - Hmm, so am I right to understand that you're suggesting I should basically undo the moves of marshalling-related files originally suggested by Michal and implement the BlittableOrManagedSequential check using a virtual override in ReadyToRunMetadataFieldLayoutAlgorithm?

I agree with Jan - since having interop intertwined with type layout is not our long term plan per the conversation in the other pull request (and we want to get your other change in after .NET 6 cuts off), it doesn't make sense to move interop into type system just to undo that later this year.

@trylek trylek force-pushed the 46239-NoRuntimeLayoutChanges branch from 5ed9f3c to 1c41aaa Compare May 28, 2021 15:27
@@ -349,6 +352,7 @@ protected static ComputedInstanceFieldLayout ComputeExplicitFieldLayout(Metadata
);
if (needsToBeAligned)
{
largestAlignmentRequired = LayoutInt.Max(largestAlignmentRequired, type.Context.Target.LayoutPointerSize);
Copy link
Member

Choose a reason for hiding this comment

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

I would expect that ComputeFieldSizeAndAlignment will return sufficient alignment for GC pointers or anything with GC pointers. Is this really needed? If yes, it would be worth a comment explaining the situation where it is needed.

Copy link
Member Author

Choose a reason for hiding this comment

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

I believe you're right, I have replaced this with just an assert double-checking that at this point largestAlignmentRequired must be greater than or equal to PointerSize.

cumulativeInstanceFieldPos -= offsetBias;

var layoutMetadata = type.GetClassLayout();
LayoutInt instanceSize = cumulativeInstanceFieldPos + new LayoutInt(layoutMetadata.Size) + offsetBias;
Copy link
Member

@jkotas jkotas May 28, 2021

Choose a reason for hiding this comment

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

ComputeInstanceSize bumps this up to layoutMetadata.Size again.

I assume that this needs to be here because ComputeInstanceSize applies it on top of InstanceByteCountUnaligned, but this one applies it on top InstanceByteCount? A comment may be useful since this does not make sense by just looking at the code.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for pointing that out, auditing this aspect has revealed a few rough edges around the base class size calculation; I'm now locally testing an update cleaning this up by consistently using CalculateFieldBaseOffset in all the relevant places, I'll push the extra commit once I make sure it works reasonably well.

@trylek
Copy link
Member Author

trylek commented May 28, 2021

OK, I believe the initial results aren't the worst, the test 46239 still fails on arm but otherwise the Pri1 runs seem mostly clean. I'm working on retesting the change after cleaning up base class size manipulation per JanK's PR feedback and I'm going to look into the arm issue but I believe the change is mostly functional.

@trylek trylek force-pushed the 46239-NoRuntimeLayoutChanges branch 3 times, most recently from b2497bc to 87067ae Compare June 2, 2021 15:19
trylek added 12 commits June 2, 2021 22:01
The regression test

<code>src\tests\JIT\Regressions\JitBlue\Runtime_46239</code>

exercises various interesting corner cases of type layout that
weren't handled properly in Crossgen2 on x86 and ARM[32]. This
change fixes the remaining deficiencies and it also adds
provisions for better runtime logging upon type layout mismatches.

Thanks

Tomas
With this change, the only remaining pipelines using Crossgen1 are
"r2r.yml", "r2r-extra.yml" and "release-tests.yml". I haven't yet
identified the pipeline running the "release-tests.yml" script;
for the "r2r*.yml", these now remain the only pipelines exercising
Crossgen1. I don't think it makes sense to switch them over to
CG2 as we already have their CG2 counterparts; my expectation is
that, once CG1 is finally decommissioned, they will be just deleted.

Thanks

Tomas
1) Mimic CoreCLR runtime bug filed under dotnet#53542;

2) Fix pointer alignment for byref-like fields.
@trylek trylek force-pushed the 46239-NoRuntimeLayoutChanges branch from 87067ae to 3dcdc31 Compare June 2, 2021 20:01
@trylek
Copy link
Member Author

trylek commented Jun 3, 2021

OK, I finally have a green outerloop run (including the CG2 legs). I believe the change is ready to be merged in.

LayoutInt cumulativeInstanceFieldPos = CalculateFieldBaseOffset(type, requiresAlign8: false, requiresAlignedBase: false) - offsetBias;
if (!type.IsValueType)
{
// CoreCLR runtime has a bug in field offset calculation in the presence of class inheritance
Copy link
Member

Choose a reason for hiding this comment

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

What is a simple repro to demonstrate this bug?

I have tried:

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Explicit)]
class A1
{
   [FieldOffset(0)]
   public int x;
}

[StructLayout(LayoutKind.Explicit)]
class A2 : A1
{
   [FieldOffset(0)]
   public int y;
}

[StructLayout(LayoutKind.Explicit)]
class A3 : A2
{
   [FieldOffset(0)]
   public int z;
}

class My
{
    static unsafe void Main()
    {
        A3 a = new A3();
        fixed (int *px = &a.x)
        fixed (int *pz = &a.z)
        {
            Console.WriteLine(pz - px);
        }
    }
}

It prints 2 for me. I would expect it to print more than that given this bug that doubles the base offsets.

Copy link
Member Author

@trylek trylek Jun 3, 2021

Choose a reason for hiding this comment

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

When I modify your example like this:

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Explicit)]
class A1
{
   [FieldOffset(0)]
   public byte x;
   [FieldOffset(2)]
   public char x2;
}

[StructLayout(LayoutKind.Explicit)]
class A2 : A1
{
   [FieldOffset(0)]
   public int y;
}

[StructLayout(LayoutKind.Explicit)]
class A3 : A2
{
   [FieldOffset(0)]
   public byte z;
}

class My
{
    static unsafe void Main()
    {
        A3 a = new A3();
        fixed (byte *px = &a.x)
        fixed (byte *pz = &a.z)
        {
            Console.WriteLine(pz - px);
        }
    }
}

I receive 24; if properly packed, I think it should say 8 like you said. Your example doesn't exhibit the issue because it hits this weird statement I stumbled upon a couple of times when working on the change:

if (IsBlittable() || IsManagedSequential())

Thanks

Tomas

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess I should probably add this condition to the quirk, will do.

Copy link
Member

Choose a reason for hiding this comment

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

I receive 24;

And it prints 19 on .NET Framework and .NET Core 3.1. It looks like we accidentally changing behavior here. @jkoritzinsky Can it be caused by your field layout refactoring? It would be nice to get this fixed and covered by tests.

Copy link
Member

Choose a reason for hiding this comment

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

I guess I should probably add this condition to the quirk, will do.

I do not think we need to maintain this quirk. I would delete this, disable the test that it hitting this corner case and file a bug to get it fixed. Note that fixing this is not going to be R2R breaking change.

Copy link
Member

Choose a reason for hiding this comment

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

Possibly. I think I changed a little bit about how classes with inheritance are considered blittable/non-blittable. That might have changed this.

Copy link
Member Author

Choose a reason for hiding this comment

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

OK, I'll remove the quirk and I'll retest to see what exactly breaks.

Copy link
Member Author

Choose a reason for hiding this comment

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

@trylek trylek force-pushed the 46239-NoRuntimeLayoutChanges branch from 16c32ae to f14893c Compare June 3, 2021 18:00
@trylek
Copy link
Member Author

trylek commented Jun 3, 2021

Removal of the quirk naturally hit one of the typesystem tests. I'll fix that once the outerloop tests finish along with any potential additions to issues.targets for tests affected by this issue.

@trylek
Copy link
Member Author

trylek commented Jun 3, 2021

OK, I have removed the double base size quirk and we're discussing the fix on the issue thread #53542. My previous outerloop testing was green so I'm not planning to run a new outerloop test as that doesn't exercise the Crossgen2 unit testing. Please let me know if there's anything else that needs addressing before merging this long-standing change in.

Copy link
Member

@davidwrighton davidwrighton left a comment

Choose a reason for hiding this comment

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

I've been following this change, and it looks good to me now.

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.

LGTM as well. Thank you!

@trylek trylek merged commit b0b317e into dotnet:main Jun 4, 2021
@trylek trylek deleted the 46239-NoRuntimeLayoutChanges branch June 4, 2021 08:40
MichalStrehovsky added a commit that referenced this pull request Jun 4, 2021
These numbers changed in #53424. One of the reasons why I'm not a huge fan of too much commenting...
@mangod9
Copy link
Member

mangod9 commented Jun 4, 2021

Thanks @trylek on fixing this!

stephentoub pushed a commit that referenced this pull request Jun 4, 2021
These numbers changed in #53424. One of the reasons why I'm not a huge fan of too much commenting...
@ghost ghost locked as resolved and limited conversation to collaborators Jul 4, 2021
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.

7 participants