未验证 提交 c6ca9dc0 编写于 作者: S Sergey Andreenko 提交者: GitHub

[crossgen2] Promote single byref aot. (#65682)

* Rename `CORINFO_FLG_DONT_PROMOTE` to `CORINFO_FLG_DONT_DIG_FIELDS`.

* Support promotion of `struct{ 1 gcref; }` outside of version bubble.
上级 04be7a99
......@@ -841,7 +841,7 @@ enum CorInfoFlag
CORINFO_FLG_ARRAY = 0x00080000, // class is an array class (initialized differently)
CORINFO_FLG_OVERLAPPING_FIELDS = 0x00100000, // struct or class has fields that overlap (aka union)
CORINFO_FLG_INTERFACE = 0x00200000, // it is an interface
CORINFO_FLG_DONT_PROMOTE = 0x00400000, // don't try to promote fields (used for types outside of AOT compilation version bubble)
CORINFO_FLG_DONT_DIG_FIELDS = 0x00400000, // don't ask field info, AOT can't rely on it (used for types outside of AOT compilation version bubble)
CORINFO_FLG_CUSTOMLAYOUT = 0x00800000, // does this struct have custom layout?
CORINFO_FLG_CONTAINS_GC_PTR = 0x01000000, // does the class contain a gc ptr ?
CORINFO_FLG_DELEGATE = 0x02000000, // is this a subclass of delegate or multicast delegate ?
......
......@@ -4149,6 +4149,8 @@ public:
void PromoteStructVar(unsigned lclNum);
void SortStructFields();
bool CanConstructAndPromoteField(lvaStructPromotionInfo* structPromotionInfo);
lvaStructFieldInfo GetFieldInfo(CORINFO_FIELD_HANDLE fieldHnd, BYTE ordinal);
bool TryPromoteStructField(lvaStructFieldInfo& outerFieldInfo);
......
......@@ -4480,9 +4480,9 @@ inline static bool StructHasCustomLayout(DWORD attribs)
return ((attribs & CORINFO_FLG_CUSTOMLAYOUT) != 0);
}
inline static bool StructHasNoPromotionFlagSet(DWORD attribs)
inline static bool StructHasDontDigFieldsFlagSet(DWORD attribs)
{
return ((attribs & CORINFO_FLG_DONT_PROMOTE) != 0);
return ((attribs & CORINFO_FLG_DONT_DIG_FIELDS) != 0);
}
//------------------------------------------------------------------------------
......
......@@ -1685,13 +1685,6 @@ bool Compiler::StructPromotionHelper::CanPromoteStructType(CORINFO_CLASS_HANDLE
structPromotionInfo.fieldCnt = (unsigned char)fieldCnt;
DWORD typeFlags = compHandle->getClassAttribs(typeHnd);
if (StructHasNoPromotionFlagSet(typeFlags))
{
// In AOT ReadyToRun compilation, don't try to promote fields of types
// outside of the current version bubble.
return false;
}
bool overlappingFields = StructHasOverlappingFields(typeFlags);
if (overlappingFields)
{
......@@ -1709,6 +1702,26 @@ bool Compiler::StructPromotionHelper::CanPromoteStructType(CORINFO_CLASS_HANDLE
unsigned structAlignment = roundUp(compHandle->getClassAlignmentRequirement(typeHnd), TARGET_POINTER_SIZE);
#endif // TARGET_ARM
// If we have "Custom Layout" then we might have an explicit Size attribute
// Managed C++ uses this for its structs, such C++ types will not contain GC pointers.
//
// The current VM implementation also incorrectly sets the CORINFO_FLG_CUSTOMLAYOUT
// whenever a managed value class contains any GC pointers.
// (See the comment for VMFLAG_NOT_TIGHTLY_PACKED in class.h)
//
// It is important to struct promote managed value classes that have GC pointers
// So we compute the correct value for "CustomLayout" here
//
if (StructHasCustomLayout(typeFlags) && ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) == 0))
{
structPromotionInfo.customLayout = true;
}
if (StructHasDontDigFieldsFlagSet(typeFlags))
{
return CanConstructAndPromoteField(&structPromotionInfo);
}
unsigned fieldsSize = 0;
for (BYTE ordinal = 0; ordinal < fieldCnt; ++ordinal)
......@@ -1760,21 +1773,6 @@ bool Compiler::StructPromotionHelper::CanPromoteStructType(CORINFO_CLASS_HANDLE
noway_assert((containsGCpointers == false) ||
((typeFlags & (CORINFO_FLG_CONTAINS_GC_PTR | CORINFO_FLG_BYREF_LIKE)) != 0));
// If we have "Custom Layout" then we might have an explicit Size attribute
// Managed C++ uses this for its structs, such C++ types will not contain GC pointers.
//
// The current VM implementation also incorrectly sets the CORINFO_FLG_CUSTOMLAYOUT
// whenever a managed value class contains any GC pointers.
// (See the comment for VMFLAG_NOT_TIGHTLY_PACKED in class.h)
//
// It is important to struct promote managed value classes that have GC pointers
// So we compute the correct value for "CustomLayout" here
//
if (StructHasCustomLayout(typeFlags) && ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) == 0))
{
structPromotionInfo.customLayout = true;
}
// Check if this promoted struct contains any holes.
assert(!overlappingFields);
if (fieldsSize != structSize)
......@@ -1790,6 +1788,62 @@ bool Compiler::StructPromotionHelper::CanPromoteStructType(CORINFO_CLASS_HANDLE
return true;
}
//--------------------------------------------------------------------------------------------
// CanConstructAndPromoteField - checks if we can construct field types without asking about them directly.
//
// Arguments:
// structPromotionInfo - struct promotion candidate information.
//
// Return value:
// true if we can figure out the fields from available knowledge.
//
// Notes:
// This is needed for AOT R2R compilation when we can't cross compilation bubble borders
// so we should not ask about fields that are not directly referenced. If we do VM will have
// to emit a type check for this field type but it does not have enough information about it.
// As a workaround for perfomance critical corner case: struct with 1 gcref, we try to construct
// the field information from indirect observations.
//
bool Compiler::StructPromotionHelper::CanConstructAndPromoteField(lvaStructPromotionInfo* structPromotionInfo)
{
const CORINFO_CLASS_HANDLE typeHnd = structPromotionInfo->typeHnd;
const COMP_HANDLE compHandle = compiler->info.compCompHnd;
const DWORD typeFlags = compHandle->getClassAttribs(typeHnd);
if (structPromotionInfo->fieldCnt != 1)
{
// Can't find out values for several fields.
return false;
}
if ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) == 0)
{
// Can't find out type of a non-gc field.
return false;
}
const unsigned structSize = compHandle->getClassSize(typeHnd);
if (structSize != TARGET_POINTER_SIZE)
{
return false;
}
assert(!structPromotionInfo->containsHoles);
assert(!structPromotionInfo->customLayout);
lvaStructFieldInfo& fldInfo = structPromotionInfo->fields[0];
fldInfo.fldHnd = compHandle->getFieldInClass(typeHnd, 0);
// We should not read it anymore.
fldInfo.fldTypeHnd = 0;
fldInfo.fldOffset = 0;
fldInfo.fldOrdinal = 0;
fldInfo.fldSize = TARGET_POINTER_SIZE;
fldInfo.fldType = TYP_BYREF;
structPromotionInfo->canPromote = true;
return true;
}
//--------------------------------------------------------------------------------------------
// CanPromoteStructVar - checks if the struct can be promoted.
//
......@@ -2761,7 +2815,7 @@ void Compiler::makeExtraStructQueries(CORINFO_CLASS_HANDLE structHandle, int lev
assert(structHandle != NO_CLASS_HANDLE);
(void)typGetObjLayout(structHandle);
DWORD typeFlags = info.compCompHnd->getClassAttribs(structHandle);
if (StructHasNoPromotionFlagSet(typeFlags))
if (StructHasDontDigFieldsFlagSet(typeFlags))
{
// In AOT ReadyToRun compilation, don't query fields of types
// outside of the current version bubble.
......
......@@ -2028,7 +2028,7 @@ private uint getClassAttribsInternal(TypeDesc type)
if (!_compilation.CompilationModuleGroup.VersionsWithType(type))
{
// Prevent the JIT from drilling into types outside of the current versioning bubble
result |= CorInfoFlag.CORINFO_FLG_DONT_PROMOTE;
result |= CorInfoFlag.CORINFO_FLG_DONT_DIG_FIELDS;
result &= ~CorInfoFlag.CORINFO_FLG_BEFOREFIELDINIT;
}
#endif
......
......@@ -594,7 +594,7 @@ public enum CorInfoFlag : uint
CORINFO_FLG_ARRAY = 0x00080000, // class is an array class (initialized differently)
CORINFO_FLG_OVERLAPPING_FIELDS = 0x00100000, // struct or class has fields that overlap (aka union)
CORINFO_FLG_INTERFACE = 0x00200000, // it is an interface
CORINFO_FLG_DONT_PROMOTE = 0x00400000, // don't try to promote fieds of types outside of AOT compilation version bubble
CORINFO_FLG_DONT_DIG_FIELDS = 0x00400000, // don't try to ask about fields outside of AOT compilation version bubble
CORINFO_FLG_CUSTOMLAYOUT = 0x00800000, // does this struct have custom layout?
CORINFO_FLG_CONTAINS_GC_PTR = 0x01000000, // does the class contain a gc ptr ?
CORINFO_FLG_DELEGATE = 0x02000000, // is this a subclass of delegate or multicast delegate ?
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册