Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Handle generically dissimilar type concerns as well as handle derived…
… type case in the managed compiler
  • Loading branch information
davidwrighton authored and Sergey committed Aug 24, 2021
commit f40a7dc12f4114adc52b28a706bf197a5120f321
34 changes: 32 additions & 2 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3533,8 +3533,38 @@ private uint getExpectedTargetArchitecture()

private bool doesFieldBelongToClass(CORINFO_FIELD_STRUCT_* fld, CORINFO_CLASS_STRUCT_* cls)
{
// we need it to return true for both canon and not-canon classes.
return (HandleToObject(fld).OwningType == HandleToObject(cls));
var field = HandleToObject(fld);
var queryType = HandleToObject(cls);

Debug.Assert(!field.IsStatic);

// doesFieldBelongToClass implements the predicate of...
// if field is not associated with the class in any way, return false.
// if field is the only FieldDesc that the JIT might see for a given class handle
// and logical field pair then return true. This is needed as the field handle here
// is used as a key into a hashtable mapping writes to fields to value numbers.
//
// In this implmentation this is made more complex as the JIT is exposed to CORINFO_FIELD_STRUCT
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make it clearer that the crossgen2 behavior is different than the runtime behavior?

Is this something we should fix down the road? Seems like it would make us more conservative in places when doing R2R codegen.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make it clearer that the crossgen2 behavior is different than the runtime behavior?

I will add a comment.

Is this something we should fix down the road? Seems like it would make us more conservative in places when doing R2R codegen.

I hope we will target to get rid of FldSeq and its dependency on FIELD_HANDLE and STRUCT_HANDLE.

If not we can do:

if (crossgen2)
{
 canonFieldHandle = JitEEInterface::getCanonField(fieldHandle);
  bool doesBelong = JitEEInterface::doesFieldBelongToClass(canonFieldHandle , clsHnd);
}

but I don't like such a solution, it hammers JIT to VM behavior, we can do it always, not only for crossgen2, but then it is an unnecessary VM call.

// pointers which represent exact instantions, so performing exact matching is the necessary approach

// BaseType._field, BaseType -> true
// BaseType._field, DerivedType -> true
// BaseType<__Canon>._field, BaseType<__Canon> -> true
// BaseType<__Canon>._field, BaseType<string> -> false
// BaseType<__Canon>._field, BaseType<object> -> false
// BaseType<sbyte>._field, BaseType<sbyte> -> true
// BaseType<sbyte>._field, BaseType<byte> -> false

var fieldOwnerType = field.OwningType;

while (queryType != null)
{
if (fieldOwnerType == queryType)
return true;
queryType = queryType.BaseType;
}

return false;
}

private bool isMethodDefinedInCoreLib()
Expand Down
27 changes: 24 additions & 3 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11480,8 +11480,8 @@ bool CEEJitInfo::doesFieldBelongToClass(CORINFO_FIELD_HANDLE fldHnd, CORINFO_CLA
{
CONTRACTL {
THROWS;
GC_TRIGGERS;
MODE_PREEMPTIVE;
GC_TRIGGERS;
MODE_PREEMPTIVE;
} CONTRACTL_END;

bool result;
Expand All @@ -11491,8 +11491,29 @@ bool CEEJitInfo::doesFieldBelongToClass(CORINFO_FIELD_HANDLE fldHnd, CORINFO_CLA
FieldDesc* field = (FieldDesc*) fldHnd;
TypeHandle th(cls);

_ASSERTE(!field->IsStatic());

// doesFieldBelongToClass implements the predicate of...
// if field is not associated with the class in any way, return false.
// if field is the only FieldDesc that the JIT might see for a given class handle
// and logical field pair then return true. This is needed as the field handle here
// is used as a key into a hashtable mapping writes to fields to value numbers.
//
// In the CoreCLR VM implementation, verifying that the canonical MethodTable of
// the field matches the type found via GetExactDeclaringType, as all instance fields
// are only held on the canonical MethodTable.
// This yields a truth table such as

// BaseType._field, BaseType -> true
// BaseType._field, DerivedType -> true
// BaseType<__Canon>._field, BaseType<__Canon> -> true
// BaseType<__Canon>._field, BaseType<string> -> true
// BaseType<__Canon>._field, BaseType<object> -> true
// BaseType<sbyte>._field, BaseType<sbyte> -> true
// BaseType<sbyte>._field, BaseType<byte> -> false

MethodTable* pMT = field->GetExactDeclaringType(th.GetMethodTable());
result = (pMT != nullptr);
result = (pMT != nullptr) && (pMT->GetCanonicalMethodTable() == field->GetApproxEnclosingMethodTable()->GetCanonicalMethodTable());

EE_TO_JIT_TRANSITION();

Expand Down