Skip to content
Merged
3 changes: 2 additions & 1 deletion src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9281,7 +9281,8 @@ void Compiler::impImportBlockCode(BasicBlock* block)
CORINFO_FIELD_INFO fi;
eeGetFieldInfo(&fldToken, CORINFO_ACCESS_SET, &fi);
unsigned flagsToCheck = CORINFO_FLG_FIELD_STATIC | CORINFO_FLG_FIELD_FINAL;
if ((fi.fieldFlags & flagsToCheck) == flagsToCheck)
if (((fi.fieldFlags & flagsToCheck) == flagsToCheck) &&
((info.compCompHnd->getClassAttribs(info.compClassHnd) & CORINFO_FLG_SHAREDINST) == 0))
{
#ifdef FEATURE_READYTORUN
if (opts.IsReadyToRun())
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/frozenobjectheap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Object* FrozenObjectHeapManager::TryAllocateObject(PTR_MethodTable type, size_t

_ASSERT(type != nullptr);
_ASSERT(FOH_COMMIT_SIZE >= MIN_OBJECT_SIZE);
_ASSERT(!type->Collectible());

// Currently we don't support frozen objects with special alignment requirements
// TODO: We should also give up on arrays of doubles on 32-bit platforms.
Expand Down
8 changes: 5 additions & 3 deletions src/coreclr/vm/gchelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,9 +513,11 @@ OBJECTREF TryAllocateFrozenSzArray(MethodTable* pArrayMT, INT32 cElements)

// The initial validation is copied from AllocateSzArray impl

if (pArrayMT->ContainsPointers() && cElements > 0)
if (pArrayMT->Collectible() || (pArrayMT->ContainsPointers() && cElements > 0))
{
// For arrays with GC pointers we can only work with empty arrays
// We cannot allocate in the frozen heap if:
// - the array type is collectible
// - or for non empty arrays with GC pointers
return NULL;
}

Expand Down Expand Up @@ -1122,7 +1124,7 @@ OBJECTREF TryAllocateFrozenObject(MethodTable* pObjMT)

SetTypeHandleOnThreadForAlloc(TypeHandle(pObjMT));

if (pObjMT->ContainsPointers() || pObjMT->IsComObjectType())
if (pObjMT->Collectible() || pObjMT->ContainsPointers() || pObjMT->IsComObjectType())
{
return NULL;
}
Expand Down
87 changes: 87 additions & 0 deletions src/tests/JIT/Regression/JitBlue/Runtime_100437/Runtime_100437.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// 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.Loader;
using Xunit;

public class Runtime_100437
{
[Fact]
public static int TestCollectibleEmptyArrayNotInFrozenHeap()
{
string assemblyPath = typeof(Runtime_100437).Assembly.Location;

// Skip this test for single file
if (string.IsNullOrEmpty(assemblyPath))
return 100;

WeakReference[] wrs = new WeakReference[10];
for (int i = 0; i < wrs.Length; i++)
{
var alc = new MyAssemblyLoadContext();
var a = alc.LoadFromAssemblyPath(assemblyPath);
wrs[i] = (WeakReference)a.GetType(nameof(Runtime_100437)).GetMethod(nameof(Work)).Invoke(null, null);
GC.Collect();
}

int result = 0;
foreach (var wr in wrs)
{
// This is testing that the empty array from Work(), if collected, should not have been allocated on the Frozen heap
// otherwise it will result in a random crash.
result += wr.Target?.ToString()?.GetHashCode() ?? 0;
}
return (result & 100) | 100;
}

[Fact]
public static int TestCollectibleReadOnlyStaticWithGeneric()
{
string assemblyPath = typeof(Runtime_100437).Assembly.Location;

// Skip this test for single file
if (string.IsNullOrEmpty(assemblyPath))
return 100;

WeakReference[] wrs = new WeakReference[10];
for (int i = 0; i < wrs.Length; i++)
{
var alc = new MyAssemblyLoadContext();
var a = alc.LoadFromAssemblyPath(assemblyPath);
wrs[i] = (WeakReference)a.GetType(nameof(Runtime_100437)).GetMethod(nameof(WorkForGenericCase)).Invoke(null, null);
GC.Collect();
}

int result = 0;
foreach (var wr in wrs)
{
result += wr.Target?.ToString()?.GetHashCode() ?? 0;
}
return (result & 100) | 100;
}

public static WeakReference Work()
{
return new WeakReference(Array.Empty<Runtime_100437>());
}

public static WeakReference WorkForGenericCase()
{
return new WeakReference(GenericHolder<Runtime_100437>.Singleton);
}

private class MyAssemblyLoadContext : AssemblyLoadContext
{
public MyAssemblyLoadContext()
: base(isCollectible: true)
{
}
}

private class GenericHolder<T>
{
public static readonly object Singleton = new object();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>