Skip to content

Commit

Permalink
Fix nested non-byref like VC with no pointer fields (#80642) (#80873)
Browse files Browse the repository at this point in the history
* Fix nested non-byref like VC with no pointer fields
  • Loading branch information
AaronRobinsonMSFT committed Feb 8, 2023
1 parent 1335040 commit b1b4d63
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 12 deletions.
25 changes: 13 additions & 12 deletions src/coreclr/vm/methodtablebuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8743,29 +8743,30 @@ MethodTableBuilder::HandleExplicitLayout(
if (pMT->IsByRefLike())
return CheckByRefLikeValueClassLayout(pMT, pFieldLayout);

// This method assumes there is a GC desc associated with the MethodTable.
_ASSERTE(pMT->ContainsPointers());

// Build a layout of the value class (vc). Don't know the sizes of all the fields easily, but
// do know (a) vc is already consistent so don't need to check it's overlaps and
// (b) size and location of all objectrefs. So build it by setting all non-oref
// then fill in the orefs later
// then fill in the orefs later if present.
UINT fieldSize = pMT->GetNumInstanceFieldBytes();

CQuickBytes qb;
bmtFieldLayoutTag *vcLayout = (bmtFieldLayoutTag*) qb.AllocThrows(fieldSize * sizeof(bmtFieldLayoutTag));
memset((void*)vcLayout, nonoref, fieldSize);

// use pointer series to locate the orefs
CGCDesc* map = CGCDesc::GetCGCDescFromMT(pMT);
CGCDescSeries *pSeries = map->GetLowestSeries();

for (SIZE_T j = 0; j < map->GetNumSeries(); j++)
// If the type contains pointers fill it out from the GC data
if (pMT->ContainsPointers())
{
CONSISTENCY_CHECK(pSeries <= map->GetHighestSeries());
// use pointer series to locate the orefs
CGCDesc* map = CGCDesc::GetCGCDescFromMT(pMT);
CGCDescSeries *pSeries = map->GetLowestSeries();

memset((void*)&vcLayout[pSeries->GetSeriesOffset() - OBJECT_SIZE], oref, pSeries->GetSeriesSize() + pMT->GetBaseSize());
pSeries++;
for (SIZE_T j = 0; j < map->GetNumSeries(); j++)
{
CONSISTENCY_CHECK(pSeries <= map->GetHighestSeries());

memset((void*)&vcLayout[pSeries->GetSeriesOffset() - OBJECT_SIZE], oref, pSeries->GetSeriesSize() + pMT->GetBaseSize());
pSeries++;
}
}

ExplicitClassTrust explicitClassTrust;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

using Xunit;

public class Test
{
public struct WithORefs
{
public object F;
}

public struct WithNoORefs
{
public int F;
}

public ref struct WithByRefs
{
public ref int F;
}

[StructLayout(LayoutKind.Explicit)]
public ref struct Explicit1
{
[FieldOffset(0)] public Inner1 Field1;
public ref struct Inner1
{
public WithORefs Field2;
}
}

[StructLayout(LayoutKind.Explicit)]
public ref struct Explicit2
{
[FieldOffset(0)] public Inner2 Field1;
public ref struct Inner2
{
public WithNoORefs Field2;
}
}

[StructLayout(LayoutKind.Explicit)]
public ref struct Explicit3
{
[FieldOffset(0)] public Inner3 Field1;
public ref struct Inner3
{
public WithByRefs Field2;
}
}

[Fact]
public static void Validate_Explicit1()
{
Load1();

[MethodImpl(MethodImplOptions.NoInlining)]
static string Load1()
{
return typeof(Explicit1).ToString();
}
}

[Fact]
public static void Validate_Explicit2()
{
Load2();

[MethodImpl(MethodImplOptions.NoInlining)]
static string Load2()
{
return typeof(Explicit2).ToString();
}
}

[Fact]
public static void Validate_Explicit3()
{
Load3();

[MethodImpl(MethodImplOptions.NoInlining)]
static string Load3()
{
return typeof(Explicit3).ToString();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<OutputType>Exe</OutputType>
<MonoAotIncompatible>false</MonoAotIncompatible>
</PropertyGroup>
<ItemGroup>
<Compile Include="case13.cs" />
</ItemGroup>
</Project>

0 comments on commit b1b4d63

Please sign in to comment.