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][mbr] Implement DOTNET_MODIFIABLE_ASSEMBLIES support #49507

Merged
merged 6 commits into from
Mar 13, 2021
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
71 changes: 71 additions & 0 deletions src/mono/mono/metadata/metadata-update.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifdef ENABLE_METADATA_UPDATE

#include <glib.h>
#include "mono/metadata/assembly-internals.h"
#include "mono/metadata/metadata-internals.h"
#include "mono/metadata/metadata-update.h"
#include "mono/metadata/object-internals.h"
Expand Down Expand Up @@ -62,6 +63,71 @@ typedef struct _DeltaInfo {
} DeltaInfo;


#define DOTNET_MODIFIABLE_ASSEMBLIES "DOTNET_MODIFIABLE_ASSEMBLIES"

/**
* mono_metadata_update_enable:
* \param modifiable_assemblies_out: set to MonoModifiableAssemblies value
*
* Returns \c TRUE if metadata updates are enabled at runtime. False otherwise.
*
* If \p modifiable_assemblies_out is not \c NULL, it's set on return.
*
* The result depends on the value of the DOTNET_MODIFIABLE_ASSEMBLIES
* environment variable. "debug" means debuggable assemblies are modifiable,
* all other values are ignored and metadata updates are disabled.
*/
gboolean
mono_metadata_update_enabled (int *modifiable_assemblies_out)
{
static gboolean inited = FALSE;
static int modifiable = MONO_MODIFIABLE_ASSM_NONE;

if (!inited) {
char *val = g_getenv (DOTNET_MODIFIABLE_ASSEMBLIES);
if (!g_strcasecmp (val, "debug"))
modifiable = MONO_MODIFIABLE_ASSM_DEBUG;
g_free (val);
inited = TRUE;
}
if (modifiable_assemblies_out)
*modifiable_assemblies_out = modifiable;
return modifiable != MONO_MODIFIABLE_ASSM_NONE;
}

static gboolean
assembly_update_supported (MonoAssembly *assm)
{
int modifiable = 0;
if (!mono_metadata_update_enabled (&modifiable))
return FALSE;
if (modifiable == MONO_MODIFIABLE_ASSM_DEBUG &&
mono_assembly_is_jit_optimizer_disabled (assm))
return TRUE;
return FALSE;
}

/**
* mono_metadata_update_no_inline:
* \param caller: the calling method
* \param callee: the method being called
*
* Returns \c TRUE if \p callee should not be inlined into \p caller.
*
* If metadata updates are enabled either for the caller or callee's module,
* the callee should not be inlined.
*
*/
gboolean
mono_metadata_update_no_inline (MonoMethod *caller, MonoMethod *callee)
{
if (!mono_metadata_update_enabled (NULL))
return FALSE;
MonoAssembly *caller_assm = m_class_get_image(caller->klass)->assembly;
MonoAssembly *callee_assm = m_class_get_image(callee->klass)->assembly;
return mono_assembly_is_jit_optimizer_disabled (caller_assm) || mono_assembly_is_jit_optimizer_disabled (callee_assm);
}

static void
mono_metadata_update_ee_init (MonoError *error);

Expand Down Expand Up @@ -881,6 +947,11 @@ mono_image_load_enc_delta (MonoImage *image_base, gconstpointer dmeta_bytes, uin
if (!is_ok (error))
return;

if (!assembly_update_supported (image_base->assembly)) {
mono_error_set_invalid_operation (error, "The assembly can not be edited or changed.");
return;
}

const char *basename = image_base->filename;
/* FIXME:
* (1) do we need to memcpy dmeta_bytes ? (maybe)
Expand Down
28 changes: 28 additions & 0 deletions src/mono/mono/metadata/metadata-update.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@

#ifdef ENABLE_METADATA_UPDATE

enum MonoModifiableAssemblies {
/* modifiable assemblies are disabled */
MONO_MODIFIABLE_ASSM_NONE = 0,
/* assemblies with the Debug flag are modifiable */
MONO_MODIFIABLE_ASSM_DEBUG = 1,
};

gboolean
mono_metadata_update_enabled (int *modifiable_assemblies_out);

gboolean
mono_metadata_update_no_inline (MonoMethod *caller, MonoMethod *callee);

void
mono_metadata_update_init (void);

Expand Down Expand Up @@ -44,6 +57,21 @@ mono_metadata_update_cleanup_on_close (MonoImage *base_image);
MonoImage *
mono_table_info_get_base_image (const MonoTableInfo *t);

#else /* ENABLE_METADATA_UPDATE */

static inline gboolean
mono_metadata_update_enabled (int *modifiable_assemblies_out)
{
if (modifiable_assemblies_out)
*modifiable_assemblies_out = 0;
return FALSE;
}

static inline gboolean
mono_metadata_update_no_inline (MonoMethod *caller, MonoMethod *callee)
{
return FALSE;
}

#endif /* ENABLE_METADATA_UPDATE */

Expand Down
2 changes: 0 additions & 2 deletions src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -7230,8 +7230,6 @@ copy_imethod_for_frame (InterpFrame *frame)
static void
interp_metadata_update_init (MonoError *error)
{
if ((mono_interp_opt & INTERP_OPT_INLINE) != 0)
mono_error_set_execution_engine (error, "Interpreter inlining must be turned off for metadata updates");
}

#ifdef ENABLE_METADATA_UPDATE
Expand Down
13 changes: 13 additions & 0 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -2632,6 +2632,16 @@ interp_icall_op_for_sig (MonoMethodSignature *sig)
#define INLINE_LENGTH_LIMIT 20
#define INLINE_DEPTH_LIMIT 10

static gboolean
is_metadata_update_disabled (void)
{
static gboolean disabled = FALSE;
if (disabled)
return disabled;
disabled = !mono_metadata_update_enabled (NULL);
return disabled;
}

static gboolean
interp_method_check_inlining (TransformData *td, MonoMethod *method, MonoMethodSignature *csignature)
{
Expand Down Expand Up @@ -2686,6 +2696,9 @@ interp_method_check_inlining (TransformData *td, MonoMethod *method, MonoMethodS
if (td->prof_coverage)
return FALSE;

if (!is_metadata_update_disabled () && mono_metadata_update_no_inline (td->method, method))
return FALSE;

if (g_list_find (td->dont_inline, method))
return FALSE;

Expand Down
1 change: 1 addition & 0 deletions src/mono/sample/mbr/DeltaHelper.targets
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
What other properties do I need to pass? Maybe hotreload-delta-gen should just expose an MSBuild task so we can pass everything -->
<HotreloadDeltaGenArgs Condition="'$(Configuration)' != ''">$(HotreloadDeltaGenArgs) -p:Configuration=$(Configuration)</HotreloadDeltaGenArgs>
<HotreloadDeltaGenArgs Condition="'$(RuntimeIdentifier)' != ''">$(HotreloadDeltaGenArgs) -p:RuntimeIdentifier=$(RuntimeIdentifier)</HotreloadDeltaGenArgs>
<HotreloadDeltaGenArgs Condition="'$(BuiltRuntimeConfiguration)' != ''">$(HotreloadDeltaGenArgs) -p:BuiltRuntimeConfiguration=$(BuiltRuntimeConfiguration)</HotreloadDeltaGenArgs>
<HotreloadDeltaGenArgs>$(HotreloadDeltaGenArgs) -script:$(DeltaScript)</HotreloadDeltaGenArgs>
</PropertyGroup>
<Exec Command="$(HotreloadDeltaGenFullPath) $(HotreloadDeltaGenArgs)"/>
Expand Down
2 changes: 1 addition & 1 deletion src/mono/sample/mbr/browser/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ var Module = {
App.init ();
};
config.environment_variables = {
"MONO_METADATA_UPDATE": "1"
"DOTNET_MODIFIABLE_ASSEMBLIES": "debug"
};
config.fetch_file_cb = function (asset) {
return fetch (asset, { credentials: 'same-origin' });
Expand Down
2 changes: 1 addition & 1 deletion src/mono/sample/mbr/console/ConsoleDelta.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<Target Name="TrickRuntimePackLocation" AfterTargets="ProcessFrameworkReferences">
<ItemGroup>
<RuntimePack>
<PackageDirectory>$(ArtifactsBinDir)microsoft.netcore.app.runtime.$(RuntimeIdentifier)\$(Configuration)</PackageDirectory>
<PackageDirectory>$(ArtifactsBinDir)microsoft.netcore.app.runtime.$(RuntimeIdentifier)\$(BuiltRuntimeConfiguration)</PackageDirectory>
</RuntimePack>
</ItemGroup>
<Message Text="Packaged ID: %(RuntimePack.PackageDirectory)" Importance="high" />
Expand Down
10 changes: 7 additions & 3 deletions src/mono/sample/mbr/console/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ TOP=../../../../../
DOTNET:=$(TOP)./dotnet.sh
DOTNET_Q_ARGS=--nologo -v:q -consoleloggerparameters:NoSummary

CONFIG ?=Release
# How to build the project. For hot reload this must be Debug
CONFIG ?=Debug
# How was dotnet/runtime built? should be the same as build.sh -c option
BUILT_RUNTIME_CONFIG ?= Release
MONO_ARCH=x64

OS := $(shell uname -s)
Expand All @@ -12,14 +15,15 @@ else
TARGET_OS=linux
endif

MONO_ENV_OPTIONS ?=--interp=-inline
MONO_ENV_OPTIONS = --interp

publish:
$(DOTNET) publish -c $(CONFIG) -r $(TARGET_OS)-$(MONO_ARCH)
$(DOTNET) publish -c $(CONFIG) -r $(TARGET_OS)-$(MONO_ARCH) -p:BuiltRuntimeConfiguration=$(BUILT_RUNTIME_CONFIG)

run: publish
COMPlus_DebugWriteToStdErr=1 \
MONO_ENV_OPTIONS="$(MONO_ENV_OPTIONS)" \
DOTNET_MODIFIABLE_ASSEMBLIES=debug \
$(TOP)artifacts/bin/ConsoleDelta/$(MONO_ARCH)/$(CONFIG)/$(TARGET_OS)-$(MONO_ARCH)/publish/ConsoleDelta

clean:
Expand Down
6 changes: 0 additions & 6 deletions src/mono/wasm/runtime/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -514,12 +514,6 @@ mono_wasm_load_runtime (const char *unused, int debug_level)
#else
mono_jit_set_aot_mode (MONO_AOT_MODE_INTERP_ONLY);

#ifdef ENABLE_METADATA_UPDATE
if (monoeg_g_hasenv ("MONO_METADATA_UPDATE")) {
interp_opts = "-inline";
}
#endif

/*
* debug_level > 0 enables debugging and sets the debug log level to debug_level
* debug_level == 0 disables debugging and enables interpreter optimizations
Expand Down