#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-counters.h>
#include <mono/utils/mono-digest.h>
+#include <mono/utils/mono-threads-coop.h>
#include "mini.h"
#include "seq-points.h"
}
break;
}
- case MONO_WRAPPER_LDFLD_REMOTE:
- ref->method = mono_marshal_get_ldfld_remote_wrapper (NULL);
- break;
- case MONO_WRAPPER_STFLD_REMOTE:
- ref->method = mono_marshal_get_stfld_remote_wrapper (NULL);
- break;
#endif
case MONO_WRAPPER_ALLOC: {
int atype = decode_value (p, &p);
+ ManagedAllocatorVariant variant =
+ mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS ?
+ MANAGED_ALLOCATOR_SLOW_PATH : MANAGED_ALLOCATOR_REGULAR;
- ref->method = mono_gc_get_managed_allocator_by_type (atype, !!(mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS));
+ ref->method = mono_gc_get_managed_allocator_by_type (atype, variant);
if (!ref->method) {
mono_error_set_bad_image_name (error, module->aot_name, "Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n");
return FALSE;
msg = g_strdup_printf ("not compiled with --aot=llvmonly");
usable = FALSE;
}
-#ifdef TARGET_ARM
- /* mono_arch_find_imt_method () requires this */
- if ((info->flags & MONO_AOT_FILE_FLAG_WITH_LLVM) && !mono_use_llvm) {
- msg = g_strdup_printf ("compiled against LLVM");
- usable = FALSE;
- }
- if (!(info->flags & MONO_AOT_FILE_FLAG_WITH_LLVM) && mono_use_llvm) {
- msg = g_strdup_printf ("not compiled against LLVM");
- usable = FALSE;
- }
-#endif
if (mini_get_debug_options ()->mdb_optimizations && !(info->flags & MONO_AOT_FILE_FLAG_DEBUG) && !full_aot) {
msg = g_strdup_printf ("not compiled for debugging");
usable = FALSE;
find_symbol (sofile, globals, "mono_aot_file_info", (gpointer*)&info);
}
+ // Copy aotid to MonoImage
+ memcpy(&assembly->image->aotid, info->aotid, 16);
+
if (version_symbol) {
/* Old file format */
version = atoi (version_symbol);
}
gpointer
-mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot)
+mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot, MonoError *error)
{
- MonoError error;
int i;
MonoClass *klass = vtable->klass;
MonoAotModule *amodule = (MonoAotModule *)klass->image->aot_module;
gboolean err;
MethodRef ref;
gboolean res;
+ gpointer addr;
+ MonoError inner_error;
+
+ mono_error_init (error);
if (MONO_CLASS_IS_INTERFACE (klass) || klass->rank || !amodule)
return NULL;
return NULL;
for (i = 0; i < slot; ++i) {
- decode_method_ref (amodule, &ref, p, &p, &error);
- mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ decode_method_ref (amodule, &ref, p, &p, &inner_error);
+ mono_error_cleanup (&inner_error); /* FIXME don't swallow the error */
}
- res = decode_method_ref (amodule, &ref, p, &p, &error);
- mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ res = decode_method_ref (amodule, &ref, p, &p, &inner_error);
+ mono_error_cleanup (&inner_error); /* FIXME don't swallow the error */
if (!res)
return NULL;
if (ref.no_aot_trampoline)
if (mono_metadata_token_index (ref.token) == 0 || mono_metadata_token_table (ref.token) != MONO_TABLE_METHOD)
return NULL;
- return mono_aot_get_method_from_token (domain, ref.image, ref.token);
+ addr = mono_aot_get_method_from_token (domain, ref.image, ref.token, error);
+ return addr;
}
gboolean
* METHOD might not be set if the caller only has the image/token info.
*/
static gpointer
-load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoMethod *method, guint32 token, int method_index)
+load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoMethod *method, guint32 token, int method_index,
+ MonoError *error)
{
MonoJitInfo *jinfo = NULL;
guint8 *code = NULL, *info;
gboolean res;
+ mono_error_init (error);
+
init_amodule_got (amodule);
if (mono_profiler_get_events () & MONO_PROFILE_ENTER_LEAVE) {
char *full_name;
if (!method) {
- MonoError error;
- method = mono_get_method_checked (image, token, NULL, NULL, &error);
- g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+ method = mono_get_method_checked (image, token, NULL, NULL, error);
+ if (!method)
+ return NULL;
}
full_name = mono_method_full_name (method, TRUE);
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT: NOT FOUND: %s.", full_name);
return NULL;
else if (mono_jit_stats.methods_aot == mono_last_aot_method - 1) {
if (!method) {
- MonoError error;
- method = mono_get_method_checked (image, token, NULL, NULL, &error);
+ method = mono_get_method_checked (image, token, NULL, NULL, error);
if (!method)
- mono_error_cleanup (&error);/* FIXME don't swallow the error */
+ return NULL;
}
if (method) {
char *name = mono_method_full_name (method, TRUE);
}
if (!(is_llvm_code (amodule, code) && (amodule->info.flags & MONO_AOT_FILE_FLAG_LLVM_ONLY))) {
- MonoError error;
-
- res = init_method (amodule, method_index, method, NULL, NULL, &error);
- if (!mono_error_ok (&error))
- mono_error_raise_exception (&error); /* FIXME: Don't raise here */
+ res = init_method (amodule, method_index, method, NULL, NULL, error);
if (!res)
goto cleanup;
}
char *full_name;
if (!method) {
- MonoError error;
- method = mono_get_method_checked (image, token, NULL, NULL, &error);
+ method = mono_get_method_checked (image, token, NULL, NULL, error);
if (!method)
- g_error ("AOT runtime could not load method due to %s", mono_error_get_message (&error)); /* FIXME don't swallow the error */
+ return NULL;
}
full_name = mono_method_full_name (method, TRUE);
MonoJitInfo *jinfo;
if (!method) {
- MonoError error;
- method = mono_get_method_checked (amodule->assembly->image, token, NULL, NULL, &error);
+ method = mono_get_method_checked (amodule->assembly->image, token, NULL, NULL, error);
if (!method)
- g_error ("AOT runtime could not load method due to %s", mono_error_get_message (&error)); /* FIXME don't swallow the error */
+ return NULL;
}
mono_profiler_method_jit (method);
jinfo = mono_jit_info_table_find (domain, (char*)code);
return FALSE;
}
+static void
+init_llvmonly_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoGenericContext *context)
+{
+ gboolean res;
+ MonoError error;
+
+ res = init_method (amodule, method_index, method, init_class, context, &error);
+ if (!is_ok (&error)) {
+ MonoException *ex = mono_error_convert_to_exception (&error);
+ /* Its okay to raise in llvmonly mode */
+ if (ex)
+ mono_llvm_throw_exception ((MonoObject*)ex);
+ }
+}
+
void
mono_aot_init_llvm_method (gpointer aot_module, guint32 method_index)
{
MonoAotModule *amodule = (MonoAotModule *)aot_module;
- gboolean res;
- MonoError error;
- // FIXME: Handle errors
- res = init_method (amodule, method_index, NULL, NULL, NULL, &error);
- g_assert (res);
+ init_llvmonly_method (amodule, method_index, NULL, NULL, NULL);
}
void
mono_aot_init_gshared_method_this (gpointer aot_module, guint32 method_index, MonoObject *this_obj)
{
MonoAotModule *amodule = (MonoAotModule *)aot_module;
- gboolean res;
MonoClass *klass;
MonoGenericContext *context;
MonoMethod *method;
- MonoError error;
// FIXME:
g_assert (this_obj);
context = mono_method_get_context (method);
g_assert (context);
- res = init_method (amodule, method_index, NULL, klass, context, &error);
- g_assert (res);
+ init_llvmonly_method (amodule, method_index, NULL, klass, context);
}
void
mono_aot_init_gshared_method_mrgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
{
MonoAotModule *amodule = (MonoAotModule *)aot_module;
- gboolean res;
MonoGenericContext context = { NULL, NULL };
MonoClass *klass = rgctx->class_vtable->klass;
- MonoError error;
if (klass->generic_class)
context.class_inst = klass->generic_class->context.class_inst;
context.class_inst = klass->generic_container->context.class_inst;
context.method_inst = rgctx->method_inst;
- res = init_method (amodule, method_index, NULL, rgctx->class_vtable->klass, &context, &error);
- g_assert (res);
+ init_llvmonly_method (amodule, method_index, NULL, rgctx->class_vtable->klass, &context);
}
void
mono_aot_init_gshared_method_vtable (gpointer aot_module, guint32 method_index, MonoVTable *vtable)
{
MonoAotModule *amodule = (MonoAotModule *)aot_module;
- gboolean res;
MonoClass *klass;
MonoGenericContext *context;
MonoMethod *method;
- MonoError error;
klass = vtable->klass;
context = mono_method_get_context (method);
g_assert (context);
- res = init_method (amodule, method_index, NULL, klass, context, &error);
- g_assert (res);
+ init_llvmonly_method (amodule, method_index, NULL, klass, context);
}
/*
- * mono_aot_get_method:
+ * mono_aot_get_method_checked:
*
* Return a pointer to the AOTed native code for METHOD if it can be found,
* NULL otherwise.
* On platforms with function pointers, this doesn't return a function pointer.
*/
gpointer
-mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
+mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
{
MonoClass *klass = method->klass;
MonoMethod *orig_method = method;
MonoAotModule *amodule = (MonoAotModule *)klass->image->aot_module;
guint8 *code;
gboolean cache_result = FALSE;
+ MonoError inner_error;
+
+ mono_error_init (error);
if (domain != mono_get_root_domain ())
/* Non shared AOT code can't be used in other appdomains */
* remoting.
*/
if (mono_aot_only && method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
- return mono_aot_get_method (domain, mono_marshal_method_from_wrapper (method));
+ return mono_aot_get_method_checked (domain, mono_marshal_method_from_wrapper (method), error);
g_assert (klass->inited);
if (method_index == 0xffffff && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED && method->klass->rank && strstr (method->name, "System.Collections.Generic")) {
MonoMethod *m = mono_aot_get_array_helper_from_wrapper (method);
- code = (guint8 *)mono_aot_get_method (domain, m);
+ code = (guint8 *)mono_aot_get_method_checked (domain, m, &inner_error);
+ mono_error_cleanup (&inner_error);
if (code)
return code;
}
* an out parameter, so the managed-to-native wrappers can share the same code.
*/
if (method_index == 0xffffff && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE && method->klass == mono_defaults.array_class && !strcmp (method->name, "GetGenericValueImpl")) {
- MonoError error;
MonoMethod *m;
MonoGenericContext ctx;
MonoType *args [16];
args [0] = &mono_defaults.object_class->byval_arg;
ctx.method_inst = mono_metadata_get_generic_inst (1, args);
- m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, &error), TRUE, TRUE);
+ m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, error), TRUE, TRUE);
if (!m)
- g_error ("AOT runtime could not load method due to %s", mono_error_get_message (&error)); /* FIXME don't swallow the error */
+ g_error ("AOT runtime could not load method due to %s", mono_error_get_message (error)); /* FIXME don't swallow the error */
/*
* Get the code for the <object> instantiation which should be emitted into
* the mscorlib aot image by the AOT compiler.
*/
- code = (guint8 *)mono_aot_get_method (domain, m);
+ code = (guint8 *)mono_aot_get_method_checked (domain, m, &inner_error);
+ mono_error_cleanup (&inner_error);
if (code)
return code;
}
((!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Interlocked") && (!strcmp (method->name, "CompareExchange") || !strcmp (method->name, "Exchange")) && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (mono_method_signature (method)->params [1]))) ||
(!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Read") && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (mono_method_signature (method)->ret)))) ||
(!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Write") && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (mono_method_signature (method)->params [1])))))) {
- MonoError error;
MonoMethod *m;
MonoGenericContext ctx;
MonoType *args [16];
args [0] = &mono_defaults.object_class->byval_arg;
ctx.method_inst = mono_metadata_get_generic_inst (1, args);
- m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, &error), TRUE, TRUE);
+ m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, error), TRUE, TRUE);
if (!m)
- g_error ("AOT runtime could not load method due to %s", mono_error_get_message (&error)); /* FIXME don't swallow the error */
+ g_error ("AOT runtime could not load method due to %s", mono_error_get_message (error)); /* FIXME don't swallow the error */
/* Avoid recursion */
if (method == m)
* Get the code for the <object> instantiation which should be emitted into
* the mscorlib aot image by the AOT compiler.
*/
- code = (guint8 *)mono_aot_get_method (domain, m);
+ code = (guint8 *)mono_aot_get_method_checked (domain, m, &inner_error);
+ mono_error_cleanup (&inner_error);
if (code)
return code;
}
if (info->subtype == WRAPPER_SUBTYPE_ARRAY_ACCESSOR) {
MonoMethod *array_method = info->d.array_accessor.method;
if (MONO_TYPE_IS_REFERENCE (&array_method->klass->element_class->byval_arg)) {
- MonoClass *obj_array_class = mono_array_class_get (mono_defaults.object_class, 1);
+ int rank;
+
+ if (!strcmp (array_method->name, "Set"))
+ rank = mono_method_signature (array_method)->param_count - 1;
+ else if (!strcmp (array_method->name, "Get") || !strcmp (array_method->name, "Address"))
+ rank = mono_method_signature (array_method)->param_count;
+ else
+ g_assert_not_reached ();
+ MonoClass *obj_array_class = mono_array_class_get (mono_defaults.object_class, rank);
MonoMethod *m = mono_class_get_method_from_name (obj_array_class, array_method->name, mono_method_signature (array_method)->param_count);
g_assert (m);
m = mono_marshal_get_array_accessor_wrapper (m);
if (m != method) {
- code = (guint8 *)mono_aot_get_method (domain, m);
+ code = (guint8 *)mono_aot_get_method_checked (domain, m, &inner_error);
+ mono_error_cleanup (&inner_error);
if (code)
return code;
}
method_index = mono_metadata_token_index (method->token) - 1;
}
- code = (guint8 *)load_method (domain, amodule, klass->image, method, method->token, method_index);
+ code = (guint8 *)load_method (domain, amodule, klass->image, method, method->token, method_index, error);
+ if (!is_ok (error))
+ return NULL;
if (code && cache_result) {
amodule_lock (amodule);
g_hash_table_insert (amodule->method_to_code, orig_method, code);
return code;
}
+/*
+ * mono_aot_get_method:
+ *
+ * Return a pointer to the AOTed native code for METHOD if it can be found,
+ * NULL otherwise.
+ * On platforms with function pointers, this doesn't return a function pointer.
+ */
+gpointer
+mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
+{
+ MonoError error;
+
+ gpointer res = mono_aot_get_method_checked (domain, method, &error);
+ /* This is external only, so its ok to raise here */
+ mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
+ return res;
+}
+
/**
* Same as mono_aot_get_method, but we try to avoid loading any metadata from the
* method.
*/
gpointer
-mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
+mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token, MonoError *error)
{
MonoAotModule *aot_module = (MonoAotModule *)image->aot_module;
int method_index;
+ gpointer res;
+
+ mono_error_init (error);
if (!aot_module)
return NULL;
method_index = mono_metadata_token_index (token) - 1;
- return load_method (domain, aot_module, image, NULL, token, method_index);
+ res = load_method (domain, aot_module, image, NULL, token, method_index, error);
+ return res;
}
typedef struct {
return NULL;
}
+gpointer
+mono_aot_get_method_checked (MonoDomain *domain,
+ MonoMethod *method, MonoError *error)
+{
+ mono_error_init (error);
+ return NULL;
+}
+
gboolean
mono_aot_is_got_entry (guint8 *code, guint8 *addr)
{
}
gpointer
-mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
+mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token, MonoError *error)
{
+ mono_error_init (error);
return NULL;
}
}
gpointer
-mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot)
+mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot, MonoError *error)
{
+ mono_error_init (error);
+
return NULL;
}