Skip to content

Commit febe8b1

Browse files
authored
Refactor Sequential/Explicit layout to happen in the same phase where we do Auto layout (#113454)
1 parent 60e900b commit febe8b1

12 files changed

+965
-929
lines changed

src/coreclr/vm/class.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,6 @@ VOID EEClass::FixupFieldDescForEnC(MethodTable * pMT, EnCFieldDesc *pFD, mdField
246246
bmtEnumFields.dwNumInstanceFields = 1;
247247
}
248248

249-
// We shouldn't have to fill this in b/c we're not allowed to EnC value classes, or
250-
// anything else with layout info associated with it.
251-
// Provide 2, 1 placeholder and 1 for the actual field - see BuildMethodTableThrowing().
252-
LayoutRawFieldInfo layoutRawFieldInfos[2];
253-
254249
// If not NULL, it means there are some by-value fields, and this contains an entry for each instance or static field,
255250
// which is NULL if not a by value field, and points to the EEClass of the field if a by value field. Instance fields
256251
// come first, statics come second.
@@ -288,7 +283,6 @@ VOID EEClass::FixupFieldDescForEnC(MethodTable * pMT, EnCFieldDesc *pFD, mdField
288283
GCX_PREEMP();
289284
unsigned totalDeclaredFieldSize = 0;
290285
builder.InitializeFieldDescs(pFD,
291-
layoutRawFieldInfos,
292286
&bmtInternal,
293287
&genericsInfo,
294288
&bmtMetaData,

src/coreclr/vm/class.h

Lines changed: 91 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ class EnCFieldDesc;
7272
class FieldDesc;
7373
class NativeFieldDescriptor;
7474
class EEClassNativeLayoutInfo;
75-
struct LayoutRawFieldInfo;
7675
class MetaSig;
7776
class MethodDesc;
7877
class MethodDescChunk;
@@ -126,7 +125,7 @@ class ExplicitFieldTrust
126125
};
127126

128127
//----------------------------------------------------------------------------------------------
129-
// This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
128+
// This class is a helper for ValidateExplicitLayout. To make it harder to introduce security holes
130129
// into this function, we will manage all updates to the class's trust level through the ExplicitClassTrust
131130
// class. This abstraction enforces the rule that the overall class is only as trustworthy as
132131
// the least trustworthy field.
@@ -175,7 +174,7 @@ class ExplicitClassTrust : private ExplicitFieldTrust
175174
};
176175

177176
//----------------------------------------------------------------------------------------------
178-
// This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
177+
// This class is a helper for ValidateExplicitLayout. To make it harder to introduce security holes
179178
// into this function, this class will collect trust information about individual fields to be later
180179
// aggregated into the overall class level.
181180
//
@@ -334,39 +333,22 @@ class SparseVTableMap
334333
//=======================================================================
335334
class EEClassLayoutInfo
336335
{
337-
static VOID CollectLayoutFieldMetadataThrowing(
338-
mdTypeDef cl, // cl of the NStruct being loaded
339-
BYTE packingSize, // packing size (from @dll.struct)
340-
BYTE nlType, // nltype (from @dll.struct)
341-
BOOL fExplicitOffsets, // explicit offsets?
342-
MethodTable *pParentMT, // the loaded superclass
343-
ULONG cTotalFields, // total number of fields (instance and static)
344-
HENUMInternal *phEnumField, // enumerator for fields
345-
Module* pModule, // Module that defines the scope, loader and heap (for allocate FieldMarshalers)
346-
const SigTypeContext *pTypeContext, // Type parameters for NStruct being loaded
347-
EEClassLayoutInfo *pEEClassLayoutInfoOut, // caller-allocated structure to fill in.
348-
LayoutRawFieldInfo *pInfoArrayOut, // caller-allocated array to fill in. Needs room for cTotalFields+1 elements
349-
LoaderAllocator * pAllocator,
350-
AllocMemTracker *pamTracker
351-
);
352-
353-
friend class ClassLoader;
354-
friend class EEClass;
355-
friend class MethodTableBuilder;
356-
UINT32 m_cbManagedSize;
357-
358336
public:
359-
BYTE m_ManagedLargestAlignmentRequirementOfAllMembers;
360-
337+
enum class LayoutType : BYTE
338+
{
339+
Auto = 0, // Make sure Auto is the default value as the default-constructed value represents the "auto layout" case
340+
Sequential,
341+
Explicit
342+
};
361343
private:
362344
enum {
363345
// TRUE if the GC layout of the class is bit-for-bit identical
364346
// to its unmanaged counterpart with the runtime marshalling system
365347
// (i.e. no internal reference fields, no ansi-unicode char conversions required, etc.)
366348
// Used to optimize marshaling.
367349
e_BLITTABLE = 0x01,
368-
// Is this type also sequential in managed memory?
369-
e_MANAGED_SEQUENTIAL = 0x02,
350+
// unused = 0x02,
351+
370352
// When a sequential/explicit type has no fields, it is conceptually
371353
// zero-sized, but actually is 1 byte in length. This holds onto this
372354
// fact and allows us to revert the 1 byte of padding when another
@@ -380,28 +362,27 @@ class EEClassLayoutInfo
380362
e_IS_OR_HAS_INT128_FIELD = 0x20,
381363
};
382364

383-
BYTE m_bFlags;
365+
LayoutType m_LayoutType;
366+
367+
BYTE m_ManagedLargestAlignmentRequirementOfAllMembers;
368+
369+
BYTE m_bFlags;
384370

385371
// Packing size in bytes (1, 2, 4, 8 etc.)
386-
BYTE m_cbPackingSize;
372+
BYTE m_cbPackingSize;
387373

388374
public:
389-
UINT32 GetManagedSize() const
390-
{
391-
LIMITED_METHOD_CONTRACT;
392-
return m_cbManagedSize;
393-
}
394375

395376
BOOL IsBlittable() const
396377
{
397378
LIMITED_METHOD_CONTRACT;
398379
return (m_bFlags & e_BLITTABLE) == e_BLITTABLE;
399380
}
400381

401-
BOOL IsManagedSequential() const
382+
LayoutType GetLayoutType() const
402383
{
403384
LIMITED_METHOD_CONTRACT;
404-
return (m_bFlags & e_MANAGED_SEQUENTIAL) == e_MANAGED_SEQUENTIAL;
385+
return m_LayoutType;
405386
}
406387

407388
// If true, this says that the type was originally zero-sized
@@ -433,54 +414,112 @@ class EEClassLayoutInfo
433414
return (m_bFlags & e_IS_OR_HAS_INT128_FIELD) == e_IS_OR_HAS_INT128_FIELD;
434415
}
435416

417+
BYTE GetAlignmentRequirement() const
418+
{
419+
LIMITED_METHOD_CONTRACT;
420+
return m_ManagedLargestAlignmentRequirementOfAllMembers;
421+
}
422+
436423
BYTE GetPackingSize() const
437424
{
438425
LIMITED_METHOD_CONTRACT;
439426
return m_cbPackingSize;
440427
}
441428

442-
private:
443429
void SetIsBlittable(BOOL isBlittable)
444430
{
445431
LIMITED_METHOD_CONTRACT;
446432
m_bFlags = isBlittable ? (m_bFlags | e_BLITTABLE)
447433
: (m_bFlags & ~e_BLITTABLE);
448434
}
449435

450-
void SetIsManagedSequential(BOOL isManagedSequential)
436+
void SetHasAutoLayoutField(BOOL hasAutoLayoutField)
451437
{
452438
LIMITED_METHOD_CONTRACT;
453-
m_bFlags = isManagedSequential ? (m_bFlags | e_MANAGED_SEQUENTIAL)
454-
: (m_bFlags & ~e_MANAGED_SEQUENTIAL);
439+
m_bFlags = hasAutoLayoutField ? (m_bFlags | e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT)
440+
: (m_bFlags & ~e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT);
455441
}
456442

457-
void SetIsZeroSized(BOOL isZeroSized)
443+
void SetIsInt128OrHasInt128Fields(BOOL hasInt128Field)
458444
{
459445
LIMITED_METHOD_CONTRACT;
460-
m_bFlags = isZeroSized ? (m_bFlags | e_ZERO_SIZED)
461-
: (m_bFlags & ~e_ZERO_SIZED);
446+
m_bFlags = hasInt128Field ? (m_bFlags | e_IS_OR_HAS_INT128_FIELD)
447+
: (m_bFlags & ~e_IS_OR_HAS_INT128_FIELD);
462448
}
463449

464450
void SetHasExplicitSize(BOOL hasExplicitSize)
465451
{
466452
LIMITED_METHOD_CONTRACT;
467453
m_bFlags = hasExplicitSize ? (m_bFlags | e_HAS_EXPLICIT_SIZE)
468-
: (m_bFlags & ~e_HAS_EXPLICIT_SIZE);
454+
: (m_bFlags & ~e_HAS_EXPLICIT_SIZE);
469455
}
470456

471-
void SetHasAutoLayoutField(BOOL hasAutoLayoutField)
457+
void SetAlignmentRequirement(BYTE alignment)
472458
{
473459
LIMITED_METHOD_CONTRACT;
474-
m_bFlags = hasAutoLayoutField ? (m_bFlags | e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT)
475-
: (m_bFlags & ~e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT);
460+
m_ManagedLargestAlignmentRequirementOfAllMembers = alignment;
476461
}
477462

478-
void SetIsInt128OrHasInt128Fields(BOOL hasInt128Field)
463+
ULONG InitializeSequentialFieldLayout(
464+
FieldDesc* pFields,
465+
MethodTable** pByValueClassCache,
466+
ULONG cFields,
467+
BYTE packingSize,
468+
ULONG classSizeInMetadata,
469+
MethodTable* pParentMT
470+
);
471+
472+
ULONG InitializeExplicitFieldLayout(
473+
FieldDesc* pFields,
474+
MethodTable** pByValueClassCache,
475+
ULONG cFields,
476+
BYTE packingSize,
477+
ULONG classSizeInMetadata,
478+
MethodTable* pParentMT,
479+
Module* pModule,
480+
mdTypeDef cl
481+
);
482+
483+
private:
484+
void SetIsZeroSized(BOOL isZeroSized)
479485
{
480486
LIMITED_METHOD_CONTRACT;
481-
m_bFlags = hasInt128Field ? (m_bFlags | e_IS_OR_HAS_INT128_FIELD)
482-
: (m_bFlags & ~e_IS_OR_HAS_INT128_FIELD);
487+
m_bFlags = isZeroSized ? (m_bFlags | e_ZERO_SIZED)
488+
: (m_bFlags & ~e_ZERO_SIZED);
489+
}
490+
491+
void SetPackingSize(BYTE cbPackingSize)
492+
{
493+
LIMITED_METHOD_CONTRACT;
494+
m_cbPackingSize = cbPackingSize;
483495
}
496+
497+
UINT32 SetInstanceBytesSize(UINT32 size)
498+
{
499+
LIMITED_METHOD_CONTRACT;
500+
// Bump the managed size of the structure up to 1.
501+
SetIsZeroSized(size == 0 ? TRUE : FALSE);
502+
return size == 0 ? 1 : size;
503+
}
504+
505+
void SetLayoutType(LayoutType layoutType)
506+
{
507+
LIMITED_METHOD_CONTRACT;
508+
m_LayoutType = layoutType;
509+
}
510+
public:
511+
enum class NestedFieldFlags
512+
{
513+
support_use_as_flags = -1,
514+
None = 0x0,
515+
NonBlittable = 0x1,
516+
GCPointer = 0x2,
517+
Align8 = 0x4,
518+
AutoLayout = 0x8,
519+
Int128 = 0x10,
520+
};
521+
522+
static NestedFieldFlags GetNestedFieldFlags(Module* pModule, FieldDesc *pFD, ULONG cFields, CorNativeLinkType nlType, MethodTable** pByValueClassCache);
484523
};
485524

486525
//
@@ -1964,7 +2003,7 @@ inline BOOL EEClass::IsBlittable()
19642003
inline BOOL EEClass::IsManagedSequential()
19652004
{
19662005
LIMITED_METHOD_CONTRACT;
1967-
return HasLayout() && GetLayoutInfo()->IsManagedSequential();
2006+
return HasLayout() && GetLayoutInfo()->GetLayoutType() == EEClassLayoutInfo::LayoutType::Sequential;
19682007
}
19692008

19702009
inline BOOL EEClass::HasExplicitSize()

src/coreclr/vm/classcompat.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ class EEClass;
4242
class LayoutEEClass;
4343
class EnCFieldDesc;
4444
class FieldDesc;
45-
struct LayoutRawFieldInfo;
4645
class MetaSig;
4746
class MethodDesc;
4847
class MethodDescChunk;

0 commit comments

Comments
 (0)