MonoDomain *domain = mono_domain_get ();
MonoDomain *target_domain = mono_domain_get ();
FindTrampUserData user_data;
+ MonoGenericSharingContext*gsctx;
+ const char *shared_type;
ji = mini_jit_info_table_find (domain, ip, &target_domain);
if (!ji) {
method = mono_method_full_name (ji->method, TRUE);
source = mono_debug_lookup_source_location (ji->method, (guint32)((guint8*)ip - (guint8*)ji->code_start), target_domain);
- g_print ("IP %p at offset 0x%x of method %s (%p %p)[domain %p - %s]\n", ip, (int)((char*)ip - (char*)ji->code_start), method, ji->code_start, (char*)ji->code_start + ji->code_size, target_domain, target_domain->friendly_name);
+ gsctx = mono_jit_info_get_generic_sharing_context (ji);
+ shared_type = "";
+ if (gsctx) {
+ if (gsctx->var_is_vt || gsctx->mvar_is_vt)
+ shared_type = "gsharedvt ";
+ else
+ shared_type = "gshared ";
+ }
+
+ g_print ("IP %p at offset 0x%x of %smethod %s (%p %p)[domain %p - %s]\n", ip, (int)((char*)ip - (char*)ji->code_start), shared_type, method, ji->code_start, (char*)ji->code_start + ji->code_size, target_domain, target_domain->friendly_name);
if (source)
g_print ("%s:%d\n", source->source_file, source->row);
g_free (info);
}
+G_GNUC_UNUSED static void
+break_count (void)
+{
+}
+
+/*
+ * Runtime debugging tool, use if (debug_count ()) <x> else <y> to do <x> the first COUNT times, then do <y> afterwards.
+ * Set a breakpoint in break_count () to break the last time <x> is done.
+ */
+G_GNUC_UNUSED gboolean
+mono_debug_count (void)
+{
+ static int count = 0;
+ count ++;
+
+ if (!getenv ("COUNT"))
+ return TRUE;
+
+ if (count == atoi (getenv ("COUNT"))) {
+ break_count ();
+ }
+
+ if (count > atoi (getenv ("COUNT"))) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
#define MONO_INIT_VARINFO(vi,id) do { \
(vi)->range.first_use.pos.bid = 0xffff; \
(vi)->reg = -1; \
goto handle_enum;
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
- /* FIXME: all the arguments must be references for now,
- * later look inside cfg and see if the arg num is
- * really a reference
- */
- g_assert (cfg->generic_sharing_context);
- return OP_STORE_MEMBASE_REG;
+ if (mini_type_var_is_vt (cfg, type))
+ return OP_STOREV_MEMBASE;
+ else
+ return OP_STORE_MEMBASE_REG;
default:
g_error ("unknown type 0x%02x in type_to_store_membase", type->type);
}
break;
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
- /* FIXME: all the arguments must be references for now,
- * later look inside cfg and see if the arg num is
- * really a reference
- */
g_assert (cfg->generic_sharing_context);
- return OP_LOAD_MEMBASE;
+ if (mini_type_var_is_vt (cfg, type))
+ return OP_LOADV_MEMBASE;
+ else
+ return OP_LOAD_MEMBASE;
default:
g_error ("unknown type 0x%02x in type_to_load_membase", type->type);
}
mini_type_to_ldind (MonoCompile* cfg, MonoType *type)
{
if (cfg->generic_sharing_context && !type->byref) {
- /* FIXME: all the arguments must be references for now,
- * later look inside cfg and see if the arg num is
- * really a reference
- */
- if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)
- return CEE_LDIND_REF;
+ if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) {
+ if (mini_type_var_is_vt (cfg, type))
+ return CEE_LDOBJ;
+ else
+ return CEE_LDIND_REF;
+ }
}
return mono_type_to_ldind (type);
}
mini_type_to_stind (MonoCompile* cfg, MonoType *type)
{
if (cfg->generic_sharing_context && !type->byref) {
- /* FIXME: all the arguments must be references for now,
- * later look inside cfg and see if the arg num is
- * really a reference
- */
- if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)
- return CEE_STIND_REF;
+ if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) {
+ if (mini_type_var_is_vt (cfg, type))
+ return CEE_STOBJ;
+ else
+ return CEE_STIND_REF;
+ }
}
return mono_type_to_stind (type);
}
+#ifndef DISABLE_JIT
+
int
mono_op_imm_to_op (int opcode)
{
bb->max_vreg = MAX (bb->max_vreg, cfg->next_vreg);
}
+#endif
+
static void
set_vreg_to_inst (MonoCompile *cfg, int vreg, MonoInst *inst)
{
inst->backend.is_pinvoke = 0;
inst->dreg = vreg;
+ if (inst->klass->exception_type)
+ mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD);
+
if (cfg->compute_gc_maps) {
if (type->byref) {
mono_mark_vreg_as_mp (cfg, vreg);
vmv = current;
inst = cfg->varinfo [vmv->idx];
+ t = mono_type_get_underlying_type (inst->inst_vtype);
+ if (cfg->gsharedvt && mini_is_gsharedvt_variable_type (cfg, t))
+ t = mini_get_gsharedvt_alloc_type_for_type (cfg, t);
+
/* inst->backend.is_pinvoke indicates native sized value types, this is used by the
* pinvoke wrappers when they call functions returning structures */
- if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype) && inst->inst_vtype->type != MONO_TYPE_TYPEDBYREF) {
- size = mono_class_native_size (mono_class_from_mono_type (inst->inst_vtype), &align);
+ if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (t) && t->type != MONO_TYPE_TYPEDBYREF) {
+ size = mono_class_native_size (mono_class_from_mono_type (t), &align);
}
else {
int ialign;
- size = mono_type_size (inst->inst_vtype, &ialign);
+ size = mono_type_size (t, &ialign);
align = ialign;
- if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (inst->inst_vtype)))
+ if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (t)))
align = 16;
}
if (cfg->disable_reuse_stack_slots)
reuse_slot = FALSE;
- t = mono_type_get_underlying_type (inst->inst_vtype);
switch (t->type) {
case MONO_TYPE_GENERICINST:
if (!mono_type_generic_inst_is_valuetype (t)) {
vmv = l->data;
inst = cfg->varinfo [vmv->idx];
+ t = mono_type_get_underlying_type (inst->inst_vtype);
+ if (cfg->gsharedvt && mini_is_gsharedvt_variable_type (cfg, t))
+ t = mini_get_gsharedvt_alloc_type_for_type (cfg, t);
+
/* inst->backend.is_pinvoke indicates native sized value types, this is used by the
* pinvoke wrappers when they call functions returning structures */
- if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype) && inst->inst_vtype->type != MONO_TYPE_TYPEDBYREF) {
- size = mono_class_native_size (mono_class_from_mono_type (inst->inst_vtype), &align);
+ if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (t) && t->type != MONO_TYPE_TYPEDBYREF) {
+ size = mono_class_native_size (mono_class_from_mono_type (t), &align);
} else {
int ialign;
- size = mono_type_size (inst->inst_vtype, &ialign);
+ size = mono_type_size (t, &ialign);
align = ialign;
- if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (inst->inst_vtype)))
+ if (mono_class_from_mono_type (t)->exception_type)
+ mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD);
+
+ if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (t)))
align = 16;
}
if (cfg->disable_reuse_stack_slots)
reuse_slot = FALSE;
- t = mono_type_get_underlying_type (inst->inst_vtype);
if (t->byref) {
slot_info = &scalar_stack_slots [MONO_TYPE_I];
} else {
if (cfg->disable_reuse_ref_stack_slots)
reuse_slot = FALSE;
break;
-
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR:
+ slot_info = &scalar_stack_slots [t->type];
+ break;
default:
slot_info = &scalar_stack_slots [t->type];
+ break;
}
}
#endif
}
-/* Called by native->managed wrappers */
-void
+/*
+ * mono_jit_thread_attach:
+ *
+ * Called by native->managed wrappers. Returns the original domain which needs to be
+ * restored, or NULL.
+ */
+MonoDomain*
mono_jit_thread_attach (MonoDomain *domain)
{
+ MonoDomain *orig;
+
if (!domain)
/*
* Happens when called from AOTed code which is only used in the root
mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
}
#endif
- if (mono_domain_get () != domain)
- mono_domain_set (domain, TRUE);
+ orig = mono_domain_get ();
+ if (orig != domain)
+ mono_domain_set (domain, TRUE);
+
+ return orig != domain ? orig : NULL;
}
+/* Called by native->managed wrappers */
+void
+mono_jit_set_domain (MonoDomain *domain)
+{
+ if (domain)
+ mono_domain_set (domain, TRUE);
+}
+
/**
* mono_thread_abort:
* @obj: exception object
(obj->vtable->klass == mono_defaults.threadabortexception_class)) {
mono_thread_exit ();
} else {
- MonoObject *other = NULL;
- MonoString *str = mono_object_to_string (obj, &other);
- if (str) {
- char *msg = mono_string_to_utf8 (str);
- fprintf (stderr, "[ERROR] FATAL UNHANDLED EXCEPTION: %s\n", msg);
- fflush (stderr);
- g_free (msg);
- }
-
- exit (mono_environment_exitcode_get ());
+ mono_invoke_unhandled_exception_hook (obj);
}
}
return mono_create_tls_get (cfg, mono_thread_get_tls_offset ());
}
+MonoInst*
+mono_get_lmf_intrinsic (MonoCompile* cfg)
+{
+ return mono_create_tls_get (cfg, mono_get_lmf_tls_offset ());
+}
+
void
mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
{
memcpy (res->data.rgctx_entry, patch_info->data.rgctx_entry, sizeof (MonoJumpInfoRgctxEntry));
res->data.rgctx_entry->data = mono_patch_info_dup_mp (mp, res->data.rgctx_entry->data);
break;
+ case MONO_PATCH_INFO_GSHAREDVT_CALL:
+ res->data.gsharedvt = mono_mempool_alloc (mp, sizeof (MonoJumpInfoGSharedVtCall));
+ memcpy (res->data.gsharedvt, patch_info->data.gsharedvt, sizeof (MonoJumpInfoGSharedVtCall));
+ break;
default:
break;
}
case MONO_PATCH_INFO_SFLDA:
case MONO_PATCH_INFO_SEQ_POINT_INFO:
return (ji->type << 8) | (gssize)ji->data.target;
+ case MONO_PATCH_INFO_GSHAREDVT_CALL:
+ return (ji->type << 8) | (gssize)ji->data.gsharedvt->method;
default:
return (ji->type << 8);
}
break;
case MONO_PATCH_INFO_INTERNAL_METHOD:
return g_str_equal (ji1->data.name, ji2->data.name);
-
case MONO_PATCH_INFO_RGCTX_FETCH: {
MonoJumpInfoRgctxEntry *e1 = ji1->data.rgctx_entry;
MonoJumpInfoRgctxEntry *e2 = ji2->data.rgctx_entry;
return e1->method == e2->method && e1->in_mrgctx == e2->in_mrgctx && e1->info_type == e2->info_type && mono_patch_info_equal (e1->data, e2->data);
}
+ case MONO_PATCH_INFO_GSHAREDVT_CALL: {
+ MonoJumpInfoGSharedVtCall *c1 = ji1->data.gsharedvt;
+ MonoJumpInfoGSharedVtCall *c2 = ji2->data.gsharedvt;
+
+ return c1->sig == c2->sig && c1->method == c2->method;
+ }
default:
if (ji1->data.target != ji2->data.target)
return 0;
case MONO_PATCH_INFO_ICALL_ADDR:
/* run_cctors == 0 -> AOT */
if (patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+ const char *exc_class;
+ const char *exc_arg;
+
if (run_cctors) {
- target = mono_lookup_pinvoke_call (patch_info->data.method, NULL, NULL);
- if (!target)
+ target = mono_lookup_pinvoke_call (patch_info->data.method, &exc_class, &exc_arg);
+ if (!target) {
+ if (mono_aot_only)
+ mono_raise_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
g_error ("Unable to resolve pinvoke method '%s' Re-run with MONO_LOG_LEVEL=debug for more information.\n", mono_method_full_name (patch_info->data.method, TRUE));
+ }
} else {
target = NULL;
}
switch (entry->data->type) {
case MONO_PATCH_INFO_CLASS:
- slot = mono_method_lookup_or_register_other_info (entry->method, entry->in_mrgctx, &entry->data->data.klass->byval_arg, entry->info_type, mono_method_get_context (entry->method));
+ slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, &entry->data->data.klass->byval_arg, entry->info_type, mono_method_get_context (entry->method));
break;
case MONO_PATCH_INFO_METHOD:
case MONO_PATCH_INFO_METHODCONST:
- slot = mono_method_lookup_or_register_other_info (entry->method, entry->in_mrgctx, entry->data->data.method, entry->info_type, mono_method_get_context (entry->method));
+ slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.method, entry->info_type, mono_method_get_context (entry->method));
break;
case MONO_PATCH_INFO_FIELD:
- slot = mono_method_lookup_or_register_other_info (entry->method, entry->in_mrgctx, entry->data->data.field, entry->info_type, mono_method_get_context (entry->method));
+ slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.field, entry->info_type, mono_method_get_context (entry->method));
+ break;
+ case MONO_PATCH_INFO_SIGNATURE:
+ slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.sig, entry->info_type, mono_method_get_context (entry->method));
break;
+ case MONO_PATCH_INFO_GSHAREDVT_CALL: {
+ MonoJumpInfoGSharedVtCall *call_info = mono_domain_alloc0 (domain, sizeof (MonoJumpInfoGSharedVtCall));
+
+ memcpy (call_info, entry->data->data.gsharedvt, sizeof (MonoJumpInfoGSharedVtCall));
+ slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, call_info, entry->info_type, mono_method_get_context (entry->method));
+ break;
+ }
default:
g_assert_not_reached ();
break;
mono_arch_create_vars (cfg);
}
-#endif /* #ifndef DISABLE_JIT */
-
void
mono_print_code (MonoCompile *cfg, const char* msg)
{
mono_print_bb (bb, msg);
}
-#ifndef DISABLE_JIT
-
static void
mono_postprocess_patches (MonoCompile *cfg)
{
last = ins;
}
+
+ if (bb->last_ins && bb->last_ins->opcode == OP_ENDFINALLY) {
+ MonoBasicBlock *bb2;
+ MonoInst *endfinally_seq_point = NULL;
+
+ /*
+ * The ENDFINALLY branches are not represented in the cfg, so link it with all seq points starting bbs.
+ */
+ l = g_slist_last (bb->seq_points);
+ g_assert (l);
+ endfinally_seq_point = l->data;
+
+ for (bb2 = cfg->bb_entry; bb2; bb2 = bb2->next_bb) {
+ GSList *l = g_slist_last (bb2->seq_points);
+
+ if (l) {
+ MonoInst *ins = l->data;
+
+ if (!(ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET) && ins != endfinally_seq_point)
+ next [endfinally_seq_point->backend.size] = g_slist_append (next [endfinally_seq_point->backend.size], GUINT_TO_POINTER (ins->backend.size));
+ }
+ }
+ }
}
if (cfg->verbose_level > 2) {
sp->next = g_new (int, sp->next_len);
j = 0;
if (cfg->verbose_level > 2 && next [i]) {
- printf ("\t0x%x ->", sp->il_offset);
+ printf ("\tIL0x%x ->", sp->il_offset);
for (l = next [i]; l; l = l->next) {
next_index = GPOINTER_TO_UINT (l->data);
- printf (" 0x%x", info->seq_points [next_index].il_offset);
+ printf (" IL0x%x", info->seq_points [next_index].il_offset);
}
printf ("\n");
}
}
}
+#endif /* #ifndef DISABLE_JIT */
+
+static MonoJitInfo*
+create_jit_info_for_trampoline (MonoMethod *wrapper, MonoTrampInfo *info)
+{
+ MonoDomain *domain = mono_get_root_domain ();
+ MonoJitInfo *jinfo;
+ guint8 *uw_info;
+ guint32 info_len;
+
+ if (info->uw_info) {
+ uw_info = info->uw_info;
+ info_len = info->uw_info_len;
+ } else {
+ uw_info = mono_unwind_ops_encode (info->unwind_ops, &info_len);
+ }
+
+ jinfo = mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO);
+ jinfo->method = wrapper;
+ jinfo->code_start = info->code;
+ jinfo->code_size = info->code_size;
+ jinfo->used_regs = mono_cache_unwind_info (uw_info, info_len);
+
+ return jinfo;
+}
+
+#ifndef DISABLE_JIT
+
static MonoJitInfo*
create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
{
MonoJitInfo *jinfo;
int num_clauses;
int generic_info_size, arch_eh_info_size = 0;
- int holes_size = 0, num_holes = 0;
+ int holes_size = 0, num_holes = 0, cas_size = 0;
guint32 stack_size = 0;
g_assert (method_to_compile == cfg->method);
* mono_arch_get_argument_info () is not signal safe.
*/
arg_info = g_newa (MonoJitArgumentInfo, sig->param_count + 1);
- stack_size = mono_arch_get_argument_info (sig, sig->param_count, arg_info);
+ stack_size = mono_arch_get_argument_info (cfg->generic_sharing_context, sig, sig->param_count, arg_info);
if (stack_size)
arch_eh_info_size = sizeof (MonoArchEHJitInfo);
printf ("Number of try block holes %d\n", num_holes);
}
+ if (mono_method_has_declsec (cfg->method_to_register)) {
+ cas_size = sizeof (MonoMethodCasInfo);
+ }
+
if (COMPILE_LLVM (cfg))
num_clauses = cfg->llvm_ex_info_len;
else
if (cfg->method->dynamic) {
jinfo = g_malloc0 (MONO_SIZEOF_JIT_INFO + (num_clauses * sizeof (MonoJitExceptionInfo)) +
- generic_info_size + holes_size + arch_eh_info_size);
+ generic_info_size + holes_size + arch_eh_info_size + cas_size);
} else {
jinfo = mono_domain_alloc0 (cfg->domain, MONO_SIZEOF_JIT_INFO +
(num_clauses * sizeof (MonoJitExceptionInfo)) +
- generic_info_size + holes_size + arch_eh_info_size);
+ generic_info_size + holes_size + arch_eh_info_size + cas_size);
}
jinfo->method = cfg->method_to_register;
jinfo->code_size = cfg->code_len;
jinfo->used_regs = cfg->used_int_regs;
jinfo->domain_neutral = (cfg->opt & MONO_OPT_SHARED) != 0;
- jinfo->cas_inited = FALSE; /* initialization delayed at the first stalk walk using this method */
jinfo->num_clauses = num_clauses;
+
if (COMPILE_LLVM (cfg))
jinfo->from_llvm = TRUE;
gi = mono_jit_info_get_generic_jit_info (jinfo);
g_assert (gi);
- gi->generic_sharing_context = cfg->generic_sharing_context;
+ if (cfg->method->dynamic)
+ gi->generic_sharing_context = g_new0 (MonoGenericSharingContext, 1);
+ else
+ gi->generic_sharing_context = mono_domain_alloc0 (cfg->domain, sizeof (MonoGenericSharingContext));
+ memcpy (gi->generic_sharing_context, cfg->generic_sharing_context, sizeof (MonoGenericSharingContext));
if ((method_to_compile->flags & METHOD_ATTRIBUTE_STATIC) ||
mini_method_get_context (method_to_compile)->method_inst ||
info->stack_size = stack_size;
}
+ if (cas_size) {
+ jinfo->has_cas_info = 1;
+ }
+
if (COMPILE_LLVM (cfg)) {
if (num_clauses)
memcpy (&jinfo->clauses [0], &cfg->llvm_ex_info [0], num_clauses * sizeof (MonoJitExceptionInfo));
}
#endif
+static MonoType*
+get_gsharedvt_type (MonoType *t)
+{
+ MonoGenericParam *par = t->data.generic_param;
+ MonoType *res;
+
+ /*
+ * Create an anonymous gparam with a different serial so normal gshared and gsharedvt methods have
+ * a different instantiation.
+ */
+ g_assert (mono_generic_param_info (par));
+ par = g_memdup (par, sizeof (MonoGenericParamFull));
+ par->owner = NULL;
+ // FIXME:
+ par->image = mono_defaults.corlib;
+ par->serial = 1;
+ res = mono_metadata_type_dup (NULL, t);
+ res->data.generic_param = par;
+
+ return res;
+}
+
+static gboolean
+is_gsharedvt_type (MonoType *t)
+{
+ return (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) && t->data.generic_param->serial == 1;
+}
+
+/* Return whenever METHOD is a gsharedvt method */
+static gboolean
+is_gsharedvt_method (MonoMethod *method)
+{
+ MonoGenericContext *context;
+ MonoGenericInst *inst;
+ int i;
+
+ if (!method->is_inflated)
+ return FALSE;
+ context = mono_method_get_context (method);
+ inst = context->class_inst;
+ if (inst) {
+ for (i = 0; i < inst->type_argc; ++i)
+ if (is_gsharedvt_type (inst->type_argv [i]))
+ return TRUE;
+ }
+ inst = context->method_inst;
+ if (inst) {
+ for (i = 0; i < inst->type_argc; ++i)
+ if (is_gsharedvt_type (inst->type_argv [i]))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+has_ref_constraint (MonoGenericParamInfo *info)
+{
+ MonoClass **constraints;
+
+ //return FALSE;
+
+ if (info && info->constraints) {
+ constraints = info->constraints;
+
+ while (*constraints) {
+ MonoClass *cklass = *constraints;
+ if (!(cklass == mono_defaults.object_class || (cklass->image == mono_defaults.corlib && !strcmp (cklass->name, "ValueType")) || MONO_CLASS_IS_INTERFACE (cklass)))
+ return TRUE;
+ constraints ++;
+ }
+ }
+ return FALSE;
+}
+
+static MonoGenericInst*
+get_shared_inst (MonoGenericInst *inst, MonoGenericInst *shared_inst, MonoGenericContainer *container, gboolean all_vt, gboolean gsharedvt)
+{
+ MonoGenericInst *res;
+ MonoType **type_argv;
+ int i;
+
+ type_argv = g_new0 (MonoType*, inst->type_argc);
+ for (i = 0; i < inst->type_argc; ++i) {
+ if (!all_vt && (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)) {
+ type_argv [i] = shared_inst->type_argv [i];
+ } else if (all_vt) {
+ if (container && has_ref_constraint (&container->type_params [i].info))
+ type_argv [i] = shared_inst->type_argv [i];
+ else
+ type_argv [i] = get_gsharedvt_type (shared_inst->type_argv [i]);
+ } else if (gsharedvt) {
+ type_argv [i] = get_gsharedvt_type (shared_inst->type_argv [i]);
+ } else {
+ type_argv [i] = inst->type_argv [i];
+ }
+ }
+
+ res = mono_metadata_get_generic_inst (inst->type_argc, type_argv);
+ g_free (type_argv);
+ return res;
+}
+
/*
- * mini_get_shared_method:
+ * mini_get_shared_method_full:
*
* Return the method which is actually compiled/registered when doing generic sharing.
+ * If ALL_VT is true, return the shared method belonging to an all-vtype instantiation.
+ * If IS_GSHAREDVT is true, treat METHOD as a gsharedvt method even if it fails some constraints.
+ * METHOD can be a non-inflated generic method.
*/
MonoMethod*
-mini_get_shared_method (MonoMethod *method)
+mini_get_shared_method_full (MonoMethod *method, gboolean all_vt, gboolean is_gsharedvt)
{
MonoGenericContext shared_context;
MonoMethod *declaring_method, *res;
- int i;
gboolean partial = FALSE;
+ gboolean gsharedvt = FALSE;
+ MonoGenericContainer *class_container, *method_container = NULL;
- if (method->is_generic || method->klass->generic_container)
+ if (method->is_generic || method->klass->generic_container) {
declaring_method = method;
- else
+ } else {
declaring_method = mono_method_get_declaring_generic_method (method);
+ }
if (declaring_method->is_generic)
shared_context = mono_method_get_generic_container (declaring_method)->context;
else
shared_context = declaring_method->klass->generic_container->context;
- /* Handle partial sharing */
- if (method != declaring_method && method->is_inflated && !mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE)) {
+ /* Handle gsharedvt/partial sharing */
+ if ((method != declaring_method && method->is_inflated && !mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, TRUE)) ||
+ is_gsharedvt || mini_is_gsharedvt_sharable_method (method)) {
MonoGenericContext *context = mono_method_get_context (method);
MonoGenericInst *inst;
- MonoType **type_argv;
+
+ gsharedvt = is_gsharedvt || mini_is_gsharedvt_sharable_method (method);
+
+ class_container = declaring_method->klass->generic_container;
+ method_container = mono_method_get_generic_container (declaring_method);
/*
* Create the shared context by replacing the ref type arguments with
* type parameters, and keeping the rest.
*/
partial = TRUE;
- inst = context->class_inst;
- if (inst) {
- type_argv = g_new0 (MonoType*, inst->type_argc);
- for (i = 0; i < inst->type_argc; ++i) {
- if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
- type_argv [i] = shared_context.class_inst->type_argv [i];
- else
- type_argv [i] = inst->type_argv [i];
- }
-
- shared_context.class_inst = mono_metadata_get_generic_inst (inst->type_argc, type_argv);
- g_free (type_argv);
- }
-
- inst = context->method_inst;
- if (inst) {
- type_argv = g_new0 (MonoType*, inst->type_argc);
- for (i = 0; i < inst->type_argc; ++i) {
- if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)
- type_argv [i] = shared_context.method_inst->type_argv [i];
- else
- type_argv [i] = inst->type_argv [i];
- }
+ if (context)
+ inst = context->class_inst;
+ else
+ inst = shared_context.class_inst;
+ if (inst)
+ shared_context.class_inst = get_shared_inst (inst, shared_context.class_inst, class_container, all_vt, gsharedvt);
- shared_context.method_inst = mono_metadata_get_generic_inst (inst->type_argc, type_argv);
- g_free (type_argv);
- }
+ if (context)
+ inst = context->method_inst;
+ else
+ inst = shared_context.method_inst;
+ if (inst)
+ shared_context.method_inst = get_shared_inst (inst, shared_context.method_inst, method_container, all_vt, gsharedvt);
}
res = mono_class_inflate_generic_method (declaring_method, &shared_context);
return res;
}
+MonoMethod*
+mini_get_shared_method (MonoMethod *method)
+{
+ return mini_get_shared_method_full (method, FALSE, FALSE);
+}
+
+void
+mini_init_gsctx (MonoGenericContext *context, MonoGenericSharingContext *gsctx)
+{
+ MonoGenericInst *inst;
+ int i;
+
+ memset (gsctx, 0, sizeof (MonoGenericSharingContext));
+
+ if (context->class_inst) {
+ inst = context->class_inst;
+ gsctx->var_is_vt = g_new0 (gboolean, inst->type_argc);
+
+ for (i = 0; i < inst->type_argc; ++i) {
+ MonoType *type = inst->type_argv [i];
+
+ if ((type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && type->data.generic_param->serial == 1)
+ gsctx->var_is_vt [i] = TRUE;
+ }
+ }
+ if (context->method_inst) {
+ inst = context->method_inst;
+ gsctx->mvar_is_vt = g_new0 (gboolean, inst->type_argc);
+
+ for (i = 0; i < inst->type_argc; ++i) {
+ MonoType *type = inst->type_argv [i];
+
+ if ((type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && type->data.generic_param->serial == 1)
+ gsctx->mvar_is_vt [i] = TRUE;
+ }
+ }
+}
+
#ifndef DISABLE_JIT
/*
* mini_method_compile:
gboolean deadce_has_run = FALSE;
gboolean try_generic_shared, try_llvm = FALSE;
MonoMethod *method_to_compile, *method_to_register;
+ gboolean method_is_gshared = FALSE;
InterlockedIncrement (&mono_jit_stats.methods_compiled);
if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
mono_profiler_method_jit (method);
- if (MONO_PROBE_METHOD_COMPILE_BEGIN_ENABLED ())
+ if (MONO_METHOD_COMPILE_BEGIN_ENABLED ())
MONO_PROBE_METHOD_COMPILE_BEGIN (method);
if (compile_aot)
* FIXME: Remove the method->klass->generic_class limitation.
*/
try_generic_shared = mono_class_generic_sharing_enabled (method->klass) &&
- (opts & MONO_OPT_GSHARED) && ((method->is_generic || method->klass->generic_container) || (!method->klass->generic_class && mono_method_is_generic_sharable_impl (method, TRUE)));
+ (opts & MONO_OPT_GSHARED) && ((method->is_generic || method->klass->generic_container) || (!method->klass->generic_class && mono_method_is_generic_sharable_impl_full (method, TRUE, FALSE, FALSE)));
else
try_generic_shared = mono_class_generic_sharing_enabled (method->klass) &&
- (opts & MONO_OPT_GSHARED) && mono_method_is_generic_sharable_impl (method, FALSE);
+ (opts & MONO_OPT_GSHARED) && mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, TRUE);
if (opts & MONO_OPT_GSHARED) {
if (try_generic_shared)
mono_stats.generics_unsharable_methods++;
}
+ if (mini_is_gsharedvt_sharable_method (method)) {
+ if (!mono_debug_count ())
+ try_generic_shared = FALSE;
+ if (compile_aot)
+ try_generic_shared = FALSE;
+ }
+
+ if (is_gsharedvt_method (method)) {
+ /* We are AOTing a gshared method directly */
+ method_is_gshared = TRUE;
+ g_assert (compile_aot);
+ try_generic_shared = TRUE;
+ }
+
#ifdef ENABLE_LLVM
try_llvm = mono_use_llvm;
#endif
restart_compile:
- if (try_generic_shared) {
- method_to_compile = mini_get_shared_method (method);
- g_assert (method_to_compile);
- } else {
+ if (method_is_gshared) {
method_to_compile = method;
+ } else {
+ if (try_generic_shared) {
+ method_to_compile = mini_get_shared_method (method);
+ g_assert (method_to_compile);
+ } else {
+ method_to_compile = method;
+ }
}
cfg = g_new0 (MonoCompile, 1);
cfg->explicit_null_checks = debug_options.explicit_null_checks;
cfg->soft_breakpoints = debug_options.soft_breakpoints;
if (try_generic_shared)
- cfg->generic_sharing_context = (MonoGenericSharingContext*)&cfg->generic_sharing_context;
+ cfg->generic_sharing_context = (MonoGenericSharingContext*)&cfg->gsctx;
cfg->compile_llvm = try_llvm;
cfg->token_info_hash = g_hash_table_new (NULL, NULL);
if (cfg->gen_seq_points)
cfg->seq_points = g_ptr_array_new ();
- if (cfg->compile_aot && !try_generic_shared && (method->is_generic || method->klass->generic_container)) {
+ if (cfg->compile_aot && !try_generic_shared && (method->is_generic || method->klass->generic_container || method_is_gshared)) {
cfg->exception_type = MONO_EXCEPTION_GENERIC_SHARING_FAILED;
return cfg;
}
+ if (cfg->generic_sharing_context && (mini_is_gsharedvt_sharable_method (method) || method_is_gshared)) {
+ MonoMethodInflated *inflated;
+ MonoGenericContext *context;
+
+ // FIXME: Free the contents of gsctx if compilation fails
+ if (method_is_gshared) {
+ g_assert (method->is_inflated);
+ inflated = (MonoMethodInflated*)method;
+ context = &inflated->context;
+
+ /* We are compiling a gsharedvt method directly */
+ g_assert (compile_aot);
+ } else {
+ g_assert (method_to_compile->is_inflated);
+ inflated = (MonoMethodInflated*)method_to_compile;
+ context = &inflated->context;
+ }
+
+ mini_init_gsctx (context, &cfg->gsctx);
+
+ cfg->gsharedvt = TRUE;
+ // FIXME:
+ cfg->disable_llvm = TRUE;
+ }
+
if (cfg->generic_sharing_context) {
method_to_register = method_to_compile;
} else {
cfg->exception_type = MONO_EXCEPTION_TYPE_LOAD;
cfg->exception_message = g_strdup (mono_error_get_message (&err));
mono_error_cleanup (&err);
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
return cfg;
}
cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
cfg->exception_message = g_strdup_printf ("Missing or incorrect header for method %s", cfg->method->name);
}
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
return cfg;
}
if (cfg->verbose_level > 0) {
char *method_name;
+
+ method_name = mono_method_full_name (method, TRUE);
+ g_print ("converting %s%s%smethod %s\n", COMPILE_LLVM (cfg) ? "llvm " : "", cfg->gsharedvt ? "gsharedvt " : "", (cfg->generic_sharing_context && !cfg->gsharedvt) ? "gshared " : "", method_name);
+ /*
if (COMPILE_LLVM (cfg))
g_print ("converting llvm method %s\n", method_name = mono_method_full_name (method, TRUE));
+ else if (cfg->gsharedvt)
+ g_print ("converting gsharedvt method %s\n", method_name = mono_method_full_name (method_to_compile, TRUE));
else if (cfg->generic_sharing_context)
g_print ("converting shared method %s\n", method_name = mono_method_full_name (method_to_compile, TRUE));
else
g_print ("converting method %s\n", method_name = mono_method_full_name (method, TRUE));
+ */
g_free (method_name);
}
if (i < 0) {
if (try_generic_shared && cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
if (compile_aot) {
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
return cfg;
}
}
g_assert (cfg->exception_type != MONO_EXCEPTION_GENERIC_SHARING_FAILED);
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
/* cfg contains the details of the failure, so let the caller cleanup */
return cfg;
/* after method_to_ir */
if (parts == 1) {
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
return cfg;
}
/* after SSA translation */
if (parts == 2) {
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
return cfg;
}
/* after SSA removal */
if (parts == 3) {
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
return cfg;
}
mono_domain_unlock (cfg->domain);
}
+#if 0
+ if (cfg->gsharedvt)
+ printf ("GSHAREDVT: %s\n", mono_method_full_name (cfg->method, TRUE));
+#endif
+
/* collect statistics */
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->jit_methods++;
mono_perfcounters->jit_bytes += header->code_size;
+#endif
mono_jit_stats.allocated_code_size += cfg->code_len;
code_size_ratio = cfg->code_len;
if (code_size_ratio > mono_jit_stats.biggest_method_size && mono_jit_stats.enabled) {
}
mono_jit_stats.native_code_size += cfg->code_len;
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
return cfg;
if (ji)
return ji;
- if (!mono_method_is_generic_sharable_impl (method, FALSE))
+ if (!mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, TRUE))
return NULL;
return mono_domain_lookup_shared_generic (domain, method);
}
return NULL;
}
+ if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
+ WrapperInfo *info = mono_marshal_get_wrapper_info (method);
+
+ if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN || info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT) {
+ static MonoTrampInfo *in_tinfo, *out_tinfo;
+ MonoTrampInfo *tinfo;
+ MonoJitInfo *jinfo;
+ gboolean is_in = info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN;
+
+ if (is_in && in_tinfo)
+ return in_tinfo->code;
+ else if (!is_in && out_tinfo)
+ return out_tinfo->code;
+
+ /*
+ * This is a special wrapper whose body is implemented in assembly, like a trampoline. We use a wrapper so EH
+ * works.
+ * FIXME: The caller signature doesn't match the callee, which might cause problems on some platforms
+ */
+ if (mono_aot_only)
+ mono_aot_get_trampoline_full (is_in ? "gsharedvt_trampoline" : "gsharedvt_out_trampoline", &tinfo);
+ else
+ mono_arch_get_gsharedvt_trampoline (&tinfo, FALSE);
+ jinfo = create_jit_info_for_trampoline (method, tinfo);
+ mono_jit_info_table_add (mono_get_root_domain (), jinfo);
+ if (is_in)
+ in_tinfo = tinfo;
+ else
+ out_tinfo = tinfo;
+ return tinfo->code;
+ }
+ }
+
if (mono_aot_only) {
char *fullname = mono_method_full_name (method, TRUE);
- char *msg = g_strdup_printf ("Attempting to JIT compile method '%s' while running with --aot-only.\n", fullname);
+ char *msg = g_strdup_printf ("Attempting to JIT compile method '%s' while running with --aot-only. See http://docs.xamarin.com/ios/about/limitations for more information.\n", fullname);
*jit_ex = mono_get_exception_execution_engine (msg);
g_free (fullname);
mono_domain_jit_code_hash_unlock (target_domain);
code = cfg->native_code;
- if (cfg->generic_sharing_context && mono_method_is_generic_sharable_impl (method, FALSE))
+ if (cfg->generic_sharing_context && mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, TRUE))
mono_stats.generics_shared_methods++;
+ if (cfg->gsharedvt)
+ mono_stats.gsharedvt_methods++;
} else {
mono_domain_jit_code_hash_unlock (target_domain);
}
else
target_domain = domain;
+ if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
+ WrapperInfo *info = mono_marshal_get_wrapper_info (method);
+
+ g_assert (info);
+ if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER)
+ method = info->d.synchronized_inner.method;
+ }
+
info = lookup_method (target_domain, method);
if (info) {
/* We can't use a domain specific method in another domain */
invalidated_delegate_trampoline (char *desc)
{
g_error ("Unmanaged code called delegate of type %s which was already garbage collected.\n"
- "See http://www.go-mono.com/delegate.html for an explanation and ways to fix this.",
+ "See http://www.mono-project.com/Diagnostic:Delegate for an explanation and ways to fix this.",
desc);
}
#endif
}
}
- if (mono_method_needs_static_rgctx_invoke (method, FALSE))
- info->compiled_method = mono_create_static_rgctx_trampoline (method, info->compiled_method);
+ info->compiled_method = mini_add_method_trampoline (NULL, method, info->compiled_method, NULL, mono_method_needs_static_rgctx_invoke (method, FALSE));
}
/*
g_hash_table_destroy (info->runtime_invoke_hash);
g_hash_table_destroy (info->seq_points);
g_hash_table_destroy (info->arch_seq_points);
-
if (info->agent_info)
mono_debugger_agent_free_domain_info (domain);
+ if (info->gsharedvt_arg_tramp_hash)
+ g_hash_table_destroy (info->gsharedvt_arg_tramp_hash);
g_free (domain->runtime_info);
domain->runtime_info = NULL;
MonoRuntimeCallbacks callbacks;
MonoThreadInfoRuntimeCallbacks ticallbacks;
- MONO_PROBE_VES_INIT_BEGIN ();
+ MONO_VES_INIT_BEGIN ();
#if defined(__linux__) && !defined(__native_client__)
if (access ("/proc/self/maps", F_OK) != 0) {
if (!default_opt_set)
default_opt = mono_parse_default_optimizations (NULL);
+#ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
+ if (mono_aot_only)
+ mono_set_generic_sharing_vt_supported (TRUE);
+#endif
+
InitializeCriticalSection (&jit_mutex);
#ifdef MONO_DEBUGGER_SUPPORTED
g_thread_init (NULL);
mono_native_tls_alloc (&mono_jit_tls_id, NULL);
- setup_jit_tls_data ((gpointer)-1, mono_thread_abort);
if (default_opt & MONO_OPT_AOT)
mono_aot_init ();
if (mono_aot_only) {
/* This helps catch code allocation requests */
mono_code_manager_set_read_only (domain->code_mp);
+ mono_marshal_use_aot_wrappers (TRUE);
}
#ifdef MONO_ARCH_HAVE_IMT
mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers",
mono_runtime_install_handlers);
+#ifdef PLATFORM_ANDROID
+ mono_add_internal_call ("System.Diagnostics.Debugger::Mono_UnhandledException_internal",
+ mono_debugger_agent_unhandled_exception);
+#endif
+
+#ifndef DISABLE_JIT
mono_create_helper_signatures ();
+#endif
register_jit_stats ();
register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
register_icall (mono_get_lmf_addr, "mono_get_lmf_addr", "ptr", TRUE);
- register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "void", TRUE);
+ register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "ptr ptr", TRUE);
+ register_icall (mono_jit_set_domain, "mono_jit_set_domain", "void ptr", TRUE);
register_icall (mono_domain_get, "mono_domain_get", "ptr", TRUE);
register_icall (mono_get_throw_exception (), "mono_arch_throw_exception", "void object", TRUE);
register_icall (mono_array_new_1, "mono_array_new_1", "object ptr int", FALSE);
register_icall (mono_array_new_2, "mono_array_new_2", "object ptr int int", FALSE);
register_icall (mono_array_new_3, "mono_array_new_3", "object ptr int int int", FALSE);
+ register_icall (mono_array_new_4, "mono_array_new_4", "object ptr int int int int", FALSE);
register_icall (mono_get_native_calli_wrapper, "mono_get_native_calli_wrapper", "ptr ptr ptr ptr", FALSE);
register_icall (mono_resume_unwind, "mono_resume_unwind", "void", TRUE);
+ register_icall (mono_object_tostring_gsharedvt, "mono_object_tostring_gsharedvt", "object ptr ptr ptr", TRUE);
+ register_icall (mono_object_gethashcode_gsharedvt, "mono_object_gethashcode_gsharedvt", "int ptr ptr ptr", TRUE);
register_icall (mono_gc_wbarrier_value_copy_bitmap, "mono_gc_wbarrier_value_copy_bitmap", "void ptr ptr int int", FALSE);
mono_profiler_runtime_initialized ();
- MONO_PROBE_VES_INIT_END ();
+ MONO_VES_INIT_END ();
return domain;
}
g_print ("Sharable generic methods: %ld\n", mono_stats.generics_sharable_methods);
g_print ("Unsharable generic methods: %ld\n", mono_stats.generics_unsharable_methods);
g_print ("Shared generic methods: %ld\n", mono_stats.generics_shared_methods);
+ g_print ("Shared vtype generic methods: %ld\n", mono_stats.gsharedvt_methods);
g_print ("Dynamic code allocs: %ld\n", mono_stats.dynamic_code_alloc_count);
g_print ("Dynamic code bytes: %ld\n", mono_stats.dynamic_code_bytes_count);
g_print ("JIT info table lookups: %ld\n", mono_stats.jit_info_table_lookup_count);
g_print ("Hazardous pointers: %ld\n", mono_stats.hazardous_pointer_count);
- g_print ("Minor GC collections: %ld\n", mono_stats.minor_gc_count);
- g_print ("Major GC collections: %ld\n", mono_stats.major_gc_count);
- g_print ("Minor GC time in msecs: %lf\n", (double)mono_stats.minor_gc_time_usecs / 1000.0);
- g_print ("Major GC time in msecs: %lf\n", (double)mono_stats.major_gc_time_usecs / 1000.0);
if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
g_print ("\nDecl security check : %ld\n", mono_jit_stats.cas_declsec_check);
g_print ("LinkDemand (user) : %ld\n", mono_jit_stats.cas_linkdemand);
mono_set_defaults (int verbose_level, guint32 opts)
{
mini_verbose = verbose_level;
- default_opt = opts;
- default_opt_set = TRUE;
+ mono_set_optimizations (opts);
}
void
{
default_opt = opts;
default_opt_set = TRUE;
+#ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
+ mono_set_generic_sharing_vt_supported (mono_aot_only || ((default_opt & MONO_OPT_GSHAREDVT) != 0));
+#endif
}
void
mini_verbose = level;
}
-/*
+/**
* mono_get_runtime_build_info:
*
- * Return the runtime version + build date in string format.
- * The returned string is owned by the caller.
+ * Return the runtime version + build date in string format.
+ * The returned string is owned by the caller. The returned string
+ * format is "VERSION (FULL_VERSION BUILD_DATE)" and build date is optional.
*/
char*
mono_get_runtime_build_info (void)
}
#endif
+
+/* Dummy versions of some arch specific functions to avoid ifdefs at call sites */
+
+#ifndef MONO_ARCH_GSHAREDVT_SUPPORTED
+
+gboolean
+mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig)
+{
+ return FALSE;
+}
+
+gpointer
+mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, MonoGenericSharingContext *gsctx, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+gpointer
+mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+gpointer
+mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+#endif
+
+#ifdef DISABLE_JIT
+
+gpointer
+mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+gpointer
+mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+#endif
+
+#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED) && !defined(MONOTOUCH) && !defined(MONO_EXTENSIONS)
+
+gboolean
+mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig)
+{
+ return FALSE;
+}
+
+gpointer
+mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, MonoGenericSharingContext *gsctx, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
+{
+ NOT_IMPLEMENTED;
+ return NULL;
+}
+
+#endif