2 #include "mono/utils/mono-compiler.h"
4 #ifdef ENABLE_NETCORE // MonoAssemblyLoadContext support only in netcore Mono
6 #include "mono/metadata/assembly.h"
7 #include "mono/metadata/domain-internals.h"
8 #include "mono/metadata/exception-internals.h"
9 #include "mono/metadata/icall-decl.h"
10 #include "mono/metadata/loader-internals.h"
11 #include "mono/metadata/loaded-images-internals.h"
12 #include "mono/utils/mono-error-internals.h"
13 #include "mono/utils/mono-logger-internals.h"
15 GENERATE_GET_CLASS_WITH_CACHE (assembly_load_context
, "System.Runtime.Loader", "AssemblyLoadContext");
18 mono_alc_init (MonoAssemblyLoadContext
*alc
, MonoDomain
*domain
)
20 MonoLoadedImages
*li
= g_new0 (MonoLoadedImages
, 1);
21 mono_loaded_images_init (li
, alc
);
23 alc
->loaded_images
= li
;
24 alc
->loaded_assemblies
= NULL
;
25 mono_coop_mutex_init (&alc
->assemblies_lock
);
29 mono_alc_cleanup (MonoAssemblyLoadContext
*alc
)
32 * As it stands, ALC and domain cleanup is probably broken on netcore. Without ALC collectability, this should not
33 * be hit. I've documented roughly the things that still need to be accomplish, but the implementation is TODO and
34 * the ideal order and locking unclear.
36 * For now, this makes two important assumptions:
37 * 1. The minimum refcount on assemblies is 2: one for the domain and one for the ALC. The domain refcount might
38 * be less than optimal on netcore, but its removal is too likely to cause issues for now.
39 * 2. An ALC will have been removed from the domain before cleanup.
42 //MonoDomain *domain = alc->domain;
47 * + Release GC roots for all assemblies in the ALC
48 * + Iterate over the domain_assemblies and remove ones that belong to the ALC, which will probably require
49 * converting domain_assemblies to a doubly-linked list, ideally GQueue
50 * + Close dynamic and then remaining assemblies, potentially nulling the data field depending on refcount
51 * + Second pass to call mono_assembly_close_finish on remaining assemblies
52 * + Free the loaded_assemblies list itself
55 alc
->loaded_assemblies
= NULL
;
56 mono_coop_mutex_destroy (&alc
->assemblies_lock
);
58 mono_loaded_images_free (alc
->loaded_images
);
60 g_assert_not_reached ();
64 mono_alc_assemblies_lock (MonoAssemblyLoadContext
*alc
)
66 mono_coop_mutex_lock (&alc
->assemblies_lock
);
70 mono_alc_assemblies_unlock (MonoAssemblyLoadContext
*alc
)
72 mono_coop_mutex_unlock (&alc
->assemblies_lock
);
76 ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalInitializeNativeALC (gpointer this_gchandle_ptr
, MonoBoolean is_default_alc
, MonoBoolean collectible
, MonoError
*error
)
78 /* If the ALC is collectible, this_gchandle is weak, otherwise it's strong. */
79 uint32_t this_gchandle
= (uint32_t)GPOINTER_TO_UINT (this_gchandle_ptr
);
81 mono_error_set_execution_engine (error
, "Collectible AssemblyLoadContexts are not yet supported by MonoVM");
85 MonoDomain
*domain
= mono_domain_get ();
86 MonoAssemblyLoadContext
*alc
= NULL
;
89 alc
= mono_domain_default_alc (domain
);
92 alc
->gchandle
= this_gchandle
;
95 alc
= mono_domain_create_individual_alc (domain
, this_gchandle
, collectible
, error
);
101 ves_icall_System_Runtime_Loader_AssemblyLoadContext_GetLoadContextForAssembly (MonoReflectionAssemblyHandle assm_obj
, MonoError
*error
)
103 MonoAssembly
*assm
= MONO_HANDLE_GETVAL (assm_obj
, assembly
);
104 MonoAssemblyLoadContext
*alc
= mono_assembly_get_alc (assm
);
106 return GUINT_TO_POINTER (alc
->gchandle
);
110 mono_alc_is_default (MonoAssemblyLoadContext
*alc
)
112 return alc
== mono_alc_domain (alc
)->default_alc
;
116 invoke_resolve_method (MonoMethod
*resolve_method
, MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, MonoError
*error
)
118 MonoAssembly
*result
= NULL
;
119 char* aname_str
= NULL
;
121 if (mono_runtime_get_no_exec ())
124 HANDLE_FUNCTION_ENTER ();
126 aname_str
= mono_stringify_assembly_name (aname
);
128 MonoStringHandle aname_obj
= mono_string_new_handle (mono_alc_domain (alc
), aname_str
, error
);
129 goto_if_nok (error
, leave
);
131 MonoReflectionAssemblyHandle assm
;
133 gchandle
= GUINT_TO_POINTER (alc
->gchandle
);
135 args
[0] = &gchandle
;
136 args
[1] = MONO_HANDLE_RAW (aname_obj
);
137 assm
= MONO_HANDLE_CAST (MonoReflectionAssembly
, mono_runtime_try_invoke_handle (resolve_method
, NULL_HANDLE
, args
, error
));
138 goto_if_nok (error
, leave
);
140 if (MONO_HANDLE_BOOL (assm
))
141 result
= MONO_HANDLE_GETVAL (assm
, assembly
);
145 HANDLE_FUNCTION_RETURN_VAL (result
);
149 mono_alc_invoke_resolve_using_load (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, MonoError
*error
)
151 static MonoMethod
*resolve
;
154 ERROR_DECL (local_error
);
155 MonoClass
*alc_class
= mono_class_get_assembly_load_context_class ();
156 g_assert (alc_class
);
157 MonoMethod
*m
= mono_class_get_method_from_name_checked (alc_class
, "MonoResolveUsingLoad", -1, 0, local_error
);
158 mono_error_assert_ok (local_error
);
163 return invoke_resolve_method (resolve
, alc
, aname
, error
);
167 mono_alc_invoke_resolve_using_load_nofail (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
)
169 MonoAssembly
*result
= NULL
;
172 result
= mono_alc_invoke_resolve_using_load (alc
, aname
, error
);
174 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Error while invoking ALC Load(\"%s\") method: '%s'", aname
->name
, mono_error_get_message (error
));
176 mono_error_cleanup (error
);
182 mono_alc_invoke_resolve_using_resolving_event (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, MonoError
*error
)
184 static MonoMethod
*resolve
;
187 ERROR_DECL (local_error
);
188 MonoClass
*alc_class
= mono_class_get_assembly_load_context_class ();
189 g_assert (alc_class
);
190 MonoMethod
*m
= mono_class_get_method_from_name_checked (alc_class
, "MonoResolveUsingResolvingEvent", -1, 0, local_error
);
191 mono_error_assert_ok (local_error
);
196 return invoke_resolve_method (resolve
, alc
, aname
, error
);
200 mono_alc_invoke_resolve_using_resolving_event_nofail (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
)
202 MonoAssembly
*result
= NULL
;
205 result
= mono_alc_invoke_resolve_using_resolving_event (alc
, aname
, error
);
207 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Error while invoking ALC Resolving(\"%s\") event: '%s'", aname
->name
, mono_error_get_message (error
));
209 mono_error_cleanup (error
);
215 mono_alc_invoke_resolve_using_resolve_satellite (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, MonoError
*error
)
217 static MonoMethod
*resolve
;
220 ERROR_DECL (local_error
);
221 MonoClass
*alc_class
= mono_class_get_assembly_load_context_class ();
222 g_assert (alc_class
);
223 MonoMethod
*m
= mono_class_get_method_from_name_checked (alc_class
, "MonoResolveUsingResolveSatelliteAssembly", -1, 0, local_error
);
224 mono_error_assert_ok (local_error
);
229 return invoke_resolve_method (resolve
, alc
, aname
, error
);
233 mono_alc_invoke_resolve_using_resolve_satellite_nofail (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
)
235 MonoAssembly
*result
= NULL
;
238 result
= mono_alc_invoke_resolve_using_resolve_satellite (alc
, aname
, error
);
240 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Error while invoking ALC ResolveSatelliteAssembly(\"%s\") method: '%s'", aname
->name
, mono_error_get_message (error
));
242 mono_error_cleanup (error
);
247 #endif /* ENABLE_NETCORE */
249 MONO_EMPTY_SOURCE_FILE (assembly_load_context
)