From 03e2c029f7bbd36e06bcad3822b1dd3866772170 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 9 Jan 2019 10:06:25 -0800 Subject: Remove extraneous eightbytes check for native structures and add tests. (#21590) * Remove extraneous eightbytes check and add tests. * Interger -> Integer * Missed Helper.cs * Handle field sizes larger than 8 bytes in AssignClassifiedEightByteTypes * Move CoreFX test case into CoreCLR. Fix the SystemV eightbyte classifier to correctly classify the second eightbyte when a single field crosses the eightbyte boundary (such as an in-place array of three 4-byte enums). * Enable passing user defined structs in in-place arrays in a structure if SystemV ABI expects it. * Correctly handle a field spanning two full eightbytes. * Just directly assign 0 to accumulatedSizeForEightByte * Change multi-eightbyte field handling to be a loop as per PR feedback. * Remove extraneous whitespace. --- src/vm/fieldmarshaler.h | 8 ++++++-- src/vm/methodtable.cpp | 37 +++++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/vm/fieldmarshaler.h b/src/vm/fieldmarshaler.h index 1f7ac88f44..24b10211c6 100644 --- a/src/vm/fieldmarshaler.h +++ b/src/vm/fieldmarshaler.h @@ -1029,8 +1029,12 @@ public: { LIMITED_METHOD_CONTRACT; - MethodTable *pElementMT = m_arrayType.GetValue().AsArray()->GetArrayElementTypeHandle().GetMethodTable(); - return OleVariant::GetElementSizeForVarType(m_vt, pElementMT) * m_numElems; + return OleVariant::GetElementSizeForVarType(m_vt, GetElementMethodTable()) * m_numElems; + } + + MethodTable* GetElementMethodTable() const + { + return GetElementTypeHandle().GetMethodTable(); } TypeHandle GetElementTypeHandle() const diff --git a/src/vm/methodtable.cpp b/src/vm/methodtable.cpp index d7e98ffa48..e158436c21 100644 --- a/src/vm/methodtable.cpp +++ b/src/vm/methodtable.cpp @@ -2649,11 +2649,6 @@ bool MethodTable::ClassifyEightBytesWithNativeLayout(SystemVStructRegisterPassin unsigned normalizedFieldOffset = fieldOffset + startOffsetOfStruct; unsigned int fieldNativeSize = pFieldMarshaler->NativeSize(); - if (fieldNativeSize > SYSTEMV_EIGHT_BYTE_SIZE_IN_BYTES) - { - // Pass on stack in this case. - return false; - } _ASSERTE(fieldNativeSize != (unsigned int)-1); @@ -2704,6 +2699,23 @@ bool MethodTable::ClassifyEightBytesWithNativeLayout(SystemVStructRegisterPassin case VT_R8: fieldClassificationType = SystemVClassificationTypeSSE; break; + case VT_RECORD: + { + MethodTable* pFieldMT = ((FieldMarshaler_FixedArray*)pFieldMarshaler)->GetElementMethodTable(); + + bool inEmbeddedStructPrev = helperPtr->inEmbeddedStruct; + helperPtr->inEmbeddedStruct = true; + bool structRet = pFieldMT->ClassifyEightBytesWithNativeLayout(helperPtr, nestingLevel + 1, normalizedFieldOffset, useNativeLayout); + helperPtr->inEmbeddedStruct = inEmbeddedStructPrev; + + if (!structRet) + { + // If the nested struct says not to enregister, there's no need to continue analyzing at this level. Just return do not enregister. + return false; + } + + continue; + } case VT_DECIMAL: case VT_DATE: case VT_BSTR: @@ -2714,7 +2726,6 @@ bool MethodTable::ClassifyEightBytesWithNativeLayout(SystemVStructRegisterPassin case VT_HRESULT: case VT_CARRAY: case VT_USERDEFINED: - case VT_RECORD: case VT_FILETIME: case VT_BLOB: case VT_STREAM: @@ -3044,7 +3055,7 @@ void MethodTable::AssignClassifiedEightByteTypes(SystemVStructRegisterPassingHe else { fieldSize = helperPtr->fieldSizes[ordinal]; - _ASSERTE(fieldSize > 0 && fieldSize <= SYSTEMV_EIGHT_BYTE_SIZE_IN_BYTES); + _ASSERTE(fieldSize > 0); fieldClassificationType = helperPtr->fieldClassifications[ordinal]; _ASSERTE(fieldClassificationType != SystemVClassificationTypeMemory && fieldClassificationType != SystemVClassificationTypeUnknown); @@ -3082,7 +3093,7 @@ void MethodTable::AssignClassifiedEightByteTypes(SystemVStructRegisterPassingHe } accumulatedSizeForEightByte += fieldSize; - if (accumulatedSizeForEightByte == SYSTEMV_EIGHT_BYTE_SIZE_IN_BYTES) + while (accumulatedSizeForEightByte >= SYSTEMV_EIGHT_BYTE_SIZE_IN_BYTES) { // Save data for this eightbyte. helperPtr->eightByteSizes[currentEightByte] = SYSTEMV_EIGHT_BYTE_SIZE_IN_BYTES; @@ -3092,8 +3103,14 @@ void MethodTable::AssignClassifiedEightByteTypes(SystemVStructRegisterPassingHe currentEightByte++; _ASSERTE(currentEightByte <= CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS); - currentEightByteOffset = offset + fieldSize; - accumulatedSizeForEightByte = 0; + currentEightByteOffset += SYSTEMV_EIGHT_BYTE_SIZE_IN_BYTES; + accumulatedSizeForEightByte -= SYSTEMV_EIGHT_BYTE_SIZE_IN_BYTES; + + // If a field is large enough to span multiple eightbytes, then set the eightbyte classification to the field's classification. + if (accumulatedSizeForEightByte > 0) + { + helperPtr->eightByteClassifications[currentEightByte] = fieldClassificationType; + } } _ASSERTE(accumulatedSizeForEightByte < SYSTEMV_EIGHT_BYTE_SIZE_IN_BYTES); -- cgit v1.2.3