-
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
Use similar types for self-referential generics instead of the exact canonical type #83995
Conversation
- Take advantage of work done a few years ago to simplify the interaction with the interop subsystem - In the problematic case, simulate loads with two different types as instantiations which are unrelated in field layout, and see if they match up. Only enable this code in a few very small isolated parts of the runtime - Filter more of the logic through the byvalue class cache which should improve performance a bit - Similarly when considering blittability, tweak the logic to use the special load path - The current fix is expected to break Unix X64, but I believe the rest of the OS/Architecture pairs should work - Handling of static fields also needs examination for correctness
Fixes #6924 |
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'm still going through this.
// Everett C++ compiler can generate a TypeRef with RS=0 | ||
// without respective TypeDef for unmanaged valuetypes, | ||
// referenced only by pointers to them. | ||
// In such case, GetTypeHandleThrowing returns null handle, | ||
// and we return E_T_VOID |
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 think we should update this.
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.
Probably, but this change is confusing enough as it is without adding a known potential behavior change. I'd like to see that done as a separate 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.
If you do that, please get rid of the weirdo ThrowButNullV11McppWorkaround logic too.
src/coreclr/vm/methodtable.cpp
Outdated
@@ -2238,11 +2239,20 @@ static SystemVClassificationType ReClassifyField(SystemVClassificationType origi | |||
} | |||
} | |||
|
|||
MethodTable* ByValueClassCacheLookup(MethodTable** pByValueClassCache, unsigned index) |
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.
MethodTable* ByValueClassCacheLookup(MethodTable** pByValueClassCache, unsigned index) | |
static MethodTable* ByValueClassCacheLookup(MethodTable** pByValueClassCache, uint32_t index) |
src/coreclr/vm/siginfo.cpp
Outdated
} | ||
} | ||
} | ||
handlingRecursiveGenericFieldScenario = 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.
recursionDetected
not used?
src/coreclr/vm/fieldmarshaler.cpp
Outdated
CONTRACTL | ||
{ | ||
THROWS; | ||
GC_TRIGGERS; | ||
MODE_ANY; | ||
} | ||
CONTRACTL_END; |
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.
CONTRACTL | |
{ | |
THROWS; | |
GC_TRIGGERS; | |
MODE_ANY; | |
} | |
CONTRACTL_END; | |
STANDARD_VM_CONTRACT; |
src/coreclr/vm/field.h
Outdated
@@ -324,6 +324,9 @@ class FieldDesc | |||
// Return -1 if the type isn't loaded yet (i.e. if LookupFieldTypeHandle() would return null) | |||
UINT GetSize(); | |||
|
|||
// Return -1 if the type is a structure and pMTOfValueTypeField is NULL and LookupFieldTypeHandle() returns null |
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 we actually depend on this returning -1 anywhere? It seems we always assume that it is going to succeed. Should we make this more restrictive and assert instead of returning -1?
This does not seem to handle indirectly self-referential generics. For example, this compiles fine, but still fails to run:
Is it expected that this does not work? EDIT: https://github.com/dotnet/runtime/pull/83995/files#diff-07105ca3a0aa4623290e4d68b73dbba2ff71b75d61ab7b0ee4f28d91e3a64864R1414 comment says this is not expected to work. |
Take advantage of work done a few years ago to simplify the interaction with the interop subsystem
In the problematic case, simulate loads with two different types as instantiations which are unrelated in field layout, and see if they match up. Only enable this code in a few very small isolated parts of the runtime
Filter more of the type loader logic through the byvalue class cache which should improve performance a bit
Similarly when considering blittability, tweak the logic to use the special load path
Support for self-recursive generics is not enabled for static fields, as that requires a somewhat different tweak, and there is less apparent demand. (For that scenario self-referential generics really should support having fields of type T.)
Support for indirect self-recursive generics is also not enabled. The approach taken here is not practical for that, and there does not appear to be significant demand for that either.
Fixes #6924