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 alc
->pinvoke_scopes
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
26 mono_coop_mutex_init (&alc
->assemblies_lock
);
27 mono_coop_mutex_init (&alc
->pinvoke_lock
);
31 mono_alc_cleanup (MonoAssemblyLoadContext
*alc
)
34 * As it stands, ALC and domain cleanup is probably broken on netcore. Without ALC collectability, this should not
35 * be hit. I've documented roughly the things that still need to be accomplish, but the implementation is TODO and
36 * the ideal order and locking unclear.
38 * For now, this makes two important assumptions:
39 * 1. The minimum refcount on assemblies is 2: one for the domain and one for the ALC. The domain refcount might
40 * be less than optimal on netcore, but its removal is too likely to cause issues for now.
41 * 2. An ALC will have been removed from the domain before cleanup.
44 //MonoDomain *domain = alc->domain;
49 * + Release GC roots for all assemblies in the ALC
50 * + Iterate over the domain_assemblies and remove ones that belong to the ALC, which will probably require
51 * converting domain_assemblies to a doubly-linked list, ideally GQueue
52 * + Close dynamic and then remaining assemblies, potentially nulling the data field depending on refcount
53 * + Second pass to call mono_assembly_close_finish on remaining assemblies
54 * + Free the loaded_assemblies list itself
57 alc
->loaded_assemblies
= NULL
;
58 g_hash_table_destroy (alc
->pinvoke_scopes
);
59 mono_coop_mutex_destroy (&alc
->assemblies_lock
);
60 mono_coop_mutex_destroy (&alc
->pinvoke_lock
);
62 mono_loaded_images_free (alc
->loaded_images
);
64 g_assert_not_reached ();
68 mono_alc_assemblies_lock (MonoAssemblyLoadContext
*alc
)
70 mono_coop_mutex_lock (&alc
->assemblies_lock
);
74 mono_alc_assemblies_unlock (MonoAssemblyLoadContext
*alc
)
76 mono_coop_mutex_unlock (&alc
->assemblies_lock
);
80 ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalInitializeNativeALC (gpointer this_gchandle_ptr
, MonoBoolean is_default_alc
, MonoBoolean collectible
, MonoError
*error
)
82 /* If the ALC is collectible, this_gchandle is weak, otherwise it's strong. */
83 uint32_t this_gchandle
= (uint32_t)GPOINTER_TO_UINT (this_gchandle_ptr
);
85 mono_error_set_execution_engine (error
, "Collectible AssemblyLoadContexts are not yet supported by MonoVM");
89 MonoDomain
*domain
= mono_domain_get ();
90 MonoAssemblyLoadContext
*alc
= NULL
;
93 alc
= mono_domain_default_alc (domain
);
96 alc
->gchandle
= this_gchandle
;
99 alc
= mono_domain_create_individual_alc (domain
, this_gchandle
, collectible
, error
);
105 ves_icall_System_Runtime_Loader_AssemblyLoadContext_GetLoadContextForAssembly (MonoReflectionAssemblyHandle assm_obj
, MonoError
*error
)
107 MonoAssembly
*assm
= MONO_HANDLE_GETVAL (assm_obj
, assembly
);
108 MonoAssemblyLoadContext
*alc
= mono_assembly_get_alc (assm
);
110 return GUINT_TO_POINTER (alc
->gchandle
);
114 mono_alc_is_default (MonoAssemblyLoadContext
*alc
)
116 return alc
== mono_alc_domain (alc
)->default_alc
;
120 invoke_resolve_method (MonoMethod
*resolve_method
, MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, MonoError
*error
)
122 MonoAssembly
*result
= NULL
;
123 char* aname_str
= NULL
;
125 if (mono_runtime_get_no_exec ())
128 HANDLE_FUNCTION_ENTER ();
130 aname_str
= mono_stringify_assembly_name (aname
);
132 MonoStringHandle aname_obj
= mono_string_new_handle (mono_alc_domain (alc
), aname_str
, error
);
133 goto_if_nok (error
, leave
);
135 MonoReflectionAssemblyHandle assm
;
137 gchandle
= GUINT_TO_POINTER (alc
->gchandle
);
139 args
[0] = &gchandle
;
140 args
[1] = MONO_HANDLE_RAW (aname_obj
);
141 assm
= MONO_HANDLE_CAST (MonoReflectionAssembly
, mono_runtime_try_invoke_handle (resolve_method
, NULL_HANDLE
, args
, error
));
142 goto_if_nok (error
, leave
);
144 if (MONO_HANDLE_BOOL (assm
))
145 result
= MONO_HANDLE_GETVAL (assm
, assembly
);
149 HANDLE_FUNCTION_RETURN_VAL (result
);
153 mono_alc_invoke_resolve_using_load (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, MonoError
*error
)
155 MONO_STATIC_POINTER_INIT (MonoMethod
, resolve
)
157 ERROR_DECL (local_error
);
158 MonoClass
*alc_class
= mono_class_get_assembly_load_context_class ();
159 g_assert (alc_class
);
160 resolve
= mono_class_get_method_from_name_checked (alc_class
, "MonoResolveUsingLoad", -1, 0, local_error
);
161 mono_error_assert_ok (local_error
);
163 MONO_STATIC_POINTER_INIT_END (MonoMethod
, resolve
)
167 return invoke_resolve_method (resolve
, alc
, aname
, error
);
171 mono_alc_invoke_resolve_using_load_nofail (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
)
173 MonoAssembly
*result
= NULL
;
176 result
= mono_alc_invoke_resolve_using_load (alc
, aname
, error
);
178 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "Error while invoking ALC Load(\"%s\") method: '%s'", aname
->name
, mono_error_get_message (error
));
180 mono_error_cleanup (error
);
186 mono_alc_invoke_resolve_using_resolving_event (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, MonoError
*error
)
188 MONO_STATIC_POINTER_INIT (MonoMethod
, resolve
)
190 ERROR_DECL (local_error
);
191 MonoClass
*alc_class
= mono_class_get_assembly_load_context_class ();
192 g_assert (alc_class
);
193 resolve
= mono_class_get_method_from_name_checked (alc_class
, "MonoResolveUsingResolvingEvent", -1, 0, local_error
);
194 mono_error_assert_ok (local_error
);
196 MONO_STATIC_POINTER_INIT_END (MonoMethod
, resolve
)
200 return invoke_resolve_method (resolve
, alc
, aname
, error
);
204 mono_alc_invoke_resolve_using_resolving_event_nofail (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
)
206 MonoAssembly
*result
= NULL
;
209 result
= mono_alc_invoke_resolve_using_resolving_event (alc
, aname
, error
);
211 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "Error while invoking ALC Resolving(\"%s\") event: '%s'", aname
->name
, mono_error_get_message (error
));
213 mono_error_cleanup (error
);
219 mono_alc_invoke_resolve_using_resolve_satellite (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, MonoError
*error
)
221 MONO_STATIC_POINTER_INIT (MonoMethod
, resolve
)
223 ERROR_DECL (local_error
);
224 MonoClass
*alc_class
= mono_class_get_assembly_load_context_class ();
225 g_assert (alc_class
);
226 resolve
= mono_class_get_method_from_name_checked (alc_class
, "MonoResolveUsingResolveSatelliteAssembly", -1, 0, local_error
);
227 mono_error_assert_ok (local_error
);
229 MONO_STATIC_POINTER_INIT_END (MonoMethod
, resolve
)
233 return invoke_resolve_method (resolve
, alc
, aname
, error
);
237 mono_alc_invoke_resolve_using_resolve_satellite_nofail (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
)
239 MonoAssembly
*result
= NULL
;
242 result
= mono_alc_invoke_resolve_using_resolve_satellite (alc
, aname
, error
);
244 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "Error while invoking ALC ResolveSatelliteAssembly(\"%s\") method: '%s'", aname
->name
, mono_error_get_message (error
));
246 mono_error_cleanup (error
);
251 #endif /* ENABLE_NETCORE */
253 MONO_EMPTY_SOURCE_FILE (assembly_load_context
)