Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
namespace System.Reflection.Metadata.ApplyUpdate.Test
{
public static class IncreaseMetadataRowSize
{
public static void Main(string[] args) { }
public static int VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_1()
{
return 0;
}
public static void VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_2(int x2) {}
public static void VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_3(int x3) {}
public static void VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_4(int x4) {}
public static void VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_5(int x5) {}
}

}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>System.Runtime.Loader.Tests</RootNamespace>
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
<TestRuntime>true</TestRuntime>
<DeltaScript>deltascript.json</DeltaScript>
</PropertyGroup>
<ItemGroup>
<Compile Include="IncreaseMetadataRowSize.cs" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"changes": [
{"document": "IncreaseMetadataRowSize.cs", "update": "IncreaseMetadataRowSize_v1.cs"},
]
}

20 changes: 20 additions & 0 deletions src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -983,5 +983,25 @@ public static void TestNewMethodThrows()
Assert.True(frame1Name == null || frame1Name.Contains("NewMethodThrows.cs"));
});
}

[ConditionalFact(typeof(ApplyUpdateUtil), nameof (ApplyUpdateUtil.IsSupported))]
void TestIncreaseMetadataRowSize()
{
ApplyUpdateUtil.TestCase(static () =>
{
// Get the custom attribtues from a newly-added type and method
// and check that they are the expected ones.
var assm = typeof(ApplyUpdate.Test.IncreaseMetadataRowSize).Assembly;

ApplyUpdateUtil.ApplyUpdate(assm);
ApplyUpdateUtil.ClearAllReflectionCaches();

var r = ApplyUpdate.Test.IncreaseMetadataRowSize.VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_1();
Assert.Equal(50000, r);
MethodInfo mi = typeof(ApplyUpdate.Test.IncreaseMetadataRowSize).GetMethod("VeryLooooooooooooooooooooooooooooooooongMethodNameToPushTheStringBlobOver64k_800");
ParameterInfo[] pars = mi.GetParameters();
Assert.Equal("x800", pars[0].Name);
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
<ProjectReference Include="ApplyUpdate\System.Reflection.Metadata.ApplyUpdate.Test.GenericAddStaticField\System.Reflection.Metadata.ApplyUpdate.Test.GenericAddStaticField.csproj" />
<ProjectReference Include="ApplyUpdate\System.Reflection.Metadata.ApplyUpdate.Test.GenericAddInstanceField\System.Reflection.Metadata.ApplyUpdate.Test.GenericAddInstanceField.csproj" />
<ProjectReference Include="ApplyUpdate\System.Reflection.Metadata.ApplyUpdate.Test.NewMethodThrows\System.Reflection.Metadata.ApplyUpdate.Test.NewMethodThrows.csproj" />
<ProjectReference Include="ApplyUpdate\System.Reflection.Metadata.ApplyUpdate.Test.IncreaseMetadataRowSize\System.Reflection.Metadata.ApplyUpdate.Test.IncreaseMetadataRowSize.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetOS)' == 'browser'">
<WasmFilesToIncludeFromPublishDir Include="$(AssemblyName).dll" />
Expand Down
99 changes: 59 additions & 40 deletions src/mono/mono/component/hot_reload.c
Original file line number Diff line number Diff line change
Expand Up @@ -924,9 +924,7 @@ delta_info_initialize_mutants (const MonoImage *base, const BaselineInfo *base_i
g_assert (prev_table != NULL);

MonoTableInfo *tbl = &delta->mutants [i];
if (prev_table->rows_ == 0) {
/* 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. */
g_assert (prev_table->row_size == 0);
if (delta->delta_image->tables [i].row_size != 0 || prev_table->rows_ == 0) {
tbl->row_size = delta->delta_image->tables [i].row_size;
tbl->size_bitfield = delta->delta_image->tables [i].size_bitfield;
} else {
Expand All @@ -940,8 +938,60 @@ delta_info_initialize_mutants (const MonoImage *base, const BaselineInfo *base_i
tbl->base = mono_mempool_alloc (delta->pool, tbl->row_size * rows);
g_assert (table_info_get_rows (prev_table) == count->prev_gen_rows);

/* copy the old rows and zero out the new ones */
memcpy ((char*)tbl->base, prev_table->base, count->prev_gen_rows * tbl->row_size);
/* copy the old rows and zero out the new ones */
/* we need to copy following the new format (uncompressed one)*/
for (guint32 j = 0 ; j < count->prev_gen_rows; j++)
{
guint32 src_offset = 0, dst_offset = 0;
guint32 dst_bitfield = tbl->size_bitfield;
guint32 src_bitfield = prev_table->size_bitfield;
const char *src_base = (char*)prev_table->base + j * prev_table->row_size;
char *dst_base = (char*)tbl->base + j * tbl->row_size;
for (guint col = 0; col < mono_metadata_table_count (dst_bitfield); ++col) {
guint32 dst_col_size = mono_metadata_table_size (dst_bitfield, col);
guint32 src_col_size = mono_metadata_table_size (src_bitfield, col);
{
const char *src = src_base + src_offset;
char *dst = dst_base + dst_offset;

/* copy src to dst, via a temporary to adjust for size differences */
/* FIXME: unaligned access, endianness */
guint32 tmp;

switch (src_col_size) {
case 1:
tmp = *(guint8*)src;
break;
case 2:
tmp = *(guint16*)src;
break;
case 4:
tmp = *(guint32*)src;
break;
default:
g_assert_not_reached ();
}

/* FIXME: unaligned access, endianness */
switch (dst_col_size) {
case 1:
*(guint8*)dst = (guint8)tmp;
break;
case 2:
*(guint16*)dst = (guint16)tmp;
break;
case 4:
*(guint32*)dst = tmp;
break;
default:
g_assert_not_reached ();
}
}
src_offset += src_col_size;
dst_offset += dst_col_size;
}
g_assert (dst_offset == tbl->row_size);
}
memset (((char*)tbl->base) + count->prev_gen_rows * tbl->row_size, 0, count->inserted_rows * tbl->row_size);
}
}
Expand Down Expand Up @@ -1386,8 +1436,8 @@ delta_info_mutate_row (MonoImage *image_dmeta, DeltaInfo *cur_delta, guint32 log

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

guint32 dst_bitfield = cur_delta->mutants [token_table].size_bitfield;
Expand All @@ -1401,41 +1451,10 @@ delta_info_mutate_row (MonoImage *image_dmeta, DeltaInfo *cur_delta, guint32 log
guint32 dst_col_size = mono_metadata_table_size (dst_bitfield, col);
guint32 src_col_size = mono_metadata_table_size (src_bitfield, col);
if ((m_SuppressedDeltaColumns [token_table] & (1 << col)) == 0) {
g_assert(src_col_size <= dst_col_size);
const char *src = src_base + src_offset;
char *dst = dst_base + dst_offset;

/* copy src to dst, via a temporary to adjust for size differences */
/* FIXME: unaligned access, endianness */
guint32 tmp;

switch (src_col_size) {
case 1:
tmp = *(guint8*)src;
break;
case 2:
tmp = *(guint16*)src;
break;
case 4:
tmp = *(guint32*)src;
break;
default:
g_assert_not_reached ();
}

/* FIXME: unaligned access, endianness */
switch (dst_col_size) {
case 1:
*(guint8*)dst = (guint8)tmp;
break;
case 2:
*(guint16*)dst = (guint16)tmp;
break;
case 4:
*(guint32*)dst = tmp;
break;
default:
g_assert_not_reached ();
}
memcpy(dst, src, src_col_size);
}
src_offset += src_col_size;
dst_offset += dst_col_size;
Expand Down
Loading