-
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
Add RuntimeHelpers.IsReferenceOrContainsReferences<T>() #19493
Comments
RuntimeHelpers.IsReferenceOrContainsReferences<T>()
In Jit terms this and its associated branch can always be elided? Shared code is always a reference; and value type code is always unique per value type? |
Correct. This method will be intrinsic that the JIT can optimize out. |
@jkotas should this employ the caching behaviour internally (e.g. via I would think it best to have the cache as early as possible so there is only one cache. |
There is no point in having the cache if it is JIT intrinsic. And even if it is not JIT intrinsic, it would be just fetching a few bits from Note that there won't be a public portable version of this method. The implementation using reflection will be internal to |
Huh? In your example, it's marked as public. |
Right, this issue is about adding a new public .NET Core API implemented efficiently by the runtime, that may come to .NET Framework in future version. The slower portable Span implementation cannot use this public API because of it needs to run on existing runtimes - that's why it needs internal implementation of the API using reflection. |
Ah, I see. That makes sense. |
The API makes perfect sense. @jkotas: should we add a non-generic version that takes The only thing is that we believe we should name this concept, e.g. blittable. There are likely other areas where we'd use this nomenclature (e.g. casting from @MadsTorgersen @jaredpar, have you guys thought about naming this concept? |
blittable is a bit different though? e.g. Decimal and DateTime are not blittable; but they also are not reference types |
Right, blittable is existing concept, different from this one, specific to interop - msdn definition: https://msdn.microsoft.com/en-us/library/75dwhxf7(v=vs.110).aspx |
The C# spec calls similar concept unmanaged-type, but that concept has a known ugly problems (spooky action at a distance, etc.). I do not think it makes sense to couple this property to it either. |
Explicit blittable support is one item we're confsidering for the next version of C#. It would solve the spooky action by making usages explicit and verified. I don't think it would work for this feature though. The C# feature is a compile time artifact while the methods @jkotas listed need to make decisions at runtim. |
@jkotas ha so much I am still not partial too, so have some questions.
I understand that for JIT intrinsic it does not matter, but when it is not, will it be implemented in coreclr? So there won't be a "portable" version of this, for others e.g. me ;) to use?
So... this can't be used in
As I noted in another issue, I do believe there needs to be better qualification/clear naming of these "concepts" as these are often confused with eachother. F# uses |
Agree. Part of the reason there is no central doc is because a lot of these issues are in the very early stages. We haven't committed to doing them and hence haven't done a lot of work trying to get coherent docs in order.
The term Terms like blittable / primitive are just used today because there are existing implementations / presentations that we are looking at. It's how Midori implemented this feature and hence there is a deal of existing vocabulary that we are using. |
|
I agree with @benaadams The early concepts have nothing to do with this API. It is pretty unlikely that any of them will match what this API does. This API just checks whether the valuetype contains anything tracked by the GC, nothing else. It is meant to allow libraries to do certain operation more efficiently if it does not - the write up about intended use at the top has more details. |
I completely agree, wasn't suggesting this was better than other. Just that we need a new unambiguous term, for future. I think naming of |
This API just checks whether the valuetype contains anything tracked by the GC, nothing else.
Couldn't that be the name then, 'IsTrackedByGC()'? (or something along those lines)
On 29 Nov 2016, at 19:48, "Jan Kotas" <notifications@github.com> wrote:
|
I've heard it said there are only two hard problems in computer science: Cache invalidation, naming things well, and off-by-one errors... |
With APIs there is almost never a "for now". Once in, we can rarely change the APIs (unless it's a preview). Just going with a random name because we can't think of one "right now" isn't a good enough reason to accept breaking changes later, though. @jkotas @jaredpar: To be clear, I wasn't suggesting to use an existing concept for the name. My desire is that we should get our terminology straight. As both of you pointed out, the space is confusing precisely because we never bothered to make these things first class concepts with a better name. |
@terrajobst of course and I agree that the best case would be to get these concepts named for once. Perhaps I also misunderstood @jkotas when he said this would not be "public", since it was probably more related to not being "public" in a portable sense. Still juggling with these different terms too... what's .NET Core specific, what's .NET Standard i.e. portable API?, what's part of coreclr, whats part of corefx, what's part of both etc. And when are we getting all the cool stuff in .NET Framework? Lots to learn, which is great. Just wish there was a better introduction to this ;) |
@nietras Correct. It is consequence of adding it to existing type. It cannot be added to existing runtimes that have the type already.
@mattwarren I had similar observation earlier - my suggestion was |
@jkotas would it not make sense to add it somewhere else then? Not that I couldn't reimplement it in the places I would like to use it, but it would be good to have in a portable way, in the future at least... |
These methods should come to other runtimes in future, and become part of the portable set that you can depend on. There is a challenge with adding one-off methods, and making them available on existing runtimes: We would need to create a new type and likely even a new assembly for it. This approach is ok for large chunks like |
API triage: Ideally we would like to see this method as internal. |
Span does not need it public. It is needed as public for everything else that can take advantage of it, like the optimization in generic collections mentioned at the top of this issue. This API exits as internal in both CoreCLR and CoreFX already (under different names):
|
@jkotas you should come next week to API review meeting to close on this. |
API looks fine. We're not concerned about the language design because they are likely going down a different path. We also considered adding an overload taking |
- Rename IsReferenceFree to IsReferenceOrContainsReferences for consistency with #14047 - Remove IsReferenceFreeCore micro-optimization that is actually hurting. This code runs just once and it is cheaper to do a check via reflection than to spend time in the JIT to optimize the extra code. - Re-enabled disables test
Rename JitHelpers.ContainsReferences<T>() to RuntimeHelpers.IsReferenceOrContainsReferences<T>() and make it public. Work towards https://github.com/dotnet/corefx/issues/14047
- Rename IsReferenceFree to IsReferenceOrContainsReferences for consistency with #14047 - Remove IsReferenceFreeCore micro-optimization that is actually hurting. This code runs just once and it is cheaper to do a check via reflection than to spend time in the JIT to optimize the extra code. - Re-enabled disables test
Rename JitHelpers.ContainsReferences<T>() to RuntimeHelpers.IsReferenceOrContainsReferences<T>() and make it public. Work towards https://github.com/dotnet/corefx/issues/14047
Rename JitHelpers.ContainsReferences<T>() to RuntimeHelpers.IsReferenceOrContainsReferences<T>() and make it public. Work towards https://github.com/dotnet/corefx/issues/14047
Should this issue be closed? |
It was not exposed in the contracts yet. |
Rename JitHelpers.ContainsReferences<T>() to RuntimeHelpers.IsReferenceOrContainsReferences<T>() and make it public. Work towards https://github.com/dotnet/corefx/issues/14047
This method will return true if T is reference type; or if T is value type that contains reference type fields. false otherwise.
This API is intended to be used primarily for optimizations:
Generic List calls Array.Clear on its underlying array in the implementation of Clear, RemoveAll, RemoveRange methods today. It has to do so because the generic argument can contain references which must be freed for GC. It can be skipped using this method when not required.
Algorithms for memory manipulations can have optimized paths for memory blocks without GC references. This method can be used to determine whether the optimized path is safe to use.
Span<T>
is example of such memory manipulation algorithms. It going to use this API internally in its implementation.This API addition was tracked by CoreCLR issue. https://github.com/dotnet/coreclr/issues/1135 has a lot of discussion about the right name for this API. The alternative names considered include
ContainsReferences
,IsGCPointerOrContainsGCPointers
.The text was updated successfully, but these errors were encountered: