Convert Array.IsSimpleCopy and CanAssignArray type to managed#104103
Convert Array.IsSimpleCopy and CanAssignArray type to managed#104103jkotas merged 15 commits intodotnet:mainfrom
Conversation
|
Tagging subscribers to this area: @mangod9 |
| { | ||
| // Only pointers are valid for TypeDesc in array element | ||
|
|
||
| // Compatible pointers | ||
| if (srcTH.CanCastTo(destTH)) | ||
| return ArrayAssignType.SimpleCopy; | ||
| } |
There was a problem hiding this comment.
If any pointer type goes through the non-simple copy paths, it will result in the same fatal crash.
|
Could you please take a look at the Mono test failures? |
src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ArrayTests.cs
Outdated
Show resolved
Hide resolved
| if (result != CastResult.MaybeCast) | ||
| return result == CastResult.CanCast; | ||
|
|
||
| return CanCastTo_NoCacheLookup(m_asTAddr, destTH.m_asTAddr); |
There was a problem hiding this comment.
Nit: The first thing that the QCall is going to do is repeat the cache lookup...
There was a problem hiding this comment.
Also, the unmanaged TypeHandle.CanCastTo assumes that some cases are very cheap to check for and it does not bother to add them to the cache. These cases will be much slower here since we are always going to take the QCall transition for them. We should either check for them here and/or add them to cache (similar to how RuntimeTypeHandle::CanCastTo adds them to the cache for the same reasons).
It probably does not matter for the one caller added in this PR, but it may matter for future callers.
There was a problem hiding this comment.
similar to how
RuntimeTypeHandle::CanCastToadds them to the cache for the same reasons
The methods should probably be combined at managed side. They are doing the exact same things.
There was a problem hiding this comment.
Yes (it is fine to do it in a follow up PR).
There was a problem hiding this comment.
They are doing the exact same things.
In fact they aren't. RuntimeTypeHandle::CanCastTo allows T -> Nullable<T>.
The non-cached cases include nullables, COM and I(Dynamic)Castable interfaces. I don't think specially handling them is worthy, even for future callers.
There was a problem hiding this comment.
Yes, you would either need to have a bool flag that controls the special handling or introduce two QCalls with similar implementation.
There was a problem hiding this comment.
Do you plan to do something about this one? (Unifying with RuntimeTypeHandle::CanCastTo should be separate PR, fixing CanCastTo_NoCacheLookup to avoid unnecessary cache lookup should be in this one.)
There was a problem hiding this comment.
Yes, together with some other cases sharable between RuntimeTypeHandle and MethodTable, like type equivalence.
Yes, I expect the same pointer case should also be disabled for mono. |
| } | ||
|
|
||
| [Fact] | ||
| [SkipOnMono("Mono does not support pointer compatibility in Array.Copy")] |
There was a problem hiding this comment.
Could you please open an issue on this and disable the test against this issue?
There was a problem hiding this comment.
Is it something we'd ever want to support on mono?
There was a problem hiding this comment.
We do not want to have behavior differences between different runtime. Every behavior difference between runtime is a bug. We may choose to not fix some of these bugs, but I do not see a good reason for it here.
For example, similar Mono-specific issue in casting logic was fixed just a few days ago: #103841
There was a problem hiding this comment.
Currently the behavior is different among all three runtimes. NativeAOT allows conversion between any pointers.
The current coreclr behavior is really complex to support. Can we make a breaking change instead to support only exactly same pointers?
There was a problem hiding this comment.
The current coreclr behavior is really complex to support.
Why is it complex to support?
Can we make a breaking change instead to support only exactly same pointers?
I do not see how we would justify this breaking change.
src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ArrayTests.cs
Outdated
Show resolved
Hide resolved
|
Anything remaining for this? |
|
Cleaning up the cache lookups #104103 (comment) ? |
src/coreclr/vm/comutilnative.cpp
Outdated
| return bResult; | ||
| } | ||
|
|
||
| extern "C" BOOL QCALLTYPE TypeHandle_CanCastTo(void* fromTypeHnd, void* toTypeHnd) |
There was a problem hiding this comment.
| extern "C" BOOL QCALLTYPE TypeHandle_CanCastTo(void* fromTypeHnd, void* toTypeHnd) | |
| extern "C" BOOL QCALLTYPE TypeHandle_CanCastToNoCacheLookup(void* fromTypeHnd, void* toTypeHnd) |
I think this would be a better name for the QCall to make it clear what it does. Matches convention used for cast helpers (ChkCastAny_NoCacheLookup, etc.)
| public bool CanCastTo(TypeHandle destTH) | ||
| { | ||
| if (m_asTAddr == destTH.m_asTAddr) | ||
| return true; |
There was a problem hiding this comment.
I am wondering whether this logic should live in CastHelpers.cs next to all other casting logic, so that it is not missed if there are any bug fixes.
There was a problem hiding this comment.
They look quite inconsistent...Methods in CastHelpers are HCalls in jithelpers.
BTW does it make sense to convert such methods to QCall, and move out of jithelpers since they are not directly used by JIT?
There was a problem hiding this comment.
does it make sense to convert such methods to QCall
Yes. We want to get rid of all FCalls with HELPER_METHOD_FRAME.
not directly used by JIT
Those are slow path for helpers used by the JIT. Fast paths of those helpers are either in assembly code or in C#.
The split between JIT helpers and other helpers is blurry. It is not unusual for the two to have overlapping logic. We even have methods that are used as JIT helpers, but they are used for other purposes as well. I do not have strong opinions about the best source file split. Anything we come up with will have some downsides.
This can be worked on in a follow up.
|
/ba-g All failures have known issues opened for them. I am not able to tell why BA is not able to match them |
Move the two routines back again.
Removes a HELPER_METHOD_FRAME and improves performance for deciding the path.
Benchmark code:
Details
Result: