gboolean plt_inited;
guint8 *mem_begin;
guint8 *mem_end;
+ /* Points to either the start of JIT compiler or LLVM compiled code */
guint8 *code;
- guint8 *code_end;
+ guint8 *jit_code_start;
+ guint8 *jit_code_end;
+ guint8 *llvm_code_start;
+ guint8 *llvm_code_end;
guint8 *plt;
guint8 *plt_end;
guint8 *blob;
static void
init_plt (MonoAotModule *info);
+static void
+compute_llvm_code_range (MonoAotModule *amodule, guint8 **code_start, guint8 **code_end);
+
/*****************************************************/
/* AOT RUNTIME */
/*****************************************************/
break;
}
case MONO_WRAPPER_UNKNOWN: {
- MonoMethodDesc *desc;
- MonoMethod *orig_method;
int subtype = decode_value (p, &p);
if (subtype == WRAPPER_SUBTYPE_PTR_TO_STRUCTURE || subtype == WRAPPER_SUBTYPE_STRUCTURE_TO_PTR) {
} else if (subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT) {
ref->method = mono_marshal_get_gsharedvt_out_wrapper ();
} else {
- if (subtype == WRAPPER_SUBTYPE_FAST_MONITOR_ENTER)
- desc = mono_method_desc_new ("Monitor:Enter", FALSE);
- else if (subtype == WRAPPER_SUBTYPE_FAST_MONITOR_EXIT)
- desc = mono_method_desc_new ("Monitor:Exit", FALSE);
- else if (subtype == WRAPPER_SUBTYPE_FAST_MONITOR_ENTER_V4)
- desc = mono_method_desc_new ("Monitor:Enter(object,bool&)", FALSE);
- else
- g_assert_not_reached ();
- orig_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
- g_assert (orig_method);
- mono_method_desc_free (desc);
- ref->method = mono_monitor_get_fast_path (orig_method);
+ g_assert_not_reached ();
}
break;
}
if (!image)
return FALSE;
} else if (image_index == MONO_AOT_METHODREF_GINST) {
+ MonoError error;
MonoClass *klass;
MonoGenericContext ctx;
ctx.class_inst = klass->generic_class->context.class_inst;
ctx.method_inst = NULL;
- ref->method = mono_class_inflate_generic_method_full (ref->method, klass, &ctx);
+ ref->method = mono_class_inflate_generic_method_full_checked (ref->method, klass, &ctx, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
}
memset (&ctx, 0, sizeof (ctx));
if (!decode_generic_context (module, &ctx, p, &p))
return FALSE;
- ref->method = mono_class_inflate_generic_method_full (ref->method, klass, &ctx);
+ ref->method = mono_class_inflate_generic_method_full_checked (ref->method, klass, &ctx, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
} else if (image_index == MONO_AOT_METHODREF_ARRAY) {
MonoClass *klass;
int method_type;
return usable;
}
-/* This returns an interop address */
-static void*
-get_arm_bl_target (guint32 *ins_addr)
-{
-#ifdef TARGET_ARM
- guint32 ins = *ins_addr;
- gint32 offset;
-
- if ((ins >> ARMCOND_SHIFT) == ARMCOND_NV) {
- /* blx */
- offset = (((int)(((ins & 0xffffff) << 1) | ((ins >> 24) & 0x1))) << 7) >> 7;
- return (char*)ins_addr + (offset * 2) + 8 + 1;
- } else {
- offset = (((int)ins & 0xffffff) << 8) >> 8;
- return (char*)ins_addr + (offset * 4) + 8;
- }
-#elif defined(TARGET_ARM64)
- return mono_arch_get_call_target (((guint8*)ins_addr) + 4);
-#else
- g_assert_not_reached ();
- return NULL;
-#endif
-}
-
/*
* TABLE should point to a table of call instructions. Return the address called by the INDEXth entry.
*/
/* Mask out thumb interop bit */
amodule->code = (void*)((mgreg_t)amodule->code & ~1);
#endif
- amodule->code_end = info->methods_end;
+ amodule->jit_code_start = info->jit_code_start;
+ amodule->jit_code_end = info->jit_code_end;
amodule->method_info_offsets = info->method_info_offsets;
amodule->ex_info_offsets = info->ex_info_offsets;
amodule->class_info_offsets = info->class_info_offsets;
amodule->code_offsets [i] = 0xffffffff;
else
amodule->code_offsets [i] = (char*)addr - (char*)amodule->code;
- /*
- * FIXME: When using a separate llvm object file,
- * need to add separate symbols to denote the beginning and
- * end of llvm compiled code.
- */
- // FIXME: Update both code and code_end
- // FIXME: Last method
- if ((guint8*)addr > (guint8*)amodule->code_end)
- amodule->code_end = addr;
}
if (make_unreadable) {
#endif
}
+ /* Compute the boundaries of LLVM code */
+ if (info->flags & MONO_AOT_FILE_FLAG_WITH_LLVM)
+ compute_llvm_code_range (amodule, &amodule->llvm_code_start, &amodule->llvm_code_end);
+
mono_aot_lock ();
- aot_code_low_addr = MIN (aot_code_low_addr, (gsize)amodule->code);
- aot_code_high_addr = MAX (aot_code_high_addr, (gsize)amodule->code_end);
+ aot_code_low_addr = MIN (aot_code_low_addr, (gsize)amodule->jit_code_start);
+ aot_code_high_addr = MAX (aot_code_high_addr, (gsize)amodule->jit_code_end);
+ if (amodule->llvm_code_start) {
+ aot_code_low_addr = MIN (aot_code_low_addr, (gsize)amodule->llvm_code_start);
+ aot_code_high_addr = MAX (aot_code_high_addr, (gsize)amodule->llvm_code_end);
+ }
g_hash_table_insert (aot_modules, assembly, amodule);
mono_aot_unlock ();
- mono_jit_info_add_aot_module (assembly->image, amodule->code, amodule->code_end);
+ mono_jit_info_add_aot_module (assembly->image, amodule->jit_code_start, amodule->jit_code_end);
+ if (amodule->llvm_code_start)
+ mono_jit_info_add_aot_module (assembly->image, amodule->llvm_code_start, amodule->llvm_code_end);
assembly->image->aot_module = amodule;
return TRUE;
}
+/* Compute the boundaries of the LLVM code for AMODULE. */
+static void
+compute_llvm_code_range (MonoAotModule *amodule, guint8 **code_start, guint8 **code_end)
+{
+ guint8 *p;
+ int version, fde_count;
+ gint32 *table;
+
+ g_assert (amodule->mono_eh_frame);
+
+ p = amodule->mono_eh_frame;
+
+ /* p points to data emitted by LLVM in DwarfException::EmitMonoEHFrame () */
+
+ /* Header */
+ version = *p;
+ g_assert (version == 3);
+ p ++;
+ p ++;
+ p = ALIGN_PTR_TO (p, 4);
+
+ fde_count = *(guint32*)p;
+ p += 4;
+ table = (gint32*)p;
+
+ if (fde_count) {
+ g_assert (fde_count != 1);
+ g_assert (table [0] == -1);
+ *code_start = amodule->code + amodule->code_offsets [table [2]];
+ *code_end = amodule->code + amodule->code_offsets [table [(fde_count - 1) * 2]] + table [fde_count * 2];
+ }
+}
+
/*
* decode_mono_eh_frame:
*
g_assert (table [(pos * 2)] != -1);
offset1 = amodule->code_offsets [table [(pos * 2)]];
if (pos + 1 == fde_count) {
- offset2 = amodule->code_end - amodule->code;
+ offset2 = amodule->llvm_code_end - amodule->llvm_code_start;
} else {
g_assert (table [(pos + 1) * 2] != -1);
offset2 = amodule->code_offsets [table [(pos + 1) * 2]];
return jinfo;
}
+static gboolean
+amodule_contains_code_addr (MonoAotModule *amodule, guint8 *code)
+{
+ return (code >= amodule->jit_code_start && code <= amodule->jit_code_end) ||
+ (code >= amodule->llvm_code_start && code <= amodule->llvm_code_end);
+}
+
/*
* mono_aot_get_unwind_info:
*
g_assert (amodule);
g_assert (ji->from_aot);
- if (!(code >= amodule->code && code <= amodule->code_end)) {
+ if (!amodule_contains_code_addr (amodule, code)) {
/* ji belongs to a different aot module than amodule */
mono_aot_lock ();
g_assert (ji_to_amodule);
amodule = g_hash_table_lookup (ji_to_amodule, ji);
g_assert (amodule);
- g_assert (code >= amodule->code && code <= amodule->code_end);
+ g_assert (amodule_contains_code_addr (amodule, code));
mono_aot_unlock ();
}
/* FIXME: */
return NULL;
+ if (!amodule_contains_code_addr (amodule, addr))
+ return NULL;
+
async = mono_thread_info_is_async_context ();
offset = (guint8*)addr - amodule->code;
code_offsets = amodule->sorted_code_offsets;
offsets_len = amodule->sorted_code_offsets_len;
- if (offsets_len > 0 && (offset < code_offsets [0] || offset >= (amodule->code_end - amodule->code)))
- return NULL;
-
/* Binary search in the sorted_code_offsets table */
left = 0;
right = offsets_len;
offset1 = code_offsets [(pos * 2)];
if (pos + 1 == offsets_len)
- offset2 = amodule->code_end - amodule->code;
+ offset2 = amodule->jit_code_end - amodule->code;
else
offset2 = code_offsets [(pos + 1) * 2];
ex_info = &amodule->blob [mono_aot_get_offset (amodule->ex_info_offsets, method_index)];
if (pos == offsets_len - 1)
- code_len = amodule->code_end - code;
+ code_len = amodule->jit_code_end - code;
else
code_len = code_offsets [(pos + 1) * 2] - code_offsets [pos * 2];
case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
case MONO_PATCH_INFO_MONITOR_ENTER:
+ case MONO_PATCH_INFO_MONITOR_ENTER_V4:
case MONO_PATCH_INFO_MONITOR_EXIT:
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
case MONO_PATCH_INFO_JIT_TLS_ID:
* 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 (m, &ctx), TRUE, TRUE);
+ m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, &error), TRUE, TRUE);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
/*
* Get the code for the <object> instantiation which should be emitted into
((!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Interlocked") && (!strcmp (method->name, "CompareExchange") || !strcmp (method->name, "Exchange")) && MONO_TYPE_IS_REFERENCE (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 (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 (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 (m, &ctx), TRUE, TRUE);
+ m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, &error), TRUE, TRUE);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
/* Avoid recursion */
if (method == m)
FindAotModuleUserData *data = (FindAotModuleUserData*)user_data;
MonoAotModule *aot_module = (MonoAotModule*)value;
- if ((data->addr >= (guint8*)(aot_module->code)) && (data->addr < (guint8*)(aot_module->code_end)))
+ if (amodule_contains_code_addr (aot_module, data->addr))
data->module = aot_module;
}
} else if (!strcmp (ji->data.name, "specific_trampoline_monitor_enter")) {
target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER, mono_get_root_domain (), NULL);
target = mono_create_ftnptr_malloc (target);
+ } else if (!strcmp (ji->data.name, "specific_trampoline_monitor_enter_v4")) {
+ target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER_V4, mono_get_root_domain (), NULL);
+ target = mono_create_ftnptr_malloc (target);
} else if (!strcmp (ji->data.name, "specific_trampoline_monitor_exit")) {
target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_EXIT, mono_get_root_domain (), NULL);
target = mono_create_ftnptr_malloc (target);
MonoAotModule *amodule;
gpointer code;
guint32 *ut, *ut_end, *entry;
- int low, high, entry_index;
+ int low, high, entry_index = 0;
if (method->is_inflated && !mono_method_is_generic_sharable_full (method, FALSE, FALSE, FALSE)) {
method_index = find_extra_method (method, &amodule);