Skip to content

Commit

Permalink
[RISC-V] Avoid using native layout info to calculate register flags f…
Browse files Browse the repository at this point in the history
…or small structs where possible (#97877)

* Remove initializing native layout info for small structs during type load

Managed->managed calling convention should not depend on native info which is used for interop marshalling with unmanaged code which is above the type loader.

* Don't use native layout in GetRiscV64PassStructInRegisterFlags unless we're calculating flags for a native value type

* Remove redundant assertions, AsNativeValueType() has the same

* Cover implied repeated fields, a.k.a fixed arrays, in when calculating small struct flags from non-native layout

* Cover implied repeated fields, a.k.a fixed arrays, also in non-native branch of IsRiscV64OnlyOneField
  • Loading branch information
tomeksowi authored Mar 15, 2024
1 parent dbbd655 commit da2cb96
Showing 1 changed file with 63 additions and 36 deletions.
99 changes: 63 additions & 36 deletions src/coreclr/vm/methodtable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3420,18 +3420,12 @@ bool MethodTable::IsRiscV64OnlyOneField(MethodTable * pMT)
{
TypeHandle th(pMT);

bool useNativeLayout = false;
bool ret = false;
MethodTable* pMethodTable = nullptr;
bool ret = false;

if (!th.IsTypeDesc())
{
pMethodTable = th.AsMethodTable();
if (pMethodTable->HasLayout())
{
useNativeLayout = true;
}
else if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/)
MethodTable* pMethodTable = th.AsMethodTable();
if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/)
{
DWORD numIntroducedFields = pMethodTable->GetNumIntroducedInstanceFields();

Expand All @@ -3441,6 +3435,19 @@ bool MethodTable::IsRiscV64OnlyOneField(MethodTable * pMT)

CorElementType fieldType = pFieldStart[0].GetFieldType();

// InlineArray types and fixed buffer types have implied repeated fields.
// Checking if a type is an InlineArray type is cheap, so we'll do that first.
bool hasImpliedRepeatedFields = HasImpliedRepeatedFields(pMethodTable);

if (hasImpliedRepeatedFields)
{
numIntroducedFields = pMethodTable->GetNumInstanceFieldBytes() / pFieldStart->GetSize();
if (numIntroducedFields != 1)
{
goto _End_arg;
}
}

if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType))
{
ret = true;
Expand All @@ -3454,20 +3461,12 @@ bool MethodTable::IsRiscV64OnlyOneField(MethodTable * pMT)
}
}
}
goto _End_arg;
}
}
else
{
_ASSERTE(th.IsNativeValueType());

useNativeLayout = true;
pMethodTable = th.AsNativeValueType();
}
_ASSERTE(pMethodTable != nullptr);
MethodTable* pMethodTable = th.AsNativeValueType();

if (useNativeLayout)
{
if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/)
{
DWORD numIntroducedFields = pMethodTable->GetNativeLayoutInfo()->GetNumFields();
Expand Down Expand Up @@ -3526,18 +3525,12 @@ int MethodTable::GetRiscV64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls)
{
TypeHandle th(cls);

bool useNativeLayout = false;
int size = STRUCT_NO_FLOAT_FIELD;
MethodTable* pMethodTable = nullptr;

if (!th.IsTypeDesc())
{
pMethodTable = th.AsMethodTable();
if (pMethodTable->HasLayout())
{
useNativeLayout = true;
}
else if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/)
MethodTable* pMethodTable = th.AsMethodTable();
if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/)
{
DWORD numIntroducedFields = pMethodTable->GetNumIntroducedInstanceFields();

Expand All @@ -3547,6 +3540,44 @@ int MethodTable::GetRiscV64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls)

CorElementType fieldType = pFieldStart[0].GetFieldType();

// InlineArray types and fixed buffer types have implied repeated fields.
// Checking if a type is an InlineArray type is cheap, so we'll do that first.
bool hasImpliedRepeatedFields = HasImpliedRepeatedFields(pMethodTable);

if (hasImpliedRepeatedFields)
{
numIntroducedFields = pMethodTable->GetNumInstanceFieldBytes() / pFieldStart->GetSize();
if (numIntroducedFields > 2)
{
goto _End_arg;
}

if (fieldType == ELEMENT_TYPE_R4)
{
if (numIntroducedFields == 1)
{
size = STRUCT_FLOAT_FIELD_ONLY_ONE;
}
else if (numIntroducedFields == 2)
{
size = STRUCT_FLOAT_FIELD_ONLY_TWO;
}
goto _End_arg;
}
else if (fieldType == ELEMENT_TYPE_R8)
{
if (numIntroducedFields == 1)
{
size = STRUCT_FLOAT_FIELD_ONLY_ONE | STRUCT_FIRST_FIELD_SIZE_IS8;
}
else if (numIntroducedFields == 2)
{
size = STRUCT_FIELD_TWO_DOUBLES;
}
goto _End_arg;
}
}

if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType))
{
if (fieldType == ELEMENT_TYPE_R4)
Expand Down Expand Up @@ -3584,6 +3615,11 @@ int MethodTable::GetRiscV64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls)
goto _End_arg;
}

if (pFieldFirst->GetSize() > pFieldSecond->GetOffset())
{
goto _End_arg;
}

CorElementType fieldType = pFieldFirst[0].GetFieldType();
if (CorTypeInfo::IsPrimitiveType_NoThrow(fieldType))
{
Expand Down Expand Up @@ -3701,21 +3737,12 @@ int MethodTable::GetRiscV64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls)
size |= STRUCT_SECOND_FIELD_SIZE_IS8;
}
}

goto _End_arg;
}
}
else
{
_ASSERTE(th.IsNativeValueType());
MethodTable* pMethodTable = th.AsNativeValueType();

useNativeLayout = true;
pMethodTable = th.AsNativeValueType();
}
_ASSERTE(pMethodTable != nullptr);

if (useNativeLayout)
{
if (th.GetSize() <= 16 /*MAX_PASS_MULTIREG_BYTES*/)
{
DWORD numIntroducedFields = pMethodTable->GetNativeLayoutInfo()->GetNumFields();
Expand Down

0 comments on commit da2cb96

Please sign in to comment.