GHashTable *method_to_cfg;
GHashTable *token_info_hash;
GHashTable *method_to_pinvoke_import;
+ GHashTable *method_to_external_icall_symbol_name;
GPtrArray *extra_methods;
GPtrArray *image_table;
GPtrArray *globals;
/* This points to the current acfg in LLVM mode */
static MonoAotCompile *llvm_acfg;
+/* Cache of decoded method external icall symbol names. */
+/* Owned by acfg, but kept in this static as well since it is */
+/* accessed by code paths not having access to acfg. */
+static GHashTable *method_to_external_icall_symbol_name;
+
// This, instead of an array of pointers, to optimize away a pointer and a relocation per string.
#define MSGSTRFIELD(line) MSGSTRFIELD1(line)
#define MSGSTRFIELD1(line) str##line
}
}
+static char *
+decode_direct_icall_symbol_name_attribute (MonoMethod *method)
+{
+ ERROR_DECL (error);
+
+ int j = 0;
+ char *symbol_name = NULL;
+
+ MonoCustomAttrInfo *cattr = mono_custom_attrs_from_method_checked (method, error);
+ if (mono_error_ok(error) && cattr) {
+ for (j = 0; j < cattr->num_attrs; j++)
+ if (cattr->attrs [j].ctor && !strcmp (m_class_get_name (cattr->attrs [j].ctor->klass), "MonoDirectICallSymbolNameAttribute"))
+ break;
+
+ if (j < cattr->num_attrs) {
+ MonoCustomAttrEntry *e = &cattr->attrs [j];
+ MonoMethodSignature *sig = mono_method_signature_internal (e->ctor);
+ if (e->data && sig && sig->param_count == 1 && sig->params [0]->type == MONO_TYPE_STRING) {
+ /*
+ * Decode the cattr manually since we can't create objects
+ * during aot compilation.
+ */
+
+ /* Skip prolog */
+ const char *p = ((const char*)e->data) + 2;
+ int slen = mono_metadata_decode_value (p, &p);
+
+ symbol_name = (char *)g_memdup (p, slen + 1);
+ if (symbol_name)
+ symbol_name [slen] = 0;
+ }
+ }
+ }
+
+ return symbol_name;
+}
+static const char*
+lookup_external_icall_symbol_name_aot (MonoMethod *method)
+{
+ g_assert (method_to_external_icall_symbol_name);
+
+ gpointer key, value;
+ if (g_hash_table_lookup_extended (method_to_external_icall_symbol_name, method, &key, &value))
+ return (const char*)value;
+
+ char *symbol_name = decode_direct_icall_symbol_name_attribute (method);
+ g_hash_table_insert (method_to_external_icall_symbol_name, method, symbol_name);
+
+ return symbol_name;
+}
+
+static const char*
+lookup_icall_symbol_name_aot (MonoMethod *method)
+{
+ const char * symbol_name = mono_lookup_icall_symbol (method);
+ if (!symbol_name)
+ symbol_name = lookup_external_icall_symbol_name_aot (method);
+
+ return symbol_name;
+}
+
+gboolean
+mono_aot_direct_icalls_enabled_for_method (MonoCompile *cfg, MonoMethod *method)
+{
+ gboolean enable_icall = FALSE;
+ if (cfg->compile_aot) {
+ enable_icall = lookup_external_icall_symbol_name_aot (method) ? TRUE : FALSE;
+ } else {
+ enable_icall = FALSE;
+ }
+
+ return enable_icall;
+}
+
/*
* is_direct_callable:
*
} else if (patch_info->type == MONO_PATCH_INFO_ICALL_ADDR_CALL) {
if (!got_only && is_direct_callable (acfg, method, patch_info)) {
if (!(patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
- direct_pinvoke = mono_lookup_icall_symbol (patch_info->data.method);
+ direct_pinvoke = lookup_icall_symbol_name_aot (patch_info->data.method);
else
direct_pinvoke = get_pinvoke_import (acfg, patch_info->data.method);
if (direct_pinvoke) {
} else if (type == MONO_PATCH_INFO_ICALL_ADDR_CALL) {
MonoMethod *method = (MonoMethod *)data;
if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
- sym = mono_lookup_icall_symbol (method);
+ sym = lookup_icall_symbol_name_aot (method);
else if (llvm_acfg->aot_opts.direct_pinvoke)
sym = get_pinvoke_import (llvm_acfg, method);
} else if (type == MONO_PATCH_INFO_JIT_ICALL) {
} else if (type == MONO_PATCH_INFO_ICALL_ADDR_CALL) {
MonoMethod *method = (MonoMethod *)data;
if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
- sym = mono_lookup_icall_symbol (method);
+ sym = lookup_icall_symbol_name_aot (method);
}
if (sym)
return g_strdup (sym);
acfg->method_to_cfg = g_hash_table_new (NULL, NULL);
acfg->token_info_hash = g_hash_table_new_full (NULL, NULL, NULL, NULL);
acfg->method_to_pinvoke_import = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+ acfg->method_to_external_icall_symbol_name = g_hash_table_new_full (NULL, NULL, NULL, g_free);
acfg->image_hash = g_hash_table_new (NULL, NULL);
acfg->image_table = g_ptr_array_new ();
acfg->globals = g_ptr_array_new ();
init_got_info (&acfg->got_info);
init_got_info (&acfg->llvm_got_info);
+ method_to_external_icall_symbol_name = acfg->method_to_external_icall_symbol_name;
return acfg;
}
g_hash_table_destroy (acfg->method_to_cfg);
g_hash_table_destroy (acfg->token_info_hash);
g_hash_table_destroy (acfg->method_to_pinvoke_import);
+ g_hash_table_destroy (acfg->method_to_external_icall_symbol_name);
g_hash_table_destroy (acfg->image_hash);
g_hash_table_destroy (acfg->unwind_info_offsets);
g_hash_table_destroy (acfg->method_label_hash);
got_info_free (&acfg->llvm_got_info);
arch_free_unwind_info_section_cache (acfg);
mono_mempool_destroy (acfg->mempool);
+
+ method_to_external_icall_symbol_name = NULL;
g_free (acfg);
}
}
static gboolean
-direct_icalls_enabled (MonoCompile *cfg)
+direct_icalls_enabled (MonoCompile *cfg, MonoMethod *method)
{
- return FALSE;
+ if (cfg->gen_sdb_seq_points || cfg->disable_direct_icalls)
+ return FALSE;
+
+ if (method && mono_aot_direct_icalls_enabled_for_method (cfg, method))
+ return TRUE;
/* LLVM on amd64 can't handle calls to non-32 bit addresses */
#ifdef TARGET_AMD64
if (cfg->compile_llvm && !cfg->llvm_only)
return FALSE;
#endif
- if (cfg->gen_sdb_seq_points || cfg->disable_direct_icalls)
- return FALSE;
- return TRUE;
+
+ return FALSE;
}
MonoInst*
* The wrapper is needed to be able to do stack walks for asynchronously suspended
* threads when debugging.
*/
- if (direct_icalls_enabled (cfg)) {
+ if (direct_icalls_enabled (cfg, NULL)) {
int costs;
if (!info->wrapper_method) {
if (cmethod->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL &&
mini_class_is_system_array (cmethod->klass)) {
array_rank = m_class_get_rank (cmethod->klass);
- } else if ((cmethod->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && direct_icalls_enabled (cfg)) {
+ } else if ((cmethod->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && direct_icalls_enabled (cfg, cmethod)) {
direct_icall = TRUE;
} else if (fsig->pinvoke) {
MonoMethod *wrapper = mono_marshal_get_native_wrapper (cmethod, TRUE, cfg->compile_aot);