Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mono][debugger] Support new hot reload features from runtime #70697

Merged
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, "Baseline AddMethodToExistingType AddStaticFieldToExistingType NewTypeDefinition ChangeCustomAttributes");
lambdageek marked this conversation as resolved.
Show resolved Hide resolved
break;
}
default:
return ERR_NOT_IMPLEMENTED;
}
Expand Down
5 changes: 3 additions & 2 deletions src/mono/mono/component/debugger-protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/

#define MAJOR_VERSION 2
#define MINOR_VERSION 60
#define MINOR_VERSION 61

typedef enum {
MDBGPROT_CMD_COMPOSITE = 100
Expand All @@ -36,7 +36,8 @@ typedef enum {
MDBGPROT_CMD_VM_READ_MEMORY = 16,
MDBGPROT_CMD_VM_WRITE_MEMORY = 17,
MDBGPROT_CMD_GET_ASSEMBLY_BY_NAME = 18,
MDBGPROT_CMD_GET_MODULE_BY_GUID = 19
MDBGPROT_CMD_GET_MODULE_BY_GUID = 19,
MDBGPROT_CMD_GET_ENC_CAPABILITIES = 20
} MdbgProtCmdVM;

typedef enum {
Expand Down
11 changes: 10 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,9 @@ 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 MonoComponentHotReload fn_table = {
{ MONO_COMPONENT_ITF_VERSION, &hot_reload_stub_available },
&hot_reload_stub_set_fastpath_data,
Expand Down Expand Up @@ -134,7 +137,8 @@ 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
};

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

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

MONO_COMPONENT_EXPORT_ENTRYPOINT
MonoComponentHotReload *
Expand Down
40 changes: 34 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,9 @@ 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 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 +175,7 @@ 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
};

MonoComponentHotReload *
Expand Down Expand Up @@ -738,11 +742,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 +1380,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 +1439,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 +1449,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 +1466,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 +1487,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 +1499,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 +1545,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 +1571,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 +2518,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 +2547,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 +3127,17 @@ 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;
}
1 change: 1 addition & 0 deletions src/mono/mono/component/hot_reload.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ 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);
} 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
8 changes: 7 additions & 1 deletion src/mono/mono/metadata/metadata-update.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,4 +217,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__*/