Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
a few asserts and refactorings
  • Loading branch information
VSadov committed Mar 22, 2023
commit 4e0d3d2480438548f786dd400a4702137224069a
86 changes: 38 additions & 48 deletions src/coreclr/vm/array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -584,67 +584,73 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy
}

// Set up GC information
if (elemType == ELEMENT_TYPE_VALUETYPE || elemType == ELEMENT_TYPE_VOID)
if (CorTypeInfo::IsObjRef(elemType))
{
CGCDescSeries *pSeries;

pMT->SetContainsPointers();

// This array is all GC Pointers
CGCDesc::GetCGCDescFromMT(pMT)->Init( pMT, 1 );

pSeries = CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries();

pSeries->SetSeriesOffset(ArrayBase::GetDataPtrOffset(pMT));
// For arrays, the size is the negative of the BaseSize (the GC always adds the total
// size of the object, so what you end up with is the size of the data portion of the array)
pSeries->SetSeriesSize(-(SSIZE_T)(pMT->GetBaseSize()));
}
else if (elemType == ELEMENT_TYPE_VALUETYPE)
{
// If it's an array of value classes, there is a different format for the GCDesc if it contains pointers
if (pElemMT->ContainsPointers())
{
CGCDescSeries *pSeries;

// There must be only one series for value classes
CGCDescSeries *pByValueSeries = CGCDesc::GetCGCDescFromMT(pElemMT)->GetHighestSeries();

pMT->SetContainsPointers();

CGCDescSeries* pElemSeries = CGCDesc::GetCGCDescFromMT(pElemMT)->GetHighestSeries();

// negative series has a special meaning, indicating a different form of GCDesc
SSIZE_T nSeries = (SSIZE_T) CGCDesc::GetCGCDescFromMT(pElemMT)->GetNumSeries();
CGCDesc::GetCGCDescFromMT(pMT)->InitValueClassSeries(pMT, nSeries);

pSeries = CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries();

// sort by offset
SSIZE_T AllocSizeSeries;
if (!ClrSafeInt<SSIZE_T>::multiply(sizeof(CGCDescSeries*), nSeries, AllocSizeSeries))
COMPlusThrowOM();
CGCDescSeries** sortedSeries = (CGCDescSeries**) _alloca(AllocSizeSeries);
int index;
for (index = 0; index < nSeries; index++)
sortedSeries[index] = &pByValueSeries[-index];

// section sort
for (int i = 0; i < nSeries; i++) {
for (int j = i+1; j < nSeries; j++)
if (sortedSeries[j]->GetSeriesOffset() < sortedSeries[i]->GetSeriesOffset())
{
CGCDescSeries* temp = sortedSeries[i];
sortedSeries[i] = sortedSeries[j];
sortedSeries[j] = temp;
}
CGCDescSeries* pSeries = CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries();

#if _DEBUG
// GC series must be sorted by the offset
// we will validate that here just in case.
size_t prevOffset = pElemSeries[0].GetSeriesOffset();
for (int index = 1; index < nSeries; index++)
{
size_t offset = pElemSeries[-index].GetSeriesOffset();
_ASSERTE((offset - prevOffset) > 0);
prevOffset = offset;
}
#endif // _DEBUG

// Offset of the first pointer in the array
// This equals the offset of the first pointer if this were an array of entirely pointers, plus the offset of the
// first pointer in the value class
pSeries->SetSeriesOffset(ArrayBase::GetDataPtrOffset(pMT)
+ (sortedSeries[0]->GetSeriesOffset()) - OBJECT_SIZE);
for (index = 0; index < nSeries; index ++)
+ (pElemSeries[0].GetSeriesOffset()) - OBJECT_SIZE);

for (int index = 0; index < nSeries; index ++)
{
size_t numPtrsInBytes = sortedSeries[index]->GetSeriesSize()
size_t numPtrsInBytes = pElemSeries[-index].GetSeriesSize()
+ pElemMT->GetBaseSize();
size_t currentOffset;
size_t skip;
currentOffset = sortedSeries[index]->GetSeriesOffset()+numPtrsInBytes;
currentOffset = pElemSeries[-index].GetSeriesOffset()+numPtrsInBytes;
if (index != nSeries-1)
{
skip = sortedSeries[index+1]->GetSeriesOffset()-currentOffset;
skip = pElemSeries[-(index+1)].GetSeriesOffset()-currentOffset;
}
else if (index == 0)
{
skip = pElemMT->GetNumInstanceFieldBytes() - numPtrsInBytes;
}
else
{
skip = sortedSeries[0]->GetSeriesOffset() + pElemMT->GetBaseSize()
skip = pElemSeries[0].GetSeriesOffset() + pElemMT->GetBaseSize()
- OBJECT_BASESIZE - currentOffset;
}

Expand All @@ -665,22 +671,6 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy
}
}
}
else if (CorTypeInfo::IsObjRef(elemType))
{
CGCDescSeries *pSeries;

pMT->SetContainsPointers();

// This array is all GC Pointers
CGCDesc::GetCGCDescFromMT(pMT)->Init( pMT, 1 );

pSeries = CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries();

pSeries->SetSeriesOffset(ArrayBase::GetDataPtrOffset(pMT));
// For arrays, the size is the negative of the BaseSize (the GC always adds the total
// size of the object, so what you end up with is the size of the data portion of the array)
pSeries->SetSeriesSize(-(SSIZE_T)(pMT->GetBaseSize()));
}

// If we get here we are assuming that there was no truncation. If this is not the case then
// an array whose base type is not a value class was created and was larger then 0xffff (a word)
Expand Down