未验证 提交 6212eabc 编写于 作者: T Thays Grazia 提交者: GitHub

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

* Support new hotreload features on mobile devices.

* Implementing support to add methods in hotreload on mobile devices

* Only invalidate code when we really have some change.

* Remove printf

* add/remove extra lines in eof

* Sharing string between the debugger and the managed get capabilities API
上级 1ef55153
......@@ -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);
}
......
......@@ -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;
}
......
......@@ -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 {
......
......@@ -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,
......@@ -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
......@@ -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 *
......
......@@ -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);
......@@ -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 *
......@@ -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 ();
......@@ -1374,8 +1383,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];
guint32 rows = table_info_get_rows (table_enclog);
......@@ -1432,6 +1442,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 */
......@@ -1441,6 +1452,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 */
......@@ -1457,10 +1469,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 */
......@@ -1476,6 +1490,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;
......@@ -1487,6 +1502,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];
......@@ -1532,6 +1548,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];
......@@ -1557,6 +1574,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);
......@@ -2503,8 +2521,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;
......@@ -2532,7 +2550,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);
}
......@@ -3112,3 +3130,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";
}
......@@ -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
......
......@@ -4985,6 +4985,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);
}
......
......@@ -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);
......
......@@ -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, ())
......
......@@ -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,
......
......@@ -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);
......
......@@ -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)
{
......@@ -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);
}
\ No newline at end of file
......@@ -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__*/
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册