Skip to content

Commit b0a316f

Browse files
lambdageeklewurm
andauthored
[Mono] Initial metadata update support (#45612)
* Initial metadata-update prototype Co-Authored-By: Bernhard Urban-Forster <[email protected]> * Add metadata-update.{c,h} to CMakeLists.txt * Add icall to corelib * Add console and browser metadata update samples Both samples depend on the roslynildiff tool which should be specified with a RoslynILDiffFullPath property in the .csproj files for the projects. * Add README for mbr samples * [build] Add initial runtime support for MonoMetadataUpdate property In the runtime defines cmake ENABLE_METADATA_UPDATE option and sets a preprocessor flag. In System.Private.CoreLib, defines FEATURE_METADATA_UPDATE and uses it to throw a NotSupportedException from LoadMetadataUpdate * [runtime] ifdef out metadata updates if not enabled Also move execution engine initialization into the main update function and use a MonoError to signal failures (such as if interp inlining is not turned off) instead of asserting at startup. * [wasm] set log mask to metadata-update * [mbr] Add InjectUpdate fn to sample * [metadata-update] don't merge heaps * Don't make entrypoint public yet * Add LoadMetadataUpdate to linker descriptor * [wasm] add default Makefile variable value * fix mono/mono CI don't try to run enc tests yet since they depend on roslynildiff * remove mono/mono/tests/enc Will add as runtime tests in a future PR * [metadata-update] Add per-thread exposed generation A thread has to voluntarily roll up to the latest published generation in order to see updates. - Roll up to the latest published generation when attaching a thread - The updater thread sees the allocated unpublished generation * [mbr] Fixup console sample Use a single changing testfile * [metadata-update] delete unused method * [mbr] Use 2 threads in console sample * [metadata-update] Respect exposed generation in MethdDef RVA lookups * [interp] Expose latest metadata update before transforming methods * [mbr] Update samples after rebase Use the WasmApp.targets * [metadata-update] Don't fail after the first unsupported edit Log all the unsupported edits, then cancel the update * [metadata_update] Keep track of logical table sizes for deltas Keep track of inserted/modified rows for each table in each delta. This will help to use a simpler algorithm to locate effective table rows by keeping track of the logical number of rows in the appended tables * [metadata-update] Use a GList for MonoImage:delta_image We're going to need to walk backwards from the latest published delta * [metadata-update] add effective table lookup debug output * Address review feedback * [interp] Save top interp frame at MINT_SAFEPOINT to ThreadContext Give metadata updates a peek at the interp frames since the LMF so that it can copy the InterpMethods that are currently executing This only works with hybrid and full coop suspend. Preemptive suspend will need another mechanism. * [mbr] Extend console sample Add a busy thread to demonstrate that interp frames since the last managed frame are visible to the metadata update mechanism and the active method bodies are copied before being invalidated. * [interp] Check mono_polling_required at safepoint Co-authored-by: Bernhard Urban-Forster <[email protected]>
1 parent 4848f51 commit b0a316f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2334
-26
lines changed

src/mono/cmake/config.h.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,8 +1771,12 @@
17711771
/* Enable runtime checks of mempool references between metadata images (must set env var MONO_CHECK_MODE=metadata) */
17721772
#cmakedefine ENABLE_CHECKED_BUILD_METADATA 1
17731773

1774+
/* Enable runtime support for metadata updates */
1775+
#cmakedefine ENABLE_METADATA_UPDATE 1
1776+
17741777
#if defined(ENABLE_LLVM) && defined(HOST_WIN32) && defined(TARGET_WIN32) && (!defined(TARGET_AMD64) || !defined(_MSC_VER))
17751778
#error LLVM for host=Windows and target=Windows is only supported on x64 MSVC build.
17761779
#endif
17771780

17781781
#endif
1782+

src/mono/cmake/options.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ option (ENABLE_CHECKED_BUILD_PRIVATE_TYPES "Enable compile time checking that ge
6565
option (ENABLE_CHECKED_BUILD_GC "Enable runtime GC Safe / Unsafe mode assertion checks (must set env var MONO_CHECK_MODE=gc)")
6666
option (ENABLE_CHECKED_BUILD_THREAD "Enable runtime history of per-thread coop state transitions (must set env var MONO_CHECK_MODE=thread)")
6767
option (ENABLE_CHECKED_BUILD_METADATA "Enable runtime checks of mempool references between metadata images (must set env var MONO_CHECK_MODE=metadata)")
68+
option (ENABLE_METADATA_UPDATE "Enable runtime support for metadata updates")
6869

6970
set (GC_SUSPEND "default" CACHE STRING "GC suspend method (default, preemptive, coop, hybrid)")
7071
set (CHECKED_BUILD "" CACHE STRING "Set ENABLE_CHECKED_BUILD_ options at once. Comma-separated list of lowercase ENABLE_CHECKED_BUILD_ options ie. 'gc,threads,private_types' etc.")

src/mono/mono.proj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- MonoAOTEnableLLVM - enable LLVM for an AOT-only Mono
99
- MonoAOTLLVMDir - [optional] the directory where LLVM is located, for an AOT-only Mono
1010
- MonoVerboseBuild - enable verbose build
11+
- MonoMetadataUpdate - enable experimental method body replacement code
1112
-->
1213

1314
<PropertyGroup>
@@ -302,6 +303,12 @@
302303
<_MonoCXXFLAGS Include="-Wl,--build-id=sha1" />
303304
</ItemGroup>
304305

306+
<!-- Experimental features -->
307+
<ItemGroup Condition="'$(MonoMetadataUpdate)' == 'true'">
308+
<!-- FIXME: Add sanity check that the interpreter is enabled -->
309+
<_MonoCMakeArgs Include="-DENABLE_METADATA_UPDATE=1" />
310+
</ItemGroup>
311+
305312
<PropertyGroup>
306313
<_MonoCFLAGSOption>-DCMAKE_C_FLAGS="@(_MonoCPPFLAGS, ' ') @(_MonoCFLAGS, ' ')"</_MonoCFLAGSOption>
307314
<_MonoCXXFLAGSOption>-DCMAKE_CXX_FLAGS="@(_MonoCPPFLAGS, ' ') @(_MonoCXXFLAGS, ' ')"</_MonoCXXFLAGSOption>
@@ -403,6 +410,9 @@
403410
<MonoAOTCMakeArgs Condition="'$(MonoAotOffsetsFile)' != ''" Include="-DAOT_OFFSETS_FILE=&quot;$(MonoAotOffsetsFile)&quot;" />
404411
<MonoAOTCMakeArgs Condition="'$(MonoAOTEnableLLVM)' == 'true'" Include="-DLLVM_PREFIX=$(MonoAOTLLVMDir)" />
405412
<MonoAOTCMakeArgs Include="$(_MonoAOTCXXFLAGSOption)" />
413+
<!-- Experimental features -->
414+
<!-- FIXME: Add sanity check that the interpreter is enabled -->
415+
<MonoAOTCMakeArgs Condition="'$(MonoMetadataUpdate)' == 'true'" Include="-DENABLE_METADATA_UPDATE=1" />
406416

407417
<!-- Select generator platform for VS generator -->
408418
<MonoAOTCMakeArgs Condition="'$(OS)' == 'Windows_NT' and '$(_MonoUseNinja)' != 'true' and '$(Platform)' == 'x64'" Include="-A x64" />

src/mono/mono/cil/tables.def

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,16 @@ TABLEDEF(MONO_TABLE_GENERICPARAM, "GenericParam") /* 0x2a */
4444
TABLEDEF(MONO_TABLE_METHODSPEC, "MethodSpec")
4545
TABLEDEF(MONO_TABLE_GENERICPARAMCONSTRAINT, "GenericParamConstraint")
4646

47+
TABLEDEF(MONO_TABLE_UNUSED8, "Unused8")
48+
TABLEDEF(MONO_TABLE_UNUSED9, "Unused9")
49+
TABLEDEF(MONO_TABLE_UNUSED10, "Unused10")
50+
51+
/* Portable PDB tables */
52+
TABLEDEF(MONO_TABLE_DOCUMENT, "Document")
53+
TABLEDEF(MONO_TABLE_METHODBODY, "Methodbody")
54+
TABLEDEF(MONO_TABLE_LOCALSCOPE, "LocalScope")
55+
TABLEDEF(MONO_TABLE_LOCALVARIABLE, "LocalVariable")
56+
TABLEDEF(MONO_TABLE_LOCALCONSTANT, "LocalConstant")
57+
TABLEDEF(MONO_TABLE_IMPORTSCOPE, "ImportScope")
58+
TABLEDEF(MONO_TABLE_STATEMACHINEMETHOD, "StateMachineMethod")
59+
TABLEDEF(MONO_TABLE_CUSTOMDEBUGINFORMATION, "CustomDebugInformation")

src/mono/mono/metadata/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ set(metadata_common_sources
128128
metadata.c
129129
metadata-verify.c
130130
metadata-internals.h
131+
metadata-update.h
132+
metadata-update.c
131133
method-builder.h
132134
method-builder-internals.h
133135
method-builder.c

src/mono/mono/metadata/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,8 @@ common_sources = \
311311
metadata.c \
312312
metadata-verify.c \
313313
metadata-internals.h \
314+
metadata-update.h \
315+
metadata-update.c \
314316
method-builder.h \
315317
method-builder-internals.h \
316318
method-builder.c \

src/mono/mono/metadata/class.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError
197197
break;
198198
}
199199

200-
if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
200+
if (mono_metadata_table_bounds_check (image, MONO_TABLE_ASSEMBLYREF, idx)) {
201201
mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
202202
return NULL;
203203
}

src/mono/mono/metadata/domain.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,12 @@ mono_cleanup (void)
924924
void
925925
mono_close_exe_image (void)
926926
{
927-
if (exe_image)
927+
gboolean do_close = exe_image != NULL;
928+
#ifdef ENABLE_METADATA_UPDATE
929+
/* FIXME: shutdown hack. We mess something up and try to double-close/free it. */
930+
do_close = do_close && !exe_image->delta_image;
931+
#endif
932+
if (do_close)
928933
mono_image_close (exe_image);
929934
}
930935

src/mono/mono/metadata/icall-decl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,4 +308,8 @@ ICALL_EXPORT void ves_icall_System_Threading_LowLevelLifoSemaphore_ReleaseIn
308308
ICALL_EXPORT void ves_icall_System_Runtime_Intrinsics_X86_X86Base___cpuidex (int abcd[4], int function_id, int subfunction_id);
309309
#endif
310310

311+
#if defined(ENABLE_NETCORE) && defined(ENABLE_METADATA_UPDATE)
312+
ICALL_EXPORT void ves_icall_Mono_Runtime_LoadMetadataUpdate (MonoAssembly *assm, gconstpointer dmeta_bytes, int32_t dmeta_len, gconstpointer dil_bytes, int32_t dil_len);
313+
#endif
314+
311315
#endif // __MONO_METADATA_ICALL_DECL_H__

src/mono/mono/metadata/icall-def-netcore.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,11 @@ HANDLES_REUSE_WRAPPER(MPROP_3, "get_metadata_token", ves_icall_reflection_get_to
326326
HANDLES(MPROP_4, "get_property_info", ves_icall_RuntimePropertyInfo_get_property_info, void, 3, (MonoReflectionProperty, MonoPropertyInfo_ref, PInfo))
327327
HANDLES(MPROP_5, "internal_from_handle_type", ves_icall_System_Reflection_RuntimePropertyInfo_internal_from_handle_type, MonoReflectionProperty, 2, (MonoProperty_ptr, MonoType_ptr))
328328

329+
#ifdef ENABLE_METADATA_UPDATE
330+
ICALL_TYPE(RUNF, "System.Runtime.CompilerServices.RuntimeFeature", RUNF_1)
331+
NOHANDLES(ICALL(RUNF_1, "LoadMetadataUpdate_internal", ves_icall_Mono_Runtime_LoadMetadataUpdate))
332+
#endif
333+
329334
ICALL_TYPE(RUNH, "System.Runtime.CompilerServices.RuntimeHelpers", RUNH_1)
330335
HANDLES(RUNH_1, "GetObjectValue", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue, MonoObject, 1, (MonoObject))
331336
HANDLES(RUNH_2, "GetUninitializedObjectInternal", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetUninitializedObjectInternal, MonoObject, 1, (MonoType_ptr))

0 commit comments

Comments
 (0)