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

CoreCLR support for InlineArrayAttribute. (struct layout part) #82744

Merged
merged 30 commits into from
Mar 16, 2023

Conversation

VSadov
Copy link
Member

@VSadov VSadov commented Feb 27, 2023

Implements support for InlineArrayAtribute as in #61135
Re: #81145

  • port relevant changes from the prototype
  • make the layout replication based on an attribute
  • add the actual attribute
  • write tests
  • friendly loader errors
  • optimized layout for "all-objects" case - will be a separate follow up change.

@VSadov
Copy link
Member Author

VSadov commented Mar 4, 2023

CC: @mangod9 @AaronRobinsonMSFT

@VSadov VSadov marked this pull request as ready for review March 4, 2023 00:47
@VSadov VSadov requested a review from MichalStrehovsky as a code owner March 4, 2023 00:47
@VSadov
Copy link
Member Author

VSadov commented Mar 4, 2023

I think the PR is ready to be reviewed.

@mangod9
Copy link
Member

mangod9 commented Mar 4, 2023

@davidwrighton as well.

@@ -852,7 +852,7 @@ enum CorInfoFlag
CORINFO_FLG_ARRAY = 0x00080000, // class is an array class (initialized differently)
CORINFO_FLG_OVERLAPPING_FIELDS = 0x00100000, // struct or class has fields that overlap (aka union)
CORINFO_FLG_INTERFACE = 0x00200000, // it is an interface
CORINFO_FLG_DONT_DIG_FIELDS = 0x00400000, // don't ask field info, AOT can't rely on it (used for types outside of AOT compilation version bubble)
CORINFO_FLG_DONT_DIG_FIELDS = 0x00400000, // don't ask field info (used for types outside of AOT compilation version bubble and value arrays)
Copy link
Member Author

Choose a reason for hiding this comment

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

This flag was called CORINFO_FLG_DONT_PROMOTE at the time of the prototype. We do not want inline arrays to promote as indexing relies on contiguous layout.

I assume the flag still has the effect of suppressing field promotion.

Copy link
Member

Choose a reason for hiding this comment

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

We should double check with the JIT team - I would think we should be setting similar flags that we set for explicit layout structs and explicit layout structs don't set this one.

Copy link
Member Author

Choose a reason for hiding this comment

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

@dotnet/jit-contrib can someone from the JIT team take a look at this part?

Copy link
Member

Choose a reason for hiding this comment

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

CORINFO_FLG_DONT_DIG_FIELDS doesn't always suppress promotion (eg a single gc ref field struct will still get promoted).

I would introduce a new flag describing this, something like CORINFO_FLG_INDEXABLE_FIELDS, and update the jit to block promotion when it sees it. Looks like there is still one free bit?

Down the road we might be doing more flexible partial promotion and perhaps even handle cases like these where we know exactly which fields are being touched over some span of 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.

update the jit to block promotion when it sees it

Is there an easy way to find all the places that need to care about the bit?

Copy link
Member

Choose a reason for hiding this comment

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

@VSadov I do think we need a JIT-EE GUID update here -- otherwise it can expose all sorts of latent issues for the JIT team once we get newer collections with this flag that older JITs do not handle.

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes sense. Thanks!! I will change the guid in a follow up change.

In theory the presence of the attribute will imply the new runtime and prevent many versioning issues, but it is better to be sure.

Copy link
Member Author

Choose a reason for hiding this comment

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

how hard would it be to begin consuming the support?

Fairly easy. Roslyn will add a layer of convenience, but otherwise the feature can be used directly.
I’ve added some use cases in corlib and libraries as a part of the change.

The only usual caveat with using a feature this early is possibly having to change things if the feature changes based on feedback.

Copy link
Member Author

Choose a reason for hiding this comment

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

@jakobbotsch Sorry, did not notice your yesterdays comment.

Copy link
Member

Choose a reason for hiding this comment

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

In theory the presence of the attribute will imply the new runtime and prevent many versioning issues, but it is better to be sure.

The problem for the JIT team is that we disambiguate compatibility of SPMI collections via the JIT-EE GUID. We automatically collect every Sunday, so after that we will start seeing contexts with the new flag set and no indication that newer JITs are needed to properly handle this. That might not cause any problems except silent bad codegen for our SPMI runs, but it could also conceivably cause spurious assertion failures.

FWIW, @EgorBo just merged #83430 which includes a JIT-EE GUID bump, so you won't need to do that in a follow-up change after all.

Fairly easy. Roslyn will add a layer of convenience, but otherwise the feature can be used directly.
I’ve added some use cases in corlib and libraries as a part of the change.

I've looked at some of the examples, that looks fairly straightforward. I guess the main thing is how to get access to InlineArrayAttribute from the programs I'm generating.

}
else
{
// TODO: diagnostics, repeat must be > 0
Copy link
Member Author

Choose a reason for hiding this comment

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

Do we want a special diagnostic messages for this or IDS_CLASSLOAD_GENERAL is good enough?

Copy link
Member

Choose a reason for hiding this comment

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

The bar for type loader error messages has been:

  • Good error message if it is something you can hit by writing C#.
  • Generic error message is ok if it is something that can be only hit by writing IL.

Copy link
Member

Choose a reason for hiding this comment

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

oh, made a similar comment above. If there is some likelihood where customers might hit such cases a specific message would be helpful.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good error message if it is something you can hit by writing C#.

Yes, these can be hit, so need specific messages.

Copy link
Member

Choose a reason for hiding this comment

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

Good error message if it is something you can hit by writing C#.

Yes, these can be hit, so need specific messages.

Isn't C# going to have syntax for this? If so, it's likely they're going to prevent people placing this attribute on random stuff like they do for IsByRefLikeAttribute. Would want to double check, but it's not an unreasonable request to make.

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 think for now we should assume that the attribute is valid for direct use. It is not as dangerous as IsByRefLike and is relatively easy to use correctly. There could be some use scenarios that are not covered by C# features.

If eventually we see that it is better to disallow, we can do that and make errors less friendly.
I think for the time being, while C# features are in design/prototyping/development, nicer errors would be a good thing.

long size = instanceByteSizeAndAlignment.Size.AsInt;
size *= repeat;

// limit the max size of array instance to 1MiB
Copy link
Member

Choose a reason for hiding this comment

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

Add same limit to the coreclr typeloader as well?

Comment on lines 285 to 287
private object? _arg1;
private object? _arg2;
private object? _arg3;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
private object? _arg1;
private object? _arg2;
private object? _arg3;
private T _arg1;
private T _arg2;
private T _arg3;

?

@VSadov
Copy link
Member Author

VSadov commented Mar 12, 2023

/azp run runtime-extra-platforms

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Diagnostics;
Copy link
Member

Choose a reason for hiding this comment

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

Unused using?

/// <summary>
/// Gets a value indicating whether this is an inline array type
/// </summary>
public virtual bool IsInlineArray
Copy link
Member

Choose a reason for hiding this comment

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

This should not be virtual. Things that are computed from flags are determined from flags (and fully inlineable).

@@ -91,6 +91,13 @@ public override bool IsSequentialLayout
}
}

public override bool IsInlineArray => Length > 0;
Copy link
Member

Choose a reason for hiding this comment

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

Let's not convert this to an inline array at this time. I'm concerned we have very little test coverage for this, at least until we can run the src/tests tree. We're not far from being able to do that.

This type is only used in marshalled interop and currently the only test coverage for marshalled interop we have is a smoke test under src/test/nativeaot, because we were very efficient in removing all built-in marshalling use within libraries.

Copy link
Member Author

Choose a reason for hiding this comment

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

Right. If there is little coverage, there is not a lot of point to make this change right now.

@@ -25,5 +25,11 @@ public partial class InstantiatedType
if (_typeDef.IsIntrinsic)
flags |= TypeFlags.IsIntrinsic;
}

partial void AddComputedInlineArrayFlag(ref TypeFlags flags)
Copy link
Member

Choose a reason for hiding this comment

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

Technically this should go to a new file TypeDesc.Metadata.cs, but maybe this is fine.

Copy link
Member Author

Choose a reason for hiding this comment

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

Technically this should go to a new file TypeDesc.Metadata.cs, but maybe this is fine.

I will not change this part then.
Let me know if you rethink this.

Copy link
Member

@AndyAyersMS AndyAyersMS left a comment

Choose a reason for hiding this comment

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

Jit changes look good.

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!

@VSadov
Copy link
Member Author

VSadov commented Mar 16, 2023

Thanks!!

@VSadov VSadov merged commit a2b70f9 into dotnet:main Mar 16, 2023
@VSadov VSadov deleted the valArr branch March 16, 2023 21:45
@ghost ghost locked as resolved and limited conversation to collaborators Apr 16, 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.

10 participants