Skip to content

Commit 5c8176d

Browse files
authored
[release/9.0-staging][mono][hotreload]Adjust row_size and size_bitfield from the baseline based on the delta sizes (#114119)
* Backport to .net9
1 parent 7a148c6 commit 5c8176d

File tree

7 files changed

+933
-40
lines changed

7 files changed

+933
-40
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
using System;
4+
namespace System.Reflection.Metadata.ApplyUpdate.Test
5+
{
6+
public static class IncreaseMetadataRowSize
7+
{
8+
public static void Main(string[] args) { }
9+
public static int VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_1()
10+
{
11+
return 0;
12+
}
13+
public static void VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_2(int x2) {}
14+
public static void VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_3(int x3) {}
15+
public static void VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_4(int x4) {}
16+
public static void VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_5(int x5) {}
17+
}
18+
19+
}

src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.IncreaseMetadataRowSize/IncreaseMetadataRowSize_v1.cs

Lines changed: 817 additions & 0 deletions
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<RootNamespace>System.Runtime.Loader.Tests</RootNamespace>
4+
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
5+
<TestRuntime>true</TestRuntime>
6+
<DeltaScript>deltascript.json</DeltaScript>
7+
</PropertyGroup>
8+
<ItemGroup>
9+
<Compile Include="IncreaseMetadataRowSize.cs" />
10+
</ItemGroup>
11+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"changes": [
3+
{"document": "IncreaseMetadataRowSize.cs", "update": "IncreaseMetadataRowSize_v1.cs"},
4+
]
5+
}
6+

src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,5 +983,25 @@ public static void TestNewMethodThrows()
983983
Assert.True(frame1Name == null || frame1Name.Contains("NewMethodThrows.cs"));
984984
});
985985
}
986+
987+
[ConditionalFact(typeof(ApplyUpdateUtil), nameof (ApplyUpdateUtil.IsSupported))]
988+
void TestIncreaseMetadataRowSize()
989+
{
990+
ApplyUpdateUtil.TestCase(static () =>
991+
{
992+
// Get the custom attribtues from a newly-added type and method
993+
// and check that they are the expected ones.
994+
var assm = typeof(ApplyUpdate.Test.IncreaseMetadataRowSize).Assembly;
995+
996+
ApplyUpdateUtil.ApplyUpdate(assm);
997+
ApplyUpdateUtil.ClearAllReflectionCaches();
998+
999+
var r = ApplyUpdate.Test.IncreaseMetadataRowSize.VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_1();
1000+
Assert.Equal(50000, r);
1001+
MethodInfo mi = typeof(ApplyUpdate.Test.IncreaseMetadataRowSize).GetMethod("VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_800");
1002+
ParameterInfo[] pars = mi.GetParameters();
1003+
Assert.Equal("x800", pars[0].Name);
1004+
});
1005+
}
9861006
}
9871007
}

src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
<ProjectReference Include="ApplyUpdate\System.Reflection.Metadata.ApplyUpdate.Test.GenericAddStaticField\System.Reflection.Metadata.ApplyUpdate.Test.GenericAddStaticField.csproj" />
6868
<ProjectReference Include="ApplyUpdate\System.Reflection.Metadata.ApplyUpdate.Test.GenericAddInstanceField\System.Reflection.Metadata.ApplyUpdate.Test.GenericAddInstanceField.csproj" />
6969
<ProjectReference Include="ApplyUpdate\System.Reflection.Metadata.ApplyUpdate.Test.NewMethodThrows\System.Reflection.Metadata.ApplyUpdate.Test.NewMethodThrows.csproj" />
70+
<ProjectReference Include="ApplyUpdate\System.Reflection.Metadata.ApplyUpdate.Test.IncreaseMetadataRowSize\System.Reflection.Metadata.ApplyUpdate.Test.IncreaseMetadataRowSize.csproj" />
7071
</ItemGroup>
7172
<ItemGroup Condition="'$(TargetOS)' == 'browser'">
7273
<WasmFilesToIncludeFromPublishDir Include="$(AssemblyName).dll" />

src/mono/mono/component/hot_reload.c

Lines changed: 59 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -924,9 +924,7 @@ delta_info_initialize_mutants (const MonoImage *base, const BaselineInfo *base_i
924924
g_assert (prev_table != NULL);
925925

926926
MonoTableInfo *tbl = &delta->mutants [i];
927-
if (prev_table->rows_ == 0) {
928-
/* table was empty in the baseline and it was empty in the prior generation, but now we have some rows. Use the format of the mutant table. */
929-
g_assert (prev_table->row_size == 0);
927+
if (delta->delta_image->tables [i].row_size != 0 || prev_table->rows_ == 0) {
930928
tbl->row_size = delta->delta_image->tables [i].row_size;
931929
tbl->size_bitfield = delta->delta_image->tables [i].size_bitfield;
932930
} else {
@@ -940,8 +938,60 @@ delta_info_initialize_mutants (const MonoImage *base, const BaselineInfo *base_i
940938
tbl->base = mono_mempool_alloc (delta->pool, tbl->row_size * rows);
941939
g_assert (table_info_get_rows (prev_table) == count->prev_gen_rows);
942940

943-
/* copy the old rows and zero out the new ones */
944-
memcpy ((char*)tbl->base, prev_table->base, count->prev_gen_rows * tbl->row_size);
941+
/* copy the old rows and zero out the new ones */
942+
/* we need to copy following the new format (uncompressed one)*/
943+
for (guint32 j = 0 ; j < count->prev_gen_rows; j++)
944+
{
945+
guint32 src_offset = 0, dst_offset = 0;
946+
guint32 dst_bitfield = tbl->size_bitfield;
947+
guint32 src_bitfield = prev_table->size_bitfield;
948+
const char *src_base = (char*)prev_table->base + j * prev_table->row_size;
949+
char *dst_base = (char*)tbl->base + j * tbl->row_size;
950+
for (guint col = 0; col < mono_metadata_table_count (dst_bitfield); ++col) {
951+
guint32 dst_col_size = mono_metadata_table_size (dst_bitfield, col);
952+
guint32 src_col_size = mono_metadata_table_size (src_bitfield, col);
953+
{
954+
const char *src = src_base + src_offset;
955+
char *dst = dst_base + dst_offset;
956+
957+
/* copy src to dst, via a temporary to adjust for size differences */
958+
/* FIXME: unaligned access, endianness */
959+
guint32 tmp;
960+
961+
switch (src_col_size) {
962+
case 1:
963+
tmp = *(guint8*)src;
964+
break;
965+
case 2:
966+
tmp = *(guint16*)src;
967+
break;
968+
case 4:
969+
tmp = *(guint32*)src;
970+
break;
971+
default:
972+
g_assert_not_reached ();
973+
}
974+
975+
/* FIXME: unaligned access, endianness */
976+
switch (dst_col_size) {
977+
case 1:
978+
*(guint8*)dst = (guint8)tmp;
979+
break;
980+
case 2:
981+
*(guint16*)dst = (guint16)tmp;
982+
break;
983+
case 4:
984+
*(guint32*)dst = tmp;
985+
break;
986+
default:
987+
g_assert_not_reached ();
988+
}
989+
}
990+
src_offset += src_col_size;
991+
dst_offset += dst_col_size;
992+
}
993+
g_assert (dst_offset == tbl->row_size);
994+
}
945995
memset (((char*)tbl->base) + count->prev_gen_rows * tbl->row_size, 0, count->inserted_rows * tbl->row_size);
946996
}
947997
}
@@ -1386,8 +1436,8 @@ delta_info_mutate_row (MonoImage *image_dmeta, DeltaInfo *cur_delta, guint32 log
13861436

13871437
/* The complication here is that we want the mutant table to look like the table in
13881438
* the baseline image with respect to column widths, but the delta tables are generally coming in
1389-
* uncompressed (4-byte columns). So we have to copy one column at a time and adjust the
1390-
* widths as we go.
1439+
* uncompressed (4-byte columns). And we have already adjusted the baseline image column widths
1440+
* so we can use memcpy here.
13911441
*/
13921442

13931443
guint32 dst_bitfield = cur_delta->mutants [token_table].size_bitfield;
@@ -1401,41 +1451,10 @@ delta_info_mutate_row (MonoImage *image_dmeta, DeltaInfo *cur_delta, guint32 log
14011451
guint32 dst_col_size = mono_metadata_table_size (dst_bitfield, col);
14021452
guint32 src_col_size = mono_metadata_table_size (src_bitfield, col);
14031453
if ((m_SuppressedDeltaColumns [token_table] & (1 << col)) == 0) {
1454+
g_assert(src_col_size <= dst_col_size);
14041455
const char *src = src_base + src_offset;
14051456
char *dst = dst_base + dst_offset;
1406-
1407-
/* copy src to dst, via a temporary to adjust for size differences */
1408-
/* FIXME: unaligned access, endianness */
1409-
guint32 tmp;
1410-
1411-
switch (src_col_size) {
1412-
case 1:
1413-
tmp = *(guint8*)src;
1414-
break;
1415-
case 2:
1416-
tmp = *(guint16*)src;
1417-
break;
1418-
case 4:
1419-
tmp = *(guint32*)src;
1420-
break;
1421-
default:
1422-
g_assert_not_reached ();
1423-
}
1424-
1425-
/* FIXME: unaligned access, endianness */
1426-
switch (dst_col_size) {
1427-
case 1:
1428-
*(guint8*)dst = (guint8)tmp;
1429-
break;
1430-
case 2:
1431-
*(guint16*)dst = (guint16)tmp;
1432-
break;
1433-
case 4:
1434-
*(guint32*)dst = tmp;
1435-
break;
1436-
default:
1437-
g_assert_not_reached ();
1438-
}
1457+
memcpy(dst, src, src_col_size);
14391458
}
14401459
src_offset += src_col_size;
14411460
dst_offset += dst_col_size;

0 commit comments

Comments
 (0)