#include <mono/metadata/tokentype.h>
#include <mono/metadata/loader.h>
#include <mono/metadata/threads.h>
-#include <mono/metadata/threadpool-ms.h>
+#include <mono/metadata/threadpool.h>
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/reflection.h>
#include <mono/metadata/mono-debug.h>
#include "interp.h"
+#include "interp-internals.h"
#include "mintops.h"
-#include "embed.h"
#include "hacks.h"
-#define OPDEF(a,b,c,d,e,f,g,h,i,j) \
- a = i,
+#include <mono/mini/mini.h>
+#include <mono/mini/jit-icalls.h>
-enum {
-#include "mono/cil/opcode.def"
- CEE_LASTOP
-};
-#undef OPDEF
/* Mingw 2.1 doesnt need this any more, but leave it in for now for older versions */
#ifdef _WIN32
#endif
#endif
-static gint *abort_requested;
-
-/* If true, then we output the opcodes as we interpret them */
-static int global_tracing = 1;
-static int global_no_pointers = 0;
-
-int mono_interp_traceopt = 0;
-
-static int debug_indent_level = 0;
-
-#define INIT_FRAME(frame,parent_frame,obj_this,method_args,method_retval,domain,mono_method,error) \
+#define INIT_FRAME(frame,parent_frame,method_args,method_retval,domain,mono_method,error) \
do { \
(frame)->parent = (parent_frame); \
- (frame)->obj = (obj_this); \
(frame)->stack_args = (method_args); \
(frame)->retval = (method_retval); \
(frame)->runtime_method = mono_interp_get_runtime_method ((domain), (mono_method), (error)); \
#define DEBUG_INTERP 0
#define COUNT_OPS 0
#if DEBUG_INTERP
+int mono_interp_traceopt = 2;
+/* If true, then we output the opcodes as we interpret them */
+static int global_tracing = 2;
+
+static int debug_indent_level = 0;
static int break_on_method = 0;
static int nested_trace = 0;
debug_indent_level++;
output_indent ();
mn = mono_method_full_name (method, FALSE);
- g_printerr ("(0x%08x) Entering %s (", mono_thread_internal_current (), mn);
+ g_print ("(%p) Entering %s (", mono_thread_internal_current (), mn);
g_free (mn);
- g_printerr ("%s)\n", args);
+ g_print ("%s)\n", args);
g_free (args);
}
if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE)
args = dump_retval (frame); \
output_indent (); \
mn = mono_method_full_name (frame->runtime_method->method, FALSE); \
- g_printerr ("(0x%08x) Leaving %s", mono_thread_internal_current (), mn); \
+ g_print ("(%p) Leaving %s", mono_thread_internal_current (), mn); \
g_free (mn); \
- g_printerr (" => %s\n", args); \
+ g_print (" => %s\n", args); \
g_free (args); \
debug_indent_level--; \
if (tracing == 3) global_tracing = 0; \
#else
+int mono_interp_traceopt = 0;
static void debug_enter (MonoInvocation *frame, int *tracing)
{
}
THROW_EX (mono_get_exception_execution_engine (NULL), ip); \
} while (0);
-static gpointer
-interp_create_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target, MonoError *error)
-{
- g_error ("FIXME: use domain and error");
- // return mono_interp_get_runtime_method (mono_marshal_get_remoting_invoke_for_target (method, target));
-}
-
static mono_mutex_t runtime_method_lookup_section;
RuntimeMethod*
mono_interp_get_runtime_method (MonoDomain *domain, MonoMethod *method, MonoError *error)
{
RuntimeMethod *rtm;
- mono_error_init (error);
+ error_init (error);
mono_os_mutex_lock (&runtime_method_lookup_section);
if ((rtm = mono_internal_hash_table_lookup (&domain->jit_code_hash, method))) {
if ((m->flags & METHOD_ATTRIBUTE_FINAL) || !(m->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
RuntimeMethod *ret = NULL;
- if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
+ if (mono_object_is_transparent_proxy (obj)) {
ret = mono_interp_get_runtime_method (domain, mono_marshal_get_remoting_invoke (m), &error);
- else if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
+ mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+ } else if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
ret = mono_interp_get_runtime_method (domain, mono_marshal_get_synchronized_wrapper (m), &error);
- else
+ mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+ } else {
ret = runtime_method;
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+ }
return ret;
}
- if (m->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
- // return ((RuntimeMethod **)obj->vtable->interface_offsets [m->klass->interface_id]) [m->slot];
- g_error ("FIXME: interface method lookup");
- return NULL;
- } else {
- return ((RuntimeMethod **)obj->vtable->vtable) [m->slot];
+ mono_class_setup_vtable (obj->vtable->klass);
+
+ int slot = mono_method_get_vtable_slot (m);
+ if (mono_class_is_interface (m->klass)) {
+ g_assert (obj->vtable->klass != m->klass);
+ /* TODO: interface offset lookup is slow, go through IMT instead */
+ slot += mono_class_interface_offset (obj->vtable->klass, m->klass);
}
+ MonoMethod *virtual_method = obj->vtable->klass->vtable [slot];
+ RuntimeMethod *virtual_runtime_method = mono_interp_get_runtime_method (domain, virtual_method, &error);
+ mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+ return virtual_runtime_method;
}
static void inline
if (type->data.klass->enumtype) {
stackval_from_data (mono_class_enum_basetype (type->data.klass), result, data, pinvoke);
return;
- } else {
- int size;
-
- if (pinvoke)
- size = mono_class_native_size (type->data.klass, NULL);
- else
- size = mono_class_value_size (type->data.klass, NULL);
- memcpy (result->data.vt, data, size);
- }
+ } else
+ mono_value_copy (result->data.vt, data, type->data.klass);
+ return;
+ case MONO_TYPE_GENERICINST:
+ stackval_from_data (&type->data.generic_class->container_class->byval_arg, result, data, pinvoke);
return;
default:
g_warning ("got type 0x%02x", type->type);
if (type->data.klass->enumtype) {
stackval_to_data (mono_class_enum_basetype (type->data.klass), val, data, pinvoke);
return;
- } else {
- int size;
-
- if (pinvoke)
- size = mono_class_native_size (type->data.klass, NULL);
- else
- size = mono_class_value_size (type->data.klass, NULL);
-
- memcpy (data, val->data.p, size);
- }
+ } else
+ mono_value_copy (data, val->data.vt, type->data.klass);
+ return;
+ case MONO_TYPE_GENERICINST:
+ stackval_to_data (&type->data.generic_class->container_class->byval_arg, val, data, pinvoke);
return;
default:
g_warning ("got type %x", type->type);
gpointer ea;
MonoType *mt;
- o = frame->obj;
+ o = frame->stack_args->data.p;
ao = (MonoArray *)o;
ac = o->vtable->klass;
return;
}
-#if 0 /* FIX */
- if (sp [ac->rank].data.p && !mono_object_isinst (sp [ac->rank].data.p, mono_object_class (o)->element_class)) {
- frame->ex = mono_get_exception_array_type_mismatch ();
- FILL_IN_TRACE (frame->ex, frame);
- return;
+ if (sp [ac->rank].data.p && !mono_object_class (o)->element_class->valuetype) {
+ MonoError error;
+ MonoObject *isinst = mono_object_isinst_checked (sp [ac->rank].data.p, mono_object_class (o)->element_class, &error);
+ mono_error_cleanup (&error);
+ if (!isinst) {
+ frame->ex = mono_get_exception_array_type_mismatch ();
+ FILL_IN_TRACE (frame->ex, frame);
+ return;
+ }
}
-#endif
esize = mono_array_element_size (ac);
ea = mono_array_addr_with_size (ao, esize, pos);
gpointer ea;
MonoType *mt;
- o = frame->obj;
+ o = frame->stack_args->data.p;
ao = (MonoArray *)o;
ac = o->vtable->klass;
gint32 i, t, pos, esize;
gpointer ea;
- o = frame->obj;
+ o = frame->stack_args->data.p;
ao = (MonoArray *)o;
ac = o->vtable->klass;
}
}
+static MonoPIFunc mono_interp_enter_icall_trampoline = NULL;
+
+struct _MethodArguments {
+ size_t ilen;
+ gpointer *iargs;
+ size_t flen;
+ gpointer *fargs;
+ gpointer *retval;
+};
+
+typedef struct _MethodArguments MethodArguments;
+
+// TODO: this function is also arch dependent (register width).
+static MethodArguments* build_args_from_sig (MonoMethodSignature *sig, MonoInvocation *frame)
+{
+ // TODO: don't malloc this data structure.
+ MethodArguments *margs = g_malloc0 (sizeof (MethodArguments));
+
+ if (sig->hasthis)
+ margs->ilen++;
+
+ for (int i = 0; i < sig->param_count; i++) {
+ guint32 ptype = sig->params [i]->byref ? MONO_TYPE_PTR : sig->params [i]->type;
+ switch (ptype) {
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_I8:
+ case MONO_TYPE_VALUETYPE:
+ margs->ilen++;
+ break;
+ default:
+ g_error ("build_args_from_sig: not implemented yet (1): 0x%x\n", ptype);
+ }
+ }
+
+ if (margs->ilen > 0)
+ margs->iargs = g_malloc0 (sizeof (gpointer) * margs->ilen);
+
+ if (margs->ilen > 6)
+ g_error ("build_args_from_sig: TODO, more than 6 iregs: %d\n", margs->ilen);
+
+ if (margs->flen > 0)
+ g_error ("build_args_from_sig: TODO, allocate floats: %d\n", margs->flen);
+
+
+ size_t int_i = 0;
+
+ if (sig->hasthis) {
+ margs->iargs [0] = frame->stack_args->data.p;
+ int_i++;
+ }
+
+ for (int i = 0; i < sig->param_count; i++) {
+ guint32 ptype = sig->params [i]->byref ? MONO_TYPE_PTR : sig->params [i]->type;
+ switch (ptype) {
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_I8:
+ case MONO_TYPE_VALUETYPE:
+ 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;
+ default:
+ g_error ("build_args_from_sig: not implemented yet (2): 0x%x\n", ptype);
+ }
+ }
+
+ if (sig->ret->type != MONO_TYPE_VOID) {
+ margs->retval = &(frame->retval->data.p);
+ } else {
+ margs->retval = NULL;
+ }
+
+ return margs;
+}
+
static void
ves_pinvoke_method (MonoInvocation *frame, MonoMethodSignature *sig, MonoFuncV addr, gboolean string_ctor, ThreadContext *context)
{
jmp_buf env;
- MonoPIFunc func;
MonoInvocation *old_frame = context->current_frame;
MonoInvocation *old_env_frame = context->env_frame;
jmp_buf *old_env = context->current_env;
context->env_frame = frame;
context->current_env = &env;
- if (frame->runtime_method) {
- func = frame->runtime_method->func;
- } else {
- g_error ("FIXME: not available?");
-#if 0
- func = mono_arch_create_trampoline (sig, string_ctor);
-#endif
+ g_assert (!frame->runtime_method);
+ if (!mono_interp_enter_icall_trampoline) {
+ MonoTrampInfo *info;
+ mono_interp_enter_icall_trampoline = mono_arch_get_enter_icall_trampoline (&info);
+ // TODO:
+ // mono_tramp_info_register (info, NULL);
}
+ MethodArguments *margs = build_args_from_sig (sig, frame);
+#if DEBUG_INTERP
+ g_print ("ICALL: mono_interp_enter_icall_trampoline = %p, addr = %p\n", mono_interp_enter_icall_trampoline, addr);
+ g_print ("margs(out): ilen=%d, flen=%d\n", margs->ilen, margs->flen);
+#endif
+
context->current_frame = frame;
context->managed_code = 0;
- func (addr, &frame->retval->data.p, frame->obj, frame->stack_args);
+ mono_interp_enter_icall_trampoline (addr, margs);
context->managed_code = 1;
/* domain can only be changed by native code */
context->domain = mono_domain_get ();
- if (*abort_requested)
+ if (*mono_thread_interruption_request_flag ())
mono_thread_interruption_checkpoint ();
- if (string_ctor) {
- stackval_from_data (&mono_defaults.string_class->byval_arg, frame->retval, (char*)&frame->retval->data.p, sig->pinvoke);
- } else if (!MONO_TYPE_ISSTRUCT (sig->ret))
+ if (!MONO_TYPE_ISSTRUCT (sig->ret))
stackval_from_data (sig->ret, frame->retval, (char*)&frame->retval->data.p, sig->pinvoke);
context->current_frame = old_frame;
context->env_frame = old_env_frame;
context->current_env = old_env;
+
+ g_free (margs->iargs);
+ g_free (margs->fargs);
+ g_free (margs);
}
static void
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
delegate->target = target;
- if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
+ if (target && mono_object_is_transparent_proxy (target)) {
MonoMethod *method = mono_marshal_get_remoting_invoke (runtime_method->method);
delegate->method_ptr = mono_interp_get_runtime_method (domain, method, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
{
MonoMethod *method = frame->runtime_method->method;
const char *name = method->name;
- MonoObject *obj = (MonoObject*)frame->obj;
+ MonoObject *obj = (MonoObject*) frame->stack_args->data.p;
MonoObject *isinst_obj;
MonoError error;
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
if (obj && isinst_obj) {
if (*name == '.' && (strcmp (name, ".ctor") == 0)) {
- interp_delegate_ctor (context->domain, obj, frame->stack_args[0].data.p, frame->stack_args[1].data.p);
+ interp_delegate_ctor (context->domain, obj, frame->stack_args [1].data.p, frame->stack_args[2].data.p);
return;
}
}
return g_string_free (str, FALSE);
while (s < sp) {
- g_string_append_printf (str, "[%lld/0x%0llx] ", s->data.l, s->data.l);
+ g_string_append_printf (str, "[%p (%lld)] ", s->data.l, s->data.l);
++s;
}
return g_string_free (str, FALSE);
break;
case MONO_TYPE_I8:
case MONO_TYPE_U8:
- default:
- g_string_append_printf (str, "[%lld/0x%0llx] ", s->data.l, s->data.l);
+ default: {
+ GString *res = g_string_new ("");
+ mono_type_get_desc (res, type, TRUE);
+ g_string_append_printf (str, "[{%s} %lld/0x%0llx] ", res->str, s->data.l, s->data.l);
+ g_string_free (res, TRUE);
break;
}
+ }
}
static char*
int i;
MonoMethodSignature *signature = mono_method_signature (inv->runtime_method->method);
- if (signature->param_count == 0)
+ if (signature->param_count == 0 && !signature->hasthis)
return g_string_free (str, FALSE);
- if (signature->hasthis)
- g_string_append_printf (str, "%p ", inv->obj);
+ if (signature->hasthis) {
+ MonoMethod *method = inv->runtime_method->method;
+ dump_stackval (str, inv->stack_args, &method->klass->byval_arg);
+ }
for (i = 0; i < signature->param_count; ++i)
- dump_stackval (str, inv->stack_args + i, signature->params [i]);
+ dump_stackval (str, inv->stack_args + (!!signature->hasthis) + i, signature->params [i]);
return g_string_free (str, FALSE);
}
#define CHECK_MUL_OVERFLOW_NAT_UN(a,b) CHECK_MUL_OVERFLOW64_UN(a,b)
#endif
-static MonoObject*
-interp_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
+MonoObject*
+mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
{
MonoInvocation frame;
ThreadContext * volatile context = mono_native_tls_get_value (thread_context_id);
int i, type, isobject = 0;
void *ret = NULL;
stackval result;
- stackval *args = alloca (sizeof (stackval) * sig->param_count);
+ stackval *args = alloca (sizeof (stackval) * (sig->param_count + !!sig->hasthis));
ThreadContext context_struct;
MonoInvocation *old_frame = NULL;
jmp_buf env;
- mono_error_init (error);
+ error_init (error);
frame.ex = NULL;
break;
}
+ if (sig->hasthis)
+ args [0].data.p = obj;
+
for (i = 0; i < sig->param_count; ++i) {
+ int a_index = i + !!sig->hasthis;
if (sig->params [i]->byref) {
- args [i].data.p = params [i];
+ args [a_index].data.p = params [i];
continue;
}
type = sig->params [i]->type;
case MONO_TYPE_U1:
case MONO_TYPE_I1:
case MONO_TYPE_BOOLEAN:
- args [i].data.i = *(MonoBoolean*)params [i];
+ args [a_index].data.i = *(MonoBoolean*)params [i];
break;
case MONO_TYPE_U2:
case MONO_TYPE_I2:
case MONO_TYPE_CHAR:
- args [i].data.i = *(gint16*)params [i];
+ args [a_index].data.i = *(gint16*)params [i];
break;
#if SIZEOF_VOID_P == 4
case MONO_TYPE_U: /* use VAL_POINTER? */
#endif
case MONO_TYPE_U4:
case MONO_TYPE_I4:
- args [i].data.i = *(gint32*)params [i];
+ args [a_index].data.i = *(gint32*)params [i];
break;
#if SIZEOF_VOID_P == 8
case MONO_TYPE_U:
#endif
case MONO_TYPE_U8:
case MONO_TYPE_I8:
- args [i].data.l = *(gint64*)params [i];
+ args [a_index].data.l = *(gint64*)params [i];
break;
case MONO_TYPE_VALUETYPE:
if (sig->params [i]->data.klass->enumtype) {
type = mono_class_enum_basetype (sig->params [i]->data.klass)->type;
goto handle_enum;
} else {
- args [i].data.p = params [i];
+ args [a_index].data.p = params [i];
}
break;
case MONO_TYPE_STRING:
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_OBJECT:
- args [i].data.p = params [i];
+ args [a_index].data.p = params [i];
break;
default:
g_error ("type 0x%x not handled in runtime invoke", sig->params [i]->type);
}
}
- if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
+ if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
method = mono_marshal_get_native_wrapper (method, FALSE, FALSE);
- INIT_FRAME(&frame,context->current_frame,obj,args,&result,mono_get_root_domain (),method,error);
+ INIT_FRAME (&frame,context->current_frame,args,&result,mono_get_root_domain (),method,error);
if (exc)
frame.invoke_trap = 1;
context->managed_code = 1;
func ();
break;
}
+ case MINT_ICALL_V_P: {
+ gpointer (*func)() = ptr;
+ sp++;
+ sp [-1].data.p = func ();
+ break;
+ }
case MINT_ICALL_P_V: {
void (*func)(gpointer) = ptr;
func (sp [-1].data.p);
static GHashTable *method_pointer_hash = NULL;
+static MonoMethod *method_pointers [2] = {0};
+
+static MonoObject *
+mp_tramp_0 (MonoObject *this_obj, void **params, MonoObject **exc, void *compiled_method) {
+ MonoError error;
+ void *params_real[] = {this_obj, ¶ms, &exc, &compiled_method};
+ MonoObject *ret = mono_interp_runtime_invoke (method_pointers [0], NULL, params_real, NULL, &error);
+ mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+ return ret;
+}
+
+static MonoObject *
+mp_tramp_1 (MonoObject *this_obj, void **params, MonoObject **exc, void *compiled_method) {
+ MonoError error;
+ void *params_real[] = {this_obj, ¶ms, &exc, &compiled_method};
+ MonoObject *ret = mono_interp_runtime_invoke (method_pointers [1], NULL, params_real, NULL, &error);
+ mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+ return ret;
+}
+
+gpointer *mp_tramps[] = {(gpointer) mp_tramp_0, (gpointer) mp_tramp_1};
+
+static int tramps_used = 0;
+
gpointer
-mono_create_method_pointer (MonoMethod *method, MonoError *error)
+mono_interp_create_method_pointer (MonoMethod *method, MonoError *error)
{
gpointer addr;
MonoJitInfo *ji;
- mono_error_init (error);
mono_os_mutex_lock (&create_method_pointer_mutex);
if (!method_pointer_hash) {
mono_jit_info_table_add (mono_get_root_domain (), ji);
}
else {
- g_error ("FIXME: not available? figure out new API");
-#if 0
- addr = mono_arch_create_method_pointer (method);
-#endif
+ g_assert (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE);
+ g_assert (tramps_used < 2);
+
+ /* FIXME: needs locking */
+ method_pointers [tramps_used] = method;
+ addr = mp_tramps [tramps_used];
+ tramps_used++;
}
g_hash_table_insert (method_pointer_hash, method, addr);
} \
sp->data.l = 0; \
output_indent (); \
- g_print ("(%u) ", mono_thread_internal_current ()); \
+ char *mn = mono_method_full_name (frame->runtime_method->method, FALSE); \
+ g_print ("(%p) %s -> ", mono_thread_internal_current (), mn); \
+ g_free (mn); \
mono_interp_dis_mintop(rtm->code, ip); \
g_print ("\t%d:%s\n", vt_sp - vtalloc, ins); \
g_free (ins); \
if (!frame->runtime_method->transformed) {
context->managed_code = 0;
+#if DEBUG_INTERP
+ char *mn = mono_method_full_name (frame->runtime_method->method, FALSE);
+ g_print ("(%p) Transforming %s\n", mono_thread_internal_current (), mn);
+ g_free (mn);
+#endif
frame->ex = mono_interp_transform_method (frame->runtime_method, context);
context->managed_code = 1;
if (frame->ex) {
vt_sp -= READ32(ip + 2);
if (ret_size > 0) {
memmove (vt_sp, ret_vt_sp, ret_size);
+ sp [-1].data.p = vt_sp;
vt_sp += (ret_size + 7) & ~7;
}
ip += 4;
child_frame.retval = sp;
/* decrement by the actual number of args */
sp -= csignature->param_count;
- child_frame.stack_args = sp;
- if (csignature->hasthis) {
+ if (csignature->hasthis)
--sp;
- child_frame.obj = sp->data.p;
- } else {
- child_frame.obj = NULL;
- }
- if (csignature->hasthis && ((MonoObject *)child_frame.obj)->vtable->klass == mono_defaults.transparent_proxy_class) {
+ child_frame.stack_args = sp;
+
+ /* `this' can be NULL for string:.ctor */
+ if (csignature->hasthis && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
} else if (child_frame.runtime_method->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
child_frame.retval = sp;
/* decrement by the actual number of args */
sp -= csignature->param_count;
- child_frame.stack_args = sp;
- if (csignature->hasthis) {
+ if (csignature->hasthis)
--sp;
- child_frame.obj = sp->data.p;
- } else {
- child_frame.obj = NULL;
- }
+ child_frame.stack_args = sp;
ves_pinvoke_method (&child_frame, csignature, (MonoFuncV) code, FALSE, context);
context->current_frame = frame;
child_frame.retval = sp;
/* decrement by the actual number of args */
sp -= child_frame.runtime_method->param_count;
- child_frame.stack_args = sp;
- if (child_frame.runtime_method->hasthis) {
+ if (child_frame.runtime_method->hasthis)
--sp;
- child_frame.obj = sp->data.p;
- } else {
- child_frame.obj = NULL;
- }
- if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype && ((MonoObject *)child_frame.obj)->vtable->klass == mono_defaults.transparent_proxy_class) {
+ child_frame.stack_args = sp;
+
+ /* `this' can be NULL for string:.ctor */
+ if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
}
child_frame.retval = sp;
/* decrement by the actual number of args */
sp -= child_frame.runtime_method->param_count;
- child_frame.stack_args = sp;
- if (child_frame.runtime_method->hasthis) {
+ if (child_frame.runtime_method->hasthis)
--sp;
- child_frame.obj = sp->data.p;
- } else {
- child_frame.obj = NULL;
- }
+ child_frame.stack_args = sp;
- if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype && ((MonoObject *)child_frame.obj)->vtable->klass == mono_defaults.transparent_proxy_class) {
+ if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype && mono_object_is_transparent_proxy (sp->data.p)) {
child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
}
child_frame.retval = sp;
/* decrement by the actual number of args */
- sp -= child_frame.runtime_method->param_count;
+ sp -= child_frame.runtime_method->param_count + 1;
child_frame.stack_args = sp;
- --sp;
- child_frame.obj = this_arg = sp->data.p;
+ this_arg = sp->data.p;
if (!this_arg)
THROW_EX (mono_get_exception_null_reference(), ip - 2);
child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
if (this_arg->vtable->klass->valuetype && child_frame.runtime_method->valuetype) {
- child_frame.obj = (char *)this_arg + sizeof(MonoObject);
+ /* unbox */
+ gpointer *unboxed = mono_object_unbox (this_arg);
+ stackval_from_data (&this_arg->vtable->klass->byval_arg, sp, (char *) unboxed, FALSE);
}
ves_exec_method_with_context (&child_frame, context);
child_frame.retval = sp;
/* decrement by the actual number of args */
- sp -= child_frame.runtime_method->param_count;
+ sp -= child_frame.runtime_method->param_count + 1;
child_frame.stack_args = sp;
- --sp;
- child_frame.obj = this_arg = sp->data.p;
+ this_arg = sp->data.p;
if (!this_arg)
THROW_EX (mono_get_exception_null_reference(), ip - 2);
child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
if (this_arg->vtable->klass->valuetype && child_frame.runtime_method->valuetype) {
- child_frame.obj = (char *)this_arg + sizeof(MonoObject);
+ gpointer *unboxed = mono_object_unbox (this_arg);
+ stackval_from_data (&this_arg->vtable->klass->byval_arg, sp, (char *) unboxed, FALSE);
}
ves_exec_method_with_context (&child_frame, context);
}
MINT_IN_BREAK;
}
- MINT_IN_CASE(MINT_CALLINT)
- ves_pinvoke_method (frame, mono_method_signature (frame->runtime_method->method), ((MonoMethodPInvoke*) frame->runtime_method->method)->addr,
- frame->runtime_method->method->string_ctor, context);
- if (frame->ex) {
- rtm = NULL;
- goto handle_exception;
- }
- goto exit_frame;
MINT_IN_CASE(MINT_CALLRUN)
ves_runtime_method (frame, context);
if (frame->ex) {
++ip;
sp[-1].data.l = *(gint64*)sp[-1].data.p;
MINT_IN_BREAK;
- MINT_IN_CASE(MINT_LDIND_I)
- ++ip;
- sp[-1].data.p = *(gpointer*)sp[-1].data.p;
+ MINT_IN_CASE(MINT_LDIND_I) {
+ guint16 offset = * (guint16 *)(ip + 1);
+ sp[-1 - offset].data.p = *(gpointer*)sp[-1 - offset].data.p;
+ ip += 2;
MINT_IN_BREAK;
+ }
MINT_IN_CASE(MINT_LDIND_R4)
++ip;
sp[-1].data.f = *(gfloat*)sp[-1].data.p;
g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count));
}*/
-
if (newobj_class->parent == mono_defaults.array_class) {
sp -= csig->param_count;
o = ves_array_create (context->domain, newobj_class, csig, sp);
goto array_constructed;
}
+ g_assert (csig->hasthis);
+ if (csig->param_count) {
+ sp -= csig->param_count;
+ memmove (sp + 1, sp, csig->param_count * sizeof (stackval));
+ }
+ child_frame.stack_args = sp;
+
/*
* First arg is the object.
*/
if (newobj_class->valuetype) {
- if (!newobj_class->enumtype && (newobj_class->byval_arg.type == MONO_TYPE_VALUETYPE)) {
- child_frame.obj = vt_sp;
+ MonoType *t = &newobj_class->byval_arg;
+ if (!newobj_class->enumtype && (t->type == MONO_TYPE_VALUETYPE || (t->type == MONO_TYPE_GENERICINST && mono_type_generic_inst_is_valuetype (t)))) {
+ sp->data.p = vt_sp;
valuetype_this.data.p = vt_sp;
} else {
memset (&valuetype_this, 0, sizeof (stackval));
- child_frame.obj = &valuetype_this;
+ sp->data.p = &valuetype_this;
}
} else {
if (newobj_class != mono_defaults.string_class) {
o = mono_object_new_checked (context->domain, newobj_class, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
context->managed_code = 1;
- if (*abort_requested)
+ if (*mono_thread_interruption_request_flag ())
mono_thread_interruption_checkpoint ();
- child_frame.obj = o;
+ sp->data.p = o;
} else {
+ sp->data.p = NULL;
child_frame.retval = &retval;
}
}
- if (csig->param_count) {
- sp -= csig->param_count;
- child_frame.stack_args = sp;
- } else {
- child_frame.stack_args = NULL;
- }
-
g_assert (csig->call_convention == MONO_CALL_DEFAULT);
child_frame.ip = NULL;
MINT_IN_CASE(MINT_CASTCLASS)
c = rtm->data_items [*(guint16 *)(ip + 1)];
if ((o = sp [-1].data.p)) {
- if (c->marshalbyref) {
- MonoObject *isinst_obj = mono_object_isinst_mbyref_checked (o, c, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- if (!isinst_obj)
- THROW_EX (mono_get_exception_invalid_cast (), ip);
- } else {
- MonoVTable *vt = o->vtable;
- MonoClass *oklass = vt->klass;
- if (c->flags & TYPE_ATTRIBUTE_INTERFACE) {
- g_error ("FIXME: interface method lookup");
- if (c->interface_id > vt->max_interface_id /* || vt->interface_offsets [c->interface_id] == 0 */) {
- THROW_EX (mono_get_exception_invalid_cast (), ip);
- }
- } else if (c->rank) {
- MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- if (!isinst_obj)
- THROW_EX (mono_get_exception_invalid_cast (), ip);
- } else if (!mono_class_has_parent (oklass, c)) {
- THROW_EX (mono_get_exception_invalid_cast (), ip);
- }
- }
+ MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
+ mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+ if (!isinst_obj)
+ THROW_EX (mono_get_exception_invalid_cast (), ip);
}
ip += 2;
MINT_IN_BREAK;
MINT_IN_CASE(MINT_ISINST)
c = rtm->data_items [*(guint16 *)(ip + 1)];
if ((o = sp [-1].data.p)) {
- if (c->marshalbyref) {
- MonoObject *isinst_obj = mono_object_isinst_mbyref_checked (o, c, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- if (!isinst_obj)
- sp [-1].data.p = NULL;
- } else {
- MonoVTable *vt = o->vtable;
- MonoClass *oklass = vt->klass;
- if (c->flags & TYPE_ATTRIBUTE_INTERFACE) {
- g_error ("FIXME: interface method lookup");
- if (c->interface_id > vt->max_interface_id /* || vt->interface_offsets [c->interface_id] == 0 */) {
- sp [-1].data.p = NULL;
- }
- } else if (c->rank) {
- MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- if (!isinst_obj)
- sp [-1].data.p = NULL;
- } else if (!mono_class_has_parent (oklass, c)) {
- sp [-1].data.p = NULL;
- }
- }
+ MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
+ mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+ if (!isinst_obj)
+ sp [-1].data.p = NULL;
}
ip += 2;
MINT_IN_BREAK;
o = sp [-1].data.p;
if (!o)
- THROW_EX (mono_get_exception_null_reference(), ip);
+ THROW_EX (mono_get_exception_null_reference (), ip);
MonoObject *isinst_obj = mono_object_isinst_checked (o, c, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- if (!(isinst_obj ||
- ((o->vtable->klass->rank == 0) &&
- (o->vtable->klass->element_class == c->element_class))))
+ if (!(isinst_obj || ((o->vtable->klass->rank == 0) && (o->vtable->klass->element_class == c->element_class))))
THROW_EX (mono_get_exception_invalid_cast (), ip);
- sp [-1].data.p = (char *)o + sizeof (MonoObject);
+ if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
+ int size = mono_class_native_size (c, NULL);
+ sp [-1].data.p = vt_sp;
+ vt_sp += (size + 7) & ~7;
+ }
+ stackval_from_data (&c->byval_arg, &sp [-1], mono_object_unbox (o), FALSE);
ip += 2;
MINT_IN_BREAK;
MINT_IN_CASE(MINT_THROW)
THROW_EX (mono_get_exception_null_reference (), ip);
field = rtm->data_items[* (guint16 *)(ip + 1)];
ip += 2;
- if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
+ if (mono_object_is_transparent_proxy (o)) {
MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
field = rtm->data_items[* (guint16 *)(ip + 1)];
i32 = READ32(ip + 2);
ip += 4;
- if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
+ if (mono_object_is_transparent_proxy (o)) {
MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
field = rtm->data_items[* (guint16 *)(ip + 1)];
ip += 2;
- if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
+ if (mono_object_is_transparent_proxy (o)) {
MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
i32 = READ32(ip + 2);
ip += 4;
- if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
+ if (mono_object_is_transparent_proxy (o)) {
MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
}
MINT_IN_CASE(MINT_LDSFLDA) {
MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
- MonoVTable *vt = mono_class_vtable (context->domain, field->parent);
- gpointer addr;
-
- if (!vt->initialized) {
- frame->ip = ip;
- mono_runtime_class_init_full (vt, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- }
+ sp->data.p = mono_class_static_field_address (context->domain, field);
ip += 2;
-
- if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
- sp->data.p = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
- else
- sp->data.p = (char*)(vt->vtable) + field->offset;
++sp;
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_LDSFLD) {
- MonoVTable *vt;
- MonoClassField *field;
- gpointer addr;
-
- field = rtm->data_items[*(guint16 *)(ip + 1)];
- vt = rtm->data_items [*(guint16 *)(ip + 2)];
- if (!vt->initialized) {
- frame->ip = ip;
- mono_runtime_class_init_full (vt, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- }
- ip += 3;
- if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
- addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
- else
- addr = (char*)(vt->vtable) + field->offset;
-
+ MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
+ gpointer addr = mono_class_static_field_address (context->domain, field);
stackval_from_data (field->type, sp, addr, FALSE);
- ++sp;
- MINT_IN_BREAK;
- }
- MINT_IN_CASE(MINT_LDSFLD_I4) {
- MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
- MonoVTable *vt = rtm->data_items [*(guint16 *)(ip + 2)];
- if (!vt->initialized) {
- frame->ip = ip;
- mono_runtime_class_init_full (vt, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- }
- ip += 3;
- sp->data.i = * (gint32 *)((char*)(vt->vtable) + field->offset);
- ++sp;
- MINT_IN_BREAK;
- }
- MINT_IN_CASE(MINT_LDSFLD_O) {
- MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
- MonoVTable *vt = rtm->data_items [*(guint16 *)(ip + 2)];
- if (!vt->initialized) {
- frame->ip = ip;
- mono_runtime_class_init_full (vt, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- }
- ip += 3;
- sp->data.p = * (gpointer *)((char*)(vt->vtable) + field->offset);
+ ip += 2;
++sp;
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_LDSFLD_VT) {
- MonoVTable *vt;
- MonoClassField *field;
- guint32 token;
- gpointer addr;
- int size;
-
- token = * (guint16 *)(ip + 1);
- size = READ32(ip + 2);
- field = rtm->data_items[token];
+ MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
+ gpointer addr = mono_class_static_field_address (context->domain, field);
+ int size = READ32 (ip + 2);
ip += 4;
-
- vt = mono_class_vtable (context->domain, field->parent);
- if (!vt->initialized) {
- frame->ip = ip - 2;
- mono_runtime_class_init_full (vt, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- }
-
- if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
- addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
- else
- addr = (char*)(vt->vtable) + field->offset;
sp->data.p = vt_sp;
vt_sp += (size + 7) & ~7;
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_STSFLD) {
- MonoVTable *vt;
- MonoClassField *field;
- guint32 token;
- gpointer addr;
-
- token = * (guint16 *)(ip + 1);
- field = rtm->data_items[token];
+ MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
+ gpointer addr = mono_class_static_field_address (context->domain, field);
ip += 2;
--sp;
-
- vt = mono_class_vtable (context->domain, field->parent);
- if (!vt->initialized) {
- frame->ip = ip - 2;
- mono_runtime_class_init_full (vt, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- }
-
- if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
- addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
- else
- addr = (char*)(vt->vtable) + field->offset;
-
stackval_to_data (field->type, sp, addr, FALSE);
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_STSFLD_VT) {
- MonoVTable *vt;
- MonoClassField *field;
- guint32 token;
- gpointer addr;
- int size;
-
- token = * (guint16 *)(ip + 1);
- size = READ32(ip + 2);
- field = rtm->data_items[token];
+ MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
+ gpointer addr = mono_class_static_field_address (context->domain, field);
+ int size = READ32 (ip + 2);
ip += 4;
-
- vt = mono_class_vtable (context->domain, field->parent);
- if (!vt->initialized) {
- frame->ip = ip - 2;
- mono_runtime_class_init_full (vt, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- }
-
- if (context->domain->special_static_fields && (addr = g_hash_table_lookup (context->domain->special_static_fields, field)))
- addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
- else
- addr = (char*)(vt->vtable) + field->offset;
+
--sp;
stackval_to_data (field->type, sp, addr, FALSE);
vt_sp -= (size + 7) & ~7;
sp [-1].data.i = (mono_u)sp [-1].data.l;
++ip;
MINT_IN_BREAK;
- MINT_IN_CASE(MINT_BOX)
+ MINT_IN_CASE(MINT_BOX) {
c = rtm->data_items [* (guint16 *)(ip + 1)];
+ guint16 offset = * (guint16 *)(ip + 2);
if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
int size = mono_class_value_size (c, NULL);
- sp [-1].data.p = mono_value_box_checked (context->domain, c, sp [-1].data.p, &error);
+ sp [-1 - offset].data.p = mono_value_box_checked (context->domain, c, sp [-1 - offset].data.p, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
size = (size + 7) & ~7;
vt_sp -= size;
- }
- else {
- stackval_to_data (&c->byval_arg, &sp [-1], (char*)&sp [-1], FALSE);
- sp [-1].data.p = mono_value_box_checked (context->domain, c, &sp [-1], &error);
+ } else {
+ stackval_to_data (&c->byval_arg, &sp [-1 - offset], (char *) &sp [-1 - offset], FALSE);
+ sp [-1 - offset].data.p = mono_value_box_checked (context->domain, c, &sp [-1 - offset], &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
}
- ip += 2;
+ ip += 3;
MINT_IN_BREAK;
+ }
MINT_IN_CASE(MINT_NEWARR)
sp [-1].data.p = (MonoObject*) mono_array_new_checked (context->domain, rtm->data_items[*(guint16 *)(ip + 1)], sp [-1].data.i, &error);
mono_error_cleanup (&error); /* FIXME: don't swallow the error */
MINT_IN_CASE(MINT_LDELEM_I) /* fall through */
MINT_IN_CASE(MINT_LDELEM_R4) /* fall through */
MINT_IN_CASE(MINT_LDELEM_R8) /* fall through */
- MINT_IN_CASE(MINT_LDELEM_REF) {
+ MINT_IN_CASE(MINT_LDELEM_REF) /* fall through */
+ MINT_IN_CASE(MINT_LDELEM_VT) {
MonoArray *o;
mono_u aindex;
case MINT_LDELEM_REF:
sp [0].data.p = mono_array_get (o, gpointer, aindex);
break;
+ case MINT_LDELEM_VT: {
+ MonoClass *klass_vt = rtm->data_items [*(guint16 *) (ip + 1)];
+ i32 = READ32 (ip + 2);
+ char *src_addr = mono_array_addr_with_size ((MonoArray *) o, i32, aindex);
+ sp [0].data.vt = vt_sp;
+ stackval_from_data (&klass_vt->byval_arg, sp, src_addr, FALSE);
+ vt_sp += (i32 + 7) & ~7;
+ ip += 3;
+ break;
+ }
default:
ves_abort();
}
MINT_IN_CASE(MINT_STELEM_I8) /* fall through */
MINT_IN_CASE(MINT_STELEM_R4) /* fall through */
MINT_IN_CASE(MINT_STELEM_R8) /* fall through */
- MINT_IN_CASE(MINT_STELEM_REF) {
+ MINT_IN_CASE(MINT_STELEM_REF) /* fall through */
+ MINT_IN_CASE(MINT_STELEM_VT) {
mono_u aindex;
sp -= 3;
if (sp [2].data.p && !isinst_obj)
THROW_EX (mono_get_exception_array_type_mismatch (), ip);
mono_array_set ((MonoArray *)o, gpointer, aindex, sp [2].data.p);
- } break;
+ break;
+ }
+ case MINT_STELEM_VT: {
+ MonoClass *klass_vt = rtm->data_items [*(guint16 *) (ip + 1)];
+ i32 = READ32 (ip + 2);
+ char *dst_addr = mono_array_addr_with_size ((MonoArray *) o, i32, aindex);
+
+ stackval_to_data (&klass_vt->byval_arg, &sp [2], dst_addr, FALSE);
+ vt_sp -= (i32 + 7) & ~7;
+ ip += 3;
+ break;
+ }
default:
ves_abort();
}
goto handle_finally;
MINT_IN_BREAK;
MINT_IN_CASE(MINT_ICALL_V_V)
+ MINT_IN_CASE(MINT_ICALL_V_P)
MINT_IN_CASE(MINT_ICALL_P_V)
MINT_IN_CASE(MINT_ICALL_P_P)
MINT_IN_CASE(MINT_ICALL_PP_V)
MINT_IN_BREAK;
}
- MINT_IN_CASE(MINT_LDTHIS)
- sp->data.p = frame->obj;
- ++ip;
- ++sp;
- MINT_IN_BREAK;
- MINT_IN_CASE(MINT_STTHIS)
- --sp;
- frame->obj = sp->data.p;
- ++ip;
- MINT_IN_BREAK;
MINT_IN_CASE(MINT_LDTHISA)
- sp->data.p = &frame->obj;
+ g_error ("should not happen");
+ // sp->data.p = &frame->obj;
++ip;
++sp;
MINT_IN_BREAK;
g_error ("No entry point method found in %s", mono_image_get_filename (image));
rval = mono_runtime_run_main_checked (method, argc, argv, &error);
- return_val_and_set_pending_if_nok (&error, rval);
+ mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+ return rval;
}
static void
exit (1);
}
-static void
-add_signal_handler (int signo, void (*handler)(int))
-{
-#ifdef HOST_WIN32
- signal (signo, handler);
-#else
- struct sigaction sa;
-
- sa.sa_handler = handler;
- sigemptyset (&sa.sa_mask);
- sa.sa_flags = 0;
-
- g_assert (sigaction (signo, &sa, NULL) != -1);
-#endif
-}
-
-static void
-segv_handler (int signum)
-{
- ThreadContext *context = mono_native_tls_get_value (thread_context_id);
- MonoException *segv_exception;
-
- if (context == NULL)
- return;
- segv_exception = mono_get_exception_null_reference ();
- segv_exception->message = mono_string_new (mono_domain_get (), "Null Reference (SIGSEGV)");
- mono_raise_exception (segv_exception);
-}
-
-
-static void
-quit_handler (int signum)
-{
- ThreadContext *context = mono_native_tls_get_value (thread_context_id);
- MonoException *quit_exception;
-
- if (context == NULL)
- return;
- quit_exception = mono_get_exception_execution_engine ("Interrupted (SIGQUIT).");
- mono_raise_exception (quit_exception);
-}
-
-static void
-abrt_handler (int signum)
-{
- ThreadContext *context = mono_native_tls_get_value (thread_context_id);
- MonoException *abrt_exception;
-
- if (context == NULL)
- return;
- abrt_exception = mono_get_exception_execution_engine ("Abort (SIGABRT).");
- mono_raise_exception (abrt_exception);
-}
-
-#if 0
-static void
-thread_abort_handler (int signum)
-{
- ThreadContext *context = mono_native_tls_get_value (thread_context_id);
- MonoException *exc;
-
- if (context == NULL)
- return;
-
- exc = mono_thread_request_interruption (context->managed_code);
- if (exc) mono_raise_exception (exc);
-}
-#endif
-
static MonoBoolean
-ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
+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)
}
static MonoArray *
-ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
+interp_ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
{
MonoDomain *domain = mono_domain_get ();
MonoArray *res;
return delegate;
}
-
-typedef struct
-{
- MonoDomain *domain;
- int enable_debugging;
- char *file;
- int argc;
- char **argv;
-} MainThreadArgs;
-
-static void main_thread_handler (gpointer user_data)
-{
- MainThreadArgs *main_args=(MainThreadArgs *)user_data;
- MonoAssembly *assembly;
-
- if (main_args->enable_debugging) {
- mono_debug_init (MONO_DEBUG_FORMAT_MONO);
- }
-
- assembly = mono_domain_assembly_open (main_args->domain, main_args->file);
-
- if (!assembly){
- fprintf (stderr, "Can not open image %s\n", main_args->file);
- exit (1);
- }
-
- ves_exec (main_args->domain, assembly, main_args->argc, main_args->argv);
-}
-
-static void
-mono_runtime_install_handlers (void)
-{
- add_signal_handler (SIGSEGV, segv_handler);
- add_signal_handler (SIGINT, quit_handler);
- add_signal_handler (SIGABRT, abrt_handler);
-#if 0
- add_signal_handler (mono_thread_get_abort_signal (), thread_abort_handler);
-#endif
-}
-
-static void
-quit_function (MonoDomain *domain, gpointer user_data)
-{
- mono_profiler_shutdown ();
-
- mono_runtime_cleanup (domain);
- mono_domain_free (domain, TRUE);
-
-}
-
void
-mono_interp_cleanup(MonoDomain *domain)
-{
- quit_function (domain, NULL);
-}
-
-int
-mono_interp_exec(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
-{
- return ves_exec (domain, assembly, argc, argv);
-}
-
-gpointer*
-interp_get_imt_trampoline (MonoVTable *vtable, int imt_slot_index)
+mono_interp_init ()
{
- // FIXME: implement me
- return NULL;
-}
-
-static gpointer
-interp_create_ftnptr (MonoDomain *domain, gpointer addr)
-{
- // FIXME: true on all arch?
- return addr;
-}
-
-MonoDomain *
-mono_interp_init(const char *file)
-{
- MonoDomain *domain;
- MonoRuntimeCallbacks callbacks;
- MonoRuntimeExceptionHandlingCallbacks ecallbacks;
- MonoError error;
-
- g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
- g_log_set_fatal_mask (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR);
-
mono_native_tls_alloc (&thread_context_id, NULL);
mono_native_tls_set_value (thread_context_id, NULL);
mono_os_mutex_init_recursive (&runtime_method_lookup_section);
mono_os_mutex_init_recursive (&create_method_pointer_mutex);
- // TODO: use callbacks?
- mono_runtime_install_handlers ();
mono_interp_transform_init ();
-
- memset (&callbacks, 0, sizeof (callbacks));
- // TODO: replace with `mono_install_callbacks`
- callbacks.compile_method = mono_create_method_pointer;
- callbacks.runtime_invoke = interp_mono_runtime_invoke;
- callbacks.get_imt_trampoline = interp_get_imt_trampoline;
- callbacks.create_ftnptr = interp_create_ftnptr;
-#ifndef DISABLE_REMOTING
- mono_install_remoting_trampoline (interp_create_remoting_trampoline);
-#endif
- callbacks.create_jit_trampoline = interp_create_trampoline;
- mono_install_callbacks (&callbacks);
-
-
- memset (&ecallbacks, 0, sizeof (ecallbacks));
- ecallbacks.mono_raise_exception = interp_ex_handler;
-#if 0
- // FIXME: ...
- mono_install_stack_walk (interp_walk_stack);
-#endif
- mono_install_eh_callbacks (&ecallbacks);
-
- mono_install_runtime_cleanup (quit_function);
-
- abort_requested = mono_thread_interruption_request_flag ();
-
- domain = mono_init_from_assembly (file, file);
-#ifdef __hpux /* generates very big stack frames */
- mono_threads_set_default_stacksize(32*1024*1024);
-#endif
- mono_icall_init ();
- mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info", ves_icall_get_frame_info);
- mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace", ves_icall_get_trace);
- mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers", mono_runtime_install_handlers);
- mono_add_internal_call ("System.Delegate::CreateDelegate_internal", ves_icall_System_Delegate_CreateDelegate_internal);
-
- mono_register_jit_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", mono_create_icall_signature ("void"), FALSE);
-
- mono_runtime_init_checked (domain, NULL, NULL, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
-
- mono_thread_attach (domain);
- return domain;
}
typedef int (*TestMethod) (void);
interp_regression_step (MonoImage *image, int verbose, int *total_run, int *total, GTimer *timer, MonoDomain *domain)
{
int result, expected, failed, cfailed, run;
- TestMethod func;
- double elapsed, transform_time, start_time;
+ double elapsed, transform_time;
int i;
MonoObject *result_obj;
+ static gboolean filter_method_init = FALSE;
+ static const char *filter_method = NULL;
g_print ("Test run: image=%s\n", mono_image_get_filename (image));
cfailed = failed = run = 0;
g_timer_start (timer);
for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
+ MonoObject *exc = NULL;
MonoError error;
MonoMethod *method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
if (!method) {
mono_error_cleanup (&error); /* FIXME don't swallow the error */
continue;
}
- if (strncmp (method->name, "test_", 5) == 0) {
+
+ if (!filter_method_init) {
+ filter_method = g_getenv ("INTERP_FILTER_METHOD");
+ filter_method_init = TRUE;
+ }
+ gboolean filter = FALSE;
+ if (filter_method) {
+ const char *name = filter_method;
+
+ if ((strchr (name, '.') > name) || strchr (name, ':')) {
+ MonoMethodDesc *desc = mono_method_desc_new (name, TRUE);
+ filter = mono_method_desc_full_match (desc, method);
+ mono_method_desc_free (desc);
+ } else {
+ filter = strcmp (method->name, name) == 0;
+ }
+ } else { /* no filter, check for `Category' attribute on method */
+ filter = TRUE;
+ MonoCustomAttrInfo* ainfo = mono_custom_attrs_from_method_checked (method, &error);
+ mono_error_cleanup (&error);
+
+ if (ainfo) {
+ int j;
+ for (j = 0; j < ainfo->num_attrs && filter; ++j) {
+ MonoCustomAttrEntry *centry = &ainfo->attrs [j];
+ if (centry->ctor == NULL)
+ continue;
+
+ MonoClass *klass = centry->ctor->klass;
+ if (strcmp (klass->name, "CategoryAttribute"))
+ continue;
+
+ MonoObject *obj = mono_custom_attrs_get_attr_checked (ainfo, klass, &error);
+ /* FIXME: there is an ordering problem if there're multiple attributes, do this instead:
+ * MonoObject *obj = create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, &error); */
+ mono_error_cleanup (&error);
+ MonoMethod *getter = mono_class_get_method_from_name (klass, "get_Category", -1);
+ MonoObject *str = mono_interp_runtime_invoke (getter, obj, NULL, &exc, &error);
+ mono_error_cleanup (&error);
+ char *utf8_str = mono_string_to_utf8_checked ((MonoString *) str, &error);
+ mono_error_cleanup (&error);
+ if (!strcmp (utf8_str, "!INTERPRETER")) {
+ g_print ("skip %s...\n", method->name);
+ filter = FALSE;
+ }
+ }
+ }
+ }
+ if (strncmp (method->name, "test_", 5) == 0 && filter) {
MonoError interp_error;
- RuntimeMethod *runtime_method;
- MonoInvocation frame;
- ThreadContext context;
- stackval frame_result;
+ MonoObject *exc = NULL;
- result_obj = interp_mono_runtime_invoke (method, NULL, NULL, NULL, &interp_error);
+ result_obj = mono_interp_runtime_invoke (method, NULL, NULL, &exc, &interp_error);
if (!mono_error_ok (&interp_error)) {
cfailed++;
g_print ("Test '%s' execution failed.\n", method->name);
+ } else if (exc != NULL) {
+ g_print ("Exception in Test '%s' occured:\n", method->name);
+ mono_object_describe (exc);
+ run++;
+ failed++;
} else {
result = *(gint32 *) mono_object_unbox (result_obj);
expected = atoi (method->name + 5); // FIXME: oh no.
interp_regression (MonoImage *image, int verbose, int *total_run)
{
MonoMethod *method;
- char *n;
GTimer *timer = g_timer_new ();
MonoDomain *domain = mono_domain_get ();
- guint32 i, exclude = 0;
+ guint32 i;
int total;
/* load the metadata */
}
int
-interp_regression_list (int verbose, int count, char *images [])
+mono_interp_regression_list (int verbose, int count, char *images [])
{
int i, total, total_run, run;