Skip to content

Commit cc7448c

Browse files
[Mono] Add mono hot reload support for updating parameter name (#85796)
Fixes #56626 Fixes #50978 * Add mono hot reload support for updating parameter name * Add a debugger test * Don't invalidate the whole assembly when using hot reload * don't ignore reflection cache entries when the "no invalidate" flag is set --------- Co-authored-by: Aleksey Kliger <[email protected]>
1 parent e47c4ab commit cc7448c

File tree

8 files changed

+155
-49
lines changed

8 files changed

+155
-49
lines changed

src/mono/mono/component/hot_reload.c

+2-24
Original file line numberDiff line numberDiff line change
@@ -1600,29 +1600,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de
16001600
}
16011601
case MONO_TABLE_PARAM: {
16021602
*should_invalidate_transformed_code = true;
1603-
if (!is_addition) {
1604-
/* We only allow modifications where the parameter name doesn't change. */
1605-
uint32_t base_param [MONO_PARAM_SIZE];
1606-
uint32_t upd_param [MONO_PARAM_SIZE];
1607-
int mapped_token = hot_reload_relative_delta_index (image_dmeta, delta_info, mono_metadata_make_token (token_table, token_index));
1608-
g_assert (mapped_token != -1);
1609-
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x PARAM update. mapped index = 0x%08x\n", i, log_token, mapped_token);
1610-
1611-
mono_metadata_decode_row (&image_dmeta->tables [MONO_TABLE_PARAM], mapped_token - 1, upd_param, MONO_PARAM_SIZE);
1612-
mono_metadata_decode_row (&image_base->tables [MONO_TABLE_PARAM], token_index - 1, base_param, MONO_PARAM_SIZE);
1613-
1614-
const char *base_name = mono_metadata_string_heap (image_base, base_param [MONO_PARAM_NAME]);
1615-
const char *upd_name = mono_metadata_string_heap (image_base, upd_param [MONO_PARAM_NAME]);
1616-
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "row[0x%02x: 0x%08x PARAM update: seq = %d (base = %d), name = '%s' (base = '%s')\n", i, log_token, upd_param [MONO_PARAM_SEQUENCE], base_param [MONO_PARAM_SEQUENCE], upd_name, base_name);
1617-
if (strcmp (base_name, upd_name) != 0 || base_param [MONO_PARAM_SEQUENCE] != upd_param [MONO_PARAM_SEQUENCE]) {
1618-
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "row[0x%02x]:0x%08x we do not support patching of existing PARAM table cols.", i, log_token);
1619-
mono_error_set_type_load_name (error, NULL, image_base->name, "EnC: we do not support patching of existing PARAM table cols. token=0x%08x", log_token);
1620-
unsupported_edits = TRUE;
1621-
continue;
1622-
}
1623-
break;
1624-
} else
1625-
break; /* added a row. ok */
1603+
break;
16261604
}
16271605
case MONO_TABLE_TYPEDEF: {
16281606
*should_invalidate_transformed_code = true;
@@ -3493,7 +3471,7 @@ hot_reload_get_method_params (MonoImage *base_image, uint32_t methoddef_token, u
34933471
static const char *
34943472
hot_reload_get_capabilities (void)
34953473
{
3496-
return "Baseline AddMethodToExistingType AddStaticFieldToExistingType NewTypeDefinition ChangeCustomAttributes AddInstanceFieldToExistingType GenericAddMethodToExistingType GenericUpdateMethod";
3474+
return "Baseline AddMethodToExistingType AddStaticFieldToExistingType NewTypeDefinition ChangeCustomAttributes AddInstanceFieldToExistingType GenericAddMethodToExistingType GenericUpdateMethod UpdateParameters";
34973475
}
34983476

34993477
static GENERATE_GET_CLASS_WITH_CACHE_DECL (hot_reload_instance_field_table);

src/mono/mono/metadata/metadata.c

+10-5
Original file line numberDiff line numberDiff line change
@@ -5126,12 +5126,17 @@ mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
51265126
/* FIXME: Index translation */
51275127

51285128
gboolean found = tdef->base && mono_binary_search (&loc, tdef->base, table_info_get_rows (tdef), tdef->row_size, table_locator) != NULL;
5129-
if (!found && !meta->has_updates)
5130-
return 0;
5131-
5132-
if (G_UNLIKELY (meta->has_updates)) {
5133-
if (!found && !mono_metadata_update_metadata_linear_search (meta, tdef, &loc, table_locator))
5129+
if (!found) {
5130+
if (G_LIKELY (!meta->has_updates)) {
51345131
return 0;
5132+
} else {
5133+
if ((mono_metadata_table_num_rows (meta, MONO_TABLE_CUSTOMATTRIBUTE) > table_info_get_rows (tdef))) {
5134+
if (!mono_metadata_update_metadata_linear_search (meta, tdef, &loc, table_locator))
5135+
return 0;
5136+
} else {
5137+
return 0;
5138+
}
5139+
}
51355140
}
51365141

51375142
/* Find the first entry by searching backwards */

src/mono/mono/metadata/reflection-cache.h

+48-10
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <mono/metadata/mono-hash.h>
1313
#include <mono/metadata/mempool.h>
1414
#include <mono/utils/mono-error-internals.h>
15+
#include <mono/metadata/metadata-update.h>
1516

1617
/*
1718
* We need to return always the same object for MethodInfo, FieldInfo etc..
@@ -22,8 +23,14 @@
2223
typedef struct {
2324
gpointer item;
2425
MonoClass *refclass;
26+
uint32_t generation; /* 0 is normal; hot reload may change it */
2527
} ReflectedEntry;
2628

29+
enum {
30+
MONO_REFL_CACHE_DEFAULT = 0,
31+
MONO_REFL_CACHE_NO_HOT_RELOAD_INVALIDATE = 1,
32+
};
33+
2734
gboolean
2835
mono_reflected_equal (gconstpointer a, gconstpointer b);
2936

@@ -46,7 +53,7 @@ free_reflected_entry (ReflectedEntry *entry)
4653
}
4754

4855
static inline MonoObject*
49-
cache_object (MonoMemoryManager *mem_manager, MonoClass *klass, gpointer item, MonoObject* o)
56+
cache_object (MonoMemoryManager *mem_manager, int flags, MonoClass *klass, gpointer item, MonoObject* o)
5057
{
5158
MonoObject *obj;
5259
ReflectedEntry pe;
@@ -59,6 +66,10 @@ cache_object (MonoMemoryManager *mem_manager, MonoClass *klass, gpointer item, M
5966
ReflectedEntry *e = alloc_reflected_entry (mem_manager);
6067
e->item = item;
6168
e->refclass = klass;
69+
if (G_UNLIKELY(mono_metadata_has_updates()) && ((flags & MONO_REFL_CACHE_NO_HOT_RELOAD_INVALIDATE) == 0))
70+
e->generation = mono_metadata_update_get_thread_generation();
71+
else
72+
e->generation = 0;
6273
mono_conc_g_hash_table_insert (mem_manager->refobject_hash, e, o);
6374
obj = o;
6475
}
@@ -67,7 +78,7 @@ cache_object (MonoMemoryManager *mem_manager, MonoClass *klass, gpointer item, M
6778
}
6879

6980
static inline MonoObjectHandle
70-
cache_object_handle (MonoMemoryManager *mem_manager, MonoClass *klass, gpointer item, MonoObjectHandle o)
81+
cache_object_handle (MonoMemoryManager *mem_manager, int flags, MonoClass *klass, gpointer item, MonoObjectHandle o)
7182
{
7283
MonoObjectHandle obj;
7384
ReflectedEntry pe;
@@ -83,6 +94,10 @@ cache_object_handle (MonoMemoryManager *mem_manager, MonoClass *klass, gpointer
8394
ReflectedEntry *e = alloc_reflected_entry (mem_manager);
8495
e->item = item;
8596
e->refclass = klass;
97+
if (G_UNLIKELY(mono_metadata_has_updates()) && ((flags & MONO_REFL_CACHE_NO_HOT_RELOAD_INVALIDATE) == 0))
98+
e->generation = mono_metadata_update_get_thread_generation();
99+
else
100+
e->generation = 0;
86101
mono_conc_g_hash_table_insert (mem_manager->refobject_hash, e, MONO_HANDLE_RAW (o));
87102
MONO_HANDLE_ASSIGN (obj, o);
88103
}
@@ -92,6 +107,10 @@ cache_object_handle (MonoMemoryManager *mem_manager, MonoClass *klass, gpointer
92107
ReflectedEntry *e = alloc_reflected_entry (mem_manager);
93108
e->item = item;
94109
e->refclass = klass;
110+
if (G_UNLIKELY(mono_metadata_has_updates()) && ((flags & MONO_REFL_CACHE_NO_HOT_RELOAD_INVALIDATE) == 0))
111+
e->generation = mono_metadata_update_get_thread_generation();
112+
else
113+
e->generation = 0;
95114
mono_weak_hash_table_insert (mem_manager->weak_refobject_hash, e, MONO_HANDLE_RAW (o));
96115
MONO_HANDLE_ASSIGN (obj, o);
97116
}
@@ -100,13 +119,14 @@ cache_object_handle (MonoMemoryManager *mem_manager, MonoClass *klass, gpointer
100119
return obj;
101120
}
102121

103-
#define CACHE_OBJECT(t,mem_manager,p,o,k) ((t) (cache_object ((mem_manager), (k), (p), (o))))
104-
#define CACHE_OBJECT_HANDLE(t,mem_manager,p,o,k) (MONO_HANDLE_CAST (t, cache_object_handle ((mem_manager), (k), (p), (o))))
122+
#define CACHE_OBJECT(t,mem_manager,flags,p,o,k) ((t) (cache_object ((mem_manager), (flags), (k), (p), (o))))
123+
#define CACHE_OBJECT_HANDLE(t,mem_manager,flags,p,o,k) (MONO_HANDLE_CAST (t, cache_object_handle ((mem_manager), (flags), (k), (p), (o))))
105124

106125
static inline MonoObjectHandle
107-
check_object_handle (MonoMemoryManager *mem_manager, MonoClass *klass, gpointer item)
126+
check_object_handle (MonoMemoryManager *mem_manager, int flags, MonoClass *klass, gpointer item)
108127
{
109128
MonoObjectHandle obj_handle;
129+
gpointer orig_e, orig_value;
110130
ReflectedEntry e;
111131
e.item = item;
112132
e.refclass = klass;
@@ -123,6 +143,24 @@ check_object_handle (MonoMemoryManager *mem_manager, MonoClass *klass, gpointer
123143
MonoWeakHashTable *hash = mem_manager->weak_refobject_hash;
124144
obj_handle = MONO_HANDLE_NEW (MonoObject, (MonoObject *)mono_weak_hash_table_lookup (hash, &e));
125145
}
146+
147+
if (!mem_manager->collectible) {
148+
MonoConcGHashTable *hash = mem_manager->refobject_hash;
149+
if (mono_conc_g_hash_table_lookup_extended (hash, &e, &orig_e, &orig_value))
150+
if (mono_metadata_has_updates() && ((flags & MONO_REFL_CACHE_NO_HOT_RELOAD_INVALIDATE) == 0) && ((ReflectedEntry *)orig_e)->generation < mono_metadata_update_get_thread_generation()) {
151+
mono_conc_g_hash_table_remove (hash, &e);
152+
free_reflected_entry ((ReflectedEntry *)orig_e);
153+
obj_handle = MONO_HANDLE_NEW (MonoObject, NULL);
154+
} else {
155+
obj_handle = MONO_HANDLE_NEW (MonoObject, (MonoObject *)orig_value);
156+
}
157+
else {
158+
obj_handle = MONO_HANDLE_NEW (MonoObject, NULL);
159+
}
160+
} else {
161+
MonoWeakHashTable *hash = mem_manager->weak_refobject_hash;
162+
obj_handle = MONO_HANDLE_NEW (MonoObject, (MonoObject *)mono_weak_hash_table_lookup (hash, &e));
163+
}
126164
mono_mem_manager_unlock (mem_manager);
127165

128166
return obj_handle;
@@ -131,22 +169,22 @@ check_object_handle (MonoMemoryManager *mem_manager, MonoClass *klass, gpointer
131169
typedef MonoObjectHandle (*ReflectionCacheConstructFunc_handle) (MonoClass*, gpointer, gpointer, MonoError *);
132170

133171
static inline MonoObjectHandle
134-
check_or_construct_handle (MonoMemoryManager *mem_manager, MonoClass *klass, gpointer item, gpointer user_data, MonoError *error, ReflectionCacheConstructFunc_handle construct)
172+
check_or_construct_handle (MonoMemoryManager *mem_manager, int flags, MonoClass *klass, gpointer item, gpointer user_data, MonoError *error, ReflectionCacheConstructFunc_handle construct)
135173
{
136174
error_init (error);
137-
MonoObjectHandle obj = check_object_handle (mem_manager, klass, item);
175+
MonoObjectHandle obj = check_object_handle (mem_manager, flags, klass, item);
138176
if (!MONO_HANDLE_IS_NULL (obj))
139177
return obj;
140178
MONO_HANDLE_ASSIGN (obj, construct (klass, item, user_data, error));
141179
return_val_if_nok (error, NULL_HANDLE);
142180
if (MONO_HANDLE_IS_NULL (obj))
143181
return obj;
144182
/* note no caching if there was an error in construction */
145-
return cache_object_handle (mem_manager, klass, item, obj);
183+
return cache_object_handle (mem_manager, flags, klass, item, obj);
146184
}
147185

148-
#define CHECK_OR_CONSTRUCT_HANDLE(type,mem_manager, item,klass,construct,user_data) \
186+
#define CHECK_OR_CONSTRUCT_HANDLE(type,mem_manager,flags,item,klass,construct,user_data) \
149187
(MONO_HANDLE_CAST (type, check_or_construct_handle ( \
150-
(mem_manager), (klass), (item), (user_data), error, (ReflectionCacheConstructFunc_handle) (construct))))
188+
(mem_manager), (flags), (klass), (item), (user_data), error, (ReflectionCacheConstructFunc_handle) (construct))))
151189

152190
#endif /*__MONO_METADATA_REFLECTION_CACHE_H__*/

src/mono/mono/metadata/reflection.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ MonoReflectionAssemblyHandle
243243
mono_assembly_get_object_handle (MonoAssembly *assembly, MonoError *error)
244244
{
245245
error_init (error);
246-
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionAssembly, m_image_get_mem_manager (assembly->image), assembly, NULL, assembly_object_construct, NULL);
246+
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionAssembly, m_image_get_mem_manager (assembly->image), MONO_REFL_CACHE_NO_HOT_RELOAD_INVALIDATE, assembly, NULL, assembly_object_construct, NULL);
247247
}
248248

249249
/**
@@ -311,7 +311,7 @@ MonoReflectionModuleHandle
311311
mono_module_get_object_handle (MonoImage *image, MonoError *error)
312312
{
313313
error_init (error);
314-
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionModule, m_image_get_mem_manager (image), image, NULL, module_object_construct, NULL);
314+
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionModule, m_image_get_mem_manager (image), MONO_REFL_CACHE_NO_HOT_RELOAD_INVALIDATE, image, NULL, module_object_construct, NULL);
315315
}
316316

317317
/**
@@ -670,7 +670,7 @@ mono_method_get_object_handle (MonoMethod *method, MonoClass *refclass, MonoErro
670670
refclass = method->klass;
671671

672672
// FIXME: For methods/params etc., use the mem manager for refclass or a merged one ?
673-
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionMethod, m_method_get_mem_manager (method), method, refclass, method_object_construct, NULL);
673+
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionMethod, m_method_get_mem_manager (method), MONO_REFL_CACHE_DEFAULT, method, refclass, method_object_construct, NULL);
674674
}
675675
/*
676676
* mono_method_get_object_checked:
@@ -776,7 +776,7 @@ MonoReflectionFieldHandle
776776
mono_field_get_object_handle (MonoClass *klass, MonoClassField *field, MonoError *error)
777777
{
778778
error_init (error);
779-
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionField, m_class_get_mem_manager (m_field_get_parent (field)), field, klass, field_object_construct, NULL);
779+
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionField, m_class_get_mem_manager (m_field_get_parent (field)), MONO_REFL_CACHE_DEFAULT, field, klass, field_object_construct, NULL);
780780
}
781781

782782
/*
@@ -844,7 +844,7 @@ property_object_construct (MonoClass *klass, MonoProperty *property, gpointer us
844844
MonoReflectionPropertyHandle
845845
mono_property_get_object_handle (MonoClass *klass, MonoProperty *property, MonoError *error)
846846
{
847-
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionProperty, m_class_get_mem_manager (property->parent), property, klass, property_object_construct, NULL);
847+
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionProperty, m_class_get_mem_manager (property->parent), MONO_REFL_CACHE_DEFAULT, property, klass, property_object_construct, NULL);
848848
}
849849

850850
/**
@@ -909,7 +909,7 @@ MonoReflectionEventHandle
909909
mono_event_get_object_handle (MonoClass *klass, MonoEvent *event, MonoError *error)
910910
{
911911
error_init (error);
912-
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionEvent, m_class_get_mem_manager (event->parent), event, klass, event_object_construct, NULL);
912+
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionEvent, m_class_get_mem_manager (event->parent), MONO_REFL_CACHE_DEFAULT, event, klass, event_object_construct, NULL);
913913
}
914914

915915

@@ -1167,7 +1167,7 @@ mono_param_get_objects_internal (MonoMethod *method, MonoClass *refclass, MonoEr
11671167
/* Note: the cache is based on the address of the signature into the method
11681168
* since we already cache MethodInfos with the method as keys.
11691169
*/
1170-
return CHECK_OR_CONSTRUCT_HANDLE (MonoArray, m_method_get_mem_manager (method), &method->signature, refclass, param_objects_construct, method);
1170+
return CHECK_OR_CONSTRUCT_HANDLE (MonoArray, m_method_get_mem_manager (method), MONO_REFL_CACHE_NO_HOT_RELOAD_INVALIDATE, &method->signature, refclass, param_objects_construct, method);
11711171
fail:
11721172
return MONO_HANDLE_NEW (MonoArray, NULL);
11731173
}
@@ -1392,7 +1392,7 @@ MonoReflectionMethodBodyHandle
13921392
mono_method_body_get_object_handle (MonoMethod *method, MonoError *error)
13931393
{
13941394
error_init (error);
1395-
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionMethodBody, m_method_get_mem_manager (method), method, NULL, method_body_object_construct, NULL);
1395+
return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionMethodBody, m_method_get_mem_manager (method), MONO_REFL_CACHE_NO_HOT_RELOAD_INVALIDATE, method, NULL, method_body_object_construct, NULL);
13961396
}
13971397

13981398
/**

src/mono/mono/metadata/sre.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1188,13 +1188,13 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj,
11881188
static gpointer
11891189
register_assembly (MonoReflectionAssembly *res, MonoAssembly *assembly)
11901190
{
1191-
return CACHE_OBJECT (MonoReflectionAssembly *, mono_mem_manager_get_ambient (), assembly, &res->object, NULL);
1191+
return CACHE_OBJECT (MonoReflectionAssembly *, mono_mem_manager_get_ambient (), MONO_REFL_CACHE_NO_HOT_RELOAD_INVALIDATE, assembly, &res->object, NULL);
11921192
}
11931193

11941194
static MonoReflectionModuleBuilderHandle
11951195
register_module (MonoReflectionModuleBuilderHandle res, MonoDynamicImage *module)
11961196
{
1197-
return CACHE_OBJECT_HANDLE (MonoReflectionModuleBuilder, mono_mem_manager_get_ambient (), module, MONO_HANDLE_CAST (MonoObject, res), NULL);
1197+
return CACHE_OBJECT_HANDLE (MonoReflectionModuleBuilder, mono_mem_manager_get_ambient (), MONO_REFL_CACHE_NO_HOT_RELOAD_INVALIDATE, module, MONO_HANDLE_CAST (MonoObject, res), NULL);
11981198
}
11991199

12001200
/*

src/mono/wasm/debugger/DebuggerTestSuite/HotReloadTests.cs

+38
Original file line numberDiff line numberDiff line change
@@ -599,5 +599,43 @@ await SendCommandAndCheck (JObject.FromObject(new { }), "Debugger.resume", scrip
599599
}, "c", num_fields: 2);
600600
});
601601
}
602+
603+
// Enable this test when https://github.com/dotnet/hotreload-utils/pull/264 flows into dotnet/runtime repo
604+
// [ConditionalFact(nameof(RunningOnChrome))]
605+
// public async Task DebugHotReloadMethod_ChangeParameterName()
606+
// {
607+
// string asm_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.dll");
608+
// string pdb_file = Path.Combine(DebuggerTestAppPath, "ApplyUpdateReferencedAssembly.pdb");
609+
// string asm_file_hot_reload = Path.Combine(DebuggerTestAppPath, "../wasm/ApplyUpdateReferencedAssembly.dll");
610+
611+
// var bp_notchanged = await SetBreakpoint(".*/MethodBody1.cs$", 89, 12, use_regex: true);
612+
// // var bp_invalid = await SetBreakpoint(".*/MethodBody1.cs$", 59, 12, use_regex: true);
613+
614+
// var pause_location = await LoadAssemblyAndTestHotReloadUsingSDBWithoutChanges(
615+
// asm_file, pdb_file, "MethodBody9", "test", expectBpResolvedEvent: true, sourcesToWait: new string [] { "MethodBody0.cs", "MethodBody1.cs" });
616+
617+
// CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 89, 12, scripts, pause_location["callFrames"]?[0]["location"]);
618+
// await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 90, 12, "ApplyUpdateReferencedAssembly.MethodBody9.M1",
619+
// locals_fn: async (locals) =>
620+
// {
621+
// CheckNumber(locals, "a", 1);
622+
// await Task.CompletedTask;
623+
// }
624+
// );
625+
// //apply first update
626+
// pause_location = await LoadAssemblyAndTestHotReloadUsingSDB(
627+
// asm_file_hot_reload, "MethodBody9", "test", 1);
628+
629+
// JToken top_frame = pause_location["callFrames"]?[0];
630+
// AssertEqual("ApplyUpdateReferencedAssembly.MethodBody9.M1", top_frame?["functionName"]?.Value<string>(), top_frame?.ToString());
631+
// CheckLocation("dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 89, 12, scripts, top_frame["location"]);
632+
// await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 90, 12, "ApplyUpdateReferencedAssembly.MethodBody9.M1",
633+
// locals_fn: async (locals) =>
634+
// {
635+
// CheckNumber(locals, "x", 1);
636+
// await Task.CompletedTask;
637+
// }
638+
// );
639+
// }
602640
}
603641
}

src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1.cs

+37
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,41 @@ public static void StaticMethod1 () {
5757
Console.WriteLine("original");
5858
}
5959
}
60+
61+
62+
63+
64+
65+
66+
67+
68+
69+
70+
71+
72+
73+
74+
75+
76+
77+
78+
79+
80+
81+
82+
83+
84+
85+
86+
87+
88+
// public class MethodBody9 {
89+
// public static int M1(int a, int b) {
90+
// return a + b;
91+
// }
92+
93+
// public static int test() {
94+
// return M1(1, 2);
95+
// }
96+
// }
6097
}

src/mono/wasm/debugger/tests/ApplyUpdateReferencedAssembly/MethodBody1_v1.cs

+10
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,14 @@ public void InstanceMethod () {
8484
Console.WriteLine($"add a breakpoint the instance method of the new class");
8585
}
8686
}
87+
88+
// public class MethodBody9 {
89+
// public static int M1(int x, int y) {
90+
// return x + y;
91+
// }
92+
93+
// public static int test() {
94+
// return M1(1, 2);
95+
// }
96+
// }
8797
}

0 commit comments

Comments
 (0)