2 #include "mono/metadata/assembly.h"
3 #include "mono/metadata/domain-internals.h"
4 #include "mono/metadata/icall-decl.h"
5 #include "mono/metadata/loader-internals.h"
6 #include "mono/metadata/loaded-images-internals.h"
7 #include "mono/utils/mono-error-internals.h"
8 #include "mono/utils/mono-logger-internals.h"
11 /* MonoAssemblyLoadContext support only in netcore Mono */
14 GENERATE_GET_CLASS_WITH_CACHE_DECL (assembly_load_context
);
16 GENERATE_GET_CLASS_WITH_CACHE (assembly_load_context
, "System.Runtime.Loader", "AssemblyLoadContext");
19 mono_alc_init (MonoAssemblyLoadContext
*alc
, MonoDomain
*domain
)
21 MonoLoadedImages
*li
= g_new0 (MonoLoadedImages
, 1);
22 mono_loaded_images_init (li
, alc
);
24 alc
->loaded_images
= li
;
25 alc
->loaded_assemblies
= NULL
;
26 mono_coop_mutex_init (&alc
->assemblies_lock
);
30 mono_alc_cleanup (MonoAssemblyLoadContext
*alc
)
33 * As it stands, ALC and domain cleanup is probably broken on netcore. Without ALC collectability, this should not
34 * be hit. I've documented roughly the things that still need to be accomplish, but the implementation is TODO and
35 * the ideal order and locking unclear.
37 * For now, this makes two important assumptions:
38 * 1. The minimum refcount on assemblies is 2: one for the domain and one for the ALC. The domain refcount might
39 * be less than optimal on netcore, but its removal is too likely to cause issues for now.
40 * 2. An ALC will have been removed from the domain before cleanup.
43 MonoDomain
*domain
= alc
->domain
;
48 * + Release GC roots for all assemblies in the ALC
49 * + Iterate over the domain_assemblies and remove ones that belong to the ALC, which will probably require
50 * converting domain_assemblies to a doubly-linked list, ideally GQueue
51 * + Close dynamic and then remaining assemblies, potentially nulling the data field depending on refcount
52 * + Second pass to call mono_assembly_close_finish on remaining assemblies
53 * + Free the loaded_assemblies list itself
56 alc
->loaded_assemblies
= NULL
;
57 mono_coop_mutex_destroy (&alc
->assemblies_lock
);
59 mono_loaded_images_free (alc
->loaded_images
);
61 g_assert_not_reached ();
65 mono_alc_assemblies_lock (MonoAssemblyLoadContext
*alc
)
67 mono_coop_mutex_lock (&alc
->assemblies_lock
);
71 mono_alc_assemblies_unlock (MonoAssemblyLoadContext
*alc
)
73 mono_coop_mutex_unlock (&alc
->assemblies_lock
);
77 ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalInitializeNativeALC (gpointer this_gchandle_ptr
, MonoBoolean is_default_alc
, MonoBoolean collectible
, MonoError
*error
)
79 /* If the ALC is collectible, this_gchandle is weak, otherwise it's strong. */
80 uint32_t this_gchandle
= (uint32_t)GPOINTER_TO_UINT (this_gchandle_ptr
);
82 mono_error_set_execution_engine (error
, "Collectible AssemblyLoadContexts are not yet supported by MonoVM");
86 MonoDomain
*domain
= mono_domain_get ();
87 MonoAssemblyLoadContext
*alc
= NULL
;
90 alc
= mono_domain_default_alc (domain
);
93 alc
->gchandle
= this_gchandle
;
96 alc
= mono_domain_create_individual_alc (domain
, this_gchandle
, collectible
, error
);
102 ves_icall_System_Runtime_Loader_AssemblyLoadContext_GetLoadContextForAssembly (MonoReflectionAssemblyHandle assm_obj
, MonoError
*error
)
104 MonoAssembly
*assm
= MONO_HANDLE_GETVAL (assm_obj
, assembly
);
105 MonoAssemblyLoadContext
*alc
= mono_assembly_get_alc (assm
);
107 return GUINT_TO_POINTER (alc
->gchandle
);
111 mono_alc_is_default (MonoAssemblyLoadContext
*alc
)
113 return alc
== mono_alc_domain (alc
)->default_alc
;
117 invoke_resolve_method (MonoMethod
*resolve_method
, MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, MonoError
*error
)
119 MonoAssembly
*result
= NULL
;
120 char* aname_str
= NULL
;
121 HANDLE_FUNCTION_ENTER ();
123 aname_str
= mono_stringify_assembly_name (aname
);
125 MonoStringHandle aname_obj
= mono_string_new_handle (mono_domain_get (), aname_str
, error
);
126 goto_if_nok (error
, leave
);
128 MonoReflectionAssemblyHandle assm
;
130 args
[0] = GUINT_TO_POINTER (alc
->gchandle
);
131 args
[1] = MONO_HANDLE_RAW (aname_obj
);
132 assm
= MONO_HANDLE_CAST (MonoReflectionAssembly
, mono_runtime_try_invoke_handle (resolve_method
, NULL_HANDLE
, args
, error
));
133 goto_if_nok (error
, leave
);
135 if (MONO_HANDLE_BOOL (assm
))
136 result
= MONO_HANDLE_GETVAL (assm
, assembly
);
140 HANDLE_FUNCTION_RETURN_VAL (result
);
144 mono_alc_invoke_resolve_using_load (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, MonoError
*error
)
146 static MonoMethod
*resolve
;
149 ERROR_DECL (local_error
);
150 MonoClass
*alc_class
= mono_class_get_assembly_load_context_class ();
151 g_assert (alc_class
);
152 MonoMethod
*m
= mono_class_get_method_from_name_checked (alc_class
, "MonoResolveUsingLoad", -1, 0, local_error
);
153 mono_error_assert_ok (local_error
);
158 return invoke_resolve_method (resolve
, alc
, aname
, error
);
162 mono_alc_invoke_resolve_using_load_nofail (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
)
164 MonoAssembly
*result
= NULL
;
167 result
= mono_alc_invoke_resolve_using_load (alc
, aname
, error
);
169 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Error while invoking ALC Load(\"%s\") method: '%s'", aname
->name
, mono_error_get_message (error
));
171 mono_error_cleanup (error
);
177 mono_alc_invoke_resolve_using_resolving_event (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, MonoError
*error
)
179 static MonoMethod
*resolve
;
182 ERROR_DECL (local_error
);
183 MonoClass
*alc_class
= mono_class_get_assembly_load_context_class ();
184 g_assert (alc_class
);
185 MonoMethod
*m
= mono_class_get_method_from_name_checked (alc_class
, "MonoResolveUsingResolvingEvent", -1, 0, local_error
);
186 mono_error_assert_ok (local_error
);
191 return invoke_resolve_method (resolve
, alc
, aname
, error
);
195 mono_alc_invoke_resolve_using_resolving_event_nofail (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
)
197 MonoAssembly
*result
= NULL
;
200 result
= mono_alc_invoke_resolve_using_resolving_event (alc
, aname
, error
);
202 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Error while invoking ALC Resolving(\"%s\") event: '%s'", aname
->name
, mono_error_get_message (error
));
204 mono_error_cleanup (error
);
210 mono_alc_invoke_resolve_using_resolve_satellite (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, MonoError
*error
)
212 static MonoMethod
*resolve
;
215 ERROR_DECL (local_error
);
216 MonoClass
*alc_class
= mono_class_get_assembly_load_context_class ();
217 g_assert (alc_class
);
218 MonoMethod
*m
= mono_class_get_method_from_name_checked (alc_class
, "MonoResolveUsingResolveSatelliteAssembly", -1, 0, local_error
);
219 mono_error_assert_ok (local_error
);
224 return invoke_resolve_method (resolve
, alc
, aname
, error
);
228 mono_alc_invoke_resolve_using_resolve_satellite_nofail (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
)
230 MonoAssembly
*result
= NULL
;
233 result
= mono_alc_invoke_resolve_using_resolve_satellite (alc
, aname
, error
);
235 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Error while invoking ALC ResolveSatelliteAssembly(\"%s\") method: '%s'", aname
->name
, mono_error_get_message (error
));
237 mono_error_cleanup (error
);
244 #endif /* ENABLE_NETCORE */