-
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
Convert Array.IsSimpleCopy and CanAssignArray type to managed #104103
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: The first thing that the QCall is going to do is repeat the cache lookup...
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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar to how
RuntimeTypeHandle::CanCastTo
adds 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes (it is fine to do it in a follow up PR).
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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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. |
@@ -1597,13 +1598,36 @@ public static void Copy_SourceAndDestinationNeverConvertible_ThrowsArrayTypeMism | |||
Assert.Throws<ArrayTypeMismatchException>(() => sourceArray.CopyTo(destinationArray, (long)destinationArray.GetLowerBound(0))); | |||
} | |||
|
|||
[Fact] | |||
[SkipOnMono("Mono does not support pointer compatibility in Array.Copy")] |
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.
Could you please open an issue on this and disable the test against this issue?
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.
Is it something we'd ever want to support on mono?
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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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.
Opened #104197 for mono.
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
@@ -1846,6 +1846,39 @@ extern "C" BOOL QCALLTYPE MethodTable_AreTypesEquivalent(MethodTable* mta, Metho | |||
return bResult; | |||
} | |||
|
|||
extern "C" BOOL QCALLTYPE TypeHandle_CanCastTo(void* fromTypeHnd, void* toTypeHnd) |
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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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.
Thank you!
/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:
Result: