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
Expand Up @@ -55,13 +55,16 @@ public static void ApplyUpdate(Assembly assembly, ReadOnlySpan<byte> metadataDel

private static string InitializeApplyUpdateCapabilities()
{
const string caps = "Baseline AddMethodToExistingType AddStaticFieldToExistingType NewTypeDefinition";
return ApplyUpdateEnabled(justComponentCheck: 1) != 0 ? caps : string.Empty ;
string caps = GetApplyUpdateCapabilities();
return ApplyUpdateEnabled(justComponentCheck: 1) != 0 ? caps : string.Empty;
}

[MethodImpl (MethodImplOptions.InternalCall)]
private static extern int ApplyUpdateEnabled (int justComponentCheck);

[MethodImpl (MethodImplOptions.InternalCall)]
private static extern string GetApplyUpdateCapabilities();

[MethodImpl (MethodImplOptions.InternalCall)]
private static extern unsafe void ApplyUpdate_internal (IntPtr base_assm, byte* dmeta_bytes, int dmeta_length, byte *dil_bytes, int dil_length, byte *dpdb_bytes, int dpdb_length);
}
Expand Down
4 changes: 4 additions & 0 deletions src/mono/mono/component/debugger-agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -7051,6 +7051,10 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
buffer_add_moduleid (buf, mono_get_root_domain (), assembly->image);
break;
}
case MDBGPROT_CMD_GET_ENC_CAPABILITIES: {
buffer_add_string (buf, mono_enc_capabilities ());
break;
}
default:
return ERR_NOT_IMPLEMENTED;
}
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/component/debugger-protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ typedef enum {
MDBGPROT_CMD_GET_ASSEMBLY_BY_NAME = 18,
MDBGPROT_CMD_GET_MODULE_BY_GUID = 19,
MDBGPROT_CMD_GET_ASSEMBLY_BYTES = 20, //wasm specific
MDBGPROT_CMD_GET_ENC_CAPABILITIES = 21
} MdbgProtCmdVM;

typedef enum {
Expand Down
21 changes: 20 additions & 1 deletion src/mono/mono/component/hot_reload-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ hot_reload_stub_added_fields_iter (MonoClass *klass, gboolean lazy, gpointer *it
static uint32_t
hot_reload_get_num_fields_added (MonoClass *klass);

static uint32_t
hot_reload_get_num_methods_added (MonoClass *klass);

static const char *
hot_reload_get_capabilities (void);

static MonoComponentHotReload fn_table = {
{ MONO_COMPONENT_ITF_VERSION, &hot_reload_stub_available },
&hot_reload_stub_set_fastpath_data,
Expand Down Expand Up @@ -134,7 +140,9 @@ static MonoComponentHotReload fn_table = {
&hot_reload_stub_get_typedef_skeleton_events,
&hot_reload_stub_added_methods_iter,
&hot_reload_stub_added_fields_iter,
&hot_reload_get_num_fields_added
&hot_reload_get_num_fields_added,
&hot_reload_get_num_methods_added,
&hot_reload_get_capabilities
};

static bool
Expand Down Expand Up @@ -323,6 +331,17 @@ hot_reload_get_num_fields_added (MonoClass *klass)
return 0;
}

static uint32_t
hot_reload_get_num_methods_added (MonoClass *klass)
{
return 0;
}

static const char *
hot_reload_get_capabilities (void)
{
return "";
}

MONO_COMPONENT_EXPORT_ENTRYPOINT
MonoComponentHotReload *
Expand Down
50 changes: 44 additions & 6 deletions src/mono/mono/component/hot_reload.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ hot_reload_added_fields_iter (MonoClass *klass, gboolean lazy, gpointer *iter);
static uint32_t
hot_reload_get_num_fields_added (MonoClass *klass);

static uint32_t
hot_reload_get_num_methods_added (MonoClass *klass);

static const char *
hot_reload_get_capabilities (void);

static MonoClassMetadataUpdateField *
metadata_update_field_setup_basic_info_and_resolve (MonoImage *image_base, BaselineInfo *base_info, uint32_t generation, DeltaInfo *delta_info, MonoClass *parent_klass, uint32_t fielddef_token, uint32_t field_flags, MonoError *error);

Expand Down Expand Up @@ -172,6 +178,8 @@ static MonoComponentHotReload fn_table = {
&hot_reload_added_methods_iter,
&hot_reload_added_fields_iter,
&hot_reload_get_num_fields_added,
&hot_reload_get_num_methods_added,
&hot_reload_get_capabilities
};

MonoComponentHotReload *
Expand Down Expand Up @@ -738,11 +746,12 @@ hot_reload_wait_for_update (uint32_t timeout_ms)
}

static void
hot_reload_update_publish (MonoAssemblyLoadContext *alc, uint32_t generation)
hot_reload_update_publish (MonoAssemblyLoadContext *alc, uint32_t generation, gboolean should_invalidate_transformed_code)
{
g_assert (update_published < generation && generation <= update_alloc_frontier);
/* TODO: wait for all threads that are using old metadata to update. */
hot_reload_update_published_invoke_hook (alc, generation);
if (should_invalidate_transformed_code)
hot_reload_update_published_invoke_hook (alc, generation);
update_published = update_alloc_frontier;
mono_memory_write_barrier ();
publish_unlock ();
Expand Down Expand Up @@ -1375,8 +1384,9 @@ prepare_mutated_rows (const MonoTableInfo *table_enclog, MonoImage *image_base,
* function will fail and the metadata update should be aborted. This should
* run before anything in the metadata world is updated. */
static gboolean
apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *delta_info, gconstpointer dil_data, uint32_t dil_length, MonoError *error)
apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *delta_info, gconstpointer dil_data, uint32_t dil_length, gboolean *should_invalidate_transformed_code, MonoError *error)
{
*should_invalidate_transformed_code = false;
MonoTableInfo *table_enclog = &image_dmeta->tables [MONO_TABLE_ENCLOG];
int rows = table_info_get_rows (table_enclog);

Expand Down Expand Up @@ -1433,6 +1443,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de
/* okay, supported */
break;
case MONO_TABLE_METHOD:
*should_invalidate_transformed_code = true;
if (func_code == ENC_FUNC_ADD_PARAM)
continue; /* ok, allowed */
/* handled above */
Expand All @@ -1442,6 +1453,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de
g_assert (func_code == ENC_FUNC_DEFAULT);
break;
case MONO_TABLE_PROPERTYMAP: {
*should_invalidate_transformed_code = true;
if (func_code == ENC_FUNC_ADD_PROPERTY) {
g_assert (i + 1 < rows);
i++; /* skip the next record */
Expand All @@ -1458,10 +1470,12 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de
}
case MONO_TABLE_PROPERTY: {
/* ok */
*should_invalidate_transformed_code = true;
g_assert (func_code == ENC_FUNC_DEFAULT);
break;
}
case MONO_TABLE_EVENTMAP: {
*should_invalidate_transformed_code = true;
if (func_code == ENC_FUNC_ADD_EVENT) {
g_assert (i + 1 < rows);
i++; /* skip the next record */
Expand All @@ -1477,6 +1491,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de
break;
}
case MONO_TABLE_METHODSEMANTICS: {
*should_invalidate_transformed_code = true;
if (is_addition) {
/* new rows are fine */
break;
Expand All @@ -1488,6 +1503,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de
}
}
case MONO_TABLE_CUSTOMATTRIBUTE: {
*should_invalidate_transformed_code = true;
if (!is_addition) {
/* modifying existing rows is ok, as long as the parent and ctor are the same */
guint32 ca_upd_cols [MONO_CUSTOM_ATTR_SIZE];
Expand Down Expand Up @@ -1533,6 +1549,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de
}
}
case MONO_TABLE_PARAM: {
*should_invalidate_transformed_code = true;
if (!is_addition) {
/* We only allow modifications where the parameter name doesn't change. */
uint32_t base_param [MONO_PARAM_SIZE];
Expand All @@ -1558,6 +1575,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, DeltaInfo *de
break; /* added a row. ok */
}
case MONO_TABLE_TYPEDEF: {
*should_invalidate_transformed_code = true;
if (func_code == ENC_FUNC_ADD_METHOD) {
/* next record should be a MONO_TABLE_METHOD addition (func == default) */
g_assert (i + 1 < rows);
Expand Down Expand Up @@ -2504,8 +2522,8 @@ hot_reload_apply_changes (int origin, MonoImage *image_base, gconstpointer dmeta

mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "Populated mutated tables for delta image %p", image_dmeta);


if (!apply_enclog_pass1 (image_base, image_dmeta, delta_info, dil_bytes, dil_length, error)) {
gboolean should_invalidate_transformed_code = false;
if (!apply_enclog_pass1 (image_base, image_dmeta, delta_info, dil_bytes, dil_length, &should_invalidate_transformed_code, error)) {
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "Error on sanity-checking delta image to base=%s, due to: %s", basename, mono_error_get_message (error));
hot_reload_update_cancel (generation);
return;
Expand Down Expand Up @@ -2533,7 +2551,7 @@ hot_reload_apply_changes (int origin, MonoImage *image_base, gconstpointer dmeta
pass2_context_destroy (&pass2ctx);

MonoAssemblyLoadContext *alc = mono_image_get_alc (image_base);
hot_reload_update_publish (alc, generation);
hot_reload_update_publish (alc, generation, should_invalidate_transformed_code);

mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, ">>> EnC delta for base=%s (generation %d) applied", basename, generation);
}
Expand Down Expand Up @@ -3113,3 +3131,23 @@ hot_reload_get_num_fields_added (MonoClass *klass)
return 0;
return g_slist_length (info->added_fields);
}

static uint32_t
hot_reload_get_num_methods_added (MonoClass *klass)
{
uint32_t count = 0;
GSList *members = hot_reload_get_added_members (klass);
for (GSList *ptr = members; ptr; ptr = ptr->next) {
uint32_t token = GPOINTER_TO_UINT(ptr->data);
if (mono_metadata_token_table (token) != MONO_TABLE_METHOD)
continue;
count++;
}
return count;
}

static const char *
hot_reload_get_capabilities (void)
{
return "Baseline AddMethodToExistingType AddStaticFieldToExistingType NewTypeDefinition ChangeCustomAttributes";
}
2 changes: 2 additions & 0 deletions src/mono/mono/component/hot_reload.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ typedef struct _MonoComponentHotReload {
MonoMethod* (*added_methods_iter) (MonoClass *klass, gpointer *iter);
MonoClassField* (*added_fields_iter) (MonoClass *klass, gboolean lazy, gpointer *iter);
uint32_t (*get_num_fields_added) (MonoClass *klass);
uint32_t (*get_num_methods_added) (MonoClass *klass);
const char* (*get_capabilities) (void);
} MonoComponentHotReload;

MONO_COMPONENT_EXPORT_ENTRYPOINT
Expand Down
4 changes: 4 additions & 0 deletions src/mono/mono/metadata/class.c
Original file line number Diff line number Diff line change
Expand Up @@ -4986,6 +4986,10 @@ mono_class_num_fields (MonoClass *klass)
int
mono_class_num_methods (MonoClass *klass)
{
MonoImage *image = m_class_get_image (klass);
if (G_UNLIKELY (image->has_updates)) {
return mono_class_get_method_count (klass) + mono_metadata_update_get_num_methods_added (klass);
}
return mono_class_get_method_count (klass);
}

Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/metadata/icall-decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ ICALL_EXPORT void ves_icall_System_Runtime_Intrinsics_X86_X86Base___cpuidex (int

ICALL_EXPORT void ves_icall_AssemblyExtensions_ApplyUpdate (MonoAssembly *assm, gconstpointer dmeta_bytes, int32_t dmeta_len, gconstpointer dil_bytes, int32_t dil_len, gconstpointer dpdb_bytes, int32_t dpdb_len);
ICALL_EXPORT gint32 ves_icall_AssemblyExtensions_ApplyUpdateEnabled (gint32 just_component_check);
ICALL_EXPORT gint32 ves_icall_AssemblyExtensions_ApplyUpdateEnabled (gint32 just_component_check);

ICALL_EXPORT guint32 ves_icall_RuntimeTypeHandle_GetCorElementType (MonoQCallTypeHandle type_handle);

Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/metadata/icall-def.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ HANDLES(FILEDI_2, "internal_from_handle_type", ves_icall_System_Reflection_Field
ICALL_TYPE(MDUP, "System.Reflection.Metadata.MetadataUpdater", MDUP_1)
NOHANDLES(ICALL(MDUP_1, "ApplyUpdateEnabled", ves_icall_AssemblyExtensions_ApplyUpdateEnabled))
NOHANDLES(ICALL(MDUP_2, "ApplyUpdate_internal", ves_icall_AssemblyExtensions_ApplyUpdate))
HANDLES(MDUP_3, "GetApplyUpdateCapabilities", ves_icall_AssemblyExtensions_GetApplyUpdateCapabilities, MonoString, 0, ())

ICALL_TYPE(MBASE, "System.Reflection.MethodBase", MBASE_1)
HANDLES(MBASE_1, "GetCurrentMethod", ves_icall_GetCurrentMethod, MonoReflectionMethod, 0, ())
Expand Down
9 changes: 9 additions & 0 deletions src/mono/mono/metadata/icall.c
Original file line number Diff line number Diff line change
Expand Up @@ -5334,6 +5334,15 @@ ves_icall_AssemblyExtensions_ApplyUpdate (MonoAssembly *assm,
mono_error_set_pending_exception (error);
}

MonoStringHandle
ves_icall_AssemblyExtensions_GetApplyUpdateCapabilities (MonoError *error)
{
MonoStringHandle s;
s = mono_string_new_handle (mono_enc_capabilities (), error);
return_val_if_nok (error, NULL_HANDLE_STRING);
return s;
}

gint32 ves_icall_AssemblyExtensions_ApplyUpdateEnabled (gint32 just_component_check)
{
// if just_component_check is true, we only care whether the hot_reload component is enabled,
Expand Down
3 changes: 3 additions & 0 deletions src/mono/mono/metadata/metadata-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,9 @@ enum MonoEnCDeltaOrigin {
MONO_COMPONENT_API void
mono_image_load_enc_delta (int delta_origin, MonoImage *base_image, gconstpointer dmeta, uint32_t dmeta_len, gconstpointer dil, uint32_t dil_len, gconstpointer dpdb, uint32_t dpdb_len, MonoError *error);

MONO_COMPONENT_API const char*
mono_enc_capabilities (void);

gboolean
mono_image_load_cli_header (MonoImage *image, MonoCLIImageInfo *iinfo);

Expand Down
12 changes: 12 additions & 0 deletions src/mono/mono/metadata/metadata-update.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ mono_image_load_enc_delta (int origin, MonoImage *base_image, gconstpointer dmet
}
}

const char*
mono_enc_capabilities (void)
{
return mono_component_hot_reload ()->get_capabilities();
}

static void
mono_image_close_except_pools_all_list (GList *images)
{
Expand Down Expand Up @@ -217,4 +223,10 @@ uint32_t
mono_metadata_update_get_num_fields_added (MonoClass *klass)
{
return mono_component_hot_reload()->get_num_fields_added (klass);
}

uint32_t
mono_metadata_update_get_num_methods_added (MonoClass *klass)
{
return mono_component_hot_reload()->get_num_methods_added (klass);
}
3 changes: 3 additions & 0 deletions src/mono/mono/metadata/metadata-update.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,7 @@ mono_metadata_update_added_fields_iter (MonoClass *klass, gboolean lazy, gpointe

uint32_t
mono_metadata_update_get_num_fields_added (MonoClass *klass);

uint32_t
mono_metadata_update_get_num_methods_added (MonoClass *klass);
#endif /*__MONO_METADATA_UPDATE_H__*/