Skip to content

Commit

Permalink
DEBUG-ONLY: FieldInfo (2.0)
Browse files Browse the repository at this point in the history
Allows this change to be tested via SPMI.
  • Loading branch information
SingleAccretion committed Mar 14, 2022
1 parent 44ec3c9 commit b8bd75a
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 13 deletions.
11 changes: 8 additions & 3 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ var_types Compiler::getJitGCType(BYTE gcType)
// true if the given struct type contains only one pointer-sized integer value type,
// false otherwise.
//
bool Compiler::isTrivialPointerSizedStruct(CORINFO_CLASS_HANDLE clsHnd) const
bool Compiler::isTrivialPointerSizedStruct(CORINFO_CLASS_HANDLE clsHnd)
{
assert(info.compCompHnd->isValueClass(clsHnd));
if (info.compCompHnd->getClassSize(clsHnd) != TARGET_POINTER_SIZE)
Expand All @@ -409,6 +409,8 @@ bool Compiler::isTrivialPointerSizedStruct(CORINFO_CLASS_HANDLE clsHnd) const
CORINFO_FIELD_HANDLE fldHnd = info.compCompHnd->getFieldInClass(clsHnd, 0);
CorInfoType fieldType = info.compCompHnd->getFieldType(fldHnd, pClsHnd);

INDEBUG(RecordStructFieldInfo(fldHnd));

var_types vt = JITtype2varType(fieldType);

if (fieldType == CORINFO_TYPE_VALUECLASS)
Expand Down Expand Up @@ -1914,8 +1916,11 @@ void Compiler::compInit(ArenaAllocator* pAlloc,
m_nodeTestData = nullptr;
m_loopHoistCSEClass = FIRST_LOOP_HOIST_CSE_CLASS;
#endif
m_switchDescMap = nullptr;
m_blockToEHPreds = nullptr;
m_switchDescMap = nullptr;
m_blockToEHPreds = nullptr;
#ifdef DEBUG
m_fieldInfoMap = nullptr;
#endif // DEBUG
m_fieldSeqStore = nullptr;
m_zeroOffsetFieldMap = nullptr;
m_arrayInfoMap = nullptr;
Expand Down
70 changes: 61 additions & 9 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2648,7 +2648,7 @@ class Compiler
#endif // FEATURE_MULTIREG_RET

#ifdef TARGET_X86
bool isTrivialPointerSizedStruct(CORINFO_CLASS_HANDLE clsHnd) const;
bool isTrivialPointerSizedStruct(CORINFO_CLASS_HANDLE clsHnd);
#endif // TARGET_X86

//-------------------------------------------------------------------------
Expand Down Expand Up @@ -11135,20 +11135,64 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
void JitTestCheckVN(); // Value numbering tests.
#endif // DEBUG

#ifdef DEBUG
FieldInfoMap* m_fieldInfoMap;

FieldInfoMap* GetFieldInfoMap()
{
Compiler* rootCompiler = impInlineRoot();
if (rootCompiler->m_fieldInfoMap == nullptr)
{
CompAllocator allocator = rootCompiler->getAllocator(CMK_DebugOnly);
rootCompiler->m_fieldInfoMap = new (allocator) FieldInfoMap(allocator);
}

return rootCompiler->m_fieldInfoMap;
}

void RecordFieldInfo(CORINFO_FIELD_HANDLE fieldHnd, CORINFO_FIELD_INFO* eeFieldInfo)
{
FieldInfoMap* map = GetFieldInfoMap();

if (!map->Lookup(fieldHnd))
{
map->Set(fieldHnd, new (map->GetAllocator()) FieldInfo(eeFieldInfo));
}
}

void RecordStructFieldInfo(CORINFO_FIELD_HANDLE fieldHnd)
{
FieldInfoMap* map = GetFieldInfoMap();

if (!map->Lookup(fieldHnd))
{
map->Set(fieldHnd, new (map->GetAllocator()) FieldInfo());
}
}

const FieldInfo* GetFieldInfo(CORINFO_FIELD_HANDLE fieldHnd)
{
const FieldInfo* fieldInfo = nullptr;
bool fieldInfoFound = GetFieldInfoMap()->Lookup(fieldHnd, &fieldInfo);
assert(fieldInfoFound);

return fieldInfo;
}
#endif // DEBUG

// The "FieldSeqStore", for canonicalizing field sequences. See the definition of FieldSeqStore for
// operations.
FieldSeqStore* m_fieldSeqStore;

FieldSeqStore* GetFieldSeqStore()
{
Compiler* compRoot = impInlineRoot();
if (compRoot->m_fieldSeqStore == nullptr)
Compiler* rootCompiler = impInlineRoot();
if (rootCompiler->m_fieldSeqStore == nullptr)
{
// Create a CompAllocator that labels sub-structure with CMK_FieldSeqStore, and use that for allocation.
CompAllocator ialloc(getAllocator(CMK_FieldSeqStore));
compRoot->m_fieldSeqStore = new (ialloc) FieldSeqStore(ialloc);
CompAllocator allocator = getAllocator(CMK_FieldSeqStore);
rootCompiler->m_fieldSeqStore = new (allocator) FieldSeqStore(allocator);
}
return compRoot->m_fieldSeqStore;
return rootCompiler->m_fieldSeqStore;
}

typedef JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, FieldSeqNode*> NodeToFieldSeqMap;
Expand Down Expand Up @@ -11262,15 +11306,23 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
{
m_refAnyClass = info.compCompHnd->getBuiltinClass(CLASSID_TYPED_BYREF);
}
return info.compCompHnd->getFieldInClass(m_refAnyClass, 0);

CORINFO_FIELD_HANDLE dataFieldHnd = info.compCompHnd->getFieldInClass(m_refAnyClass, 0);
INDEBUG(RecordStructFieldInfo(dataFieldHnd));

return dataFieldHnd;
}
CORINFO_FIELD_HANDLE GetRefanyTypeField()
{
if (m_refAnyClass == nullptr)
{
m_refAnyClass = info.compCompHnd->getBuiltinClass(CLASSID_TYPED_BYREF);
}
return info.compCompHnd->getFieldInClass(m_refAnyClass, 1);

CORINFO_FIELD_HANDLE typeFieldHnd = info.compCompHnd->getFieldInClass(m_refAnyClass, 1);
INDEBUG(RecordStructFieldInfo(typeFieldHnd));

return typeFieldHnd;
}

#if VARSET_COUNTOPS
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/jit/ee_il_dll.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ void Compiler::eeGetFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
CORINFO_FIELD_INFO* pResult)
{
info.compCompHnd->getFieldInfo(pResolvedToken, info.compMethodHnd, accessFlags, pResult);
INDEBUG(RecordFieldInfo(pResolvedToken->hField, pResult));
}

/*****************************************************************************
Expand All @@ -64,7 +65,11 @@ bool Compiler::eeIsIntrinsic(CORINFO_METHOD_HANDLE ftn)
FORCEINLINE
bool Compiler::eeIsFieldStatic(CORINFO_FIELD_HANDLE fldHnd)
{
#ifdef DEBUG
return GetFieldInfo(fldHnd)->IsStatic();
#else
return info.compCompHnd->isFieldStatic(fldHnd);
#endif
}

FORCEINLINE
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12737,6 +12737,8 @@ GenTree* Compiler::gtFoldBoxNullable(GenTree* tree)
CORINFO_CLASS_HANDLE nullableHnd = gtGetStructHandle(arg->AsOp()->gtOp1);
CORINFO_FIELD_HANDLE fieldHnd = info.compCompHnd->getFieldInClass(nullableHnd, 0);

INDEBUG(RecordStructFieldInfo(fieldHnd));

// Replace the box with an access of the nullable 'hasValue' field.
JITDUMP("\nSuccess: replacing BOX_NULLABLE(&x) [%06u] with x.hasValue\n", dspTreeID(op));
GenTree* newOp = gtNewFieldRef(TYP_BOOL, fieldHnd, arg, 0);
Expand Down
42 changes: 42 additions & 0 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,48 @@ struct FieldSeqNode
}
};

#ifdef DEBUG
// This class carries some about fields information neeeded for asserts from imporation to VN.
// Essentially, this is CORINFO_FIELD_INFO but Jit-specific and smaller.
class FieldInfo
{
const unsigned m_flags;
const CORINFO_FIELD_ACCESSOR m_accessor;

public:
FieldInfo(CORINFO_FIELD_INFO* eeFieldInfo)
: m_flags(eeFieldInfo->fieldFlags), m_accessor(eeFieldInfo->fieldAccessor)
{
}

FieldInfo() : m_flags(0), m_accessor(CORINFO_FIELD_INSTANCE)
{
}

bool IsStatic() const
{
return (m_flags & CORINFO_FLG_FIELD_STATIC) != 0;
}

bool IsBoxedStatic() const
{
return (m_flags & CORINFO_FLG_FIELD_STATIC_IN_HEAP) != 0;
}

bool IsSharedStatic() const
{
return m_accessor == CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER;
}

bool IsReadOnly() const
{
return (m_flags & CORINFO_FLG_FIELD_FINAL) != 0;
}
};

typedef JitHashTable<CORINFO_FIELD_HANDLE, JitPtrKeyFuncs<CORINFO_FIELD_STRUCT_>, const FieldInfo*> FieldInfoMap;
#endif // DEBUG

// This class canonicalizes field sequences.
class FieldSeqStore
{
Expand Down
14 changes: 13 additions & 1 deletion src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3712,6 +3712,9 @@ GenTree* Compiler::impCreateSpanIntrinsic(CORINFO_SIG_INFO* sig)
CORINFO_FIELD_HANDLE pointerFieldHnd = info.compCompHnd->getFieldInClass(spanHnd, 0);
CORINFO_FIELD_HANDLE lengthFieldHnd = info.compCompHnd->getFieldInClass(spanHnd, 1);

INDEBUG(RecordStructFieldInfo(pointerFieldHnd));
INDEBUG(RecordStructFieldInfo(lengthFieldHnd));

GenTreeLclFld* pointerField = gtNewLclFldNode(spanTempNum, TYP_BYREF, 0);
pointerField->SetFieldSeq(GetFieldSeqStore()->CreateSingleton(pointerFieldHnd));
GenTree* pointerFieldAsg = gtNewAssignNode(pointerField, pointerValue);
Expand Down Expand Up @@ -3994,6 +3997,8 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
assert(byReferenceStruct != nullptr);
impPushOnStack(byReferenceStruct, typeInfo(TI_STRUCT, clsHnd));
retNode = assign;

INDEBUG(RecordStructFieldInfo(fldHnd));
break;
}

Expand All @@ -4004,6 +4009,8 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
CORINFO_FIELD_HANDLE fldHnd = info.compCompHnd->getFieldInClass(clsHnd, 0);
GenTree* field = gtNewFieldRef(TYP_BYREF, fldHnd, op1, 0);
retNode = field;

INDEBUG(RecordStructFieldInfo(fldHnd));
break;
}

Expand Down Expand Up @@ -4128,6 +4135,8 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
GenTree* length = gtNewFieldRef(TYP_INT, lengthHnd, ptrToSpan, lengthOffset);
GenTree* boundsCheck = new (this, GT_BOUNDS_CHECK) GenTreeBoundsChk(index, length, SCK_RNGCHK_FAIL);

INDEBUG(RecordStructFieldInfo(lengthHnd));

// Element access
index = indexClone;

Expand All @@ -4153,6 +4162,8 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
GenTree* data = gtNewFieldRef(TYP_BYREF, ptrHnd, ptrToSpanClone, ptrOffset);
GenTree* result = gtNewOperNode(GT_ADD, TYP_BYREF, data, index);

INDEBUG(RecordStructFieldInfo(ptrHnd));

// Prepare result
var_types resultType = JITtype2varType(sig->retType);
assert(resultType == result->TypeGet());
Expand Down Expand Up @@ -7110,6 +7121,8 @@ int Compiler::impBoxPatternMatch(CORINFO_RESOLVED_TOKEN* pResolvedToken,
const CORINFO_FIELD_HANDLE hasValueFldHnd =
info.compCompHnd->getFieldInClass(nullableCls, 0);

INDEBUG(RecordStructFieldInfo(hasValueFldHnd));

assert(info.compCompHnd->getFieldOffset(hasValueFldHnd) == 0);
assert(!strcmp(info.compCompHnd->getFieldName(hasValueFldHnd, nullptr),
"hasValue"));
Expand Down Expand Up @@ -8231,7 +8244,6 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT
!isBoxedStatic ? GetFieldSeqStore()->CreateSingleton(pResolvedToken->hField) : FieldSeqStore::NotAField();

GenTree* op1;

switch (pFieldInfo->fieldAccessor)
{
case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER:
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/jit/importer_vectorization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,9 @@ GenTree* Compiler::impSpanEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO*
CORINFO_FIELD_HANDLE lengthHnd = info.compCompHnd->getFieldInClass(spanCls, 1);
const unsigned lengthOffset = info.compCompHnd->getFieldOffset(lengthHnd);

INDEBUG(RecordStructFieldInfo(pointerHnd));
INDEBUG(RecordStructFieldInfo(lengthHnd));

// Create a placeholder for Span object - we're not going to Append it to statements
// in advance to avoid redundant spills in case if we fail to vectorize
unsigned spanObjRef = lvaGrabTemp(true DEBUGARG("spanObj tmp"));
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/jit/lclvars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1730,6 +1730,8 @@ bool Compiler::StructPromotionHelper::CanPromoteStructType(CORINFO_CLASS_HANDLE
structPromotionInfo.fields[ordinal] = GetFieldInfo(fieldHnd, ordinal);
const lvaStructFieldInfo& fieldInfo = structPromotionInfo.fields[ordinal];

INDEBUG(compiler->RecordStructFieldInfo(fieldHnd));

noway_assert(fieldInfo.fldOffset < structSize);

if (fieldInfo.fldSize == 0)
Expand Down Expand Up @@ -2192,6 +2194,9 @@ bool Compiler::StructPromotionHelper::TryPromoteStructField(lvaStructFieldInfo&
// the struct field.
CORINFO_FIELD_HANDLE innerFieldHndl = compHandle->getFieldInClass(fieldInfo.fldTypeHnd, 0);
unsigned innerFieldOffset = compHandle->getFieldOffset(innerFieldHndl);

INDEBUG(compiler->RecordStructFieldInfo(innerFieldHndl));

if (innerFieldOffset != 0)
{
return false;
Expand Down Expand Up @@ -2833,6 +2838,9 @@ void Compiler::makeExtraStructQueries(CORINFO_CLASS_HANDLE structHandle, int lev
CORINFO_CLASS_HANDLE fieldClassHandle = NO_CLASS_HANDLE;
CorInfoType fieldCorType = info.compCompHnd->getFieldType(fieldHandle, &fieldClassHandle);
var_types fieldVarType = JITtype2varType(fieldCorType);

INDEBUG(RecordStructFieldInfo(fieldHandle));

if (fieldClassHandle != NO_CLASS_HANDLE)
{
if (varTypeIsStruct(fieldVarType))
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/jit/morphblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,9 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField()
CORINFO_CLASS_HANDLE classHnd = srcVarDsc->GetStructHnd();
CORINFO_FIELD_HANDLE fieldHnd =
m_comp->info.compCompHnd->getFieldInClass(classHnd, srcFieldVarDsc->lvFldOrdinal);

INDEBUG(m_comp->RecordStructFieldInfo(fieldHnd));

FieldSeqNode* curFieldSeq = m_comp->GetFieldSeqStore()->CreateSingleton(fieldHnd);

unsigned srcFieldOffset = m_comp->lvaGetDesc(srcFieldLclNum)->lvFldOffset;
Expand Down Expand Up @@ -1342,6 +1345,9 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField()
CORINFO_FIELD_HANDLE fieldHnd =
m_comp->info.compCompHnd->getFieldInClass(classHnd,
m_comp->lvaGetDesc(dstFieldLclNum)->lvFldOrdinal);

INDEBUG(m_comp->RecordStructFieldInfo(fieldHnd));

FieldSeqNode* curFieldSeq = m_comp->GetFieldSeqStore()->CreateSingleton(fieldHnd);
var_types destType = m_comp->lvaGetDesc(dstFieldLclNum)->lvType;

Expand Down

0 comments on commit b8bd75a

Please sign in to comment.