#include <mono/mini/mini.h>
#include <mono/mini/jit-icalls.h>
+#ifdef TARGET_ARM
+#include <mono/mini/mini-arm.h>
+#endif
/* Mingw 2.1 doesnt need this any more, but leave it in for now for older versions */
#ifdef _WIN32
void ves_exec_method (MonoInvocation *frame);
-static char* dump_stack (stackval *stack, stackval *sp);
static char* dump_frame (MonoInvocation *inv);
static MonoArray *get_trace_ips (MonoDomain *domain, MonoInvocation *top);
static void ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, unsigned short *start_with_ip, MonoException *filter_exception, int exit_at_finally);
goto main_loop; \
} while (0)
-static void
-interp_ex_handler (MonoException *ex) {
- MonoError error;
- ThreadContext *context = mono_native_tls_get_value (thread_context_id);
- char *stack_trace;
- if (context == NULL)
- return;
- stack_trace = dump_frame (context->current_frame);
- ex->stack_trace = mono_string_new_checked (mono_domain_get(), stack_trace, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- g_free (stack_trace);
- if (context->current_env == NULL || strcmp(ex->object.vtable->klass->name, "ExecutionEngineException") == 0) {
- char *strace = mono_string_to_utf8_checked (ex->stack_trace, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- fprintf(stderr, "Nothing can catch this exception: ");
- fprintf(stderr, "%s", ex->object.vtable->klass->name);
- if (ex->message != NULL) {
- char *m = mono_string_to_utf8_checked (ex->message, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- fprintf(stderr, ": %s", m);
- g_free(m);
- }
- fprintf(stderr, "\n%s\n", strace);
- g_free (strace);
- if (ex->inner_ex != NULL) {
- ex = (MonoException *)ex->inner_ex;
- fprintf(stderr, "Inner exception: %s", ex->object.vtable->klass->name);
- if (ex->message != NULL) {
- char *m = mono_string_to_utf8_checked (ex->message, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- fprintf(stderr, ": %s", m);
- g_free(m);
- }
- strace = mono_string_to_utf8_checked (ex->stack_trace, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- fprintf(stderr, "\n");
- fprintf(stderr, "%s\n", strace);
- g_free (strace);
- }
- /* wait for other threads to also collapse */
- // Sleep(1000); // TODO: proper sleep
- exit(1);
- }
- context->env_frame->ex = ex;
- context->search_for_handler = 1;
- longjmp (*context->current_env, 1);
-}
-
static void
ves_real_abort (int line, MonoMethod *mh,
const unsigned short *ip, stackval *stack, stackval *sp)
} else
mono_value_copy (result->data.vt, data, type->data.klass);
return;
- case MONO_TYPE_GENERICINST:
+ case MONO_TYPE_GENERICINST: {
+ if (mono_type_generic_inst_is_valuetype (type)) {
+ mono_value_copy (result->data.vt, data, mono_class_from_mono_type (type));
+ return;
+ }
stackval_from_data (&type->data.generic_class->container_class->byval_arg, result, data, pinvoke);
return;
+ }
default:
g_warning ("got type 0x%02x", type->type);
g_assert_not_reached ();
}
static gint32
-ves_array_calculate_index (MonoArray *ao, stackval *sp, MonoInvocation *frame)
+ves_array_calculate_index (MonoArray *ao, stackval *sp, MonoInvocation *frame, gboolean safe)
{
g_assert (!frame->ex);
MonoClass *ac = ((MonoObject *) ao)->vtable->klass;
guint32 idx = sp [i].data.i;
guint32 lower = ao->bounds [i].lower_bound;
guint32 len = ao->bounds [i].length;
- if (idx < lower || (idx - lower) >= len) {
+ if (safe && (idx < lower || (idx - lower) >= len)) {
frame->ex = mono_get_exception_index_out_of_range ();
FILL_IN_TRACE (frame->ex, frame);
return -1;
}
} else {
pos = sp [0].data.i;
- if (pos >= ao->max_length) {
+ if (safe && pos >= ao->max_length) {
frame->ex = mono_get_exception_index_out_of_range ();
FILL_IN_TRACE (frame->ex, frame);
return -1;
g_assert (ac->rank >= 1);
- gint32 pos = ves_array_calculate_index (ao, sp, frame);
+ gint32 pos = ves_array_calculate_index (ao, sp, frame, TRUE);
if (frame->ex)
return;
}
static void
-ves_array_get (MonoInvocation *frame)
+ves_array_get (MonoInvocation *frame, gboolean safe)
{
stackval *sp = frame->stack_args + 1;
g_assert (ac->rank >= 1);
- gint32 pos = ves_array_calculate_index (ao, sp, frame);
+ gint32 pos = ves_array_calculate_index (ao, sp, frame, safe);
if (frame->ex)
return;
g_assert (ac->rank >= 1);
- gint32 pos = ves_array_calculate_index (ao, sp, frame);
+ gint32 pos = ves_array_calculate_index (ao, sp, frame, TRUE);
if (frame->ex)
return NULL;
static MonoPIFunc mono_interp_enter_icall_trampoline = NULL;
-// TODO: this function is also arch dependent (register width).
static InterpMethodArguments* build_args_from_sig (MonoMethodSignature *sig, MonoInvocation *frame)
{
InterpMethodArguments *margs = g_malloc0 (sizeof (InterpMethodArguments));
+#ifdef TARGET_ARM
+ g_assert (mono_arm_eabi_supported ());
+#endif
+
if (sig->hasthis)
margs->ilen++;
case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
case MONO_TYPE_STRING:
- case MONO_TYPE_I8:
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_GENERICINST:
+#if SIZEOF_VOID_P == 8
+ case MONO_TYPE_I8:
+#endif
margs->ilen++;
break;
+#if SIZEOF_VOID_P == 4
+ case MONO_TYPE_I8:
+#ifdef TARGET_ARM
+ /* pairs begin at even registers */
+ if (margs->ilen & 1)
+ margs->ilen++;
+#endif
+ margs->ilen += 2;
+ break;
+#endif
case MONO_TYPE_R4:
+#if SIZEOF_VOID_P == 8
case MONO_TYPE_R8:
+#endif
margs->flen++;
break;
+#if SIZEOF_VOID_P == 4
+ case MONO_TYPE_R8:
+ margs->flen += 2;
+ break;
+#endif
default:
g_error ("build_args_from_sig: not implemented yet (1): 0x%x\n", ptype);
}
case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
case MONO_TYPE_STRING:
- case MONO_TYPE_I8:
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_GENERICINST:
+#if SIZEOF_VOID_P == 8
+ case MONO_TYPE_I8:
+#endif
margs->iargs [int_i] = frame->stack_args [i].data.p;
#if DEBUG_INTERP
g_print ("build_args_from_sig: margs->iargs [%d]: %p (frame @ %d)\n", int_i, margs->iargs [int_i], i);
#endif
int_i++;
break;
+#if SIZEOF_VOID_P == 4
+ case MONO_TYPE_I8: {
+ stackval *sarg = &frame->stack_args [i];
+#ifdef TARGET_ARM
+ /* pairs begin at even registers */
+ if (int_i & 1)
+ int_i++;
+#endif
+ margs->iargs [int_i] = (gpointer) sarg->data.pair.lo;
+ int_i++;
+ margs->iargs [int_i] = (gpointer) sarg->data.pair.hi;
+#if DEBUG_INTERP
+ g_print ("build_args_from_sig: margs->iargs [%d/%d]: 0x%016llx, hi=0x%08x lo=0x%08x (frame @ %d)\n", int_i - 1, int_i, *((guint64 *) &margs->iargs [int_i - 1]), sarg->data.pair.hi, sarg->data.pair.lo, i);
+#endif
+ int_i++;
+ break;
+ }
+#endif
case MONO_TYPE_R4:
case MONO_TYPE_R8:
if (ptype == MONO_TYPE_R4)
#if DEBUG_INTERP
g_print ("build_args_from_sig: margs->fargs [%d]: %p (%f) (frame @ %d)\n", int_f, margs->fargs [int_f], margs->fargs [int_f], i);
#endif
+#if SIZEOF_VOID_P == 4
+ int_f += 2;
+#else
int_f++;
+#endif
break;
default:
g_error ("build_args_from_sig: not implemented yet (2): 0x%x\n", ptype);
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_GENERICINST:
margs->retval = &(frame->retval->data.p);
+ margs->is_float_ret = 0;
break;
case MONO_TYPE_R4:
case MONO_TYPE_R8:
stackval_from_data (mt, frame->retval, (char *) frame->stack_args, FALSE);
return;
}
+ if (!strcmp (method->name, "UnsafeLoad")) {
+ ves_array_get (frame, FALSE);
+ return;
+ }
}
isinst_obj = mono_object_isinst_checked (obj, mono_defaults.array_class, &error);
return;
}
if (*name == 'G' && (strcmp (name, "Get") == 0)) {
- ves_array_get (frame);
+ ves_array_get (frame, TRUE);
return;
}
}
method->name);
}
+#if DEBUG_INTERP
static char*
dump_stack (stackval *stack, stackval *sp)
{
}
return g_string_free (str, FALSE);
}
+#endif
static void
dump_stackval (GString *str, stackval *s, MonoType *type)
}
}
+#if DEBUG_INTERP
+static char*
+dump_retval (MonoInvocation *inv)
+{
+ GString *str = g_string_new ("");
+ MonoType *ret = mono_method_signature (inv->runtime_method->method)->ret;
+
+ if (ret->type != MONO_TYPE_VOID)
+ dump_stackval (str, inv->retval, ret);
+
+ return g_string_free (str, FALSE);
+}
+#endif
+
static char*
dump_args (MonoInvocation *inv)
{
return g_string_free (str, FALSE);
}
-
-static char*
-dump_retval (MonoInvocation *inv)
-{
- GString *str = g_string_new ("");
- MonoType *ret = mono_method_signature (inv->runtime_method->method)->ret;
-
- if (ret->type != MONO_TYPE_VOID)
- dump_stackval (str, inv->retval, ret);
-
- return g_string_free (str, FALSE);
-}
static char*
dump_frame (MonoInvocation *inv)
switch (op) {
case MINT_ICALL_V_V: {
- void (*func)() = ptr;
+ void (*func)(void) = ptr;
func ();
break;
}
case MINT_ICALL_V_P: {
- gpointer (*func)() = ptr;
+ gpointer (*func)(void) = ptr;
sp++;
sp [-1].data.p = func ();
break;
#if DEBUG_INTERP
gint tracing = global_tracing;
unsigned char *vtalloc;
+#else
+ gint tracing = 0;
#endif
int i32;
unsigned char *vt_sp;
frame->ip = NULL;
context->current_frame = frame;
-#if DEBUG_INTERP
debug_enter (frame, &tracing);
-#endif
if (!frame->runtime_method->transformed) {
context->managed_code = 0;
context->current_frame = frame->parent;
}
-static int
-ves_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
-{
- MonoImage *image = mono_assembly_get_image (assembly);
- MonoMethod *method;
- MonoError error;
- int rval;
-
- method = mono_get_method_checked (image, mono_image_get_entry_point (image), NULL, NULL, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
-
- if (!method)
- g_error ("No entry point method found in %s", mono_image_get_filename (image));
-
- rval = mono_runtime_run_main_checked (method, argc, argv, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- return rval;
-}
-
-static void
-usage (void)
-{
- fprintf (stderr,
- "mint %s, the Mono ECMA CLI interpreter, (C) 2001, 2002 Ximian, Inc.\n\n"
- "Usage is: mint [options] executable args...\n\n", VERSION);
- fprintf (stderr,
- "Runtime Debugging:\n"
-#ifdef DEBUG_INTERP
- " --debug\n"
-#endif
- " --dieonex\n"
- " --noptr\t\t\tdon't print pointer addresses in trace output\n"
- " --opcode-count\n"
- " --print-vtable\n"
- " --traceclassinit\n"
- "\n"
- "Development:\n"
- " --debug method_name\n"
- " --profile\n"
- " --trace\n"
- " --traceops\n"
- " --regression\n"
- "\n"
- "Runtime:\n"
- " --config filename load the specified config file instead of the default\n"
- " --workers n maximum number of worker threads\n"
- );
- exit (1);
-}
-
-static MonoBoolean
-interp_ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
- MonoReflectionMethod **method,
- gint32 *iloffset, gint32 *native_offset,
- MonoString **file, gint32 *line, gint32 *column)
-{
- ThreadContext *context = mono_native_tls_get_value (thread_context_id);
- MonoInvocation *inv = context->current_frame;
- MonoError error;
- int i;
-
- for (i = 0; inv && i < skip; inv = inv->parent)
- if (inv->runtime_method != NULL)
- ++i;
-
- if (iloffset)
- *iloffset = 0;
- if (native_offset)
- *native_offset = 0;
- if (method) {
- if (inv == NULL) {
- *method = NULL;
- } else {
- *method = mono_method_get_object_checked (context->domain, inv->runtime_method->method, NULL, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- }
- }
- if (line)
- *line = 0;
- if (need_file_info) {
- if (column)
- *column = 0;
- if (file) {
- *file = mono_string_new_checked (mono_domain_get (), "unknown", &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- }
- }
-
- return TRUE;
-}
-
-static MonoArray *
-interp_ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
-{
- MonoDomain *domain = mono_domain_get ();
- MonoArray *res;
- MonoArray *ta = exc->trace_ips;
- MonoError error;
- int i, len;
-
- if (ta == NULL) {
- /* Exception is not thrown yet */
- MonoArray *array = mono_array_new_checked (domain, mono_defaults.stack_frame_class, 0, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- return array;
- }
-
- len = mono_array_length (ta);
-
- res = mono_array_new_checked (domain, mono_defaults.stack_frame_class, len > skip ? len - skip : 0, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
-
- for (i = skip; i < len / 2; i++) {
- MonoStackFrame *sf = (MonoStackFrame *)mono_object_new_checked (domain, mono_defaults.stack_frame_class, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- gushort *ip = mono_array_get (ta, gpointer, 2 * i + 1);
- RuntimeMethod *rtm = mono_array_get (ta, gpointer, 2 * i);
-
- if (rtm != NULL) {
- sf->method = mono_method_get_object_checked (domain, rtm->method, NULL, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- sf->native_offset = ip - rtm->code;
- }
-
-#if 0
- sf->il_offset = mono_debug_il_offset_from_address (ji->method, sf->native_offset, domain);
-
- if (need_file_info) {
- gchar *filename;
-
- filename = mono_debug_source_location_from_address (ji->method, sf->native_offset, &sf->line, domain);
-
- sf->filename = NULL;
- if (filename) {
- sf->filename = mono_string_new_checked (domain, filename, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- }
- sf->column = 0;
-
- g_free (filename);
- }
-#endif
-
- mono_array_set (res, gpointer, i, sf);
- }
-
- return res;
-}
-
void
mono_interp_parse_options (const char *options)
{