-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
RuntimeHelpers.CreateSpan<T> #61079
RuntimeHelpers.CreateSpan<T> #61079
Conversation
* Add non-intrinsic implementation for CreateSpan<T>. * Validate RVA field for Span<T> Co-authored-by: David Wrighton <davidwr@microsoft.com>
* Implement CreateSpan<T> intrinsic.
…t is legal for them to be of a primitive type. Fix the CreateSpan intrinsic to handle that case (dotnet#60525)
… does not support CreateSpan
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label. |
@echesakov Could you help us out with the implementation of the intrinsic? I'd like to remove the hackathon comments and make the codegen as clean as possible. (Currently the codegen creates a ReadOnlySpan local, and then copies from that local whenever its used, but that seems like it should be fixable. Also, there are some hackathon comments in the IL intrinsic implementation that I'd like guidance on. |
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs
Outdated
Show resolved
Hide resolved
Couple items I didn't see covered in the issue / PR
|
Judging by the current implementation it throws ArgumentException for anything other than primitives and enums
Will it protect the API from passing structs with reference types inside? if not why bother 🙂 It needs a sort of "T : nogc" constraint, similar to T : unamanged |
That is what
This is an argument I'm honestly having a hard time responding to. The goal of the typed languages is to move errors that occur at runtime to compile time. There is no path I'm aware of that would ever allow this to work with reference types hence why allow it as an argument when there is an easy option to stop it? |
The constraint does not add much here since this API can be only ever meaningfully used by compiler generated code. We can add it. It does not matter.
Yes, relaxing constraint is not considered a breaking change.
Yes, it is what runtime feature flags are for. |
oops, yeah it makes my comments completely irrelevant, sorry for my 5 cents @jaredpar |
@jaredpar, @jkotas, @EgorBo I don't see why we would want to use a constraint here. We don't have the ability to actually express a useful constraint that actually covers the actual behavior, all usage of this api is actually compiler controlled, and while a struct or unmanaged constraint seems like it might make sense, I can also see counterexamples. For instance, what if we decided to come up with an encoding for a ReadOnlySpan that specified that the PE file would hold the data as a series of null terminated utf8 strings and make that useable from While not in the api proposal, violations of the preconditions are documented in the api comments (which will turn into documentation) to specify that violations will turn into |
All of the intended usage is compiler controlled. There is nothing stopping users from calling this directly. I do understand and agree with the reasons of there isn't a perfect constraint here and hence we should do none. I would lean towards I don't buy the reasoning in this thread about "this is a compiler API" factoring into the decision though. It's an API, if we have the right tools we should be expressing the right contracts.
Sounds reasonable. |
public static ReadOnlySpan<T> CreateSpan<T>(RuntimeFieldHandle fldHandle) | ||
{ | ||
unsafe | ||
{ | ||
void* data = default; | ||
int count = default; | ||
GetSpanDataFrom(fldHandle, typeof(T).TypeHandle, &data, &count); | ||
return new ReadOnlySpan<T>(data, count); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public static ReadOnlySpan<T> CreateSpan<T>(RuntimeFieldHandle fldHandle) | |
{ | |
unsafe | |
{ | |
void* data = default; | |
int count = default; | |
GetSpanDataFrom(fldHandle, typeof(T).TypeHandle, &data, &count); | |
return new ReadOnlySpan<T>(data, count); | |
} | |
} | |
public static unsafe ReadOnlySpan<T> CreateSpan<T>(RuntimeFieldHandle fldHandle) | |
=> new ReadOnlySpan<T>(GetSpanDataFrom(fldHandle, typeof(T).TypeHandle, out int length), length); |
Nit: You can make it one-liner if you change GetSpanDataFrom to return the pointer.
src/mono/mono/metadata/class.c
Outdated
const char *rvaData; | ||
|
||
if (!image_is_dynamic (m_class_get_image (klass))) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and other places should use K&R indentation.
Awesome to this go in! Is someone on point to follow-up on productizing the prototype on the Roslyn side of things? |
Implement
RuntimeHelpers.CreateSpan<T>
#60948Implementation provides for