#include <glib.h>
#include <setjmp.h>
#include <signal.h>
+#include <math.h>
+#include <locale.h>
#include <mono/os/gc_wrapper.h>
#include <mono/metadata/cil-coff.h>
#include <mono/metadata/mono-endian.h>
#include <mono/metadata/tabledefs.h>
-#include <mono/metadata/blob.h>
#include <mono/metadata/tokentype.h>
#include <mono/metadata/loader.h>
#include <mono/metadata/threads.h>
#include <mono/metadata/verify.h>
#include <mono/metadata/opcodes.h>
#include <mono/metadata/debug-helpers.h>
-#include <mono/io-layer/io-layer.h>
-#include <mono/metadata/socket-io.h>
#include <mono/metadata/mono-config.h>
#include <mono/metadata/marshal.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/mono-debug.h>
#include <mono/os/util.h>
-/*#include <mono/cli/types.h>*/
#include "interp.h"
+#include "mintops.h"
+#include "embed.h"
#include "hacks.h"
+#define OPDEF(a,b,c,d,e,f,g,h,i,j) \
+ a = i,
+
+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
#define isnan _isnan
#define finite _finite
#endif
+#ifndef HAVE_FINITE
+#ifdef HAVE_ISFINITE
+#define finite isfinite
+#endif
+#endif
+
+static gint *abort_requested;
/* If true, then we output the opcodes as we interpret them */
static int global_tracing = 0;
static int global_no_pointers = 0;
-static int debug_indent_level = 0;
-
-/*
- * Pull the list of opcodes
- */
-#define OPDEF(a,b,c,d,e,f,g,h,i,j) \
- a = i,
-
-enum {
-#include "mono/cil/opcode.def"
- LAST = 0xff
-};
-#undef OPDEF
+int mono_interp_traceopt = 0;
-#define GET_NATI(sp) ((sp).data.nati)
-#define CSIZE(x) (sizeof (x) / 4)
+static int debug_indent_level = 0;
#define INIT_FRAME(frame,parent_frame,obj_this,method_args,method_retval,mono_method) \
do { \
(frame)->obj = (obj_this); \
(frame)->stack_args = (method_args); \
(frame)->retval = (method_retval); \
- (frame)->method = (mono_method); \
- (frame)->ex_handler = NULL; \
+ (frame)->runtime_method = mono_interp_get_runtime_method (mono_method); \
(frame)->ex = NULL; \
- (frame)->child = NULL; \
+ (frame)->ip = NULL; \
(frame)->invoke_trap = 0; \
} while (0)
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);
+
typedef void (*ICallMethod) (MonoInvocation *frame);
static guint32 die_on_exception = 0;
-static guint32 frame_thread_id = 0;
+static guint32 thread_context_id = 0;
#define DEBUG_INTERP 1
+#define COUNT_OPS 0
#if DEBUG_INTERP
-static unsigned long opcode_count = 0;
-static unsigned long fcall_count = 0;
static int break_on_method = 0;
+static int nested_trace = 0;
static GList *db_methods = NULL;
static void
}
#define DEBUG_ENTER() \
- fcall_count++; \
- g_list_foreach (db_methods, db_match_method, (gpointer)frame->method); \
- if (break_on_method) tracing=2; \
- break_on_method = 0; \
+ if (db_methods) { \
+ g_list_foreach (db_methods, db_match_method, (gpointer)frame->runtime_method->method); \
+ if (break_on_method) tracing=nested_trace ? (global_tracing = 2, 3) : 2; \
+ break_on_method = 0; \
+ } \
if (tracing) { \
- char *mn, *args = dump_stack (frame->stack_args, frame->stack_args+signature->param_count); \
+ MonoMethod *method = frame->runtime_method->method ;\
+ char *mn, *args = dump_args (frame); \
debug_indent_level++; \
output_indent (); \
- mn = mono_method_full_name (frame->method, FALSE); \
- g_print ("(%d) Entering %s (", GetCurrentThreadId(), mn); \
+ mn = mono_method_full_name (method, FALSE); \
+ g_print ("(%u) Entering %s (", GetCurrentThreadId(), mn); \
g_free (mn); \
- if (signature->hasthis) { \
- if (global_no_pointers) { \
- g_print ("this%s ", frame->obj ? "" : "=null"); \
- } else { \
- g_print ("%p ", frame->obj); } \
- } \
g_print ("%s)\n", args); \
g_free (args); \
} \
if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE) \
- mono_profiler_method_enter (frame->method);
+ mono_profiler_method_enter (frame->runtime_method->method);
#define DEBUG_LEAVE() \
if (tracing) { \
char *mn, *args; \
- if (signature->ret->type != MONO_TYPE_VOID) \
- args = dump_stack (frame->retval, frame->retval + 1); \
- else \
- args = g_strdup (""); \
+ args = dump_retval (frame); \
output_indent (); \
- mn = mono_method_full_name (frame->method, FALSE); \
- g_print ("(%d) Leaving %s", GetCurrentThreadId(), mn); \
+ mn = mono_method_full_name (frame->runtime_method->method, FALSE); \
+ g_print ("(%u) Leaving %s", GetCurrentThreadId(), mn); \
g_free (mn); \
g_print (" => %s\n", args); \
g_free (args); \
debug_indent_level--; \
+ if (tracing == 3) global_tracing = 0; \
} \
if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE) \
- mono_profiler_method_leave (frame->method);
+ mono_profiler_method_leave (frame->runtime_method->method);
#else
static void
interp_ex_handler (MonoException *ex) {
- MonoInvocation *frame = TlsGetValue (frame_thread_id);
- frame->ex = ex;
- longjmp (*(jmp_buf*)frame->locals, 1);
+ ThreadContext *context = TlsGetValue (thread_context_id);
+ char *stack_trace;
+ if (context == NULL)
+ return;
+ stack_trace = dump_frame (context->current_frame);
+ ex->stack_trace = mono_string_new (mono_domain_get(), stack_trace);
+ g_free (stack_trace);
+ if (context->current_env == NULL || strcmp(ex->object.vtable->klass->name, "ExecutionEngineException") == 0) {
+ char *strace = mono_string_to_utf8 (ex->stack_trace);
+ 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 (ex->message);
+ fprintf(stderr, ": %s", m);
+ g_free(m);
+ }
+ fprintf(stderr, "\n");
+ fprintf(stderr, "%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 (ex->message);
+ fprintf(stderr, ": %s", m);
+ g_free(m);
+ }
+ strace = mono_string_to_utf8 (ex->stack_trace);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "%s\n", strace);
+ g_free (strace);
+ }
+ /* wait for other threads to also collapse */
+ Sleep(1000);
+ 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 char *ip, stackval *stack, stackval *sp)
+ const unsigned short *ip, stackval *stack, stackval *sp)
{
- MonoMethodNormal *mm = (MonoMethodNormal *)mh;
fprintf (stderr, "Execution aborted in method: %s::%s\n", mh->klass->name, mh->name);
fprintf (stderr, "Line=%d IP=0x%04x, Aborted execution\n", line,
- ip-mm->header->code);
+ ip-(const unsigned short *)mono_method_get_header (mh)->code);
g_print ("0x%04x %02x\n",
- ip-mm->header->code, *ip);
+ ip-(const unsigned short *)mono_method_get_header (mh)->code, *ip);
if (sp > stack)
- printf ("\t[%d] %d 0x%08x %0.5f\n", sp-stack, sp[-1].type, sp[-1].data.i, sp[-1].data.f);
+ printf ("\t[%d] 0x%08x %0.5f\n", sp-stack, sp[-1].data.i, sp[-1].data.f);
}
-#define ves_abort() do {ves_real_abort(__LINE__, frame->method, ip, frame->stack, sp); THROW_EX (mono_get_exception_execution_engine (NULL), ip);} while (0);
+
+#define ves_abort() \
+ do {\
+ ves_real_abort(__LINE__, frame->runtime_method->method, ip, frame->stack, sp); \
+ THROW_EX (mono_get_exception_execution_engine (NULL), ip); \
+ } while (0);
static gpointer
-interp_create_remoting_trampoline (MonoMethod *method)
+interp_create_remoting_trampoline (MonoMethod *method, MonoRemotingTarget target)
+{
+ return mono_interp_get_runtime_method (mono_marshal_get_remoting_invoke_for_target (method, target));
+}
+
+static CRITICAL_SECTION runtime_method_lookup_section;
+
+RuntimeMethod*
+mono_interp_get_runtime_method (MonoMethod *method)
{
- return mono_marshal_get_remoting_invoke (method);
+ MonoDomain *domain = mono_domain_get ();
+ RuntimeMethod *rtm;
+
+ EnterCriticalSection (&runtime_method_lookup_section);
+ if ((rtm = g_hash_table_lookup (domain->jit_code_hash, method))) {
+ LeaveCriticalSection (&runtime_method_lookup_section);
+ return rtm;
+ }
+ rtm = mono_mempool_alloc (domain->mp, sizeof (RuntimeMethod));
+ memset (rtm, 0, sizeof (*rtm));
+ rtm->method = method;
+ rtm->param_count = mono_method_signature (method)->param_count;
+ rtm->hasthis = mono_method_signature (method)->hasthis;
+ rtm->valuetype = method->klass->valuetype;
+ g_hash_table_insert (domain->jit_code_hash, method, rtm);
+ LeaveCriticalSection (&runtime_method_lookup_section);
+
+ return rtm;
}
-static MonoMethod*
-get_virtual_method (MonoDomain *domain, MonoMethod *m, stackval *objs)
+static gpointer
+interp_create_trampoline (MonoMethod *method)
{
- MonoObject *obj;
- MonoClass *klass;
- MonoMethod **vtable;
- gboolean is_proxy = FALSE;
- MonoMethod *res;
+ if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
+ method = mono_marshal_get_synchronized_wrapper (method);
+ return mono_interp_get_runtime_method (method);
+}
- if ((m->flags & METHOD_ATTRIBUTE_FINAL) || !(m->flags & METHOD_ATTRIBUTE_VIRTUAL))
- return m;
+static inline RuntimeMethod*
+get_virtual_method (RuntimeMethod *runtime_method, MonoObject *obj)
+{
+ MonoMethod *m = runtime_method->method;
- obj = objs->data.p;
- if ((klass = obj->vtable->klass) == mono_defaults.transparent_proxy_class) {
- klass = ((MonoTransparentProxy *)obj)->klass;
- is_proxy = TRUE;
+ if ((m->flags & METHOD_ATTRIBUTE_FINAL) || !(m->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
+ if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
+ return mono_interp_get_runtime_method (mono_marshal_get_remoting_invoke (m));
+ else if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
+ return mono_interp_get_runtime_method (mono_marshal_get_synchronized_wrapper (m));
+ else
+ return runtime_method;
}
- vtable = (MonoMethod **)klass->vtable;
if (m->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
- res = *(MonoMethod**)((char*)obj->vtable->interface_offsets [m->klass->interface_id] + (m->slot<<2));
+ return ((RuntimeMethod **)obj->vtable->interface_offsets [m->klass->interface_id]) [m->slot];
} else {
- res = vtable [m->slot];
+ return ((RuntimeMethod **)obj->vtable->vtable) [m->slot];
}
- g_assert (res);
-
- if (is_proxy)
- return mono_marshal_get_remoting_invoke (res);
-
- return res;
}
void inline
case MONO_TYPE_STRING:
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY:
- result->type = VAL_OBJ;
break;
default:
- result->type = VAL_VALUETA;
break;
}
result->data.p = *(gpointer*)data;
- result->data.vt.klass = mono_class_from_mono_type (type);
return;
}
switch (type->type) {
case MONO_TYPE_VOID:
return;
case MONO_TYPE_I1:
- result->type = VAL_I32;
result->data.i = *(gint8*)data;
return;
case MONO_TYPE_U1:
case MONO_TYPE_BOOLEAN:
- result->type = VAL_I32;
result->data.i = *(guint8*)data;
return;
case MONO_TYPE_I2:
- result->type = VAL_I32;
result->data.i = *(gint16*)data;
return;
case MONO_TYPE_U2:
case MONO_TYPE_CHAR:
- result->type = VAL_I32;
result->data.i = *(guint16*)data;
return;
case MONO_TYPE_I4:
- result->type = VAL_I32;
result->data.i = *(gint32*)data;
return;
case MONO_TYPE_U:
case MONO_TYPE_I:
+ result->data.nati = *(mono_i*)data;
+ return;
case MONO_TYPE_PTR:
- result->type = VAL_TP;
result->data.p = *(gpointer*)data;
return;
case MONO_TYPE_U4:
- result->type = VAL_I32;
result->data.i = *(guint32*)data;
return;
case MONO_TYPE_R4:
- result->type = VAL_DOUBLE;
result->data.f = *(float*)data;
return;
case MONO_TYPE_I8:
case MONO_TYPE_U8:
- result->type = VAL_I64;
result->data.l = *(gint64*)data;
return;
case MONO_TYPE_R8:
- result->type = VAL_DOUBLE;
result->data.f = *(double*)data;
return;
case MONO_TYPE_STRING:
case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
case MONO_TYPE_ARRAY:
- result->type = VAL_OBJ;
result->data.p = *(gpointer*)data;
- result->data.vt.klass = mono_class_from_mono_type (type);
return;
case MONO_TYPE_VALUETYPE:
if (type->data.klass->enumtype) {
- return stackval_from_data (type->data.klass->enum_basetype, result, data, pinvoke);
+ stackval_from_data (type->data.klass->enum_basetype, result, data, pinvoke);
+ return;
} else {
int size;
- result->type = VAL_VALUET;
- result->data.vt.klass = type->data.klass;
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.vt, data, size);
+ memcpy (result->data.vt, data, size);
}
return;
default:
*p = val->data.p;
return;
}
- //printf ("TODAT0 %p\n", data);
+ /* printf ("TODAT0 %p\n", data); */
switch (type->type) {
case MONO_TYPE_I1:
case MONO_TYPE_U1: {
*p = val->data.i;
return;
}
-#if SIZEOF_VOID_P == 4
- case MONO_TYPE_I:
- case MONO_TYPE_U:
-#endif
+ case MONO_TYPE_I: {
+ mono_i *p = (mono_i*)data;
+ /* In theory the value used by stloc should match the local var type
+ but in practice it sometimes doesn't (a int32 gets dup'd and stloc'd into
+ a native int - both by csc and mcs). Not sure what to do about sign extension
+ as it is outside the spec... doing the obvious */
+ *p = (mono_i)val->data.nati;
+ return;
+ }
+ case MONO_TYPE_U: {
+ mono_u *p = (mono_u*)data;
+ /* see above. */
+ *p = (mono_u)val->data.nati;
+ return;
+ }
case MONO_TYPE_I4:
case MONO_TYPE_U4: {
gint32 *p = (gint32*)data;
*p = val->data.i;
return;
}
-#if SIZEOF_VOID_P == 8
- case MONO_TYPE_I:
- case MONO_TYPE_U:
-#endif
case MONO_TYPE_I8:
case MONO_TYPE_U8: {
gint64 *p = (gint64*)data;
}
case MONO_TYPE_VALUETYPE:
if (type->data.klass->enumtype) {
- return stackval_to_data (type->data.klass->enum_basetype, val, data, pinvoke);
+ stackval_to_data (type->data.klass->enum_basetype, val, data, pinvoke);
+ return;
} else {
int size;
else
size = mono_class_value_size (type->data.klass, NULL);
- memcpy (data, val->data.vt.vt, size);
+ memcpy (data, val->data.p, size);
}
return;
default:
}
}
+static void
+fill_in_trace (MonoException *exception, MonoInvocation *frame)
+{
+ char *stack_trace = dump_frame (frame);
+ MonoDomain *domain = mono_domain_get();
+ (exception)->stack_trace = mono_string_new (domain, stack_trace);
+ (exception)->trace_ips = get_trace_ips (domain, frame);
+ g_free (stack_trace);
+}
+
+#define FILL_IN_TRACE(exception, frame) fill_in_trace(exception, frame)
+
+#define THROW_EX(exception,ex_ip) \
+ do {\
+ frame->ip = (ex_ip); \
+ frame->ex = (MonoException*)(exception); \
+ FILL_IN_TRACE(frame->ex, frame); \
+ goto handle_exception; \
+ } while (0)
+
static MonoObject*
ves_array_create (MonoDomain *domain, MonoClass *klass, MonoMethodSignature *sig, stackval *values)
{
for (i = 1; i < ac->rank; i++) {
if ((t = sp [i].data.i - ao->bounds [i].lower_bound) >=
ao->bounds [i].length) {
- g_warning ("wrong array index");
- g_assert_not_reached ();
+ frame->ex = mono_get_exception_index_out_of_range ();
+ FILL_IN_TRACE(frame->ex, frame);
+ return;
}
pos = pos*ao->bounds [i].length + sp [i].data.i -
ao->bounds [i].lower_bound;
}
+ } else if (pos >= ao->max_length) {
+ frame->ex = mono_get_exception_index_out_of_range ();
+ FILL_IN_TRACE(frame->ex, frame);
+ 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;
}
+#endif
esize = mono_array_element_size (ac);
ea = mono_array_addr_with_size (ao, esize, pos);
- mt = frame->method->signature->params [ac->rank];
+ mt = mono_method_signature (frame->runtime_method->method)->params [ac->rank];
stackval_to_data (mt, &sp [ac->rank], ea, FALSE);
}
MonoObject *o;
MonoArray *ao;
MonoClass *ac;
- gint32 i, pos, esize;
+ gint32 i, t, pos, esize;
gpointer ea;
MonoType *mt;
pos = sp [0].data.i;
if (ao->bounds != NULL) {
pos -= ao->bounds [0].lower_bound;
- for (i = 1; i < ac->rank; i++)
+ for (i = 1; i < ac->rank; i++) {
+ if ((t = sp [i].data.i - ao->bounds [i].lower_bound) >=
+ ao->bounds [i].length) {
+ frame->ex = mono_get_exception_index_out_of_range ();
+ FILL_IN_TRACE(frame->ex, frame);
+ return;
+ }
+
pos = pos*ao->bounds [i].length + sp [i].data.i -
ao->bounds [i].lower_bound;
+ }
+ } else if (pos >= ao->max_length) {
+ frame->ex = mono_get_exception_index_out_of_range ();
+ FILL_IN_TRACE(frame->ex, frame);
+ return;
}
esize = mono_array_element_size (ac);
ea = mono_array_addr_with_size (ao, esize, pos);
- mt = frame->method->signature->ret;
+ mt = mono_method_signature (frame->runtime_method->method)->ret;
stackval_from_data (mt, frame->retval, ea, FALSE);
}
MonoObject *o;
MonoArray *ao;
MonoClass *ac;
- gint32 i, pos, esize;
+ gint32 i, t, pos, esize;
gpointer ea;
o = frame->obj;
pos = sp [0].data.i;
if (ao->bounds != NULL) {
pos -= ao->bounds [0].lower_bound;
- for (i = 1; i < ac->rank; i++)
+ for (i = 1; i < ac->rank; i++) {
+ if ((t = sp [i].data.i - ao->bounds [i].lower_bound) >=
+ ao->bounds [i].length) {
+ frame->ex = mono_get_exception_index_out_of_range ();
+ FILL_IN_TRACE(frame->ex, frame);
+ return;
+ }
pos = pos*ao->bounds [i].length + sp [i].data.i -
ao->bounds [i].lower_bound;
+ }
+ } else if (pos >= ao->max_length) {
+ frame->ex = mono_get_exception_index_out_of_range ();
+ FILL_IN_TRACE(frame->ex, frame);
+ return;
}
esize = mono_array_element_size (ac);
ea = mono_array_addr_with_size (ao, esize, pos);
- frame->retval->type = VAL_TP;
frame->retval->data.p = ea;
}
static void
-interp_walk_stack (MonoStackWalk func, gpointer user_data)
+interp_walk_stack (MonoStackWalk func, gboolean do_il_offset, gpointer user_data)
{
- MonoInvocation *frame = TlsGetValue (frame_thread_id);
+ ThreadContext *context = TlsGetValue (thread_context_id);
+ MonoInvocation *frame;
int il_offset;
MonoMethodHeader *hd;
+ if (!context) return;
+
+ frame = context->current_frame;
+
while (frame) {
gboolean managed = FALSE;
- if (!frame->method || (frame->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
- (frame->method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
+ MonoMethod *method = frame->runtime_method->method;
+ if (!method || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+ (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
il_offset = -1;
else {
- hd = ((MonoMethodNormal*)frame->method)->header;
- il_offset = frame->ip - hd->code;
- if (!frame->method->wrapper_type)
+ hd = mono_method_get_header (method);
+ il_offset = frame->ip - (const unsigned short *)hd->code;
+ if (!method->wrapper_type)
managed = TRUE;
}
- if (func (frame->method, -1, il_offset, managed, user_data))
+ if (func (method, -1, il_offset, managed, user_data))
return;
frame = frame->parent;
}
}
static void
-ves_pinvoke_method (MonoInvocation *frame, MonoMethodSignature *sig, MonoFunc addr, gboolean string_ctor)
+ves_pinvoke_method (MonoInvocation *frame, MonoMethodSignature *sig, MonoFunc 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;
if (setjmp (env)) {
- TlsSetValue (frame_thread_id, frame->args);
+ context->current_frame = old_frame;
+ context->env_frame = old_env_frame;
+ context->current_env = old_env;
+ context->managed_code = 1;
return;
}
- if (frame->method) {
- if (!frame->method->info) {
- func = frame->method->info = mono_create_trampoline (sig, string_ctor);
- } else {
- func = (MonoPIFunc)frame->method->info;
- }
+ frame->ex = NULL;
+ context->env_frame = frame;
+ context->current_env = &env;
+
+ if (frame->runtime_method) {
+ func = frame->runtime_method->func;
} else {
- func = mono_create_trampoline (sig, string_ctor);
+ func = mono_arch_create_trampoline (sig, string_ctor);
}
- /*
- * frame->locals and args are unused for P/Invoke methods, so we reuse them.
- * locals will point to the jmp_buf, while args will point to the previous
- * MonoInvocation frame: this is needed to make exception searching work across
- * managed/unmanaged boundaries.
- */
- frame->locals = (char*)&env;
- frame->args = (char*)TlsGetValue (frame_thread_id);
- TlsSetValue (frame_thread_id, frame);
+ context->current_frame = frame;
+ context->managed_code = 0;
func (addr, &frame->retval->data.p, frame->obj, frame->stack_args);
+ context->managed_code = 1;
+ /* domain can only be changed by native code */
+ context->domain = mono_domain_get ();
+
+ if (*abort_requested)
+ 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))
stackval_from_data (sig->ret, frame->retval, (char*)&frame->retval->data.p, sig->pinvoke);
- TlsSetValue (frame_thread_id, frame->args);
+ context->current_frame = old_frame;
+ context->env_frame = old_env_frame;
+ context->current_env = old_env;
+}
+
+static void
+interp_delegate_ctor (MonoDomain *domain, MonoObject *this, MonoObject *target, RuntimeMethod *runtime_method)
+{
+ MonoDelegate *delegate = (MonoDelegate *)this;
+
+ delegate->method_info = mono_method_get_object (domain, runtime_method->method, NULL);
+ delegate->target = target;
+
+ if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
+ MonoMethod *method = mono_marshal_get_remoting_invoke (runtime_method->method);
+ delegate->method_ptr = mono_interp_get_runtime_method (method);
+ } else {
+ delegate->method_ptr = runtime_method;
+ }
+}
+
+MonoDelegate*
+mono_interp_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
+{
+ MonoDelegate *d;
+ MonoJitInfo *ji;
+ MonoDomain *domain = mono_domain_get ();
+
+ d = (MonoDelegate*)mono_object_new (domain, klass);
+
+ ji = mono_jit_info_table_find (domain, ftn);
+ if (ji == NULL)
+ mono_raise_exception (mono_get_exception_argument ("", "Function pointer was not created by a Delegate."));
+
+ /* FIXME: discard the wrapper and call the original method */
+ interp_delegate_ctor (domain, (MonoObject*)d, NULL, mono_interp_get_runtime_method (ji->method));
+
+ return d;
}
/*
* provided by the runtime and is primarily used for the methods of delegates.
*/
static void
-ves_runtime_method (MonoInvocation *frame)
+ves_runtime_method (MonoInvocation *frame, ThreadContext *context)
{
- const char *name = frame->method->name;
+ MonoMethod *method = frame->runtime_method->method;
+ const char *name = method->name;
MonoObject *obj = (MonoObject*)frame->obj;
- MonoMulticastDelegate *delegate = (MonoMulticastDelegate*)frame->obj;
- MonoInvocation call;
- MonoMethod *nm;
-
- mono_class_init (frame->method->klass);
+ mono_class_init (method->klass);
if (obj && mono_object_isinst (obj, mono_defaults.multicastdelegate_class)) {
if (*name == '.' && (strcmp (name, ".ctor") == 0)) {
- mono_delegate_ctor (obj, frame->stack_args[0].data.p, frame->stack_args[1].data.p);
- return;
- }
- if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
- guchar *code;
- MonoJitInfo *ji;
- MonoMethod *method;
-
- while (delegate) {
-
- code = (guchar*)delegate->delegate.method_ptr;
- if ((ji = mono_jit_info_table_find (mono_root_domain, code))) {
- method = ji->method;
- INIT_FRAME(&call,frame,delegate->delegate.target,frame->stack_args,frame->retval,method);
- ves_exec_method (&call);
- frame->ex = call.ex;
- if (frame->ex)
- return;
- } else {
- g_assert_not_reached ();
- }
-
- delegate = delegate->prev;
- }
- return;
- }
- if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0)) {
- nm = mono_marshal_get_delegate_begin_invoke (frame->method);
- INIT_FRAME(&call,frame,obj,frame->stack_args,frame->retval,nm);
- ves_exec_method (&call);
- frame->ex = call.ex;
- return;
- }
- if (*name == 'E' && (strcmp (name, "EndInvoke") == 0)) {
- nm = mono_marshal_get_delegate_end_invoke (frame->method);
- INIT_FRAME(&call,frame,obj,frame->stack_args,frame->retval,nm);
- ves_exec_method (&call);
- frame->ex = call.ex;
+ interp_delegate_ctor (context->domain, obj, frame->stack_args[0].data.p, frame->stack_args[1].data.p);
return;
}
}
}
g_error ("Don't know how to exec runtime method %s.%s::%s",
- frame->method->klass->name_space, frame->method->klass->name,
- frame->method->name);
+ method->klass->name_space, method->klass->name,
+ method->name);
}
static char*
return g_string_free (str, FALSE);
while (s < sp) {
- switch (s->type) {
- case VAL_I32: g_string_sprintfa (str, "[%d] ", s->data.i); break;
- case VAL_I64: g_string_sprintfa (str, "[%lld] ", s->data.l); break;
- case VAL_DOUBLE: g_string_sprintfa (str, "[%0.5f] ", s->data.f); break;
- case VAL_VALUET:
- if (!global_no_pointers)
- g_string_sprintfa (str, "[vt: %p] ", s->data.vt.vt);
- else
- g_string_sprintfa (str, "[vt%s] ", s->data.vt.vt ? "" : "=null");
- break;
- case VAL_OBJ: {
- MonoObject *obj = s->data.p;
- if (global_no_pointers && obj && obj->vtable) {
- MonoClass *klass = mono_object_class (obj);
- if (klass == mono_defaults.string_class) {
- char *utf8 = mono_string_to_utf8 ((MonoString*) obj);
- g_string_sprintfa (str, "[str:%s] ", utf8);
- g_free (utf8);
- break;
- } else if (klass == mono_defaults.sbyte_class) {
- g_string_sprintfa (str, "[b:%d] ",
- *(gint8 *)((guint8 *) obj + sizeof (MonoObject)));
- break;
- } else if (klass == mono_defaults.int16_class) {
- g_string_sprintfa (str, "[b:%d] ",
- *(gint16 *)((guint8 *) obj + sizeof (MonoObject)));
- break;
- } else if (klass == mono_defaults.int32_class) {
- g_string_sprintfa (str, "[b:%d] ",
- *(gint32 *)((guint8 *) obj + sizeof (MonoObject)));
- break;
- } else if (klass == mono_defaults.byte_class) {
- g_string_sprintfa (str, "[b:%u] ",
- *(guint8 *)((guint8 *) obj + sizeof (MonoObject)));
- break;
- } else if (klass == mono_defaults.char_class
- || klass == mono_defaults.uint16_class) {
- g_string_sprintfa (str, "[b:%u] ",
- *(guint16 *)((guint8 *) obj + sizeof (MonoObject)));
- break;
- } else if (klass == mono_defaults.uint32_class) {
- g_string_sprintfa (str, "[b:%u] ",
- *(guint32 *)((guint8 *) obj + sizeof (MonoObject)));
- break;
- } else if (klass == mono_defaults.int64_class) {
- g_string_sprintfa (str, "[b:%lld] ",
- *(gint64 *)((guint8 *) obj + sizeof (MonoObject)));
- break;
- } else if (klass == mono_defaults.uint64_class) {
- g_string_sprintfa (str, "[b:%llu] ",
- *(guint64 *)((guint8 *) obj + sizeof (MonoObject)));
- break;
- } else if (klass == mono_defaults.double_class) {
- g_string_sprintfa (str, "[b:%0.5f] ",
- *(gdouble *)((guint8 *) obj + sizeof (MonoObject)));
- break;
- } else if (klass == mono_defaults.single_class) {
- g_string_sprintfa (str, "[b:%0.5f] ",
- *(gfloat *)((guint8 *) obj + sizeof (MonoObject)));
- break;
- } else if (klass == mono_defaults.boolean_class) {
- g_string_sprintfa (str, "[b:%s] ",
- *(gboolean *)((guint8 *) obj + sizeof (MonoObject))
- ? "true" : "false");
- break;
- }
- }
- /* fall thru */
- }
- default:
- if (!global_no_pointers)
- g_string_sprintfa (str, "[%p] ", s->data.p);
- else
- g_string_sprintfa (str, s->data.p ? "[ptr] " : "[null] ");
- break;
- }
+ g_string_sprintfa (str, "[%lld/0x%0llx] ", s->data.l, s->data.l);
++s;
}
return g_string_free (str, FALSE);
}
+static void
+dump_stackval (GString *str, stackval *s, MonoType *type)
+{
+ switch (type->type) {
+ 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_CHAR:
+ case MONO_TYPE_BOOLEAN:
+ g_string_sprintfa (str, "[%d] ", s->data.i);
+ break;
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ g_string_sprintfa (str, "[%p] ", s->data.p);
+ break;
+ case MONO_TYPE_VALUETYPE:
+ if (type->data.klass->enumtype)
+ g_string_sprintfa (str, "[%d] ", s->data.i);
+ else
+ g_string_sprintfa (str, "[vt:%p] ", s->data.p);
+ break;
+ case MONO_TYPE_R4:
+ case MONO_TYPE_R8:
+ g_string_sprintfa (str, "[%g] ", s->data.f);
+ break;
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ default:
+ g_string_sprintfa (str, "[%lld/0x%0llx] ", s->data.l, s->data.l);
+ break;
+ }
+}
+
static char*
-dump_frame (MonoInvocation *inv)
+dump_args (MonoInvocation *inv)
{
GString *str = g_string_new ("");
int i;
- char *args;
- for (i = 0; inv; inv = inv->parent, ++i) {
- MonoClass *k = inv->method->klass;
- int codep;
- const char * opname;
- gchar *source = NULL;
- if (inv->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL ||
- inv->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
- codep = 0;
- opname = "";
- } else {
- MonoMethodHeader *hd = ((MonoMethodNormal *)inv->method)->header;
+ MonoMethodSignature *signature = mono_method_signature (inv->runtime_method->method);
+
+ if (signature->param_count == 0)
+ return g_string_free (str, FALSE);
- if (inv->ip)
- codep = *(inv->ip) == 0xfe? inv->ip [1] + 256: *(inv->ip);
- else
- codep = 0;
- opname = mono_opcode_names [codep];
- codep = inv->ip - hd->code;
+ if (signature->hasthis)
+ g_string_sprintfa (str, "%p ", inv->obj);
+
+ for (i = 0; i < signature->param_count; ++i)
+ dump_stackval (str, inv->stack_args + i, signature->params [i]);
- source = mono_debug_source_location_from_il_offset (inv->method, codep, NULL);
- }
- args = dump_stack (inv->stack_args, inv->stack_args + inv->method->signature->param_count);
- if (source)
- g_string_sprintfa (str, "#%d: 0x%05x %-10s in %s.%s::%s (%s) at %s\n", i, codep, opname,
- k->name_space, k->name, inv->method->name, args, source);
- else
- g_string_sprintfa (str, "#%d: 0x%05x %-10s in %s.%s::%s (%s)\n", i, codep, opname,
- k->name_space, k->name, inv->method->name, args);
- g_free (args);
- g_free (source);
- }
return g_string_free (str, FALSE);
}
-static CRITICAL_SECTION metadata_lock;
+static char*
+dump_retval (MonoInvocation *inv)
+{
+ GString *str = g_string_new ("");
+ MonoType *ret = mono_method_signature (inv->runtime_method->method)->ret;
-typedef enum {
- INLINE_STRING_LENGTH = 1,
- INLINE_ARRAY_LENGTH,
- INLINE_ARRAY_RANK,
- INLINE_TYPE_ELEMENT_TYPE
-} InlineMethod;
+ if (ret->type != MONO_TYPE_VOID)
+ dump_stackval (str, inv->retval, ret);
-static void
-calc_offsets (MonoImage *image, MonoMethod *method)
+ return g_string_free (str, FALSE);
+}
+
+static char*
+dump_frame (MonoInvocation *inv)
{
- int i, align, size, offset = 0;
- MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
- MonoMethodSignature *signature = method->signature;
- int hasthis = signature->hasthis;
- register const unsigned char *ip, *end;
- const MonoOpcode *opcode;
- guint32 token;
- MonoMethod *m;
- MonoClass *class;
- MonoDomain *domain = mono_domain_get ();
- guint32 *offsets;
-
- mono_profiler_method_jit (method); /* sort of... */
- offsets = g_new0 (guint32, 2 + header->num_locals + signature->param_count + signature->hasthis);
- for (i = 0; i < header->num_locals; ++i) {
- size = mono_type_size (header->locals [i], &align);
- offset += align - 1;
- offset &= ~(align - 1);
- offsets [2 + i] = offset;
- offset += size;
- }
- offsets [0] = offset;
- offset = 0;
- if (hasthis) {
- offset += sizeof (gpointer) - 1;
- offset &= ~(sizeof (gpointer) - 1);
- offsets [2 + header->num_locals] = offset;
- offset += sizeof (gpointer);
- }
- for (i = 0; i < signature->param_count; ++i) {
- if (signature->pinvoke)
- size = mono_type_native_stack_size (signature->params [i], &align);
- else
- size = mono_type_stack_size (signature->params [i], &align);
- offset += align - 1;
- offset &= ~(align - 1);
- offsets [2 + hasthis + header->num_locals + i] = offset;
- offset += size;
- }
- offsets [1] = offset;
-
- /* FIXME: This might cause a deadlock with domain->lock */
- EnterCriticalSection (&metadata_lock);
- /* intern the strings in the method. */
- ip = header->code;
- end = ip + header->code_size;
- while (ip < end) {
- i = *ip;
- if (*ip == 0xfe) {
- ip++;
- i = *ip + 256;
- }
- opcode = &mono_opcodes [i];
- switch (opcode->argument) {
- case MonoInlineNone:
- ++ip;
- break;
- case MonoInlineString:
- mono_ldstr (domain, image, mono_metadata_token_index (read32 (ip + 1)));
- ip += 5;
- break;
- case MonoInlineType:
- if (method->wrapper_type == MONO_WRAPPER_NONE) {
- class = mono_class_get (image, read32 (ip + 1));
- mono_class_init (class);
- if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE))
- mono_class_vtable (domain, class);
- }
- ip += 5;
- break;
- case MonoInlineField:
- token = read32 (ip + 1);
- if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF) {
- mono_field_from_memberref (image, token, &class);
- } else {
- class = mono_class_get (image,
- MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (image, token & 0xffffff));
- }
- mono_class_init (class);
- mono_class_vtable (domain, class);
- ip += 5;
- break;
- case MonoInlineMethod:
- if (method->wrapper_type == MONO_WRAPPER_NONE) {
- m = mono_get_method (image, read32 (ip + 1), NULL);
- mono_class_init (m->klass);
- if (!(m->klass->flags & TYPE_ATTRIBUTE_INTERFACE))
- mono_class_vtable (domain, m->klass);
+ GString *str = g_string_new ("");
+ int i;
+ char *args;
+ for (i = 0; inv; inv = inv->parent) {
+ if (inv->runtime_method != NULL) {
+ MonoMethod *method = inv->runtime_method->method;
+ MonoClass *k;
+
+ int codep = 0;
+ const char * opname = "";
+ char *name;
+ gchar *source = NULL;
+
+ k = method->klass;
+
+ if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 &&
+ (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) == 0) {
+ MonoMethodHeader *hd = mono_method_get_header (method);
+
+ if (hd != NULL) {
+ if (inv->ip) {
+ opname = mono_interp_opname [*inv->ip];
+ codep = inv->ip - inv->runtime_method->code;
+ } else
+ opname = "";
+
+ source = mono_debug_source_location_from_il_offset (method, codep, NULL);
+ }
}
- ip += 5;
- break;
- case MonoInlineTok:
- case MonoInlineSig:
- case MonoShortInlineR:
- case MonoInlineI:
- case MonoInlineBrTarget:
- ip += 5;
- break;
- case MonoInlineVar:
- ip += 3;
- break;
- case MonoShortInlineVar:
- case MonoShortInlineI:
- case MonoShortInlineBrTarget:
- ip += 2;
- break;
- case MonoInlineSwitch: {
- guint32 n;
- ++ip;
- n = read32 (ip);
- ip += 4;
- ip += 4 * n;
- break;
- }
- case MonoInlineR:
- case MonoInlineI8:
- ip += 9;
- break;
- default:
- g_assert_not_reached ();
+ args = dump_args (inv);
+ name = mono_method_full_name (method, TRUE);
+ if (source)
+ g_string_sprintfa (str, "#%d: 0x%05x %-10s in %s (%s) at %s\n", i, codep, opname,
+ name, args, source);
+ else
+ g_string_sprintfa (str, "#%d: 0x%05x %-10s in %s (%s)\n", i, codep, opname,
+ name, args);
+ g_free (name);
+ g_free (args);
+ g_free (source);
+ ++i;
}
-
- }
- method->info = offsets;
-
- /*
- * We store the inline info in addr, since it's unused for IL methods.
- */
- if (method->klass == mono_defaults.string_class) {
- if (strcmp (method->name, "get_Length") == 0)
- method->addr = GUINT_TO_POINTER (INLINE_STRING_LENGTH);
- } else if (method->klass == mono_defaults.array_class) {
- if (strcmp (method->name, "get_Length") == 0)
- method->addr = GUINT_TO_POINTER (INLINE_ARRAY_LENGTH);
- else if (strcmp (method->name, "get_Rank") == 0 || strcmp (method->name, "GetRank") == 0)
- method->addr = GUINT_TO_POINTER (INLINE_ARRAY_RANK);
- } else if (method->klass == mono_defaults.monotype_class) {
- if (strcmp (method->name, "GetElementType") == 0)
- method->addr = GUINT_TO_POINTER (INLINE_TYPE_ELEMENT_TYPE);
}
- LeaveCriticalSection (&metadata_lock);
- mono_profiler_method_end_jit (method, MONO_PROFILE_OK);
+ return g_string_free (str, FALSE);
}
-#define LOCAL_POS(n) (frame->locals + offsets [2 + (n)])
-#define LOCAL_TYPE(header, n) ((header)->locals [(n)])
-
-#define ARG_POS(n) (args_pointers [(n)])
-#define ARG_TYPE(sig, n) ((n) ? (sig)->params [(n) - (sig)->hasthis] : \
- (sig)->hasthis ? &frame->method->klass->this_arg: (sig)->params [(0)])
+static MonoArray *
+get_trace_ips (MonoDomain *domain, MonoInvocation *top)
+{
+ int i;
+ MonoArray *res;
+ MonoInvocation *inv;
-#define THROW_EX(exception,ex_ip) \
- do {\
- char *stack_trace; \
- frame->ip = (ex_ip); \
- stack_trace = dump_frame (frame); \
- frame->ex = (MonoException*)(exception); \
- frame->ex->stack_trace = mono_string_new (domain, stack_trace); \
- g_free (stack_trace); \
- goto handle_exception; \
- } while (0)
-
-typedef struct _vtallocation vtallocation;
-
-struct _vtallocation {
- vtallocation *next;
- guint32 size;
- char data [MONO_ZERO_LEN_ARRAY];
-};
+ for (i = 0, inv = top; inv; inv = inv->parent)
+ if (inv->runtime_method != NULL)
+ ++i;
-#define vt_alloc(vtype,sp,native) \
- if ((vtype)->type == MONO_TYPE_VALUETYPE && !(vtype)->data.klass->enumtype) { \
- if (!(vtype)->byref) { \
- guint32 align; \
- guint32 size; \
- vtallocation *tmp, *prev; \
- if (native) size = mono_class_native_size ((vtype)->data.klass, &align); \
- else size = mono_class_value_size ((vtype)->data.klass, &align); \
- prev = NULL; \
- tmp = vtalloc; \
- while (tmp && (tmp->size < size)) { \
- prev = tmp; \
- tmp = tmp->next; \
- } \
- if (!tmp) { \
- tmp = alloca (sizeof (vtallocation) + size); \
- tmp->size = size; \
- g_assert (size < 10000); \
- } \
- else \
- if (prev) \
- prev->next = tmp->next; \
- else \
- vtalloc = tmp->next; \
- (sp)->data.vt.vt = tmp->data; \
- } else { \
- (sp)->data.vt.klass = (vtype)->data.klass; \
- } \
- }
+ res = mono_array_new (domain, mono_defaults.int_class, 2 * i);
-#define vt_free(sp) \
- do { \
- if ((sp)->type == VAL_VALUET) { \
- vtallocation *tmp = (vtallocation*)(((char*)(sp)->data.vt.vt) - G_STRUCT_OFFSET (vtallocation, data)); \
- tmp->next = vtalloc; \
- vtalloc = tmp; \
- } \
- } while (0)
+ for (i = 0, inv = top; inv; inv = inv->parent)
+ if (inv->runtime_method != NULL) {
+ mono_array_set (res, gpointer, i, inv->runtime_method);
+ ++i;
+ mono_array_set (res, gpointer, i, (gpointer)inv->ip);
+ ++i;
+ }
-/*
-static void
-verify_method (MonoMethod *m)
-{
- GSList *errors, *tmp;
- MonoVerifyInfo *info;
-
- errors = mono_method_verify (m, MONO_VERIFY_ALL);
- if (errors)
- g_print ("Method %s.%s::%s has invalid IL.\n", m->klass->name_space, m->klass->name, m->name);
- for (tmp = errors; tmp; tmp = tmp->next) {
- info = tmp->data;
- g_print ("%s\n", info->message);
- }
- if (errors)
- G_BREAKPOINT ();
- mono_free_verify_list (errors);
+ return res;
}
-*/
+
#define MYGUINT64_MAX 18446744073709551615ULL
#define MYGINT64_MAX 9223372036854775807LL
(gint32)(b) >= 0 ? (gint32)(MYGINT32_MAX) - (gint32)(b) < (gint32)(a) ? -1 : 0 \
: (gint32)(MYGINT32_MIN) - (gint32)(b) > (gint32)(a) ? +1 : 0
+#define CHECK_SUB_OVERFLOW(a,b) \
+ (gint32)(b) < 0 ? (gint32)(MYGINT32_MAX) + (gint32)(b) < (gint32)(a) ? -1 : 0 \
+ : (gint32)(MYGINT32_MIN) + (gint32)(b) > (gint32)(a) ? +1 : 0
+
#define CHECK_ADD_OVERFLOW_UN(a,b) \
(guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
+#define CHECK_SUB_OVERFLOW_UN(a,b) \
+ (guint32)(a) < (guint32)(b) ? -1 : 0
+
#define CHECK_ADD_OVERFLOW64(a,b) \
(gint64)(b) >= 0 ? (gint64)(MYGINT64_MAX) - (gint64)(b) < (gint64)(a) ? -1 : 0 \
: (gint64)(MYGINT64_MIN) - (gint64)(b) > (gint64)(a) ? +1 : 0
+#define CHECK_SUB_OVERFLOW64(a,b) \
+ (gint64)(b) < 0 ? (gint64)(MYGINT64_MAX) + (gint64)(b) < (gint64)(a) ? -1 : 0 \
+ : (gint64)(MYGINT64_MIN) + (gint64)(b) > (gint64)(a) ? +1 : 0
+
#define CHECK_ADD_OVERFLOW64_UN(a,b) \
(guint64)(MYGUINT64_MAX) - (guint64)(b) < (guint64)(a) ? -1 : 0
-/* Resolves to TRUE if the operands would overflow */
+#define CHECK_SUB_OVERFLOW64_UN(a,b) \
+ (guint64)(a) < (guint64)(b) ? -1 : 0
+
+#if SIZEOF_VOID_P == 4
+#define CHECK_ADD_OVERFLOW_NAT(a,b) CHECK_ADD_OVERFLOW(a,b)
+#define CHECK_ADD_OVERFLOW_NAT_UN(a,b) CHECK_ADD_OVERFLOW_UN(a,b)
+#else
+#define CHECK_ADD_OVERFLOW_NAT(a,b) CHECK_ADD_OVERFLOW64(a,b)
+#define CHECK_ADD_OVERFLOW_NAT_UN(a,b) CHECK_ADD_OVERFLOW64_UN(a,b)
+#endif
+
+/* Resolves to TRUE if the operands would overflow */
#define CHECK_MUL_OVERFLOW(a,b) \
((gint32)(a) == 0) || ((gint32)(b) == 0) ? 0 : \
- (((gint32)(a) > 0) && ((gint32)(b) > 0)) || (((gint32)(a) < 0) && ((gint32)(b) < 0)) ? \
- (gint32)(b) > ((MYGINT32_MAX) / (gint32)(a)) : \
- (gint32)(b) < ((MYGINT32_MIN) / (gint32)(a))
+ (((gint32)(a) > 0) && ((gint32)(b) == -1)) ? FALSE : \
+ (((gint32)(a) < 0) && ((gint32)(b) == -1)) ? (a == - MYGINT32_MAX) : \
+ (((gint32)(a) > 0) && ((gint32)(b) > 0)) ? (gint32)(a) > ((MYGINT32_MAX) / (gint32)(b)) : \
+ (((gint32)(a) > 0) && ((gint32)(b) < 0)) ? (gint32)(a) > ((MYGINT32_MIN) / (gint32)(b)) : \
+ (((gint32)(a) < 0) && ((gint32)(b) > 0)) ? (gint32)(a) < ((MYGINT32_MIN) / (gint32)(b)) : \
+ (gint32)(a) < ((MYGINT32_MAX) / (gint32)(b))
#define CHECK_MUL_OVERFLOW_UN(a,b) \
((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
(guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
-
+
#define CHECK_MUL_OVERFLOW64(a,b) \
((gint64)(a) == 0) || ((gint64)(b) == 0) ? 0 : \
- (((gint64)(a) > 0) && ((gint64)(b) > 0)) || (((gint64)(a) < 0) && ((gint64)(b) < 0)) ? \
- (gint64)(b) > ((MYGINT64_MAX) / (gint64)(a)) : \
- (gint64)(b) < ((MYGINT64_MIN) / (gint64)(a))
+ (((gint64)(a) > 0) && ((gint64)(b) == -1)) ? FALSE : \
+ (((gint64)(a) < 0) && ((gint64)(b) == -1)) ? (a == - MYGINT64_MAX) : \
+ (((gint64)(a) > 0) && ((gint64)(b) > 0)) ? (gint64)(a) > ((MYGINT64_MAX) / (gint64)(b)) : \
+ (((gint64)(a) > 0) && ((gint64)(b) < 0)) ? (gint64)(a) > ((MYGINT64_MIN) / (gint64)(b)) : \
+ (((gint64)(a) < 0) && ((gint64)(b) > 0)) ? (gint64)(a) < ((MYGINT64_MIN) / (gint64)(b)) : \
+ (gint64)(a) < ((MYGINT64_MAX) / (gint64)(b))
#define CHECK_MUL_OVERFLOW64_UN(a,b) \
((guint64)(a) == 0) || ((guint64)(b) == 0) ? 0 : \
(guint64)(b) > ((MYGUINT64_MAX) / (guint64)(a))
+#if SIZEOF_VOID_P == 4
+#define CHECK_MUL_OVERFLOW_NAT(a,b) CHECK_MUL_OVERFLOW(a,b)
+#define CHECK_MUL_OVERFLOW_NAT_UN(a,b) CHECK_MUL_OVERFLOW_UN(a,b)
+#else
+#define CHECK_MUL_OVERFLOW_NAT(a,b) CHECK_MUL_OVERFLOW64(a,b)
+#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)
{
- MonoInvocation frame, *parent;
+ MonoInvocation frame;
+ ThreadContext * volatile context = TlsGetValue (thread_context_id);
MonoObject *retval = NULL;
- MonoMethodSignature *sig = method->signature;
+ MonoMethodSignature *sig = mono_method_signature (method);
MonoClass *klass = mono_class_from_mono_type (sig->ret);
int i, type, isobject = 0;
- void *ret;
+ void *ret = NULL;
stackval result;
stackval *args = alloca (sizeof (stackval) * sig->param_count);
+ ThreadContext context_struct;
+ MonoInvocation *old_frame = NULL;
+ jmp_buf env;
+
+ frame.ex = NULL;
+
+ if (setjmp(env)) {
+ if (context != &context_struct) {
+ context->domain = mono_domain_get ();
+ context->current_frame = old_frame;
+ context->managed_code = 0;
+ } else
+ TlsSetValue (thread_context_id, NULL);
+ if (exc != NULL)
+ *exc = (MonoObject *)frame.ex;
+ return retval;
+ }
+
+ if (context == NULL) {
+ context = &context_struct;
+ context_struct.base_frame = &frame;
+ context_struct.current_frame = NULL;
+ context_struct.env_frame = &frame;
+ context_struct.current_env = &env;
+ context_struct.search_for_handler = 0;
+ context_struct.managed_code = 0;
+ TlsSetValue (thread_context_id, context);
+ }
+ else
+ old_frame = context->current_frame;
- /* FIXME: Set frame for execption handling. */
+ context->domain = mono_domain_get ();
switch (sig->ret->type) {
case MONO_TYPE_VOID:
isobject = 1;
break;
case MONO_TYPE_VALUETYPE:
- retval = mono_object_new (mono_domain_get (), klass);
+ retval = mono_object_new (context->domain, klass);
ret = ((char*)retval) + sizeof (MonoObject);
if (!sig->ret->data.klass->enumtype)
- result.data.vt.vt = ret;
+ result.data.vt = ret;
break;
default:
- retval = mono_object_new (mono_domain_get (), klass);
+ retval = mono_object_new (context->domain, klass);
ret = ((char*)retval) + sizeof (MonoObject);
break;
}
for (i = 0; i < sig->param_count; ++i) {
if (sig->params [i]->byref) {
- args [i].type = VAL_POINTER;
args [i].data.p = params [i];
continue;
}
case MONO_TYPE_U1:
case MONO_TYPE_I1:
case MONO_TYPE_BOOLEAN:
- args [i].type = VAL_I32;
args [i].data.i = *(MonoBoolean*)params [i];
- args [i].data.vt.klass = NULL;
break;
case MONO_TYPE_U2:
case MONO_TYPE_I2:
case MONO_TYPE_CHAR:
- args [i].type = VAL_I32;
args [i].data.i = *(gint16*)params [i];
- args [i].data.vt.klass = NULL;
break;
#if SIZEOF_VOID_P == 4
case MONO_TYPE_U: /* use VAL_POINTER? */
#endif
case MONO_TYPE_U4:
case MONO_TYPE_I4:
- args [i].type = VAL_I32;
args [i].data.i = *(gint32*)params [i];
- args [i].data.vt.klass = NULL;
break;
#if SIZEOF_VOID_P == 8
case MONO_TYPE_U:
#endif
case MONO_TYPE_U8:
case MONO_TYPE_I8:
- args [i].type = VAL_I64;
args [i].data.l = *(gint64*)params [i];
- args [i].data.vt.klass = NULL;
break;
case MONO_TYPE_VALUETYPE:
if (sig->params [i]->data.klass->enumtype) {
type = sig->params [i]->data.klass->enum_basetype->type;
goto handle_enum;
} else {
- args [i].type = VAL_POINTER;
args [i].data.p = params [i];
- args [i].data.vt.klass = NULL;
}
break;
case MONO_TYPE_STRING:
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_OBJECT:
- args [i].type = VAL_OBJ;
args [i].data.p = params [i];
- args [i].data.vt.klass = NULL;
break;
default:
g_error ("type 0x%x not handled in runtime invoke", sig->params [i]->type);
}
}
- /* chain with managed parent if any */
- parent = TlsGetValue (frame_thread_id);
- INIT_FRAME(&frame,parent,obj,args,&result,method);
+ if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
+ method = mono_marshal_get_native_wrapper (method);
+ INIT_FRAME(&frame,context->current_frame,obj,args,&result,method);
if (exc)
frame.invoke_trap = 1;
- ves_exec_method (&frame);
- if (exc && frame.ex) {
- *exc = (MonoObject*) frame.ex;
- return NULL;
+ context->managed_code = 1;
+ ves_exec_method_with_context (&frame, context);
+ context->managed_code = 0;
+ if (context == &context_struct)
+ TlsSetValue (thread_context_id, NULL);
+ else
+ context->current_frame = old_frame;
+ if (frame.ex != NULL) {
+ if (exc != NULL) {
+ *exc = (MonoObject*) frame.ex;
+ return NULL;
+ }
+ if (context->current_env != NULL) {
+ context->env_frame->ex = frame.ex;
+ longjmp(*context->current_env, 1);
+ }
+ else
+ printf("dropped exception...\n");
}
if (sig->ret->type == MONO_TYPE_VOID && !method->string_ctor)
return NULL;
return retval;
}
-/*
- * Need to optimize ALU ops when natural int == int32
- *
- * IDEA: if we maintain a stack of ip, sp to be checked
- * in the return opcode, we could inline simple methods that don't
- * use the stack or local variables....
- *
- * The {,.S} versions of many opcodes can/should be merged to reduce code
- * duplication.
- *
- */
-void
-ves_exec_method (MonoInvocation *frame)
+static stackval *
+do_icall (ThreadContext *context, int op, stackval *sp, gpointer ptr)
{
- MonoDomain *domain = mono_domain_get ();
- MonoInvocation child_frame;
- MonoMethodHeader *header;
- MonoMethodSignature *signature;
- MonoImage *image;
- GSList *finally_ips = NULL;
- const unsigned char *endfinally_ip;
- register const unsigned char *ip;
- register stackval *sp = NULL;
- void **args_pointers;
- guint32 *offsets;
- gint il_ins_count = -1;
- gint tracing = global_tracing;
- unsigned char tail_recursion = 0;
- unsigned char unaligned_address = 0;
- unsigned char volatile_address = 0;
- vtallocation *vtalloc = NULL;
- MonoVTable *method_class_vt;
- GOTO_LABEL_VARS;
+ MonoInvocation *old_frame = context->current_frame;
+ MonoInvocation *old_env_frame = context->env_frame;
+ jmp_buf *old_env = context->current_env;
+ jmp_buf env;
- if (frame->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
- frame->method = mono_marshal_get_native_wrapper (frame->method);
+ if (setjmp (env)) {
+ context->current_frame = old_frame;
+ context->env_frame = old_env_frame;
+ context->current_env = old_env;
+ context->managed_code = 1;
+ return sp;
+ }
- method_class_vt = mono_class_vtable (domain, frame->method->klass);
- if (!method_class_vt->initialized)
- mono_runtime_class_init (method_class_vt);
- signature = frame->method->signature;
+ context->env_frame = context->current_frame;
+ context->current_env = &env;
+ context->managed_code = 0;
- DEBUG_ENTER ();
+ switch (op) {
+ case MINT_ICALL_V_V: {
+ void (*func)() = ptr;
+ func ();
+ break;
+ }
+ case MINT_ICALL_P_V: {
+ void (*func)(gpointer) = ptr;
+ func (sp [-1].data.p);
+ sp --;
+ break;
+ }
+ case MINT_ICALL_P_P: {
+ gpointer (*func)(gpointer) = ptr;
+ sp [-1].data.p = func (sp [-1].data.p);
+ break;
+ }
+ case MINT_ICALL_PP_V: {
+ void (*func)(gpointer,gpointer) = ptr;
+ sp -= 2;
+ func (sp [0].data.p, sp [1].data.p);
+ break;
+ }
+ case MINT_ICALL_PI_V: {
+ void (*func)(gpointer,int) = ptr;
+ sp -= 2;
+ func (sp [0].data.p, sp [1].data.i);
+ break;
+ }
+ case MINT_ICALL_PP_P: {
+ gpointer (*func)(gpointer,gpointer) = ptr;
+ --sp;
+ sp [-1].data.p = func (sp [-1].data.p, sp [0].data.p);
+ break;
+ }
+ case MINT_ICALL_PI_P: {
+ gpointer (*func)(gpointer,int) = ptr;
+ --sp;
+ sp [-1].data.p = func (sp [-1].data.p, sp [0].data.i);
+ break;
+ }
+ case MINT_ICALL_PPP_V: {
+ void (*func)(gpointer,gpointer,gpointer) = ptr;
+ sp -= 3;
+ func (sp [0].data.p, sp [1].data.p, sp [2].data.p);
+ break;
+ }
+ case MINT_ICALL_PPI_V: {
+ void (*func)(gpointer,gpointer,int) = ptr;
+ sp -= 3;
+ func (sp [0].data.p, sp [1].data.p, sp [2].data.i);
+ break;
+ }
+ default:
+ g_assert_not_reached ();
+ }
- if (frame->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
- if (!frame->method->addr) {
- /* ugly, but needed by the iflags setting in loader.c */
- if (frame->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
- ves_runtime_method (frame);
- if (frame->ex)
- goto handle_exception;
- DEBUG_LEAVE ();
- return;
- }
- if (frame->method->addr) {
- frame->ex = (MonoException*)mono_get_exception_missing_method ();
- goto handle_exception;
- }
- }
- ves_pinvoke_method (frame, frame->method->signature, frame->method->addr,
- frame->method->string_ctor);
- if (frame->ex)
- goto handle_exception;
- DEBUG_LEAVE ();
- return;
- }
+ context->env_frame = old_env_frame;
+ context->current_env = old_env;
- if (frame->method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
- ves_runtime_method (frame);
- if (frame->ex)
- goto handle_exception;
- DEBUG_LEAVE ();
- return;
- }
+ return sp;
+}
- /*verify_method (frame->method);*/
+static CRITICAL_SECTION create_method_pointer_mutex;
- header = ((MonoMethodNormal *)frame->method)->header;
- image = frame->method->klass->image;
+static MonoGHashTable *method_pointer_hash = NULL;
- if (!frame->method->info)
- calc_offsets (image, frame->method);
- offsets = frame->method->info;
+static void *
+mono_create_method_pointer (MonoMethod *method)
+{
+ gpointer addr;
+ MonoJitInfo *ji;
- /*
- * with alloca we get the expected huge performance gain
- * stackval *stack = g_new0(stackval, header->max_stack);
- */
- g_assert (header->max_stack < 10000);
- sp = frame->stack = alloca (sizeof (stackval) * header->max_stack);
-
- if (header->num_locals) {
- g_assert (offsets [0] < 10000);
- frame->locals = alloca (offsets [0]);
- /*
- * yes, we do it unconditionally, because it needs to be done for
- * some cases anyway and checking for that would be even slower.
- */
- memset (frame->locals, 0, offsets [0]);
+ EnterCriticalSection (&create_method_pointer_mutex);
+ if (!method_pointer_hash) {
+ MONO_GC_REGISTER_ROOT (method_pointer_hash);
+ method_pointer_hash = mono_g_hash_table_new (NULL, NULL);
+ }
+ addr = mono_g_hash_table_lookup (method_pointer_hash, method);
+ if (addr) {
+ LeaveCriticalSection (&create_method_pointer_mutex);
+ return addr;
}
+
/*
- * Copy args from stack_args to args.
+ * If it is a static P/Invoke method, we can just return the pointer
+ * to the method implementation.
*/
- if (signature->param_count || signature->hasthis) {
- int i;
- int has_this = signature->hasthis;
-
- g_assert (offsets [1] < 10000);
- frame->args = alloca (offsets [1]);
- g_assert ((signature->param_count + has_this) < 1000);
- args_pointers = alloca (sizeof(void*) * (signature->param_count + has_this));
- if (has_this) {
- gpointer *this_arg;
- this_arg = args_pointers [0] = frame->args;
- *this_arg = frame->obj;
- }
- for (i = 0; i < signature->param_count; ++i) {
- args_pointers [i + has_this] = frame->args + offsets [2 + header->num_locals + has_this + i];
- stackval_to_data (signature->params [i], frame->stack_args + i, args_pointers [i + has_this], signature->pinvoke);
+ if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL && ((MonoMethodPInvoke*) method)->addr) {
+ ji = g_new0 (MonoJitInfo, 1);
+ ji->method = method;
+ ji->code_size = 1;
+ ji->code_start = addr = ((MonoMethodPInvoke*) method)->addr;
+
+ mono_jit_info_table_add (mono_get_root_domain (), ji);
+ }
+ else
+ addr = mono_arch_create_method_pointer (method);
+
+ mono_g_hash_table_insert (method_pointer_hash, method, addr);
+ LeaveCriticalSection (&create_method_pointer_mutex);
+
+ return addr;
+}
+
+#if COUNT_OPS
+static int opcode_counts[512];
+
+#define COUNT_OP(op) opcode_counts[op]++
+#else
+#define COUNT_OP(op)
+#endif
+
+#if DEBUG_INTERP
+#define DUMP_INSTR() \
+ if (tracing > 1) { \
+ char *ins; \
+ if (sp > frame->stack) { \
+ ins = dump_stack (frame->stack, sp); \
+ } else { \
+ ins = g_strdup (""); \
+ } \
+ sp->data.l = 0; \
+ output_indent (); \
+ g_print ("(%u) ", GetCurrentThreadId()); \
+ mono_interp_dis_mintop(rtm->code, ip); \
+ g_print ("\t%d:%s\n", vt_sp - vtalloc, ins); \
+ g_free (ins); \
+ }
+#else
+#define DUMP_INSTR()
+#endif
+
+#ifdef __GNUC__
+#define USE_COMPUTED_GOTO 1
+#endif
+#if USE_COMPUTED_GOTO
+#define MINT_IN_SWITCH(op) COUNT_OP(op); goto *in_labels[op];
+#define MINT_IN_CASE(x) LAB_ ## x:
+#if DEBUG_INTERP
+#define MINT_IN_BREAK if (tracing > 1) goto main_loop; else { COUNT_OP(*ip); goto *in_labels[*ip]; }
+#else
+#define MINT_IN_BREAK { COUNT_OP(*ip); goto *in_labels[*ip]; }
+#endif
+#define MINT_IN_DEFAULT mint_default: if (0) goto mint_default; /* make gcc shut up */
+#else
+#define MINT_IN_SWITCH(op) switch (op)
+#define MINT_IN_CASE(x) case x:
+#define MINT_IN_BREAK break
+#define MINT_IN_DEFAULT default:
+#endif
+
+/*
+ * Defining this causes register allocation errors in some versions of gcc:
+ * error: unable to find a register to spill in class `SIREG'
+ */
+/* #define MINT_USE_DEDICATED_IP_REG */
+
+static void
+ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
+{
+ MonoInvocation child_frame;
+ GSList *finally_ips = NULL;
+ const unsigned short *endfinally_ip = NULL;
+#if defined(__GNUC__) && defined (i386) && defined (MINT_USE_DEDICATED_IP_REG)
+ register const unsigned short *ip asm ("%esi");
+#else
+ register const unsigned short *ip;
+#endif
+ register stackval *sp;
+ RuntimeMethod *rtm;
+#if DEBUG_INTERP
+ gint tracing = global_tracing;
+ unsigned char *vtalloc;
+#endif
+ int i32;
+ unsigned char *vt_sp;
+ char *locals;
+ MonoObject *o = NULL;
+ MonoClass *c;
+#if USE_COMPUTED_GOTO
+ static void *in_labels[] = {
+#define OPDEF(a,b,c,d) \
+ &&LAB_ ## a,
+#include "mintops.def"
+ 0 };
+#endif
+
+ frame->ex = NULL;
+ frame->ex_handler = NULL;
+ frame->ip = NULL;
+ context->current_frame = frame;
+
+ DEBUG_ENTER ();
+
+ if (!frame->runtime_method->transformed) {
+ context->managed_code = 0;
+ frame->ex = mono_interp_transform_method (frame->runtime_method, context);
+ context->managed_code = 1;
+ if (frame->ex) {
+ rtm = NULL;
+ ip = NULL;
+ goto exit_frame;
}
}
+ rtm = frame->runtime_method;
+ frame->args = alloca (rtm->alloca_size);
+ sp = frame->stack = (stackval *)((char *)frame->args + rtm->args_size);
+#if DEBUG_INTERP
+ if (tracing > 1)
+ memset(sp, 0, rtm->stack_size);
+#endif
+ vt_sp = (char *)sp + rtm->stack_size;
+#if DEBUG_INTERP
+ vtalloc = vt_sp;
+#endif
+ locals = vt_sp + rtm->vt_stack_size;
+
child_frame.parent = frame;
- frame->child = &child_frame;
- frame->ex = NULL;
/* ready to go */
- ip = header->code;
+ ip = rtm->code;
/*
* using while (ip < end) may result in a 15% performance drop,
*/
while (1) {
main_loop:
- /*g_assert (sp >= stack);*/
-#if DEBUG_INTERP
- opcode_count++;
- if (tracing > 1) {
- char *ins, *discode;
- if (sp > frame->stack) {
- ins = dump_stack (frame->stack, sp);
- } else {
- ins = g_strdup ("");
- }
- output_indent ();
- discode = mono_disasm_code_one (NULL, frame->method, ip, NULL);
- discode [strlen (discode) - 1] = 0; /* no \n */
- g_print ("(%d) %-29s %s\n", GetCurrentThreadId(), discode, ins);
- g_free (ins);
- g_free (discode);
- }
- if (il_ins_count > 0)
- if (!(--il_ins_count))
- G_BREAKPOINT ();
-#endif
-
- SWITCH (*ip) {
- CASE (CEE_NOP)
+ /* g_assert (sp >= frame->stack); */
+ /* g_assert(vt_sp - vtalloc <= rtm->vt_stack_size); */
+ DUMP_INSTR();
+ MINT_IN_SWITCH (*ip) {
+ MINT_IN_CASE(MINT_INITLOCALS)
+ memset (locals, 0, rtm->locals_size);
++ip;
- BREAK;
- CASE (CEE_BREAK)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_NOP)
++ip;
- G_BREAKPOINT (); /* this is not portable... */
- BREAK;
- CASE (CEE_LDARG_0)
- CASE (CEE_LDARG_1)
- CASE (CEE_LDARG_2)
- CASE (CEE_LDARG_3) {
- int n = (*ip)-CEE_LDARG_0;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BREAK)
++ip;
- vt_alloc (ARG_TYPE (signature, n), sp, signature->pinvoke);
- stackval_from_data (ARG_TYPE (signature, n), sp, ARG_POS (n), signature->pinvoke);
- ++sp;
- BREAK;
- }
- CASE (CEE_LDLOC_0)
- CASE (CEE_LDLOC_1)
- CASE (CEE_LDLOC_2)
- CASE (CEE_LDLOC_3) {
- int n = (*ip)-CEE_LDLOC_0;
+ G_BREAKPOINT (); /* this is not portable... */
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDNULL)
+ sp->data.p = NULL;
++ip;
- if ((LOCAL_TYPE (header, n))->type == MONO_TYPE_I4) {
- sp->type = VAL_I32;
- sp->data.i = *(gint32*) LOCAL_POS (n);
- ++sp;
- BREAK;
- } else {
- vt_alloc (LOCAL_TYPE (header, n), sp, FALSE);
- stackval_from_data (LOCAL_TYPE (header, n), sp, LOCAL_POS (n), FALSE);
- }
++sp;
- BREAK;
- }
- CASE (CEE_STLOC_0)
- CASE (CEE_STLOC_1)
- CASE (CEE_STLOC_2)
- CASE (CEE_STLOC_3) {
- int n = (*ip)-CEE_STLOC_0;
- ++ip;
- --sp;
- if ((LOCAL_TYPE (header, n))->type == MONO_TYPE_I4) {
- gint32 *p = (gint32*)LOCAL_POS (n);
- *p = sp->data.i;
- BREAK;
- } else {
- stackval_to_data (LOCAL_TYPE (header, n), sp, LOCAL_POS (n), FALSE);
- vt_free (sp);
- BREAK;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_VTRESULT) {
+ int ret_size = * (guint16 *)(ip + 1);
+ char *ret_vt_sp = vt_sp;
+ vt_sp -= READ32(ip + 2);
+ if (ret_size > 0) {
+ memmove (vt_sp, ret_vt_sp, ret_size);
+ vt_sp += (ret_size + 7) & ~7;
}
+ ip += 4;
+ MINT_IN_BREAK;
}
- CASE (CEE_LDARG_S)
- ++ip;
- vt_alloc (ARG_TYPE (signature, *ip), sp, signature->pinvoke);
- stackval_from_data (ARG_TYPE (signature, *ip), sp, ARG_POS (*ip), signature->pinvoke);
- ++sp;
- ++ip;
- BREAK;
- CASE (CEE_LDARGA_S) {
- MonoType *t;
- MonoClass *c;
-
- ++ip;
- t = ARG_TYPE (signature, *ip);
- c = mono_class_from_mono_type (t);
- sp->data.vt.klass = c;
- sp->data.vt.vt = ARG_POS (*ip);
-
- if (c->valuetype)
- sp->type = VAL_VALUETA;
- else
- sp->type = VAL_TP;
-
- ++sp;
- ++ip;
- BREAK;
- }
- CASE (CEE_STARG_S)
- ++ip;
- --sp;
- stackval_to_data (ARG_TYPE (signature, *ip), sp, ARG_POS (*ip), signature->pinvoke);
- vt_free (sp);
- ++ip;
- BREAK;
- CASE (CEE_LDLOC_S)
- ++ip;
- vt_alloc (LOCAL_TYPE (header, *ip), sp, FALSE);
- stackval_from_data (LOCAL_TYPE (header, *ip), sp, LOCAL_POS (*ip), FALSE);
- ++ip;
- ++sp;
- BREAK;
- CASE (CEE_LDLOCA_S) {
- MonoType *t;
- MonoClass *c;
-
- ++ip;
- t = LOCAL_TYPE (header, *ip);
- c = mono_class_from_mono_type (t);
- sp->data.vt.klass = c;
- sp->data.p = LOCAL_POS (*ip);
-
- if (c->valuetype)
- sp->type = VAL_VALUETA;
- else
- sp->type = VAL_TP;
-
- ++sp;
- ++ip;
- BREAK;
- }
- CASE (CEE_STLOC_S)
- ++ip;
- --sp;
- stackval_to_data (LOCAL_TYPE (header, *ip), sp, LOCAL_POS (*ip), FALSE);
- vt_free (sp);
- ++ip;
- BREAK;
- CASE (CEE_LDNULL)
- ++ip;
- sp->type = VAL_OBJ;
- sp->data.p = NULL;
- sp->data.vt.klass = NULL;
- ++sp;
- BREAK;
- CASE (CEE_LDC_I4_M1)
- ++ip;
- sp->type = VAL_I32;
- sp->data.i = -1;
- ++sp;
- BREAK;
- CASE (CEE_LDC_I4_0)
- CASE (CEE_LDC_I4_1)
- CASE (CEE_LDC_I4_2)
- CASE (CEE_LDC_I4_3)
- CASE (CEE_LDC_I4_4)
- CASE (CEE_LDC_I4_5)
- CASE (CEE_LDC_I4_6)
- CASE (CEE_LDC_I4_7)
- CASE (CEE_LDC_I4_8)
- sp->type = VAL_I32;
- sp->data.i = (*ip) - CEE_LDC_I4_0;
+#define LDC(n) do { sp->data.i = (n); ++ip; ++sp; } while (0)
+ MINT_IN_CASE(MINT_LDC_I4_M1)
+ LDC(-1);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDC_I4_0)
+ LDC(0);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDC_I4_1)
+ LDC(1);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDC_I4_2)
+ LDC(2);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDC_I4_3)
+ LDC(3);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDC_I4_4)
+ LDC(4);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDC_I4_5)
+ LDC(5);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDC_I4_6)
+ LDC(6);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDC_I4_7)
+ LDC(7);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDC_I4_8)
+ LDC(8);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDC_I4_S)
+ sp->data.i = *(const short *)(ip + 1);
+ ip += 2;
++sp;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDC_I4)
++ip;
- BREAK;
- CASE (CEE_LDC_I4_S)
- ++ip;
- sp->type = VAL_I32;
- sp->data.i = *(const gint8 *)ip;
- ++ip;
+ sp->data.i = READ32 (ip);
+ ip += 2;
++sp;
- BREAK;
- CASE (CEE_LDC_I4)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDC_I8)
++ip;
- sp->type = VAL_I32;
- sp->data.i = read32 (ip);
+ sp->data.l = READ64 (ip);
ip += 4;
++sp;
- BREAK;
- CASE (CEE_LDC_I8)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDC_R4) {
+ guint32 val;
++ip;
- sp->type = VAL_I64;
- sp->data.l = read64 (ip);
- ip += 8;
- ++sp;
- BREAK;
- CASE (CEE_LDC_R4) {
- float val;
- ++ip;
- sp->type = VAL_DOUBLE;
- readr4 (ip, &val);
- sp->data.f = val;
- ip += 4;
+ val = READ32(ip);
+ sp->data.f = * (float *)&val;
+ ip += 2;
++sp;
- BREAK;
+ MINT_IN_BREAK;
}
- CASE (CEE_LDC_R8)
- ++ip;
- sp->type = VAL_DOUBLE;
- readr8(ip, &sp->data.f);
- ip += 8;
+ MINT_IN_CASE(MINT_LDC_R8)
+ sp->data.l = READ64 (ip + 1); /* note union usage */
+ ip += 5;
+ ++sp;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_DUP)
+ sp [0] = sp[-1];
++sp;
- BREAK;
- CASE (CEE_UNUSED99) ves_abort (); BREAK;
- CASE (CEE_DUP)
- if (sp [-1].type == VAL_VALUET) {
- MonoClass *c = sp [-1].data.vt.klass;
- vt_alloc (&c->byval_arg, sp, FALSE);
- stackval_from_data (&c->byval_arg, sp, sp [-1].data.vt.vt, FALSE);
- } else {
- *sp = sp [-1];
- }
- ++sp;
++ip;
- BREAK;
- CASE (CEE_POP)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_DUP_VT)
+ i32 = READ32 (ip + 1);
+ sp->data.p = vt_sp;
+ memcpy(sp->data.p, sp [-1].data.p, i32);
+ vt_sp += (i32 + 7) & ~7;
+ ++sp;
+ ip += 3;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_POP)
++ip;
--sp;
- vt_free (sp);
- BREAK;
- CASE (CEE_JMP) ves_abort(); BREAK;
- CASE (CEE_CALLVIRT) /* Fall through */
- CASE (CEE_CALLI) /* Fall through */
- CASE (CEE_CALL) {
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_JMP) {
+ RuntimeMethod *new_method = rtm->data_items [* (guint16 *)(ip + 1)];
+ if (!new_method->transformed) {
+ frame->ip = ip;
+ frame->ex = mono_interp_transform_method (new_method, context);
+ if (frame->ex)
+ goto exit_frame;
+ }
+ ip += 2;
+ if (new_method->alloca_size > rtm->alloca_size)
+ g_error ("MINT_JMP to method which needs more stack space (%d > %d)", new_method->alloca_size, rtm->alloca_size);
+ rtm = frame->runtime_method = new_method;
+ vt_sp = (char *)sp + rtm->stack_size;
+#if DEBUG_INTERP
+ vtalloc = vt_sp;
+#endif
+ locals = vt_sp + rtm->vt_stack_size;
+ ip = rtm->new_body_start; /* bypass storing input args from callers frame */
+ MINT_IN_BREAK;
+ }
+ MINT_IN_CASE(MINT_CALLI) {
MonoMethodSignature *csignature;
- stackval retval;
stackval *endsp = sp;
- guint32 token;
- int virtual = *ip == CEE_CALLVIRT;
- int calli = *ip == CEE_CALLI;
- unsigned char *code = NULL;
-
- /*
- * We ignore tail recursion for now.
- */
- tail_recursion = 0;
frame->ip = ip;
- ++ip;
- token = read32 (ip);
- ip += 4;
- if (calli) {
- MonoJitInfo *ji;
- --sp;
- code = sp->data.p;
- if (frame->method->wrapper_type != MONO_WRAPPER_NONE) {
- csignature = (MonoMethodSignature *)mono_method_get_wrapper_data (frame->method, token);
- child_frame.method = NULL;
- } else if ((ji = mono_jit_info_table_find (mono_root_domain, code))) {
- child_frame.method = ji->method;
- } else {
- g_assert_not_reached ();
- }
- g_assert (code);
- } else {
- child_frame.method = mono_get_method (image, token, NULL);
- if (!child_frame.method)
- THROW_EX (mono_get_exception_missing_method (), ip -5);
- csignature = child_frame.method->signature;
- if (virtual) {
- stackval *this_arg = &sp [-csignature->param_count-1];
- if (!this_arg->data.p)
- THROW_EX (mono_get_exception_null_reference(), ip - 5);
- child_frame.method = get_virtual_method (domain, child_frame.method, this_arg);
- if (!child_frame.method)
- THROW_EX (mono_get_exception_missing_method (), ip -5);
- }
- }
+ csignature = rtm->data_items [* (guint16 *)(ip + 1)];
+ ip += 2;
+ --sp;
+ --endsp;
+ child_frame.runtime_method = sp->data.p;
- g_assert (csignature->call_convention == MONO_CALL_DEFAULT);
+ sp->data.p = vt_sp;
+ child_frame.retval = sp;
/* decrement by the actual number of args */
- if (csignature->param_count) {
- sp -= csignature->param_count;
- child_frame.stack_args = sp;
- } else {
- child_frame.stack_args = NULL;
- }
+ sp -= csignature->param_count;
+ child_frame.stack_args = sp;
if (csignature->hasthis) {
- g_assert (sp >= frame->stack);
--sp;
- /*
- * It may also be a TP from LD(S)FLDA
- * g_assert (sp->type == VAL_OBJ || sp->type == VAL_VALUETA);
- */
- if (sp->type == VAL_OBJ && child_frame.method &&
- child_frame.method->klass->valuetype) /* unbox it */
- child_frame.obj = (char*)sp->data.p + sizeof (MonoObject);
- else
- child_frame.obj = sp->data.p;
+ child_frame.obj = sp->data.p;
} else {
child_frame.obj = NULL;
}
- if (csignature->ret->type != MONO_TYPE_VOID) {
- vt_alloc (csignature->ret, &retval, csignature->pinvoke);
- child_frame.retval = &retval;
- } else {
- child_frame.retval = NULL;
- }
+ if (csignature->hasthis &&
+ ((MonoObject *)child_frame.obj)->vtable->klass == mono_defaults.transparent_proxy_class) {
+ child_frame.runtime_method = mono_interp_get_runtime_method (
+ mono_marshal_get_remoting_invoke (child_frame.runtime_method->method));
+ } else if (child_frame.runtime_method->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
+ child_frame.runtime_method = mono_interp_get_runtime_method (
+ mono_marshal_get_native_wrapper (child_frame.runtime_method->method));
- child_frame.ex = NULL;
- child_frame.ex_handler = NULL;
-
- if (!child_frame.method) {
- g_assert (code);
- ves_pinvoke_method (&child_frame, csignature, (MonoFunc) code, FALSE);
- } else if (csignature->hasthis && sp->type == VAL_OBJ &&
- ((MonoObject *)sp->data.p)->vtable->klass == mono_defaults.transparent_proxy_class) {
- g_assert (child_frame.method);
- child_frame.method = mono_marshal_get_remoting_invoke (child_frame.method);
- ves_exec_method (&child_frame);
- } else {
- switch (GPOINTER_TO_UINT (child_frame.method->addr)) {
- case INLINE_STRING_LENGTH:
- retval.type = VAL_I32;
- retval.data.i = ((MonoString*)sp->data.p)->length;
- /*g_print ("length of '%s' is %d\n", mono_string_to_utf8 (sp->data.p), retval.data.i);*/
- break;
- case INLINE_ARRAY_LENGTH:
- retval.type = VAL_I32;
- retval.data.i = mono_array_length ((MonoArray*)sp->data.p);
- break;
- case INLINE_ARRAY_RANK:
- retval.type = VAL_I32;
- retval.data.i = mono_object_class (sp->data.p)->rank;
- break;
- case INLINE_TYPE_ELEMENT_TYPE:
- retval.type = VAL_OBJ;
- {
- MonoClass *c = mono_class_from_mono_type (((MonoReflectionType*)sp->data.p)->type);
- retval.data.vt.klass = NULL;
- if (c->enumtype && c->enum_basetype) /* types that are modifierd typebuilkders may not have enum_basetype set */
- retval.data.p = mono_type_get_object (domain, c->enum_basetype);
- else if (c->element_class)
- retval.data.p = mono_type_get_object (domain, &c->element_class->byval_arg);
- else
- retval.data.p = NULL;
- }
- break;
- default:
- ves_exec_method (&child_frame);
- }
- }
+ ves_exec_method_with_context (&child_frame, context);
- while (endsp > sp) {
- --endsp;
- vt_free (endsp);
- }
+ context->current_frame = frame;
if (child_frame.ex) {
/*
/* need to handle typedbyref ... */
if (csignature->ret->type != MONO_TYPE_VOID) {
- *sp = retval;
+ *sp = *endsp;
sp++;
}
- BREAK;
+ MINT_IN_BREAK;
}
- CASE (CEE_RET)
- if (signature->ret->type != MONO_TYPE_VOID) {
- --sp;
- if (sp->type == VAL_VALUET) {
- /* the caller has already allocated the memory */
- stackval_from_data (signature->ret, frame->retval, sp->data.vt.vt, signature->pinvoke);
- vt_free (sp);
- } else {
- *frame->retval = *sp;
- }
- }
- if (sp > frame->stack)
- g_warning ("more values on stack: %d", sp-frame->stack);
+ MINT_IN_CASE(MINT_CALLI_NAT) {
+ MonoMethodSignature *csignature;
+ stackval *endsp = sp;
+ unsigned char *code = NULL;
- DEBUG_LEAVE ();
- return;
- CASE (CEE_BR_S) /* Fall through */
- CASE (CEE_BR)
- if (*ip == CEE_BR) {
- ++ip;
- ip += (gint32) read32(ip);
- ip += 4;
+ frame->ip = ip;
+
+ csignature = rtm->data_items [* (guint16 *)(ip + 1)];
+ ip += 2;
+ --sp;
+ --endsp;
+ code = sp->data.p;
+ child_frame.runtime_method = NULL;
+
+ sp->data.p = vt_sp;
+ child_frame.retval = sp;
+ /* decrement by the actual number of args */
+ sp -= csignature->param_count;
+ child_frame.stack_args = sp;
+ if (csignature->hasthis) {
+ --sp;
+ child_frame.obj = sp->data.p;
} else {
- ++ip;
- ip += (signed char) *ip;
- ++ip;
+ child_frame.obj = NULL;
}
- BREAK;
- CASE (CEE_BRFALSE) /* Fall through */
- CASE (CEE_BRFALSE_S) {
- int result;
- int broffset;
- if (*ip == CEE_BRFALSE_S) {
- broffset = (signed char)ip [1];
- ip += 2;
- } else {
- broffset = (gint32) read32 (ip + 1);
- ip += 5;
+ ves_pinvoke_method (&child_frame, csignature, (MonoFunc) code, FALSE, context);
+
+ context->current_frame = frame;
+
+ if (child_frame.ex) {
+ /*
+ * An exception occurred, need to run finally, fault and catch handlers..
+ */
+ frame->ex = child_frame.ex;
+ if (context->search_for_handler) {
+ context->search_for_handler = 0;
+ goto handle_exception;
+ }
+ goto handle_finally;
}
- --sp;
- switch (sp->type) {
- case VAL_I32: result = sp->data.i == 0; break;
- case VAL_I64: result = sp->data.l == 0; break;
- case VAL_DOUBLE: result = sp->data.f ? 0: 1; break;
- default: result = sp->data.p == NULL; break;
+
+ /* need to handle typedbyref ... */
+ if (csignature->ret->type != MONO_TYPE_VOID) {
+ *sp = *endsp;
+ sp++;
}
- if (result)
- ip += broffset;
- BREAK;
+ MINT_IN_BREAK;
}
- CASE (CEE_BRTRUE) /* Fall through */
- CASE (CEE_BRTRUE_S) {
- int result;
- int broffset;
- if (*ip == CEE_BRTRUE_S) {
- broffset = (signed char)ip [1];
- ip += 2;
+ MINT_IN_CASE(MINT_CALL) {
+ stackval *endsp = sp;
+
+ frame->ip = ip;
+
+ child_frame.runtime_method = rtm->data_items [* (guint16 *)(ip + 1)];
+ ip += 2;
+ sp->data.p = vt_sp;
+ 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) {
+ --sp;
+ child_frame.obj = sp->data.p;
} else {
- broffset = (gint32) read32 (ip + 1);
- ip += 5;
+ child_frame.obj = NULL;
}
- --sp;
- switch (sp->type) {
- case VAL_I32: result = sp->data.i != 0; break;
- case VAL_I64: result = sp->data.l != 0; break;
- case VAL_DOUBLE: result = sp->data.f ? 1 : 0; break;
- default: result = sp->data.p != NULL; break;
+ if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype &&
+ ((MonoObject *)child_frame.obj)->vtable->klass == mono_defaults.transparent_proxy_class) {
+ child_frame.runtime_method = mono_interp_get_runtime_method (
+ mono_marshal_get_remoting_invoke (child_frame.runtime_method->method));
}
- if (result)
- ip += broffset;
- BREAK;
- }
- CASE (CEE_BEQ) /* Fall through */
- CASE (CEE_BEQ_S) {
- int result;
- int broffset;
- if (*ip == CEE_BEQ_S) {
- broffset = (signed char)ip [1];
- ip += 2;
- } else {
- broffset = (gint32) read32 (ip + 1);
- ip += 5;
+ ves_exec_method_with_context (&child_frame, context);
+
+ context->current_frame = frame;
+
+ if (child_frame.ex) {
+ /*
+ * An exception occurred, need to run finally, fault and catch handlers..
+ */
+ frame->ex = child_frame.ex;
+ goto handle_finally;
}
- sp -= 2;
- if (sp->type == VAL_I32)
- result = sp [0].data.i == (gint)GET_NATI (sp [1]);
- else if (sp->type == VAL_I64)
- result = sp [0].data.l == sp [1].data.l;
- else if (sp->type == VAL_DOUBLE)
- result = sp [0].data.f == sp [1].data.f;
- else
- result = (gint)GET_NATI (sp [0]) == (gint)GET_NATI (sp [1]);
- if (result)
- ip += broffset;
- BREAK;
+
+ /* need to handle typedbyref ... */
+ *sp = *endsp;
+ sp++;
+ MINT_IN_BREAK;
}
- CASE (CEE_BGE) /* Fall through */
- CASE (CEE_BGE_S) {
- int result;
- int broffset;
- if (*ip == CEE_BGE_S) {
- broffset = (signed char)ip [1];
- ip += 2;
+ MINT_IN_CASE(MINT_VCALL) {
+ frame->ip = ip;
+
+ child_frame.runtime_method = rtm->data_items [* (guint16 *)(ip + 1)];
+ ip += 2;
+
+ sp->data.p = vt_sp;
+ 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) {
+ --sp;
+ child_frame.obj = sp->data.p;
} else {
- broffset = (gint32) read32 (ip + 1);
- ip += 5;
+ child_frame.obj = NULL;
}
- sp -= 2;
- if (sp->type == VAL_I32)
- result = sp [0].data.i >= (gint)GET_NATI (sp [1]);
- else if (sp->type == VAL_I64)
- result = sp [0].data.l >= sp [1].data.l;
- else if (sp->type == VAL_DOUBLE)
- result = sp [0].data.f >= sp [1].data.f;
- else
- result = (gint)GET_NATI (sp [0]) >= (gint)GET_NATI (sp [1]);
- if (result)
- ip += broffset;
- BREAK;
- }
- CASE (CEE_BGT) /* Fall through */
- CASE (CEE_BGT_S) {
- int result;
- int broffset;
- if (*ip == CEE_BGT_S) {
- broffset = (signed char)ip [1];
- ip += 2;
- } else {
- broffset = (gint32) read32 (ip + 1);
- ip += 5;
+
+ if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype &&
+ ((MonoObject *)child_frame.obj)->vtable->klass == mono_defaults.transparent_proxy_class) {
+ child_frame.runtime_method = mono_interp_get_runtime_method (
+ mono_marshal_get_remoting_invoke (child_frame.runtime_method->method));
}
- sp -= 2;
- if (sp->type == VAL_I32)
- result = sp [0].data.i > (gint)GET_NATI (sp [1]);
- else if (sp->type == VAL_I64)
- result = sp [0].data.l > sp [1].data.l;
- else if (sp->type == VAL_DOUBLE)
- result = sp [0].data.f > sp [1].data.f;
- else
- result = (gint)GET_NATI (sp [0]) > (gint)GET_NATI (sp [1]);
- if (result)
- ip += broffset;
- BREAK;
- }
- CASE (CEE_BLT) /* Fall through */
- CASE (CEE_BLT_S) {
- int result;
- int broffset;
- if (*ip == CEE_BLT_S) {
- broffset = (signed char)ip [1];
- ip += 2;
- } else {
- broffset = (gint32) read32 (ip + 1);
- ip += 5;
+
+ ves_exec_method_with_context (&child_frame, context);
+
+ context->current_frame = frame;
+
+ if (child_frame.ex) {
+ /*
+ * An exception occurred, need to run finally, fault and catch handlers..
+ */
+ frame->ex = child_frame.ex;
+ goto handle_finally;
}
- sp -= 2;
- if (sp->type == VAL_I32)
- result = sp[0].data.i < (gint)GET_NATI(sp[1]);
- else if (sp->type == VAL_I64)
- result = sp[0].data.l < sp[1].data.l;
- else if (sp->type == VAL_DOUBLE)
- result = sp[0].data.f < sp[1].data.f;
- else
- result = (gint)GET_NATI(sp[0]) < (gint)GET_NATI(sp[1]);
- if (result)
- ip += broffset;
- BREAK;
+ MINT_IN_BREAK;
}
- CASE (CEE_BLE) /* fall through */
- CASE (CEE_BLE_S) {
- int result;
- int broffset;
- if (*ip == CEE_BLE_S) {
- broffset = (signed char)ip [1];
- ip += 2;
- } else {
- broffset = (gint32) read32 (ip + 1);
- ip += 5;
+ MINT_IN_CASE(MINT_CALLVIRT) {
+ stackval *endsp = sp;
+ MonoObject *this_arg;
+ guint32 token;
+
+ frame->ip = ip;
+
+ token = * (unsigned short *)(ip + 1);
+ ip += 2;
+ child_frame.runtime_method = rtm->data_items [token];
+ sp->data.p = vt_sp;
+ child_frame.retval = sp;
+
+ /* decrement by the actual number of args */
+ sp -= child_frame.runtime_method->param_count;
+ child_frame.stack_args = sp;
+ --sp;
+ child_frame.obj = this_arg = sp->data.p;
+ if (!this_arg)
+ THROW_EX (mono_get_exception_null_reference(), ip - 2);
+ child_frame.runtime_method = get_virtual_method (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);
}
- sp -= 2;
- if (sp->type == VAL_I32)
- result = sp [0].data.i <= (gint)GET_NATI (sp [1]);
- else if (sp->type == VAL_I64)
- result = sp [0].data.l <= sp [1].data.l;
- else if (sp->type == VAL_DOUBLE)
- result = sp [0].data.f <= sp [1].data.f;
- else {
+ ves_exec_method_with_context (&child_frame, context);
+
+ context->current_frame = frame;
+
+ if (child_frame.ex) {
/*
- * FIXME: here and in other places GET_NATI on the left side
- * _will_ be wrong when we change the macro to work on 64 bits
- * systems.
+ * An exception occurred, need to run finally, fault and catch handlers..
*/
- result = (gint)GET_NATI (sp [0]) <= (gint)GET_NATI (sp [1]);
- }
- if (result)
- ip += broffset;
- BREAK;
- }
- CASE (CEE_BNE_UN) /* Fall through */
- CASE (CEE_BNE_UN_S) {
- int result;
- int broffset;
- if (*ip == CEE_BNE_UN_S) {
- broffset = (signed char)ip [1];
- ip += 2;
- } else {
- broffset = (gint32) read32 (ip + 1);
- ip += 5;
+ frame->ex = child_frame.ex;
+ if (context->search_for_handler) {
+ context->search_for_handler = 0;
+ goto handle_exception;
+ }
+ goto handle_finally;
}
- sp -= 2;
- if (sp->type == VAL_I32)
- result = (guint32)sp [0].data.i != (guint32)GET_NATI (sp [1]);
- else if (sp->type == VAL_I64)
- result = (guint64)sp [0].data.l != (guint64)sp [1].data.l;
- else if (sp->type == VAL_DOUBLE)
- result = isunordered (sp [0].data.f, sp [1].data.f) ||
- (sp [0].data.f != sp [1].data.f);
- else
- result = GET_NATI (sp [0]) != GET_NATI (sp [1]);
- if (result)
- ip += broffset;
- BREAK;
+
+ /* need to handle typedbyref ... */
+ *sp = *endsp;
+ sp++;
+ MINT_IN_BREAK;
}
- CASE (CEE_BGE_UN) /* Fall through */
- CASE (CEE_BGE_UN_S) {
- int result;
- int broffset;
- if (*ip == CEE_BGE_UN_S) {
- broffset = (signed char)ip [1];
- ip += 2;
- } else {
- broffset = (gint32) read32 (ip + 1);
- ip += 5;
+ MINT_IN_CASE(MINT_VCALLVIRT) {
+ MonoObject *this_arg;
+ guint32 token;
+
+ frame->ip = ip;
+
+ token = * (unsigned short *)(ip + 1);
+ ip += 2;
+ child_frame.runtime_method = rtm->data_items [token];
+ sp->data.p = vt_sp;
+ child_frame.retval = sp;
+
+ /* decrement by the actual number of args */
+ sp -= child_frame.runtime_method->param_count;
+ child_frame.stack_args = sp;
+ --sp;
+ child_frame.obj = this_arg = sp->data.p;
+ if (!this_arg)
+ THROW_EX (mono_get_exception_null_reference(), ip - 2);
+ child_frame.runtime_method = get_virtual_method (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);
}
- sp -= 2;
- if (sp->type == VAL_I32)
- result = (guint32)sp [0].data.i >= (guint32)GET_NATI (sp [1]);
- else if (sp->type == VAL_I64)
- result = (guint64)sp [0].data.l >= (guint64)sp [1].data.l;
- else if (sp->type == VAL_DOUBLE)
- result = !isless (sp [0].data.f,sp [1].data.f);
- else
- result = GET_NATI (sp [0]) >= GET_NATI (sp [1]);
- if (result)
- ip += broffset;
- BREAK;
- }
- CASE (CEE_BGT_UN) /* Fall through */
- CASE (CEE_BGT_UN_S) {
- int result;
- int broffset;
- if (*ip == CEE_BGT_UN_S) {
- broffset = (signed char)ip [1];
- ip += 2;
- } else {
- broffset = (gint32) read32 (ip + 1);
- ip += 5;
+
+ ves_exec_method_with_context (&child_frame, context);
+
+ context->current_frame = frame;
+
+ if (child_frame.ex) {
+ /*
+ * An exception occurred, need to run finally, fault and catch handlers..
+ */
+ frame->ex = child_frame.ex;
+ if (context->search_for_handler) {
+ context->search_for_handler = 0;
+ goto handle_exception;
+ }
+ goto handle_finally;
}
- sp -= 2;
- if (sp->type == VAL_I32)
- result = (guint32)sp [0].data.i > (guint32)GET_NATI (sp [1]);
- else if (sp->type == VAL_I64)
- result = (guint64)sp [0].data.l > (guint64)sp [1].data.l;
- else if (sp->type == VAL_DOUBLE)
- result = isgreater (sp [0].data.f, sp [1].data.f);
- else
- result = GET_NATI (sp [0]) > GET_NATI (sp [1]);
- if (result)
- ip += broffset;
- BREAK;
+ MINT_IN_BREAK;
}
- CASE (CEE_BLE_UN) /* Fall through */
- CASE (CEE_BLE_UN_S) {
- int result;
- int broffset;
- if (*ip == CEE_BLE_UN_S) {
- broffset = (signed char)ip [1];
- ip += 2;
- } else {
- broffset = (gint32) read32 (ip + 1);
- ip += 5;
+ 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;
}
- sp -= 2;
- if (sp->type == VAL_I32)
- result = (guint32)sp [0].data.i <= (guint32)GET_NATI (sp [1]);
- else if (sp->type == VAL_I64)
- result = (guint64)sp [0].data.l <= (guint64)sp [1].data.l;
- else if (sp->type == VAL_DOUBLE)
- result = islessequal (sp [0].data.f, sp [1].data.f);
- else
- result = GET_NATI (sp [0]) <= GET_NATI (sp [1]);
- if (result)
- ip += broffset;
- BREAK;
- }
- CASE (CEE_BLT_UN) /* Fall through */
- CASE (CEE_BLT_UN_S) {
- int result;
- int broffset;
- if (*ip == CEE_BLT_UN_S) {
- broffset = (signed char)ip [1];
- ip += 2;
- } else {
- broffset = (gint32) read32 (ip + 1);
- ip += 5;
+ goto exit_frame;
+ MINT_IN_CASE(MINT_CALLRUN)
+ ves_runtime_method (frame, context);
+ if (frame->ex) {
+ rtm = NULL;
+ goto handle_exception;
}
- sp -= 2;
- if (sp->type == VAL_I32)
- result = (guint32)sp[0].data.i < (guint32)GET_NATI(sp[1]);
- else if (sp->type == VAL_I64)
- result = (guint64)sp[0].data.l < (guint64)sp[1].data.l;
- else if (sp->type == VAL_DOUBLE)
- result = isunordered (sp [0].data.f, sp [1].data.f) ||
- (sp [0].data.f < sp [1].data.f);
- else
- result = GET_NATI(sp[0]) < GET_NATI(sp[1]);
- if (result)
- ip += broffset;
- BREAK;
- }
- CASE (CEE_SWITCH) {
+ goto exit_frame;
+ MINT_IN_CASE(MINT_RET)
+ --sp;
+ *frame->retval = *sp;
+ if (sp > frame->stack)
+ g_warning ("ret: more values on stack: %d", sp-frame->stack);
+ goto exit_frame;
+ MINT_IN_CASE(MINT_RET_VOID)
+ if (sp > frame->stack)
+ g_warning ("ret.void: more values on stack: %d", sp-frame->stack);
+ goto exit_frame;
+ MINT_IN_CASE(MINT_RET_VT)
+ i32 = READ32(ip + 1);
+ --sp;
+ memcpy(frame->retval->data.p, sp->data.p, i32);
+ if (sp > frame->stack)
+ g_warning ("ret.vt: more values on stack: %d", sp-frame->stack);
+ goto exit_frame;
+ MINT_IN_CASE(MINT_BR_S)
+ ip += (short) *(ip + 1);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BR)
+ ip += (gint32) READ32(ip + 1);
+ MINT_IN_BREAK;
+#define ZEROP_S(datamem, op) \
+ --sp; \
+ if (sp->data.datamem op 0) \
+ ip += * (gint16 *)(ip + 1); \
+ else \
+ ip += 2;
+
+#define ZEROP(datamem, op) \
+ --sp; \
+ if (sp->data.datamem op 0) \
+ ip += READ32(ip + 1); \
+ else \
+ ip += 3;
+
+ MINT_IN_CASE(MINT_BRFALSE_I4_S)
+ ZEROP_S(i, ==);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BRFALSE_I8_S)
+ ZEROP_S(l, ==);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BRFALSE_R8_S)
+ ZEROP_S(f, ==);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BRFALSE_I4)
+ ZEROP(i, ==);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BRFALSE_I8)
+ ZEROP(l, ==);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BRFALSE_R8)
+ ZEROP_S(f, ==);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BRTRUE_I4_S)
+ ZEROP_S(i, !=);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BRTRUE_I8_S)
+ ZEROP_S(l, !=);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BRTRUE_R8_S)
+ ZEROP_S(f, !=);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BRTRUE_I4)
+ ZEROP(i, !=);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BRTRUE_I8)
+ ZEROP(l, !=);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BRTRUE_R8)
+ ZEROP(f, !=);
+ MINT_IN_BREAK;
+#define CONDBR_S(cond) \
+ sp -= 2; \
+ if (cond) \
+ ip += * (gint16 *)(ip + 1); \
+ else \
+ ip += 2;
+#define BRELOP_S(datamem, op) \
+ CONDBR_S(sp[0].data.datamem op sp[1].data.datamem)
+
+#define CONDBR(cond) \
+ sp -= 2; \
+ if (cond) \
+ ip += READ32(ip + 1); \
+ else \
+ ip += 3;
+
+#define BRELOP(datamem, op) \
+ CONDBR(sp[0].data.datamem op sp[1].data.datamem)
+
+ MINT_IN_CASE(MINT_BEQ_I4_S)
+ BRELOP_S(i, ==)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BEQ_I8_S)
+ BRELOP_S(l, ==)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BEQ_R8_S)
+ CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BEQ_I4)
+ BRELOP(i, ==)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BEQ_I8)
+ BRELOP(l, ==)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BEQ_R8)
+ CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f == sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGE_I4_S)
+ BRELOP_S(i, >=)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGE_I8_S)
+ BRELOP_S(l, >=)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGE_R8_S)
+ CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGE_I4)
+ BRELOP(i, >=)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGE_I8)
+ BRELOP(l, >=)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGE_R8)
+ CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f >= sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGT_I4_S)
+ BRELOP_S(i, >)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGT_I8_S)
+ BRELOP_S(l, >)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGT_R8_S)
+ CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGT_I4)
+ BRELOP(i, >)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGT_I8)
+ BRELOP(l, >)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGT_R8)
+ CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f > sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLT_I4_S)
+ BRELOP_S(i, <)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLT_I8_S)
+ BRELOP_S(l, <)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLT_R8_S)
+ CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLT_I4)
+ BRELOP(i, <)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLT_I8)
+ BRELOP(l, <)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLT_R8)
+ CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f < sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLE_I4_S)
+ BRELOP_S(i, <=)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLE_I8_S)
+ BRELOP_S(l, <=)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLE_R8_S)
+ CONDBR_S(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLE_I4)
+ BRELOP(i, <=)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLE_I8)
+ BRELOP(l, <=)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLE_R8)
+ CONDBR(!isunordered (sp [0].data.f, sp [1].data.f) && sp[0].data.f <= sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BNE_UN_I4_S)
+ BRELOP_S(i, !=)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BNE_UN_I8_S)
+ BRELOP_S(l, !=)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BNE_UN_R8_S)
+ CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BNE_UN_I4)
+ BRELOP(i, !=)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BNE_UN_I8)
+ BRELOP(l, !=)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BNE_UN_R8)
+ CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f != sp[1].data.f)
+ MINT_IN_BREAK;
+
+#define BRELOP_S_CAST(datamem, op, type) \
+ sp -= 2; \
+ if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
+ ip += * (gint16 *)(ip + 1); \
+ else \
+ ip += 2;
+
+#define BRELOP_CAST(datamem, op, type) \
+ sp -= 2; \
+ if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
+ ip += READ32(ip + 1); \
+ else \
+ ip += 3;
+
+ MINT_IN_CASE(MINT_BGE_UN_I4_S)
+ BRELOP_S_CAST(i, >=, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGE_UN_I8_S)
+ BRELOP_S_CAST(l, >=, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGE_UN_R8_S)
+ CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGE_UN_I4)
+ BRELOP_CAST(i, >=, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGE_UN_I8)
+ BRELOP_CAST(l, >=, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGE_UN_R8)
+ CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f >= sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGT_UN_I4_S)
+ BRELOP_S_CAST(i, >, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGT_UN_I8_S)
+ BRELOP_S_CAST(l, >, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGT_UN_R8_S)
+ CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGT_UN_I4)
+ BRELOP_CAST(i, >, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGT_UN_I8)
+ BRELOP_CAST(l, >, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BGT_UN_R8)
+ CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f > sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLE_UN_I4_S)
+ BRELOP_S_CAST(i, <=, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLE_UN_I8_S)
+ BRELOP_S_CAST(l, <=, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLE_UN_R8_S)
+ CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLE_UN_I4)
+ BRELOP_CAST(i, <=, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLE_UN_I8)
+ BRELOP_CAST(l, <=, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLE_UN_R8)
+ CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f <= sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLT_UN_I4_S)
+ BRELOP_S_CAST(i, <, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLT_UN_I8_S)
+ BRELOP_S_CAST(l, <, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLT_UN_R8_S)
+ CONDBR_S(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLT_UN_I4)
+ BRELOP_CAST(i, <, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLT_UN_I8)
+ BRELOP_CAST(l, <, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BLT_UN_R8)
+ CONDBR(isunordered (sp [0].data.f, sp [1].data.f) || sp[0].data.f < sp[1].data.f)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SWITCH) {
guint32 n;
- const unsigned char *st;
+ const unsigned short *st;
++ip;
- n = read32 (ip);
- ip += 4;
- st = ip + sizeof (gint32) * n;
+ n = READ32 (ip);
+ ip += 2;
+ st = ip + 2 * n;
--sp;
if ((guint32)sp->data.i < n) {
gint offset;
- ip += sizeof (gint32) * (guint32)sp->data.i;
- offset = read32 (ip);
+ ip += 2 * (guint32)sp->data.i;
+ offset = READ32 (ip);
ip = st + offset;
} else {
ip = st;
}
- BREAK;
+ MINT_IN_BREAK;
}
- CASE (CEE_LDIND_I1)
+ MINT_IN_CASE(MINT_LDIND_I1)
++ip;
- sp[-1].type = VAL_I32;
sp[-1].data.i = *(gint8*)sp[-1].data.p;
- BREAK;
- CASE (CEE_LDIND_U1)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDIND_U1)
++ip;
- sp[-1].type = VAL_I32;
sp[-1].data.i = *(guint8*)sp[-1].data.p;
- BREAK;
- CASE (CEE_LDIND_I2)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDIND_I2)
++ip;
- sp[-1].type = VAL_I32;
sp[-1].data.i = *(gint16*)sp[-1].data.p;
- BREAK;
- CASE (CEE_LDIND_U2)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDIND_U2)
++ip;
- sp[-1].type = VAL_I32;
sp[-1].data.i = *(guint16*)sp[-1].data.p;
- BREAK;
- CASE (CEE_LDIND_I4) /* Fall through */
- CASE (CEE_LDIND_U4)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDIND_I4) /* Fall through */
+ MINT_IN_CASE(MINT_LDIND_U4)
++ip;
- sp[-1].type = VAL_I32;
sp[-1].data.i = *(gint32*)sp[-1].data.p;
- BREAK;
- CASE (CEE_LDIND_I8)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDIND_I8)
++ip;
- sp[-1].type = VAL_I64;
sp[-1].data.l = *(gint64*)sp[-1].data.p;
- BREAK;
- CASE (CEE_LDIND_I)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDIND_I)
++ip;
- sp[-1].type = VAL_NATI;
sp[-1].data.p = *(gpointer*)sp[-1].data.p;
- BREAK;
- CASE (CEE_LDIND_R4)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDIND_R4)
++ip;
- sp[-1].type = VAL_DOUBLE;
sp[-1].data.f = *(gfloat*)sp[-1].data.p;
- BREAK;
- CASE (CEE_LDIND_R8)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDIND_R8)
++ip;
- sp[-1].type = VAL_DOUBLE;
sp[-1].data.f = *(gdouble*)sp[-1].data.p;
- BREAK;
- CASE (CEE_LDIND_REF)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDIND_REF)
++ip;
- sp[-1].type = VAL_OBJ;
sp[-1].data.p = *(gpointer*)sp[-1].data.p;
- sp[-1].data.vt.klass = NULL;
- BREAK;
- CASE (CEE_STIND_REF) {
- gpointer *p;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STIND_REF)
++ip;
sp -= 2;
- p = sp->data.p;
- *p = sp[1].data.p;
- BREAK;
- }
- CASE (CEE_STIND_I1) {
- gint8 *p;
+ * (gpointer *) sp->data.p = sp[1].data.p;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STIND_I1)
++ip;
sp -= 2;
- p = sp->data.p;
- *p = (gint8)sp[1].data.i;
- BREAK;
- }
- CASE (CEE_STIND_I2) {
- gint16 *p;
+ * (gint8 *) sp->data.p = (gint8)sp[1].data.i;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STIND_I2)
++ip;
sp -= 2;
- p = sp->data.p;
- *p = (gint16)sp[1].data.i;
- BREAK;
- }
- CASE (CEE_STIND_I4) {
- gint32 *p;
+ * (gint16 *) sp->data.p = (gint16)sp[1].data.i;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STIND_I4)
++ip;
sp -= 2;
- p = sp->data.p;
- *p = sp[1].data.i;
- BREAK;
- }
- CASE (CEE_STIND_I) {
- mono_i *p;
+ * (gint32 *) sp->data.p = sp[1].data.i;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STIND_I)
++ip;
sp -= 2;
- p = sp->data.p;
- *p = (mono_i)sp[1].data.p;
- BREAK;
- }
- CASE (CEE_STIND_I8) {
- gint64 *p;
+ * (mono_i *) sp->data.p = (mono_i)sp[1].data.p;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STIND_I8)
++ip;
sp -= 2;
- p = sp->data.p;
- *p = sp[1].data.l;
- BREAK;
- }
- CASE (CEE_STIND_R4) {
- float *p;
+ * (gint64 *) sp->data.p = sp[1].data.l;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STIND_R4)
++ip;
sp -= 2;
- p = sp->data.p;
- *p = (gfloat)sp[1].data.f;
- BREAK;
- }
- CASE (CEE_STIND_R8) {
- double *p;
+ * (float *) sp->data.p = (gfloat)sp[1].data.f;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STIND_R8)
++ip;
sp -= 2;
- p = sp->data.p;
- *p = sp[1].data.f;
- BREAK;
- }
- CASE (CEE_ADD)
+ * (double *) sp->data.p = sp[1].data.f;
+ MINT_IN_BREAK;
+#define BINOP(datamem, op) \
+ --sp; \
+ sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.datamem; \
+ ++ip;
+ MINT_IN_CASE(MINT_ADD_I4)
+ BINOP(i, +);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_ADD_I8)
+ BINOP(l, +);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_ADD_R8)
+ BINOP(f, +);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_ADD1_I4)
+ ++sp [-1].data.i;
++ip;
- --sp;
- /* should probably consider the pointers as unsigned */
- if (sp->type == VAL_I32)
- sp [-1].data.i += GET_NATI (sp [0]);
- else if (sp->type == VAL_I64)
- sp [-1].data.l += sp [0].data.l;
- else if (sp->type == VAL_DOUBLE)
- sp [-1].data.f += sp [0].data.f;
- else {
- char *p = sp [-1].data.p;
- p += GET_NATI (sp [0]);
- sp [-1].data.p = p;
- }
- BREAK;
- CASE (CEE_SUB)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SUB_I4)
+ BINOP(i, -);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SUB_I8)
+ BINOP(l, -);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SUB_R8)
+ BINOP(f, -);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SUB1_I4)
+ --sp [-1].data.i;
++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_MUL_I4)
+ BINOP(i, *);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_MUL_I8)
+ BINOP(l, *);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_MUL_R8)
+ BINOP(f, *);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_DIV_I4)
+ if (sp [-1].data.i == 0)
+ THROW_EX (mono_get_exception_divide_by_zero (), ip);
+ BINOP(i, /);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_DIV_I8)
+ if (sp [-1].data.l == 0)
+ THROW_EX (mono_get_exception_divide_by_zero (), ip);
+ BINOP(l, /);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_DIV_R8)
+ BINOP(f, /);
+ MINT_IN_BREAK;
+
+#define BINOP_CAST(datamem, op, type) \
+ --sp; \
+ sp [-1].data.datamem = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
+ ++ip;
+ MINT_IN_CASE(MINT_DIV_UN_I4)
+ if (sp [-1].data.i == 0)
+ THROW_EX (mono_get_exception_divide_by_zero (), ip);
+ BINOP_CAST(i, /, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_DIV_UN_I8)
+ if (sp [-1].data.l == 0)
+ THROW_EX (mono_get_exception_divide_by_zero (), ip);
+ BINOP_CAST(l, /, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_REM_I4)
+ if (sp [-1].data.i == 0)
+ THROW_EX (mono_get_exception_divide_by_zero (), ip);
+ BINOP(i, %);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_REM_I8)
+ if (sp [-1].data.l == 0)
+ THROW_EX (mono_get_exception_divide_by_zero (), ip);
+ BINOP(l, %);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_REM_R8)
+ /* FIXME: what do we actually do here? */
--sp;
- /* should probably consider the pointers as unsigned */
- if (sp->type == VAL_I32)
- sp [-1].data.i -= GET_NATI (sp [0]);
- else if (sp->type == VAL_I64)
- sp [-1].data.l -= sp [0].data.l;
- else if (sp->type == VAL_DOUBLE)
- sp [-1].data.f -= sp [0].data.f;
- else {
- char *p = sp [-1].data.p;
- p -= GET_NATI (sp [0]);
- sp [-1].data.p = p;
- }
- BREAK;
- CASE (CEE_MUL)
+ sp [-1].data.f = fmod (sp [-1].data.f, sp [0].data.f);
++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_REM_UN_I4)
+ if (sp [-1].data.i == 0)
+ THROW_EX (mono_get_exception_divide_by_zero (), ip);
+ BINOP_CAST(i, %, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_REM_UN_I8)
+ if (sp [-1].data.l == 0)
+ THROW_EX (mono_get_exception_divide_by_zero (), ip);
+ BINOP_CAST(l, %, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_AND_I4)
+ BINOP(i, &);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_AND_I8)
+ BINOP(l, &);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_OR_I4)
+ BINOP(i, |);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_OR_I8)
+ BINOP(l, |);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_XOR_I4)
+ BINOP(i, ^);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_XOR_I8)
+ BINOP(l, ^);
+ MINT_IN_BREAK;
+
+#define SHIFTOP(datamem, op) \
+ --sp; \
+ sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.i; \
+ ++ip;
+
+ MINT_IN_CASE(MINT_SHL_I4)
+ SHIFTOP(i, <<);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SHL_I8)
+ SHIFTOP(l, <<);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SHR_I4)
+ SHIFTOP(i, >>);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SHR_I8)
+ SHIFTOP(l, >>);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SHR_UN_I4)
--sp;
- if (sp->type == VAL_I32)
- sp [-1].data.i *= (gint)GET_NATI (sp [0]);
- else if (sp->type == VAL_I64)
- sp [-1].data.l *= sp [0].data.l;
- else if (sp->type == VAL_DOUBLE)
- sp [-1].data.f *= sp [0].data.f;
- BREAK;
- CASE (CEE_DIV)
+ sp [-1].data.i = (guint32)sp [-1].data.i >> sp [0].data.i;
++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SHR_UN_I8)
--sp;
- if (sp->type == VAL_I32) {
- if (GET_NATI (sp [0]) == 0)
- THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
- sp [-1].data.i /= (gint)GET_NATI (sp [0]);
- } else if (sp->type == VAL_I64) {
- if (sp [0].data.l == 0)
- THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
- sp [-1].data.l /= sp [0].data.l;
- } else if (sp->type == VAL_DOUBLE) {
- /* set NaN is divisor is 0.0 */
- sp [-1].data.f /= sp [0].data.f;
- }
- BREAK;
- CASE (CEE_DIV_UN)
+ sp [-1].data.l = (guint64)sp [-1].data.l >> sp [0].data.i;
++ip;
- --sp;
- if (sp->type == VAL_I32) {
- guint32 val;
- if (GET_NATI (sp [0]) == 0)
- THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
- val = sp [-1].data.i;
- val /= (guint32)GET_NATI (sp [0]);
- sp [-1].data.i = val;
- } else if (sp->type == VAL_I64) {
- guint64 val;
- if (sp [0].data.l == 0)
- THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
- val = sp [-1].data.l;
- val /= (guint64)sp [0].data.l;
- sp [-1].data.l = val;
- } else if (sp->type == VAL_NATI) {
- mono_u val;
- if (GET_NATI (sp [0]) == 0)
- THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
- val = (mono_u)sp [-1].data.p;
- val /= (mono_u)sp [0].data.p;
- sp [-1].data.p = (gpointer)val;
- }
- BREAK;
- CASE (CEE_REM)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_NEG_I4)
+ sp [-1].data.i = - sp [-1].data.i;
++ip;
- --sp;
- if (sp->type == VAL_I32) {
- if (GET_NATI (sp [0]) == 0)
- THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
- sp [-1].data.i %= (gint)GET_NATI (sp [0]);
- } else if (sp->type == VAL_I64) {
- if (sp [0].data.l == 0)
- THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
- sp [-1].data.l %= sp [0].data.l;
- } else if (sp->type == VAL_DOUBLE) {
- /* FIXME: what do we actually do here? */
- sp [-1].data.f = fmod (sp [-1].data.f, sp [0].data.f);
- } else {
- if (GET_NATI (sp [0]) == 0)
- THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
- (gint)GET_NATI (sp [-1]) %= (gint)GET_NATI (sp [0]);
- }
- BREAK;
- CASE (CEE_REM_UN)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_NEG_I8)
+ sp [-1].data.l = - sp [-1].data.l;
++ip;
- --sp;
- if (sp->type == VAL_I32) {
- if (GET_NATI (sp [0]) == 0)
- THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
- (guint)sp [-1].data.i %= (guint)GET_NATI (sp [0]);
- } else if (sp->type == VAL_I64) {
- if (sp [0].data.l == 0)
- THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
- (guint64)sp [-1].data.l %= (guint64)sp [0].data.l;
- } else if (sp->type == VAL_DOUBLE) {
- /* unspecified behaviour according to the spec */
- } else {
- if (GET_NATI (sp [0]) == 0)
- THROW_EX (mono_get_exception_divide_by_zero (), ip - 1);
- (guint64)GET_NATI (sp [-1]) %= (guint64)GET_NATI (sp [0]);
- }
- BREAK;
- CASE (CEE_AND)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_NEG_R8)
+ sp [-1].data.f = - sp [-1].data.f;
++ip;
- --sp;
- if (sp->type == VAL_I32)
- sp [-1].data.i &= GET_NATI (sp [0]);
- else if (sp->type == VAL_I64)
- sp [-1].data.l &= sp [0].data.l;
- else
- GET_NATI (sp [-1]) &= GET_NATI (sp [0]);
- BREAK;
- CASE (CEE_OR)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_NOT_I4)
+ sp [-1].data.i = ~ sp [-1].data.i;
++ip;
- --sp;
- if (sp->type == VAL_I32)
- sp [-1].data.i |= GET_NATI (sp [0]);
- else if (sp->type == VAL_I64)
- sp [-1].data.l |= sp [0].data.l;
- else
- GET_NATI (sp [-1]) |= GET_NATI (sp [0]);
- BREAK;
- CASE (CEE_XOR)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_NOT_I8)
+ sp [-1].data.l = ~ sp [-1].data.l;
++ip;
- --sp;
- if (sp->type == VAL_I32)
- sp [-1].data.i ^= GET_NATI (sp [0]);
- else if (sp->type == VAL_I64)
- sp [-1].data.l ^= sp [0].data.l;
- else
- GET_NATI (sp [-1]) ^= GET_NATI (sp [0]);
- BREAK;
- CASE (CEE_SHL)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_I1_I4)
+ sp [-1].data.i = (gint8)sp [-1].data.i;
++ip;
- --sp;
- if (sp [-1].type == VAL_I32)
- sp [-1].data.i <<= GET_NATI (sp [0]);
- else if (sp [-1].type == VAL_I64)
- sp [-1].data.l <<= GET_NATI (sp [0]);
- else
- GET_NATI (sp [-1]) <<= GET_NATI (sp [0]);
- BREAK;
- CASE (CEE_SHR)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_I1_I8)
+ sp [-1].data.i = (gint8)sp [-1].data.l;
++ip;
- --sp;
- if (sp [-1].type == VAL_I32)
- sp [-1].data.i >>= GET_NATI (sp [0]);
- else if (sp [-1].type == VAL_I64)
- sp [-1].data.l >>= GET_NATI (sp [0]);
- else
- (gint)GET_NATI (sp [-1]) >>= GET_NATI (sp [0]);
- BREAK;
- CASE (CEE_SHR_UN)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_I1_R8)
+ sp [-1].data.i = (gint8)sp [-1].data.f;
++ip;
- --sp;
- if (sp [-1].type == VAL_I32)
- (guint)sp [-1].data.i >>= GET_NATI (sp [0]);
- else if (sp [-1].type == VAL_I64)
- (guint64)sp [-1].data.l >>= GET_NATI (sp [0]);
- else
- (guint64)GET_NATI (sp [-1]) >>= GET_NATI (sp [0]);
- BREAK;
- CASE (CEE_NEG)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_U1_I4)
+ sp [-1].data.i = (guint8)sp [-1].data.i;
++ip;
- --sp;
- if (sp->type == VAL_I32)
- sp->data.i = - sp->data.i;
- else if (sp->type == VAL_I64)
- sp->data.l = - sp->data.l;
- else if (sp->type == VAL_DOUBLE)
- sp->data.f = - sp->data.f;
- else if (sp->type == VAL_NATI)
- sp->data.p = (gpointer)(- (mono_i)sp->data.p);
- ++sp;
- BREAK;
- CASE (CEE_NOT)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_U1_I8)
+ sp [-1].data.i = (guint8)sp [-1].data.l;
++ip;
- --sp;
- if (sp->type == VAL_I32)
- sp->data.i = ~ sp->data.i;
- else if (sp->type == VAL_I64)
- sp->data.l = ~ sp->data.l;
- else if (sp->type == VAL_NATI)
- sp->data.p = (gpointer)(~ (mono_i)sp->data.p);
- ++sp;
- BREAK;
- CASE (CEE_CONV_U1) /* fall through */
- CASE (CEE_CONV_I1) {
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_U1_R8)
+ sp [-1].data.i = (guint8)sp [-1].data.f;
++ip;
- switch (sp [-1].type) {
- case VAL_DOUBLE:
- sp [-1].data.i = (gint8)sp [-1].data.f;
- break;
- case VAL_I64:
- sp [-1].data.i = (gint8)sp [-1].data.l;
- break;
- case VAL_VALUET:
- ves_abort();
- case VAL_I32:
- sp [-1].data.i = (gint8)sp [-1].data.i;
- break;
- default:
- sp [-1].data.i = (gint8)sp [-1].data.nati;
- break;
- }
- sp [-1].type = VAL_I32;
- BREAK;
- }
- CASE (CEE_CONV_U2) /* fall through */
- CASE (CEE_CONV_I2) {
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_I2_I4)
+ sp [-1].data.i = (gint16)sp [-1].data.i;
++ip;
- switch (sp [-1].type) {
- case VAL_DOUBLE:
- sp [-1].data.i = (gint16)sp [-1].data.f;
- break;
- case VAL_I64:
- sp [-1].data.i = (gint16)sp [-1].data.l;
- break;
- case VAL_VALUET:
- ves_abort();
- case VAL_I32:
- sp [-1].data.i = (gint16)sp [-1].data.i;
- break;
- default:
- sp [-1].data.i = (gint16)sp [-1].data.nati;
- break;
- }
- sp [-1].type = VAL_I32;
- BREAK;
- }
- CASE (CEE_CONV_U4) /* Fall through */
-#if SIZEOF_VOID_P == 4
- CASE (CEE_CONV_I) /* Fall through */
- CASE (CEE_CONV_U) /* Fall through */
-#endif
- CASE (CEE_CONV_I4) {
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_I2_I8)
+ sp [-1].data.i = (gint16)sp [-1].data.l;
++ip;
- switch (sp [-1].type) {
- case VAL_DOUBLE:
- sp [-1].data.i = (gint32)sp [-1].data.f;
- break;
- case VAL_I64:
- sp [-1].data.i = (gint32)sp [-1].data.l;
- break;
- case VAL_VALUET:
- ves_abort();
- case VAL_I32:
- break;
- default:
- sp [-1].data.i = (gint32)sp [-1].data.p;
- break;
- }
- sp [-1].type = VAL_I32;
- BREAK;
- }
-#if SIZEOF_VOID_P == 8
- CASE (CEE_CONV_I) /* Fall through */
-#endif
- CASE (CEE_CONV_I8)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_I2_R8)
+ sp [-1].data.i = (gint16)sp [-1].data.f;
++ip;
- switch (sp [-1].type) {
- case VAL_DOUBLE:
- sp [-1].data.l = (gint64)sp [-1].data.f;
- break;
- case VAL_I64:
- break;
- case VAL_VALUET:
- ves_abort();
- case VAL_I32:
- sp [-1].data.l = (gint64)sp [-1].data.i;
- break;
- default:
- sp [-1].data.l = (gint64)sp [-1].data.nati;
- break;
- }
- sp [-1].type = VAL_I64;
- BREAK;
- CASE (CEE_CONV_R4) {
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_U2_I4)
+ sp [-1].data.i = (guint16)sp [-1].data.i;
++ip;
- switch (sp [-1].type) {
- case VAL_DOUBLE:
- sp [-1].data.f = (float)sp [-1].data.f;
- break;
- case VAL_I64:
- sp [-1].data.f = (float)sp [-1].data.l;
- break;
- case VAL_VALUET:
- ves_abort();
- case VAL_I32:
- sp [-1].data.f = (float)sp [-1].data.i;
- break;
- default:
- sp [-1].data.f = (float)sp [-1].data.nati;
- break;
- }
- sp [-1].type = VAL_DOUBLE;
- BREAK;
- }
- CASE (CEE_CONV_R8) {
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_U2_I8)
+ sp [-1].data.i = (guint16)sp [-1].data.l;
++ip;
- switch (sp [-1].type) {
- case VAL_DOUBLE:
- sp [-1].data.f = (double)sp [-1].data.f;
- break;
- case VAL_I64:
- sp [-1].data.f = (double)sp [-1].data.l;
- break;
- case VAL_VALUET:
- ves_abort();
- case VAL_I32:
- sp [-1].data.f = (double)sp [-1].data.i;
- break;
- default:
- sp [-1].data.f = (double)sp [-1].data.nati;
- break;
- }
- sp [-1].type = VAL_DOUBLE;
- BREAK;
- }
-#if SIZEOF_VOID_P == 8
- CASE (CEE_CONV_U) /* Fall through */
-#endif
- CASE (CEE_CONV_U8)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_U2_R8)
+ sp [-1].data.i = (guint16)sp [-1].data.f;
++ip;
-
- switch (sp [-1].type){
- case VAL_DOUBLE:
- sp [-1].data.l = (guint64)sp [-1].data.f;
- break;
- case VAL_I64:
- break;
- case VAL_VALUET:
- ves_abort();
- case VAL_I32:
- sp [-1].data.l = sp [-1].data.i & 0xffffffff;
- break;
- default:
- sp [-1].data.l = (guint64) sp [-1].data.nati;
- break;
- }
- sp [-1].type = VAL_I64;
- BREAK;
- CASE (CEE_CPOBJ) {
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_I4_R8)
+ sp [-1].data.i = (gint32)sp [-1].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_U4_I8)
+ MINT_IN_CASE(MINT_CONV_I4_I8)
+ sp [-1].data.i = (gint32)sp [-1].data.l;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_I4_I8_SP)
+ sp [-2].data.i = (gint32)sp [-2].data.l;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_U4_R8)
+ sp [-1].data.i = (guint32)sp [-1].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_I8_I4)
+ sp [-1].data.l = sp [-1].data.i;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_I8_I4_SP)
+ sp [-2].data.l = sp [-2].data.i;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_I8_U4)
+ sp [-1].data.l = (guint32)sp [-1].data.i;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_I8_R8)
+ sp [-1].data.l = (gint64)sp [-1].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_R4_I4)
+ sp [-1].data.f = (float)sp [-1].data.i;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_R4_I8)
+ sp [-1].data.f = (float)sp [-1].data.l;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_R4_R8)
+ sp [-1].data.f = (float)sp [-1].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_R8_I4)
+ sp [-1].data.f = (double)sp [-1].data.i;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_R8_I8)
+ sp [-1].data.f = (double)sp [-1].data.l;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_U8_I4)
+ sp [-1].data.l = sp [-1].data.i & 0xffffffff;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_U8_R8)
+ sp [-1].data.l = (guint64)sp [-1].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+#if 0
+ MINT_IN_CASE(MINT_CPOBJ) {
MonoClass *vtklass;
++ip;
- vtklass = mono_class_get (image, read32 (ip));
- ip += 4;
+ vtklass = rtm->data_items[READ32 (ip)];
+ ip += 2;
sp -= 2;
memcpy (sp [0].data.p, sp [1].data.p, mono_class_value_size (vtklass, NULL));
- BREAK;
+ MINT_IN_BREAK;
}
- CASE (CEE_LDOBJ) {
- guint32 token;
- MonoClass *c;
- char *addr;
-
- ++ip;
- token = read32 (ip);
- ip += 4;
-
- if (frame->method->wrapper_type != MONO_WRAPPER_NONE)
- c = (MonoClass *)mono_method_get_wrapper_data (frame->method, token);
- else
- c = mono_class_get (image, token);
-
- addr = sp [-1].data.vt.vt;
- vt_alloc (&c->byval_arg, &sp [-1], FALSE);
- stackval_from_data (&c->byval_arg, &sp [-1], addr, FALSE);
- BREAK;
+#endif
+ MINT_IN_CASE(MINT_LDOBJ) {
+ int size;
+ void *p;
+ c = rtm->data_items[* (guint16 *)(ip + 1)];
+ ip += 2;
+ if (c->byval_arg.type != MONO_TYPE_VALUETYPE || c->byval_arg.data.klass->enumtype) {
+ p = sp [-1].data.p;
+ stackval_from_data (&c->byval_arg, &sp [-1], p, FALSE);
+ } else {
+ size = mono_class_value_size (c, NULL);
+ p = sp [-1].data.p;
+ sp [-1].data.p = vt_sp;
+ memcpy(vt_sp, p, size);
+ vt_sp += (size + 7) & ~7;
+ }
+ MINT_IN_BREAK;
}
- CASE (CEE_LDSTR) {
- MonoObject *o;
- guint32 str_index;
-
- ip++;
- str_index = mono_metadata_token_index (read32 (ip));
- ip += 4;
-
- o = (MonoObject*)mono_ldstr (domain, image, str_index);
- sp->type = VAL_OBJ;
- sp->data.p = o;
- sp->data.vt.klass = NULL;
-
+ MINT_IN_CASE(MINT_LDSTR)
+ sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
++sp;
- BREAK;
- }
- CASE (CEE_NEWOBJ) {
- MonoObject *o;
+ ip += 2;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_NEWOBJ) {
MonoClass *newobj_class;
MonoMethodSignature *csig;
stackval valuetype_this;
- stackval *endsp = sp;
guint32 token;
stackval retval;
frame->ip = ip;
- ip++;
- token = read32 (ip);
- ip += 4;
-
- if (!(child_frame.method = mono_get_method (image, token, NULL)))
- THROW_EX (mono_get_exception_missing_method (), ip -5);
+ token = * (guint16 *)(ip + 1);
+ ip += 2;
- csig = child_frame.method->signature;
- newobj_class = child_frame.method->klass;
+ child_frame.runtime_method = rtm->data_items [token];
+ csig = mono_method_signature (child_frame.runtime_method->method);
+ newobj_class = child_frame.runtime_method->method->klass;
/*if (profiling_classes) {
guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class));
count++;
if (newobj_class->parent == mono_defaults.array_class) {
sp -= csig->param_count;
- o = ves_array_create (domain, newobj_class, csig, sp);
+ o = ves_array_create (context->domain, newobj_class, csig, sp);
goto array_constructed;
}
* First arg is the object.
*/
if (newobj_class->valuetype) {
- void *zero;
- vt_alloc (&newobj_class->byval_arg, &valuetype_this, csig->pinvoke);
if (!newobj_class->enumtype && (newobj_class->byval_arg.type == MONO_TYPE_VALUETYPE)) {
- zero = valuetype_this.data.vt.vt;
- child_frame.obj = valuetype_this.data.vt.vt;
+ child_frame.obj = vt_sp;
+ valuetype_this.data.p = vt_sp;
} else {
memset (&valuetype_this, 0, sizeof (stackval));
- zero = &valuetype_this;
child_frame.obj = &valuetype_this;
}
- stackval_from_data (&newobj_class->byval_arg, &valuetype_this, zero, csig->pinvoke);
} else {
if (newobj_class != mono_defaults.string_class) {
- o = mono_object_new (domain, newobj_class);
+ context->managed_code = 0;
+ o = mono_object_new (context->domain, newobj_class);
+ context->managed_code = 1;
+ if (*abort_requested)
+ mono_thread_interruption_checkpoint ();
child_frame.obj = o;
} else {
child_frame.retval = &retval;
g_assert (csig->call_convention == MONO_CALL_DEFAULT);
+ child_frame.ip = NULL;
child_frame.ex = NULL;
- child_frame.ex_handler = NULL;
- ves_exec_method (&child_frame);
+ ves_exec_method_with_context (&child_frame, context);
- while (endsp > sp) {
- --endsp;
- vt_free (endsp);
- }
+ context->current_frame = frame;
if (child_frame.ex) {
/*
} else if (newobj_class == mono_defaults.string_class) {
*sp = retval;
} else {
- sp->type = VAL_OBJ;
sp->data.p = o;
- sp->data.vt.klass = newobj_class;
}
++sp;
- BREAK;
+ MINT_IN_BREAK;
}
- CASE (CEE_CASTCLASS) /* Fall through */
- CASE (CEE_ISINST) {
- MonoObject *o;
- MonoVTable *vt;
- MonoClass *c , *oclass;
- guint32 token;
- int do_isinst = *ip == CEE_ISINST;
-
- ++ip;
- token = read32 (ip);
- c = mono_class_get (image, token);
-
- g_assert (sp [-1].type == VAL_OBJ);
-
+ MINT_IN_CASE(MINT_CASTCLASS)
+ c = rtm->data_items [*(guint16 *)(ip + 1)];
if ((o = sp [-1].data.p)) {
- vt = o->vtable;
- oclass = vt->klass;
-
- if (mono_object_isinst (o, c)) {
- sp [-1].data.vt.klass = c;
+ if (c->marshalbyref) {
+ if (!mono_object_isinst_mbyref (o, c))
+ THROW_EX (mono_get_exception_invalid_cast (), ip);
+ } else {
+ MonoVTable *vt = o->vtable;
+ MonoClass *oklass = vt->klass;
+ if (c->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ 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) {
+ if (!mono_object_isinst (o, c))
+ THROW_EX (mono_get_exception_invalid_cast (), ip);
+ } else if (!mono_class_has_parent (oklass, c)) {
+ THROW_EX (mono_get_exception_invalid_cast (), ip);
+ }
}
- else {
- if (do_isinst) {
+ }
+ 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) {
+ if (!mono_object_isinst_mbyref (o, c))
sp [-1].data.p = NULL;
- sp [-1].data.vt.klass = NULL;
- } else
- THROW_EX (mono_get_exception_invalid_cast (), ip - 1);
+ } else {
+ MonoVTable *vt = o->vtable;
+ MonoClass *oklass = vt->klass;
+ if (c->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if (c->interface_id > vt->max_interface_id ||
+ vt->interface_offsets [c->interface_id] == 0) {
+ sp [-1].data.p = NULL;
+ }
+ } else if (c->rank) {
+ if (!mono_object_isinst (o, c))
+ sp [-1].data.p = NULL;
+ } else if (!mono_class_has_parent (oklass, c)) {
+ sp [-1].data.p = NULL;
+ }
}
}
- ip += 4;
- BREAK;
- }
- CASE (CEE_CONV_R_UN)
+ ip += 2;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_R_UN_I4)
+ sp [-1].data.f = (double)(guint32)sp [-1].data.i;
++ip;
- switch (sp [-1].type) {
- case VAL_DOUBLE:
- break;
- case VAL_I64:
- sp [-1].data.f = (double)(guint64)sp [-1].data.l;
- break;
- case VAL_VALUET:
- ves_abort();
- case VAL_I32:
- sp [-1].data.f = (double)(guint32)sp [-1].data.i;
- break;
- default:
- sp [-1].data.f = (double)(guint64)sp [-1].data.nati;
- break;
- }
- sp [-1].type = VAL_DOUBLE;
- BREAK;
- CASE (CEE_UNUSED58)
- CASE (CEE_UNUSED1) ves_abort(); BREAK;
- CASE (CEE_UNBOX) {
- MonoObject *o;
- MonoClass *c;
- guint32 token;
-
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_R_UN_I8)
+ sp [-1].data.f = (double)(guint64)sp [-1].data.l;
++ip;
- token = read32 (ip);
-
- if (frame->method->wrapper_type != MONO_WRAPPER_NONE)
- c = (MonoClass *)mono_method_get_wrapper_data (frame->method, token);
- else
- c = mono_class_get (image, token);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_UNBOX)
+ c = rtm->data_items[*(guint16 *)(ip + 1)];
o = sp [-1].data.p;
if (!o)
- THROW_EX (mono_get_exception_null_reference(), ip - 1);
+ THROW_EX (mono_get_exception_null_reference(), ip);
- if (o->vtable->klass->element_class->type_token != c->element_class->type_token)
- THROW_EX (mono_get_exception_invalid_cast (), ip - 1);
+ if (!(mono_object_isinst (o, c) ||
+ ((o->vtable->klass->rank == 0) &&
+ (o->vtable->klass->element_class == c->element_class))))
+ THROW_EX (mono_get_exception_invalid_cast (), ip);
- sp [-1].type = VAL_MP;
sp [-1].data.p = (char *)o + sizeof (MonoObject);
-
- ip += 4;
- BREAK;
- }
- CASE (CEE_THROW)
+ ip += 2;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_THROW)
--sp;
frame->ex_handler = NULL;
if (!sp->data.p)
sp->data.p = mono_get_exception_null_reference ();
- THROW_EX (sp->data.p, ip);
- BREAK;
- CASE (CEE_LDFLDA) /* Fall through */
- CASE (CEE_LDFLD) {
- MonoObject *obj;
- MonoClassField *field;
- guint32 token;
- int load_addr = *ip == CEE_LDFLDA;
- char *addr;
-
- if (!sp [-1].data.p)
+ THROW_EX ((MonoException *)sp->data.p, ip);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDFLDA)
+ o = sp [-1].data.p;
+ if (!o)
+ THROW_EX (mono_get_exception_null_reference (), ip);
+ sp[-1].data.p = (char *)o + * (guint16 *)(ip + 1);
+ ip += 2;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CKNULL)
+ o = sp [-1].data.p;
+ if (!o)
THROW_EX (mono_get_exception_null_reference (), ip);
-
++ip;
- token = read32 (ip);
+ MINT_IN_BREAK;
+
+#define LDFLD(datamem, fieldtype) \
+ o = sp [-1].data.p; \
+ if (!o) \
+ THROW_EX (mono_get_exception_null_reference (), ip); \
+ sp[-1].data.datamem = * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) ; \
+ ip += 2;
+
+ MINT_IN_CASE(MINT_LDFLD_I1) LDFLD(i, gint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDFLD_U1) LDFLD(i, guint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDFLD_I2) LDFLD(i, gint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDFLD_U2) LDFLD(i, guint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDFLD_I4) LDFLD(i, gint32); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDFLD_I8) LDFLD(l, gint64); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDFLD_R4) LDFLD(f, float); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDFLD_R8) LDFLD(f, double); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDFLD_O) LDFLD(p, gpointer); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDFLD_P) LDFLD(p, gpointer); MINT_IN_BREAK;
+
+ MINT_IN_CASE(MINT_LDFLD_VT)
+ o = sp [-1].data.p;
+ if (!o)
+ THROW_EX (mono_get_exception_null_reference (), ip);
+ i32 = READ32(ip + 2);
+ sp [-1].data.p = vt_sp;
+ memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
+ vt_sp += (i32 + 7) & ~7;
ip += 4;
+ MINT_IN_BREAK;
- if (sp [-1].type == VAL_OBJ) {
- obj = sp [-1].data.p;
+ MINT_IN_CASE(MINT_LDRMFLD) {
+ MonoClassField *field;
+ char *addr;
- if (obj->vtable->klass == mono_defaults.transparent_proxy_class) {
- MonoClass *klass = ((MonoTransparentProxy*)obj)->klass;
- field = mono_class_get_field (klass, token);
- addr = mono_load_remote_field (obj, klass, field, NULL);
- } else {
- if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF)
- field = mono_field_from_memberref (image, token, NULL);
- else
- field = mono_class_get_field (obj->vtable->klass, token);
- addr = (char*)obj + field->offset;
- }
+ o = sp [-1].data.p;
+ if (!o)
+ 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) {
+ MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
+ addr = mono_load_remote_field (o, klass, field, NULL);
} else {
- obj = sp [-1].data.vt.vt;
- field = mono_class_get_field (sp [-1].data.vt.klass, token);
- addr = (char*)obj + field->offset - sizeof (MonoObject);
- }
+ addr = (char*)o + field->offset;
+ }
- if (load_addr) {
- sp [-1].type = VAL_TP;
- sp [-1].data.p = addr;
- sp [-1].data.vt.klass = mono_class_from_mono_type (field->type);
- } else {
- vt_alloc (field->type, &sp [-1], FALSE);
- stackval_from_data (field->type, &sp [-1], addr, FALSE);
-
- }
- BREAK;
+ stackval_from_data (field->type, &sp [-1], addr, FALSE);
+ MINT_IN_BREAK;
}
- CASE (CEE_STFLD) {
- MonoObject *obj;
+
+ MINT_IN_CASE(MINT_LDRMFLD_VT) {
MonoClassField *field;
- guint32 token, offset;
+ char *addr;
- sp -= 2;
-
- if (!sp [0].data.p)
+ o = sp [-1].data.p;
+ if (!o)
THROW_EX (mono_get_exception_null_reference (), ip);
-
- ++ip;
- token = read32 (ip);
+ field = rtm->data_items[* (guint16 *)(ip + 1)];
+ i32 = READ32(ip + 2);
ip += 4;
-
- if (sp [0].type == VAL_OBJ) {
- obj = sp [0].data.p;
+ if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
+ MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
+ addr = mono_load_remote_field (o, klass, field, NULL);
+ } else {
+ addr = (char*)o + field->offset;
+ }
+
+ sp [-1].data.p = vt_sp;
+ memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
+ vt_sp += (i32 + 7) & ~7;
+ memcpy(sp [-1].data.p, addr, i32);
+ MINT_IN_BREAK;
+ }
- if (obj->vtable->klass == mono_defaults.transparent_proxy_class) {
- MonoClass *klass = ((MonoTransparentProxy*)obj)->klass;
- field = mono_class_get_field (klass, token);
+#define STFLD(datamem, fieldtype) \
+ o = sp [-2].data.p; \
+ if (!o) \
+ THROW_EX (mono_get_exception_null_reference (), ip); \
+ sp -= 2; \
+ * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) = sp[1].data.datamem; \
+ ip += 2;
+
+ MINT_IN_CASE(MINT_STFLD_I1) STFLD(i, gint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STFLD_U1) STFLD(i, guint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STFLD_I2) STFLD(i, gint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STFLD_U2) STFLD(i, guint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STFLD_I4) STFLD(i, gint32); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STFLD_I8) STFLD(l, gint64); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STFLD_R4) STFLD(f, float); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STFLD_R8) STFLD(f, double); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STFLD_O) STFLD(p, gpointer); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STFLD_P) STFLD(p, gpointer); MINT_IN_BREAK;
+
+ MINT_IN_CASE(MINT_STFLD_VT)
+ o = sp [-2].data.p;
+ if (!o)
+ THROW_EX (mono_get_exception_null_reference (), ip);
+ i32 = READ32(ip + 2);
+ sp -= 2;
+ memcpy((char *)o + * (guint16 *)(ip + 1), sp [1].data.p, i32);
+ vt_sp -= (i32 + 7) & ~7;
+ ip += 4;
+ MINT_IN_BREAK;
- mono_store_remote_field (obj, klass, field, &sp [1].data);
- offset = field->offset;
- } else {
- if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF)
- field = mono_field_from_memberref (image, token, NULL);
- else
- field = mono_class_get_field (obj->vtable->klass, token);
- offset = field->offset;
- stackval_to_data (field->type, &sp [1], (char*)obj + offset, FALSE);
- vt_free (&sp [1]);
- }
- } else {
- obj = sp [0].data.vt.vt;
- field = mono_class_get_field (sp [0].data.vt.klass, token);
- offset = field->offset - sizeof (MonoObject);
- stackval_to_data (field->type, &sp [1], (char*)obj + offset, FALSE);
- vt_free (&sp [1]);
- }
+ MINT_IN_CASE(MINT_STRMFLD) {
+ MonoClassField *field;
+
+ o = sp [-2].data.p;
+ if (!o)
+ THROW_EX (mono_get_exception_null_reference (), ip);
+
+ field = rtm->data_items[* (guint16 *)(ip + 1)];
+ ip += 2;
- BREAK;
+ if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
+ MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
+ mono_store_remote_field (o, klass, field, &sp [-1].data);
+ } else
+ stackval_to_data (field->type, &sp [-1], (char*)o + field->offset, FALSE);
+
+ sp -= 2;
+ MINT_IN_BREAK;
}
- CASE (CEE_LDSFLD) /* Fall through */
- CASE (CEE_LDSFLDA) {
- MonoVTable *vt;
- MonoClass *klass;
+ MINT_IN_CASE(MINT_STRMFLD_VT) {
MonoClassField *field;
- guint32 token;
- int load_addr = *ip == CEE_LDSFLDA;
- gpointer addr;
- ++ip;
- token = read32 (ip);
+ o = sp [-2].data.p;
+ if (!o)
+ THROW_EX (mono_get_exception_null_reference (), ip);
+ field = rtm->data_items[* (guint16 *)(ip + 1)];
+ i32 = READ32(ip + 2);
ip += 4;
-
- /* need to handle fieldrefs */
- if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF) {
- field = mono_field_from_memberref (image, token, &klass);
- } else {
- klass = mono_class_get (image,
- MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (image, token & 0xffffff));
- field = mono_class_get_field (klass, token);
- }
- g_assert (field);
-
- vt = mono_class_vtable (domain, klass);
- if (!vt->initialized)
- mono_runtime_class_init (vt);
- if (!domain->thread_static_fields || !(addr = g_hash_table_lookup (domain->thread_static_fields, field)))
- addr = (char*)(vt->data) + field->offset;
- else
- addr = mono_threads_get_static_data (GPOINTER_TO_UINT (addr));
- if (load_addr) {
- sp->type = VAL_TP;
- sp->data.p = addr;
- sp->data.vt.klass = mono_class_from_mono_type (field->type);
- } else {
- vt_alloc (field->type, sp, FALSE);
- stackval_from_data (field->type, sp, addr, FALSE);
+ if (o->vtable->klass == mono_defaults.transparent_proxy_class) {
+ MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
+ mono_store_remote_field (o, klass, field, &sp [-1].data);
+ } else
+ memcpy((char*)o + field->offset, sp [-1].data.p, i32);
+
+ sp -= 2;
+ vt_sp -= (i32 + 7) & ~7;
+ MINT_IN_BREAK;
+ }
+ 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 (vt);
}
+ 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->data) + field->offset;
++sp;
- BREAK;
+ MINT_IN_BREAK;
}
- CASE (CEE_STSFLD) {
+ MINT_IN_CASE(MINT_LDSFLD) {
MonoVTable *vt;
- MonoClass *klass;
MonoClassField *field;
- guint32 token;
gpointer addr;
- ++ip;
- token = read32 (ip);
- ip += 4;
- --sp;
-
- /* need to handle fieldrefs */
- if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF) {
- field = mono_field_from_memberref (image, token, &klass);
- } else {
- klass = mono_class_get (image,
- MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (image, token & 0xffffff));
- field = mono_class_get_field (klass, token);
- }
- g_assert (field);
-
- vt = mono_class_vtable (domain, klass);
- if (!vt->initialized)
+ field = rtm->data_items[*(guint16 *)(ip + 1)];
+ vt = rtm->data_items [*(guint16 *)(ip + 2)];
+ if (!vt->initialized) {
+ frame->ip = ip;
mono_runtime_class_init (vt);
- if (!domain->thread_static_fields || !(addr = g_hash_table_lookup (domain->thread_static_fields, field)))
- addr = (char*)(vt->data) + field->offset;
+ }
+ 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 = mono_threads_get_static_data (GPOINTER_TO_UINT (addr));
+ addr = (char*)(vt->data) + field->offset;
- stackval_to_data (field->type, sp, addr, FALSE);
- vt_free (sp);
- BREAK;
- }
- CASE (CEE_STOBJ) {
- MonoClass *vtklass;
- ++ip;
- vtklass = mono_class_get (image, read32 (ip));
- ip += 4;
- sp -= 2;
- memcpy (sp [0].data.p, sp [1].data.vt.vt, mono_class_value_size (vtklass, NULL));
- BREAK;
- }
-#if SIZEOF_VOID_P == 8
- CASE (CEE_CONV_OVF_I_UN)
-#endif
- CASE (CEE_CONV_OVF_I8_UN) {
- switch (sp [-1].type) {
- case VAL_DOUBLE:
- if (sp [-1].data.f < 0 || sp [-1].data.f > 9223372036854775807LL)
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.l = (guint64)sp [-1].data.f;
- break;
- case VAL_I64:
- break;
- case VAL_VALUET:
- ves_abort();
- case VAL_I32:
- /* Can't overflow */
- sp [-1].data.l = (guint64)sp [-1].data.i;
- break;
- default:
- sp [-1].data.l = (guint64)sp [-1].data.nati;
- break;
- }
- sp [-1].type = VAL_I64;
- ++ip;
- BREAK;
+ stackval_from_data (field->type, sp, addr, FALSE);
+ ++sp;
+ MINT_IN_BREAK;
}
-#if SIZEOF_VOID_P == 8
- CASE (CEE_CONV_OVF_U_UN)
-#endif
- CASE (CEE_CONV_OVF_U8_UN) {
- switch (sp [-1].type) {
- case VAL_DOUBLE:
- if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT64_MAX)
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.l = (guint64)sp [-1].data.f;
- break;
- case VAL_I64:
- /* nothing to do */
- break;
- case VAL_VALUET:
- ves_abort();
- case VAL_I32:
- /* Can't overflow */
- sp [-1].data.l = (guint64)sp [-1].data.i;
- break;
- default:
- /* Can't overflow */
- sp [-1].data.l = (guint64)sp [-1].data.nati;
- 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 (vt);
}
- sp [-1].type = VAL_I64;
- ++ip;
- BREAK;
+ ip += 3;
+ sp->data.i = * (gint32 *)((char*)(vt->data) + field->offset);
+ ++sp;
+ MINT_IN_BREAK;
}
-#if SIZEOF_VOID_P == 4
- CASE (CEE_CONV_OVF_I_UN)
- CASE (CEE_CONV_OVF_U_UN)
-#endif
- CASE (CEE_CONV_OVF_I1_UN)
- CASE (CEE_CONV_OVF_I2_UN)
- CASE (CEE_CONV_OVF_I4_UN)
- CASE (CEE_CONV_OVF_U1_UN)
- CASE (CEE_CONV_OVF_U2_UN)
- CASE (CEE_CONV_OVF_U4_UN) {
- guint64 value;
- switch (sp [-1].type) {
- case VAL_DOUBLE:
- value = (guint64)sp [-1].data.f;
- break;
- case VAL_I64:
- value = (guint64)sp [-1].data.l;
- break;
- case VAL_VALUET:
- ves_abort();
- case VAL_I32:
- value = (guint64)sp [-1].data.i;
- break;
- default:
- value = (guint64)sp [-1].data.nati;
- break;
- }
- switch (*ip) {
- case CEE_CONV_OVF_I1_UN:
- if (value > 127)
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i = value;
- sp [-1].type = VAL_I32;
- break;
- case CEE_CONV_OVF_I2_UN:
- if (value > 32767)
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i = value;
- sp [-1].type = VAL_I32;
- break;
-#if SIZEOF_VOID_P == 4
- case CEE_CONV_OVF_I_UN: /* Fall through */
-#endif
- case CEE_CONV_OVF_I4_UN:
- if (value > 2147483647)
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i = value;
- sp [-1].type = VAL_I32;
- break;
- case CEE_CONV_OVF_U1_UN:
- if (value > 255)
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i = value;
- sp [-1].type = VAL_I32;
- break;
- case CEE_CONV_OVF_U2_UN:
- if (value > 65535)
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i = value;
- sp [-1].type = VAL_I32;
- break;
-#if SIZEOF_VOID_P == 4
- case CEE_CONV_OVF_U_UN: /* Fall through */
-#endif
- case CEE_CONV_OVF_U4_UN:
- if (value > 4294967295U)
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i = value;
- sp [-1].type = VAL_I32;
- break;
- default:
- g_assert_not_reached ();
+ 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 (vt);
}
- ++ip;
- BREAK;
+ ip += 3;
+ sp->data.p = * (gpointer *)((char*)(vt->data) + field->offset);
+ ++sp;
+ MINT_IN_BREAK;
}
- CASE (CEE_BOX) {
+ MINT_IN_CASE(MINT_LDSFLD_VT) {
+ MonoVTable *vt;
+ MonoClassField *field;
guint32 token;
- MonoClass *class;
-
- ip++;
- token = read32 (ip);
-
- if (frame->method->wrapper_type != MONO_WRAPPER_NONE)
- class = (MonoClass *)mono_method_get_wrapper_data (frame->method, token);
- else
- class = mono_class_get (image, token);
- g_assert (class != NULL);
-
- sp [-1].type = VAL_OBJ;
- if (class->byval_arg.type == MONO_TYPE_VALUETYPE && !class->enumtype)
- sp [-1].data.p = mono_value_box (domain, class, sp [-1].data.p);
- else {
- stackval_to_data (&class->byval_arg, &sp [-1], (char*)&sp [-1], FALSE);
- sp [-1].data.p = mono_value_box (domain, class, &sp [-1]);
- }
- /* need to vt_free (sp); */
+ gpointer addr;
+ int size;
+ token = * (guint16 *)(ip + 1);
+ size = READ32(ip + 2);
+ field = rtm->data_items[token];
ip += 4;
+
+ vt = mono_class_vtable (context->domain, field->parent);
+ if (!vt->initialized) {
+ frame->ip = ip - 2;
+ mono_runtime_class_init (vt);
+ }
+
+ 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->data) + field->offset;
- BREAK;
+ sp->data.p = vt_sp;
+ vt_sp += (size + 7) & ~7;
+ stackval_from_data (field->type, sp, addr, FALSE);
+ ++sp;
+ MINT_IN_BREAK;
}
- CASE (CEE_NEWARR) {
- MonoClass *class;
- MonoObject *o;
+ MINT_IN_CASE(MINT_STSFLD) {
+ MonoVTable *vt;
+ MonoClassField *field;
guint32 token;
+ gpointer addr;
- ip++;
- token = read32 (ip);
+ token = * (guint16 *)(ip + 1);
+ field = rtm->data_items[token];
+ ip += 2;
+ --sp;
- if (frame->method->wrapper_type != MONO_WRAPPER_NONE)
- class = (MonoClass *)mono_method_get_wrapper_data (frame->method, token);
+ vt = mono_class_vtable (context->domain, field->parent);
+ if (!vt->initialized) {
+ frame->ip = ip - 2;
+ mono_runtime_class_init (vt);
+ }
+
+ 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
- class = mono_class_get (image, token);
+ addr = (char*)(vt->data) + field->offset;
- o = (MonoObject*) mono_array_new (domain, class, sp [-1].data.i);
- ip += 4;
+ 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;
- sp [-1].type = VAL_OBJ;
- sp [-1].data.p = o;
+ token = * (guint16 *)(ip + 1);
+ size = READ32(ip + 2);
+ field = rtm->data_items[token];
+ ip += 4;
+
+ vt = mono_class_vtable (context->domain, field->parent);
+ if (!vt->initialized) {
+ frame->ip = ip - 2;
+ mono_runtime_class_init (vt);
+ }
+
+ 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->data) + field->offset;
+ --sp;
+ stackval_to_data (field->type, sp, addr, FALSE);
+ vt_sp -= (size + 7) & ~7;
+ MINT_IN_BREAK;
+ }
+ MINT_IN_CASE(MINT_STOBJ_VT) {
+ int size;
+ c = rtm->data_items[* (guint16 *)(ip + 1)];
+ ip += 2;
+ size = mono_class_value_size (c, NULL);
+ memcpy(sp [-2].data.p, sp [-1].data.p, size);
+ vt_sp -= (size + 7) & ~7;
+ sp -= 2;
+ MINT_IN_BREAK;
+ }
+ MINT_IN_CASE(MINT_STOBJ) {
+ int size;
+ c = rtm->data_items[* (guint16 *)(ip + 1)];
+ ip += 2;
+ size = mono_class_value_size (c, NULL);
+ memcpy(sp [-2].data.p, &sp [-1].data, size);
+ sp -= 2;
+ MINT_IN_BREAK;
+ }
+ MINT_IN_CASE(MINT_CONV_OVF_I4_UN_R8)
+ if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (guint32)sp [-1].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_U8_I4)
+ if (sp [-1].data.i < 0)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.l = sp [-1].data.i;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_U8_R8)
+ MINT_IN_CASE(MINT_CONV_OVF_I8_UN_R8)
+ if (sp [-1].data.f < 0 || sp [-1].data.f > 9223372036854775807LL)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.l = (guint64)sp [-1].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_I8_R8)
+ if (sp [-1].data.f < MYGINT64_MIN || sp [-1].data.f > MYGINT64_MAX)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.l = (gint64)sp [-1].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_I4_UN_I8)
+ if ((mono_u)sp [-1].data.l > MYGUINT32_MAX)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (mono_u)sp [-1].data.l;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_BOX)
+ c = rtm->data_items [* (guint16 *)(ip + 1)];
+
+ 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 (context->domain, c, sp [-1].data.p);
+ 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 (context->domain, c, &sp [-1]);
+ }
+ ip += 2;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_NEWARR)
+ sp [-1].data.p = (MonoObject*) mono_array_new (context->domain, rtm->data_items[*(guint16 *)(ip + 1)], sp [-1].data.i);
+ ip += 2;
/*if (profiling_classes) {
guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, o->vtable->klass));
count++;
g_hash_table_insert (profiling_classes, o->vtable->klass, GUINT_TO_POINTER (count));
}*/
- BREAK;
- }
- CASE (CEE_LDLEN) {
- MonoArray *o;
-
- ip++;
-
- g_assert (sp [-1].type == VAL_OBJ);
-
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDLEN)
o = sp [-1].data.p;
if (!o)
- THROW_EX (mono_get_exception_null_reference (), ip - 1);
-
- g_assert (MONO_CLASS_IS_ARRAY (o->obj.vtable->klass));
-
- sp [-1].type = VAL_I32;
- sp [-1].data.i = mono_array_length (o);
-
- BREAK;
+ THROW_EX (mono_get_exception_null_reference (), ip);
+ sp [-1].data.nati = mono_array_length ((MonoArray *)o);
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_GETCHR) {
+ MonoString *s;
+ s = sp [-2].data.p;
+ if (!s)
+ THROW_EX (mono_get_exception_null_reference (), ip);
+ i32 = sp [-1].data.i;
+ if (i32 < 0 || i32 >= mono_string_length (s))
+ THROW_EX (mono_get_exception_index_out_of_range (), ip);
+ --sp;
+ sp [-1].data.i = mono_string_chars(s)[i32];
+ ++ip;
+ MINT_IN_BREAK;
}
- CASE (CEE_LDELEMA) {
- MonoArray *o;
- guint32 esize, token;
-
+ MINT_IN_CASE(MINT_STRLEN)
++ip;
- token = read32 (ip);
- ip += 4;
+ sp [-1].data.i = mono_string_length ((MonoString*)sp [-1].data.p);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_ARRAY_RANK)
+ o = sp [-1].data.p;
+ if (!o)
+ THROW_EX (mono_get_exception_null_reference (), ip);
+ sp [-1].data.i = mono_object_class (sp [-1].data.p)->rank;
+ ip++;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDELEMA) {
+ guint32 esize;
+ mono_u aindex;
+
+ /*token = READ32 (ip)*/;
+ ip += 2;
sp -= 2;
- g_assert (sp [0].type == VAL_OBJ);
o = sp [0].data.p;
- g_assert (MONO_CLASS_IS_ARRAY (o->obj.vtable->klass));
-
- if (sp [1].data.nati >= mono_array_length (o))
- THROW_EX (mono_get_exception_index_out_of_range (), ip - 5);
+ aindex = sp [1].data.i;
+ if (aindex >= mono_array_length ((MonoArray *) o))
+ THROW_EX (mono_get_exception_index_out_of_range (), ip - 2);
/* check the array element corresponds to token */
- esize = mono_array_element_size (o->obj.vtable->klass);
+ esize = mono_array_element_size (((MonoArray *) o)->obj.vtable->klass);
- sp->type = VAL_MP;
- sp->data.p = mono_array_addr_with_size (o, esize, sp [1].data.i);
- sp->data.vt.klass = o->obj.vtable->klass->element_class;
-
+ sp->data.p = mono_array_addr_with_size ((MonoArray *) o, esize, aindex);
++sp;
- BREAK;
+ MINT_IN_BREAK;
}
- CASE (CEE_LDELEM_I1) /* fall through */
- CASE (CEE_LDELEM_U1) /* fall through */
- CASE (CEE_LDELEM_I2) /* fall through */
- CASE (CEE_LDELEM_U2) /* fall through */
- CASE (CEE_LDELEM_I4) /* fall through */
- CASE (CEE_LDELEM_U4) /* fall through */
- CASE (CEE_LDELEM_I8) /* fall through */
- CASE (CEE_LDELEM_I) /* fall through */
- CASE (CEE_LDELEM_R4) /* fall through */
- CASE (CEE_LDELEM_R8) /* fall through */
- CASE (CEE_LDELEM_REF) {
+ MINT_IN_CASE(MINT_LDELEM_I1) /* fall through */
+ MINT_IN_CASE(MINT_LDELEM_U1) /* fall through */
+ MINT_IN_CASE(MINT_LDELEM_I2) /* fall through */
+ MINT_IN_CASE(MINT_LDELEM_U2) /* fall through */
+ MINT_IN_CASE(MINT_LDELEM_I4) /* fall through */
+ MINT_IN_CASE(MINT_LDELEM_U4) /* fall through */
+ MINT_IN_CASE(MINT_LDELEM_I8) /* fall through */
+ 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) {
MonoArray *o;
mono_u aindex;
sp -= 2;
- g_assert (sp [0].type == VAL_OBJ);
o = sp [0].data.p;
if (!o)
THROW_EX (mono_get_exception_null_reference (), ip);
- g_assert (MONO_CLASS_IS_ARRAY (o->obj.vtable->klass));
-
- aindex = sp [1].data.nati;
+ aindex = sp [1].data.i;
if (aindex >= mono_array_length (o))
THROW_EX (mono_get_exception_index_out_of_range (), ip);
-
+
/*
* FIXME: throw mono_get_exception_array_type_mismatch () if needed
*/
switch (*ip) {
- case CEE_LDELEM_I1:
+ case MINT_LDELEM_I1:
sp [0].data.i = mono_array_get (o, gint8, aindex);
- sp [0].type = VAL_I32;
break;
- case CEE_LDELEM_U1:
+ case MINT_LDELEM_U1:
sp [0].data.i = mono_array_get (o, guint8, aindex);
- sp [0].type = VAL_I32;
break;
- case CEE_LDELEM_I2:
+ case MINT_LDELEM_I2:
sp [0].data.i = mono_array_get (o, gint16, aindex);
- sp [0].type = VAL_I32;
break;
- case CEE_LDELEM_U2:
+ case MINT_LDELEM_U2:
sp [0].data.i = mono_array_get (o, guint16, aindex);
- sp [0].type = VAL_I32;
break;
- case CEE_LDELEM_I:
+ case MINT_LDELEM_I:
sp [0].data.nati = mono_array_get (o, mono_i, aindex);
- sp [0].type = VAL_NATI;
break;
- case CEE_LDELEM_I4:
+ case MINT_LDELEM_I4:
sp [0].data.i = mono_array_get (o, gint32, aindex);
- sp [0].type = VAL_I32;
break;
- case CEE_LDELEM_U4:
+ case MINT_LDELEM_U4:
sp [0].data.i = mono_array_get (o, guint32, aindex);
- sp [0].type = VAL_I32;
break;
- case CEE_LDELEM_I8:
+ case MINT_LDELEM_I8:
sp [0].data.l = mono_array_get (o, guint64, aindex);
- sp [0].type = VAL_I64;
break;
- case CEE_LDELEM_R4:
+ case MINT_LDELEM_R4:
sp [0].data.f = mono_array_get (o, float, aindex);
- sp [0].type = VAL_DOUBLE;
break;
- case CEE_LDELEM_R8:
+ case MINT_LDELEM_R8:
sp [0].data.f = mono_array_get (o, double, aindex);
- sp [0].type = VAL_DOUBLE;
break;
- case CEE_LDELEM_REF:
+ case MINT_LDELEM_REF:
sp [0].data.p = mono_array_get (o, gpointer, aindex);
- sp [0].data.vt.klass = NULL;
- sp [0].type = VAL_OBJ;
break;
default:
ves_abort();
++ip;
++sp;
- BREAK;
+ MINT_IN_BREAK;
}
- CASE (CEE_STELEM_I) /* fall through */
- CASE (CEE_STELEM_I1) /* fall through */
- CASE (CEE_STELEM_I2) /* fall through */
- CASE (CEE_STELEM_I4) /* fall through */
- CASE (CEE_STELEM_I8) /* fall through */
- CASE (CEE_STELEM_R4) /* fall through */
- CASE (CEE_STELEM_R8) /* fall through */
- CASE (CEE_STELEM_REF) {
- MonoArray *o;
- MonoClass *ac;
+ MINT_IN_CASE(MINT_STELEM_I) /* fall through */
+ MINT_IN_CASE(MINT_STELEM_I1) /* fall through */
+ MINT_IN_CASE(MINT_STELEM_I2) /* fall through */
+ MINT_IN_CASE(MINT_STELEM_I4) /* fall through */
+ 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) {
mono_u aindex;
sp -= 3;
- g_assert (sp [0].type == VAL_OBJ);
o = sp [0].data.p;
if (!o)
THROW_EX (mono_get_exception_null_reference (), ip);
- ac = o->obj.vtable->klass;
- g_assert (MONO_CLASS_IS_ARRAY (ac));
-
- aindex = sp [1].data.nati;
- if (aindex >= mono_array_length (o))
+ aindex = sp [1].data.i;
+ if (aindex >= mono_array_length ((MonoArray *)o))
THROW_EX (mono_get_exception_index_out_of_range (), ip);
- /*
- * FIXME: throw mono_get_exception_array_type_mismatch () if needed
- */
switch (*ip) {
- case CEE_STELEM_I:
- mono_array_set (o, mono_i, aindex, sp [2].data.nati);
+ case MINT_STELEM_I:
+ mono_array_set ((MonoArray *)o, mono_i, aindex, sp [2].data.nati);
break;
- case CEE_STELEM_I1:
- mono_array_set (o, gint8, aindex, sp [2].data.i);
+ case MINT_STELEM_I1:
+ mono_array_set ((MonoArray *)o, gint8, aindex, sp [2].data.i);
break;
- case CEE_STELEM_I2:
- mono_array_set (o, gint16, aindex, sp [2].data.i);
+ case MINT_STELEM_I2:
+ mono_array_set ((MonoArray *)o, gint16, aindex, sp [2].data.i);
break;
- case CEE_STELEM_I4:
- mono_array_set (o, gint32, aindex, sp [2].data.i);
+ case MINT_STELEM_I4:
+ mono_array_set ((MonoArray *)o, gint32, aindex, sp [2].data.i);
break;
- case CEE_STELEM_I8:
- mono_array_set (o, gint64, aindex, sp [2].data.l);
+ case MINT_STELEM_I8:
+ mono_array_set ((MonoArray *)o, gint64, aindex, sp [2].data.l);
break;
- case CEE_STELEM_R4:
- mono_array_set (o, float, aindex, sp [2].data.f);
+ case MINT_STELEM_R4:
+ mono_array_set ((MonoArray *)o, float, aindex, sp [2].data.f);
break;
- case CEE_STELEM_R8:
- mono_array_set (o, double, aindex, sp [2].data.f);
+ case MINT_STELEM_R8:
+ mono_array_set ((MonoArray *)o, double, aindex, sp [2].data.f);
break;
- case CEE_STELEM_REF:
- g_assert (sp [2].type == VAL_OBJ);
+ case MINT_STELEM_REF:
if (sp [2].data.p && !mono_object_isinst (sp [2].data.p, mono_object_class (o)->element_class))
THROW_EX (mono_get_exception_array_type_mismatch (), ip);
- mono_array_set (o, gpointer, aindex, sp [2].data.p);
+ mono_array_set ((MonoArray *)o, gpointer, aindex, sp [2].data.p);
break;
default:
ves_abort();
}
++ip;
- BREAK;
+ MINT_IN_BREAK;
}
- CASE (CEE_LDELEM)
- CASE (CEE_STELEM)
- CASE (CEE_UNBOX_ANY)
- CASE (CEE_UNUSED5)
- CASE (CEE_UNUSED6)
- CASE (CEE_UNUSED7)
- CASE (CEE_UNUSED8)
- CASE (CEE_UNUSED9)
- CASE (CEE_UNUSED10)
- CASE (CEE_UNUSED11)
- CASE (CEE_UNUSED12)
- CASE (CEE_UNUSED13)
- CASE (CEE_UNUSED14)
- CASE (CEE_UNUSED15)
- CASE (CEE_UNUSED16)
- CASE (CEE_UNUSED17) ves_abort(); BREAK;
- CASE (CEE_CONV_OVF_I1)
- if (sp [-1].type == VAL_I32) {
- if (sp [-1].data.i < 128 || sp [-1].data.i > 127)
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i = (gint8)sp [-1].data.i;
- } else if (sp [-1].type == VAL_I64) {
- if (sp [-1].data.l < 128 || sp [-1].data.l > 127)
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i = (gint8)sp [-1].data.l;
- } else {
- ves_abort();
- }
+ MINT_IN_CASE(MINT_CONV_OVF_I4_U4)
+ if (sp [-1].data.i < 0)
+ THROW_EX (mono_get_exception_overflow (), ip);
++ip;
- BREAK;
- CASE (CEE_CONV_OVF_U1)
- if (sp [-1].type == VAL_I32) {
- if (sp [-1].data.i < 0 || sp [-1].data.i > 255)
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i = (gint8)sp [-1].data.i;
- } else if (sp [-1].type == VAL_I64) {
- if (sp [-1].data.l < 0 || sp [-1].data.l > 255)
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i = (gint8)sp [-1].data.l;
- } else {
- ves_abort();
- }
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_I4_I8)
+ if (sp [-1].data.l < MYGINT32_MIN || sp [-1].data.l > MYGINT32_MAX)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (gint32) sp [-1].data.l;
++ip;
- BREAK;
- CASE (CEE_CONV_OVF_I2)
- CASE (CEE_CONV_OVF_U2)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_I4_R8)
+ if (sp [-1].data.f < MYGINT32_MIN || sp [-1].data.f > MYGINT32_MAX)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (gint32) sp [-1].data.f;
++ip;
- /* FIXME: handle other cases */
- if (sp [-1].type == VAL_I32) {
- /* defined as NOP */
- } else {
- ves_abort();
- }
- BREAK;
- CASE (CEE_CONV_OVF_I4)
- /* FIXME: handle other cases */
- if (sp [-1].type == VAL_I32) {
- /* defined as NOP */
- } else if(sp [-1].type == VAL_I64) {
- sp [-1].data.i = (gint32)sp [-1].data.l;
- sp [-1].type = VAL_I32;
- } else {
- ves_abort();
- }
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_U4_I4)
+ if (sp [-1].data.i < 0)
+ THROW_EX (mono_get_exception_overflow (), ip);
++ip;
- BREAK;
- CASE (CEE_CONV_OVF_U4)
- /* FIXME: handle other cases */
- if (sp [-1].type == VAL_I32) {
- /* defined as NOP */
- } else if(sp [-1].type == VAL_I64) {
- sp [-1].data.i = (guint32)sp [-1].data.l;
- sp [-1].type = VAL_I32;
- } else {
- ves_abort();
- }
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_U4_I8)
+ if (sp [-1].data.l < 0 || sp [-1].data.l > MYGUINT32_MAX)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (guint32) sp [-1].data.l;
++ip;
- BREAK;
- CASE (CEE_CONV_OVF_I8)
- /* FIXME: handle other cases */
- if (sp [-1].type == VAL_I32) {
- sp [-1].data.l = (guint64)sp [-1].data.i;
- sp [-1].type = VAL_I64;
- } else if(sp [-1].type == VAL_I64) {
- /* defined as NOP */
- } else {
- ves_abort();
- }
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_U4_R8)
+ if (sp [-1].data.f < 0 || sp [-1].data.f > MYGUINT32_MAX)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (guint32) sp [-1].data.f;
++ip;
- BREAK;
- CASE (CEE_CONV_OVF_U8)
- /* FIXME: handle other cases */
- if (sp [-1].type == VAL_I32) {
- sp [-1].data.l = (guint64) sp [-1].data.i;
- sp [-1].type = VAL_I64;
- } else if(sp [-1].type == VAL_I64) {
- /* defined as NOP */
- } else {
- ves_abort();
- }
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_I2_I4)
+ if (sp [-1].data.i < -32768 || sp [-1].data.i > 32767)
+ THROW_EX (mono_get_exception_overflow (), ip);
++ip;
- BREAK;
- CASE (CEE_UNUSED50)
- CASE (CEE_UNUSED18)
- CASE (CEE_UNUSED19)
- CASE (CEE_UNUSED20)
- CASE (CEE_UNUSED21)
- CASE (CEE_UNUSED22)
- CASE (CEE_UNUSED23) ves_abort(); BREAK;
- CASE (CEE_REFANYVAL) ves_abort(); BREAK;
- CASE (CEE_CKFINITE)
- if (!finite(sp [-1].data.f))
- THROW_EX (mono_get_exception_arithmetic (), ip);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_I2_I8)
+ if (sp [-1].data.l < -32768 || sp [-1].data.l > 32767)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (gint16) sp [-1].data.l;
++ip;
- BREAK;
- CASE (CEE_UNUSED24) ves_abort(); BREAK;
- CASE (CEE_UNUSED25) ves_abort(); BREAK;
- CASE (CEE_MKREFANY) ves_abort(); BREAK;
- CASE (CEE_UNUSED59)
- CASE (CEE_UNUSED60)
- CASE (CEE_UNUSED61)
- CASE (CEE_UNUSED62)
- CASE (CEE_UNUSED63)
- CASE (CEE_UNUSED64)
- CASE (CEE_UNUSED65)
- CASE (CEE_UNUSED66)
- CASE (CEE_UNUSED67) ves_abort(); BREAK;
- CASE (CEE_LDTOKEN) {
- gpointer handle;
- MonoClass *handle_class;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_I2_R8)
+ if (sp [-1].data.f < -32768 || sp [-1].data.f > 32767)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (gint16) sp [-1].data.f;
++ip;
- handle = mono_ldtoken (image, read32 (ip), &handle_class);
- ip += 4;
- vt_alloc (&handle_class->byval_arg, sp, FALSE);
- stackval_from_data (&handle_class->byval_arg, sp, (char*)&handle, FALSE);
- ++sp;
- BREAK;
- }
- CASE (CEE_CONV_OVF_I)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_U2_I4)
+ if (sp [-1].data.i < 0 || sp [-1].data.i > 65535)
+ THROW_EX (mono_get_exception_overflow (), ip);
++ip;
- --sp;
- /* FIXME: check overflow. */
- switch (sp->type) {
- case VAL_I32:
- sp->data.p = (gpointer)(mono_i) sp->data.i;
- break;
- case VAL_I64:
- sp->data.p = (gpointer)(mono_i) sp->data.l;
- break;
- case VAL_NATI:
- break;
- case VAL_DOUBLE:
- sp->data.p = (gpointer)(mono_i) sp->data.f;
- break;
- default:
- ves_abort ();
- }
- sp->type = VAL_NATI;
- ++sp;
- BREAK;
- CASE (CEE_CONV_OVF_U) ves_abort(); BREAK;
- CASE (CEE_ADD_OVF)
- --sp;
- /* FIXME: check overflow */
- if (sp->type == VAL_I32) {
- if (CHECK_ADD_OVERFLOW (sp [-1].data.i, GET_NATI (sp [0])))
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i = (gint32)sp [-1].data.i + (gint32)GET_NATI (sp [0]);
- } else if (sp->type == VAL_I64) {
- if (CHECK_ADD_OVERFLOW64 (sp [-1].data.l, sp [0].data.l))
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.l = (gint64)sp [-1].data.l + (gint64)sp [0].data.l;
- } else if (sp->type == VAL_DOUBLE)
- sp [-1].data.f += sp [0].data.f;
- else {
- char *p = sp [-1].data.p;
- p += GET_NATI (sp [0]);
- sp [-1].data.p = p;
- }
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_U2_I8)
+ if (sp [-1].data.l < 0 || sp [-1].data.l > 65535)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (guint16) sp [-1].data.l;
++ip;
- BREAK;
- CASE (CEE_ADD_OVF_UN)
- --sp;
- /* FIXME: check overflow, make unsigned */
- if (sp->type == VAL_I32) {
- if (CHECK_ADD_OVERFLOW_UN (sp [-1].data.i, GET_NATI (sp [0])))
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i = (guint32)sp [-1].data.i + (guint32)GET_NATI (sp [0]);
- } else if (sp->type == VAL_I64) {
- if (CHECK_ADD_OVERFLOW64_UN (sp [-1].data.l, sp [0].data.l))
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.l = (guint64)sp [-1].data.l + (guint64)sp [0].data.l;
- } else if (sp->type == VAL_DOUBLE)
- sp [-1].data.f += sp [0].data.f;
- else {
- char *p = sp [-1].data.p;
- p += GET_NATI (sp [0]);
- sp [-1].data.p = p;
- }
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_U2_R8)
+ if (sp [-1].data.f < 0 || sp [-1].data.f > 65535)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (guint16) sp [-1].data.f;
++ip;
- BREAK;
- CASE (CEE_MUL_OVF)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_I1_I4)
+ if (sp [-1].data.i < -128 || sp [-1].data.i > 127)
+ THROW_EX (mono_get_exception_overflow (), ip);
++ip;
- --sp;
- /* FIXME: check overflow */
- if (sp->type == VAL_I32) {
- if (CHECK_MUL_OVERFLOW (sp [-1].data.i, GET_NATI (sp [0])))
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i *= (gint)GET_NATI (sp [0]);
- }
- else if (sp->type == VAL_I64) {
- if (CHECK_MUL_OVERFLOW64 (sp [-1].data.l, sp [0].data.l))
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.l *= sp [0].data.l;
- }
- else if (sp->type == VAL_DOUBLE)
- sp [-1].data.f *= sp [0].data.f;
- BREAK;
- CASE (CEE_MUL_OVF_UN)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_I1_I8)
+ if (sp [-1].data.l < -128 || sp [-1].data.l > 127)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (gint8) sp [-1].data.l;
++ip;
- --sp;
- /* FIXME: check overflow, make unsigned */
- if (sp->type == VAL_I32) {
- if (CHECK_MUL_OVERFLOW_UN (sp [-1].data.i, GET_NATI (sp [0])))
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.i *= (gint)GET_NATI (sp [0]);
- }
- else if (sp->type == VAL_I64) {
- if (CHECK_MUL_OVERFLOW64_UN (sp [-1].data.l, sp [0].data.l))
- THROW_EX (mono_get_exception_overflow (), ip);
- sp [-1].data.l *= sp [0].data.l;
- }
- else if (sp->type == VAL_DOUBLE)
- sp [-1].data.f *= sp [0].data.f;
- BREAK;
- CASE (CEE_SUB_OVF)
- CASE (CEE_SUB_OVF_UN)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_I1_R8)
+ if (sp [-1].data.f < -128 || sp [-1].data.f > 127)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (gint8) sp [-1].data.f;
++ip;
- --sp;
- /* FIXME: handle undeflow/unsigned */
- /* should probably consider the pointers as unsigned */
- if (sp->type == VAL_I32)
- sp [-1].data.i -= GET_NATI (sp [0]);
- else if (sp->type == VAL_I64)
- sp [-1].data.l -= sp [0].data.l;
- else if (sp->type == VAL_DOUBLE)
- sp [-1].data.f -= sp [0].data.f;
- else {
- char *p = sp [-1].data.p;
- p -= GET_NATI (sp [0]);
- sp [-1].data.p = p;
- }
- BREAK;
- CASE (CEE_ENDFINALLY)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_U1_I4)
+ if (sp [-1].data.i < 0 || sp [-1].data.i > 255)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_U1_I8)
+ if (sp [-1].data.l < 0 || sp [-1].data.l > 255)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (guint8) sp [-1].data.l;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CONV_OVF_U1_R8)
+ if (sp [-1].data.f < 0 || sp [-1].data.f > 255)
+ THROW_EX (mono_get_exception_overflow (), ip);
+ sp [-1].data.i = (guint8) sp [-1].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+#if 0
+ MINT_IN_CASE(MINT_LDELEM)
+ MINT_IN_CASE(MINT_STELEM)
+ MINT_IN_CASE(MINT_UNBOX_ANY)
+
+ MINT_IN_CASE(MINT_REFANYVAL) ves_abort(); MINT_IN_BREAK;
+#endif
+ MINT_IN_CASE(MINT_CKFINITE)
+ if (!finite(sp [-1].data.f))
+ THROW_EX (mono_get_exception_arithmetic (), ip);
+ ++ip;
+ MINT_IN_BREAK;
+#if 0
+ MINT_IN_CASE(MINT_MKREFANY) ves_abort(); MINT_IN_BREAK;
+#endif
+ MINT_IN_CASE(MINT_LDTOKEN)
+ sp->data.p = vt_sp;
+ vt_sp += 8;
+ * (gpointer *)sp->data.p = rtm->data_items[*(guint16 *)(ip + 1)];
+ ip += 2;
+ ++sp;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_ADD_OVF_I4)
+ if (CHECK_ADD_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
+ THROW_EX (mono_get_exception_overflow (), ip);
+ BINOP(i, +);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_ADD_OVF_I8)
+ if (CHECK_ADD_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
+ THROW_EX (mono_get_exception_overflow (), ip);
+ BINOP(l, +);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_ADD_OVF_UN_I4)
+ if (CHECK_ADD_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
+ THROW_EX (mono_get_exception_overflow (), ip);
+ BINOP_CAST(i, +, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_ADD_OVF_UN_I8)
+ if (CHECK_ADD_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
+ THROW_EX (mono_get_exception_overflow (), ip);
+ BINOP_CAST(l, +, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_MUL_OVF_I4)
+ if (CHECK_MUL_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
+ THROW_EX (mono_get_exception_overflow (), ip);
+ BINOP(i, *);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_MUL_OVF_I8)
+ if (CHECK_MUL_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
+ THROW_EX (mono_get_exception_overflow (), ip);
+ BINOP(l, *);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_MUL_OVF_UN_I4)
+ if (CHECK_MUL_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
+ THROW_EX (mono_get_exception_overflow (), ip);
+ BINOP_CAST(i, *, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_MUL_OVF_UN_I8)
+ if (CHECK_MUL_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
+ THROW_EX (mono_get_exception_overflow (), ip);
+ BINOP_CAST(l, *, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SUB_OVF_I4)
+ if (CHECK_SUB_OVERFLOW (sp [-2].data.i, sp [-1].data.i))
+ THROW_EX (mono_get_exception_overflow (), ip);
+ BINOP(i, -);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SUB_OVF_I8)
+ if (CHECK_SUB_OVERFLOW64 (sp [-2].data.l, sp [-1].data.l))
+ THROW_EX (mono_get_exception_overflow (), ip);
+ BINOP(l, -);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SUB_OVF_UN_I4)
+ if (CHECK_SUB_OVERFLOW_UN (sp [-2].data.i, sp [-1].data.i))
+ THROW_EX (mono_get_exception_overflow (), ip);
+ BINOP_CAST(i, -, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_SUB_OVF_UN_I8)
+ if (CHECK_SUB_OVERFLOW64_UN (sp [-2].data.l, sp [-1].data.l))
+ THROW_EX (mono_get_exception_overflow (), ip);
+ BINOP_CAST(l, -, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_ENDFINALLY)
if (finally_ips) {
ip = finally_ips->data;
finally_ips = g_slist_remove (finally_ips, ip);
}
if (frame->ex)
goto handle_fault;
- /*
- * There was no exception, we continue normally at the target address.
- */
- ip = endfinally_ip;
- BREAK;
- CASE (CEE_LEAVE) /* Fall through */
- CASE (CEE_LEAVE_S)
- sp = frame->stack; /* empty the stack */
+ ves_abort();
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LEAVE) /* Fall through */
+ MINT_IN_CASE(MINT_LEAVE_S)
+ while (sp > frame->stack) {
+ --sp;
+ }
frame->ip = ip;
- if (*ip == CEE_LEAVE_S) {
- ++ip;
- ip += (signed char) *ip;
- ++ip;
+ if (*ip == MINT_LEAVE_S) {
+ ip += (short) *(ip + 1);
} else {
- ++ip;
- ip += (gint32) read32 (ip);
- ip += 4;
+ ip += (gint32) READ32 (ip + 1);
}
-#if 0
- /*
- * We may be either inside a try block or inside an handler.
- * In the first case there was no exception and we go on
- * executing the finally handlers and after that resume control
- * at endfinally_ip.
- * In the second case we need to clear the exception and
- * continue directly at the target ip.
- */
- if (!frame->ex) {
- endfinally_ip = ip;
- goto handle_finally;
- } else {
- frame->ex = NULL;
+ endfinally_ip = ip;
+ if (frame->ex_handler != NULL && MONO_OFFSET_IN_HANDLER(frame->ex_handler, frame->ip - rtm->code)) {
frame->ex_handler = NULL;
+ frame->ex = NULL;
}
-#else
- frame->ex = NULL;
- frame->ex_handler = NULL;
- endfinally_ip = ip;
goto handle_finally;
- BREAK;
-#endif
- CASE (CEE_UNUSED41)
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_ICALL_V_V)
+ MINT_IN_CASE(MINT_ICALL_P_V)
+ MINT_IN_CASE(MINT_ICALL_P_P)
+ MINT_IN_CASE(MINT_ICALL_PP_V)
+ MINT_IN_CASE(MINT_ICALL_PI_V)
+ MINT_IN_CASE(MINT_ICALL_PP_P)
+ MINT_IN_CASE(MINT_ICALL_PI_P)
+ MINT_IN_CASE(MINT_ICALL_PPP_V)
+ MINT_IN_CASE(MINT_ICALL_PPI_V)
+ sp = do_icall (context, *ip, sp, rtm->data_items [*(guint16 *)(ip + 1)]);
+ if (frame->ex != NULL)
+ goto handle_exception;
+ ip += 2;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_MONO_LDPTR)
+ sp->data.p = rtm->data_items [*(guint16 *)(ip + 1)];
+ ip += 2;
+ ++sp;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_MONO_NEWOBJ)
+ sp->data.p = mono_object_new (context->domain, rtm->data_items [*(guint16 *)(ip + 1)]);
+ ip += 2;
+ sp++;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_MONO_FREE)
++ip;
- switch (*ip) {
- case CEE_MONO_FUNC1: {
- MonoMarshalConv conv;
- ++ip;
-
- conv = *ip;
-
- ++ip;
-
- sp--;
-
- sp->type = VAL_I32;
- sp->data.vt.klass = NULL;
-
- switch (conv) {
- case MONO_MARSHAL_CONV_STR_LPWSTR:
- sp->data.p = mono_string_to_utf16 (sp->data.p);
- break;
- case MONO_MARSHAL_CONV_LPSTR_STR:
- sp->data.p = mono_string_new_wrapper (sp->data.p);
- break;
- case MONO_MARSHAL_CONV_STR_LPTSTR:
- case MONO_MARSHAL_CONV_STR_LPSTR:
- sp->data.p = mono_string_to_utf8 (sp->data.p);
- break;
- case MONO_MARSHAL_CONV_STR_BSTR:
- sp->data.p = mono_string_to_bstr (sp->data.p);
- break;
- case MONO_MARSHAL_CONV_STR_TBSTR:
- case MONO_MARSHAL_CONV_STR_ANSIBSTR:
- sp->data.p = mono_string_to_ansibstr (sp->data.p);
- break;
- case MONO_MARSHAL_CONV_SB_LPSTR:
- sp->data.p = mono_string_builder_to_utf8 (sp->data.p);
- break;
- case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
- sp->data.p = mono_array_to_savearray (sp->data.p);
- break;
- case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
- sp->data.p = mono_array_to_lparray (sp->data.p);
- break;
- case MONO_MARSHAL_CONV_DEL_FTN:
- sp->data.p = mono_delegate_to_ftnptr (sp->data.p);
- break;
- case MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY:
- sp->data.p = mono_marshal_string_array (sp->data.p);
- break;
- default:
- g_assert_not_reached ();
- }
- sp++;
- break;
- }
- case CEE_MONO_PROC2: {
- MonoMarshalConv conv;
- ++ip;
- conv = *ip;
- ++ip;
-
- sp -= 2;
-
- switch (conv) {
- case MONO_MARSHAL_CONV_LPSTR_SB:
- mono_string_utf8_to_builder (sp [0].data.p, sp [1].data.p);
- break;
- case MONO_MARSHAL_FREE_ARRAY:
- mono_marshal_free_array (sp [0].data.p, sp [1].data.i);
- break;
- default:
- g_assert_not_reached ();
- }
- break;
- }
- case CEE_MONO_PROC3: {
- MonoMarshalConv conv;
- ++ip;
- conv = *ip;
- ++ip;
-
- sp -= 3;
-
- switch (conv) {
- case MONO_MARSHAL_CONV_STR_BYVALSTR:
- mono_string_to_byvalstr (sp [0].data.p, sp [1].data.p, sp [2].data.i);
- break;
- case MONO_MARSHAL_CONV_STR_BYVALWSTR:
- mono_string_to_byvalwstr (sp [0].data.p, sp [1].data.p, sp [2].data.i);
- break;
- default:
- g_assert_not_reached ();
- }
- break;
- }
- case CEE_MONO_VTADDR: {
- ++ip;
-
- sp->type = VAL_VALUETA;
- /* do nothing? */
- break;
- }
- case CEE_MONO_LDPTR: {
- guint32 token;
- ++ip;
-
- token = read32 (ip);
- ip += 4;
+ --sp;
+ g_free (sp->data.p);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_MONO_RETOBJ)
+ ++ip;
+ sp--;
+ stackval_from_data (mono_method_signature frame->runtime_method->method)->ret, frame->retval, sp->data.p,
+ mono_method_signature (frame->runtime_method->method)->pinvoke);
+ if (sp > frame->stack)
+ g_warning ("retobj: more values on stack: %d", sp-frame->stack);
+ goto exit_frame;
+
+#define RELOP(datamem, op) \
+ --sp; \
+ sp [-1].data.i = sp [-1].data.datamem op sp [0].data.datamem; \
+ ++ip;
+ MINT_IN_CASE(MINT_CEQ_I4)
+ RELOP(i, ==);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CEQ0_I4)
+ sp [-1].data.i = (sp [-1].data.i == 0);
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CEQ_I8)
+ RELOP(l, ==);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CEQ_R8)
+ --sp;
+ if (isunordered (sp [-1].data.f, sp [0].data.f))
+ sp [-1].data.i = 0;
+ else
+ sp [-1].data.i = sp [-1].data.f == sp [0].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CGT_I4)
+ RELOP(i, >);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CGT_I8)
+ RELOP(l, >);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CGT_R8)
+ --sp;
+ if (isunordered (sp [-1].data.f, sp [0].data.f))
+ sp [-1].data.i = 0;
+ else
+ sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+
+#define RELOP_CAST(datamem, op, type) \
+ --sp; \
+ sp [-1].data.i = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
+ ++ip;
+
+ MINT_IN_CASE(MINT_CGT_UN_I4)
+ RELOP_CAST(i, >, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CGT_UN_I8)
+ RELOP_CAST(l, >, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CGT_UN_R8)
+ --sp;
+ if (isunordered (sp [-1].data.f, sp [0].data.f))
+ sp [-1].data.i = 1;
+ else
+ sp [-1].data.i = sp [-1].data.f > sp [0].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CLT_I4)
+ RELOP(i, <);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CLT_I8)
+ RELOP(l, <);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CLT_R8)
+ --sp;
+ if (isunordered (sp [-1].data.f, sp [0].data.f))
+ sp [-1].data.i = 0;
+ else
+ sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CLT_UN_I4)
+ RELOP_CAST(i, <, guint32);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CLT_UN_I8)
+ RELOP_CAST(l, <, guint64);
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CLT_UN_R8)
+ --sp;
+ if (isunordered (sp [-1].data.f, sp [0].data.f))
+ sp [-1].data.i = 1;
+ else
+ sp [-1].data.i = sp [-1].data.f < sp [0].data.f;
+ ++ip;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDFTN) {
+ sp->data.p = rtm->data_items [* (guint16 *)(ip + 1)];
+ ++sp;
+ ip += 2;
+ MINT_IN_BREAK;
+ }
+ MINT_IN_CASE(MINT_LDVIRTFTN) {
+ RuntimeMethod *m = rtm->data_items [* (guint16 *)(ip + 1)];
+ ip += 2;
+ --sp;
+ if (!sp->data.p)
+ THROW_EX (mono_get_exception_null_reference (), ip - 2);
- sp->type = VAL_I32;
- sp->data.p = mono_method_get_wrapper_data (frame->method, token);
- sp->data.vt.klass = NULL;
- ++sp;
- break;
- }
- case CEE_MONO_FREE: {
- ++ip;
-
- sp -= 1;
- g_free (sp->data.p);
- break;
- }
- case CEE_MONO_OBJADDR: {
- ++ip;
-
- sp->type = VAL_MP;
- /* do nothing? */
- break;
- }
- case CEE_MONO_NEWOBJ: {
- MonoClass *class;
- guint32 token;
-
- ++ip;
- token = read32 (ip);
- ip += 4;
-
- class = (MonoClass *)mono_method_get_wrapper_data (frame->method, token);
- sp->data.p = mono_object_new (domain, class);
- sp++;
- break;
- }
- case CEE_MONO_RETOBJ: {
- MonoClass *class;
- guint32 token;
-
- ++ip;
- token = read32 (ip);
- ip += 4;
+ sp->data.p = get_virtual_method (m, sp->data.p);
+ ++sp;
+ MINT_IN_BREAK;
+ }
- sp--;
+ 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;
+ ++ip;
+ ++sp;
+ MINT_IN_BREAK;
- class = (MonoClass *)mono_method_get_wrapper_data (frame->method, token);
-
- stackval_from_data (signature->ret, frame->retval, sp->data.vt.vt, signature->pinvoke);
+#define LDARG(datamem, argtype) \
+ sp->data.datamem = * (argtype *)(frame->args + * (guint16 *)(ip + 1)); \
+ ip += 2; \
+ ++sp;
+
+ MINT_IN_CASE(MINT_LDARG_I1) LDARG(i, gint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDARG_U1) LDARG(i, guint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDARG_I2) LDARG(i, gint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDARG_U2) LDARG(i, guint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDARG_I4) LDARG(i, gint32); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDARG_I8) LDARG(l, gint64); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDARG_R4) LDARG(f, float); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDARG_R8) LDARG(f, double); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDARG_O) LDARG(p, gpointer); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDARG_P) LDARG(p, gpointer); MINT_IN_BREAK;
+
+ MINT_IN_CASE(MINT_LDARG_VT)
+ sp->data.p = vt_sp;
+ i32 = READ32(ip + 2);
+ memcpy(sp->data.p, frame->args + * (guint16 *)(ip + 1), i32);
+ vt_sp += (i32 + 7) & ~7;
+ ip += 4;
+ ++sp;
+ MINT_IN_BREAK;
- if (sp > frame->stack)
- g_warning ("more values on stack: %d", sp-frame->stack);
- DEBUG_LEAVE ();
- return;
- }
- default:
- g_error ("Unimplemented opcode: 0xF0 %02x at 0x%x\n", *ip, ip-header->code);
- }
- BREAK;
- CASE (CEE_UNUSED26)
- CASE (CEE_UNUSED27)
- CASE (CEE_UNUSED28)
- CASE (CEE_UNUSED29)
- CASE (CEE_UNUSED30)
- CASE (CEE_UNUSED31)
- CASE (CEE_UNUSED32)
- CASE (CEE_UNUSED33)
- CASE (CEE_UNUSED34)
- CASE (CEE_UNUSED35)
- CASE (CEE_UNUSED36)
- CASE (CEE_UNUSED37)
- CASE (CEE_UNUSED38)
- CASE (CEE_UNUSED39)
- CASE (CEE_UNUSED40)
- CASE (CEE_UNUSED42)
- CASE (CEE_UNUSED43)
- CASE (CEE_UNUSED44)
- CASE (CEE_UNUSED45)
- CASE (CEE_UNUSED46)
- CASE (CEE_UNUSED47)
- CASE (CEE_UNUSED48)
- CASE (CEE_PREFIX7)
- CASE (CEE_PREFIX6)
- CASE (CEE_PREFIX5)
- CASE (CEE_PREFIX4)
- CASE (CEE_PREFIX3)
- CASE (CEE_PREFIX2)
- CASE (CEE_PREFIXREF) ves_abort(); BREAK;
- /*
- * Note: Exceptions thrown when executing a prefixed opcode need
- * to take into account the number of prefix bytes (usually the
- * throw point is just (ip - n_prefix_bytes).
- */
- SUB_SWITCH
- ++ip;
- switch (*ip) {
- case CEE_ARGLIST: ves_abort(); break;
- case CEE_CEQ: {
- gint32 result;
- ++ip;
- sp -= 2;
-
- if (sp->type == VAL_I32)
- result = sp [0].data.i == (gint)GET_NATI (sp [1]);
- else if (sp->type == VAL_I64)
- result = sp [0].data.l == sp [1].data.l;
- else if (sp->type == VAL_DOUBLE) {
- if (isnan (sp [0].data.f) || isnan (sp [1].data.f))
- result = 0;
- else
- result = sp [0].data.f == sp [1].data.f;
- } else
- result = GET_NATI (sp [0]) == GET_NATI (sp [1]);
- sp->type = VAL_I32;
- sp->data.i = result;
+#define STARG(datamem, argtype) \
+ --sp; \
+ * (argtype *)(frame->args + * (guint16 *)(ip + 1)) = sp->data.datamem; \
+ ip += 2; \
+
+ MINT_IN_CASE(MINT_STARG_I1) STARG(i, gint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STARG_U1) STARG(i, guint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STARG_I2) STARG(i, gint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STARG_U2) STARG(i, guint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STARG_I4) STARG(i, gint32); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STARG_I8) STARG(l, gint64); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STARG_R4) STARG(f, float); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STARG_R8) STARG(f, double); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STARG_O) STARG(p, gpointer); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STARG_P) STARG(p, gpointer); MINT_IN_BREAK;
+
+ MINT_IN_CASE(MINT_STARG_VT)
+ i32 = READ32(ip + 2);
+ --sp;
+ memcpy(frame->args + * (guint16 *)(ip + 1), sp->data.p, i32);
+ vt_sp -= (i32 + 7) & ~7;
+ ip += 4;
+ MINT_IN_BREAK;
- sp++;
- break;
- }
- case CEE_CGT: {
- gint32 result;
- ++ip;
- sp -= 2;
-
- if (sp->type == VAL_I32)
- result = sp [0].data.i > (gint)GET_NATI (sp [1]);
- else if (sp->type == VAL_I64)
- result = sp [0].data.l > sp [1].data.l;
- else if (sp->type == VAL_DOUBLE) {
- if (isnan (sp [0].data.f) || isnan (sp [1].data.f))
- result = 0;
- else
- result = sp [0].data.f > sp [1].data.f;
- } else
- result = (gint)GET_NATI (sp [0]) > (gint)GET_NATI (sp [1]);
- sp->type = VAL_I32;
- sp->data.i = result;
+#define STINARG(datamem, argtype) \
+ do { \
+ int n = * (guint16 *)(ip + 1); \
+ * (argtype *)(frame->args + rtm->arg_offsets [n]) = frame->stack_args [n].data.datamem; \
+ ip += 2; \
+ } while (0)
+
+ MINT_IN_CASE(MINT_STINARG_I1) STINARG(i, gint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STINARG_U1) STINARG(i, guint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STINARG_I2) STINARG(i, gint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STINARG_U2) STINARG(i, guint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STINARG_I4) STINARG(i, gint32); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STINARG_I8) STINARG(l, gint64); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STINARG_R4) STINARG(f, float); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STINARG_R8) STINARG(f, double); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STINARG_O) STINARG(p, gpointer); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STINARG_P) STINARG(p, gpointer); MINT_IN_BREAK;
+
+ MINT_IN_CASE(MINT_STINARG_VT) {
+ int n = * (guint16 *)(ip + 1);
+ i32 = READ32(ip + 2);
+ memcpy (frame->args + rtm->arg_offsets [n], frame->stack_args [n].data.p, i32);
+ ip += 4;
+ MINT_IN_BREAK;
+ }
- sp++;
- break;
- }
- case CEE_CGT_UN: {
- gint32 result;
- ++ip;
- sp -= 2;
-
- if (sp->type == VAL_I32)
- result = (guint32)sp [0].data.i > (mono_u)GET_NATI (sp [1]);
- else if (sp->type == VAL_I64)
- result = (guint64)sp [0].data.l > (guint64)sp [1].data.l;
- else if (sp->type == VAL_DOUBLE)
- result = isnan (sp [0].data.f) || isnan (sp [1].data.f);
- else
- result = (mono_u)GET_NATI (sp [0]) > (mono_u)GET_NATI (sp [1]);
- sp->type = VAL_I32;
- sp->data.i = result;
+ MINT_IN_CASE(MINT_LDARGA)
+ sp->data.p = frame->args + * (guint16 *)(ip + 1);
+ ip += 2;
+ ++sp;
+ MINT_IN_BREAK;
- sp++;
- break;
- }
- case CEE_CLT: {
- gint32 result;
- ++ip;
- sp -= 2;
-
- if (sp->type == VAL_I32)
- result = sp [0].data.i < (gint)GET_NATI (sp [1]);
- else if (sp->type == VAL_I64)
- result = sp [0].data.l < sp [1].data.l;
- else if (sp->type == VAL_DOUBLE) {
- if (isnan (sp [0].data.f) || isnan (sp [1].data.f))
- result = 0;
- else
- result = sp [0].data.f < sp [1].data.f;
- } else
- result = (gint)GET_NATI (sp [0]) < (gint)GET_NATI (sp [1]);
- sp->type = VAL_I32;
- sp->data.i = result;
+#define LDLOC(datamem, argtype) \
+ sp->data.datamem = * (argtype *)(locals + * (guint16 *)(ip + 1)); \
+ ip += 2; \
+ ++sp;
+
+ MINT_IN_CASE(MINT_LDLOC_I1) LDLOC(i, gint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDLOC_U1) LDLOC(i, guint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDLOC_I2) LDLOC(i, gint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDLOC_U2) LDLOC(i, guint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDLOC_I4) LDLOC(i, gint32); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDLOC_I8) LDLOC(l, gint64); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDLOC_R4) LDLOC(f, float); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDLOC_R8) LDLOC(f, double); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDLOC_O) LDLOC(p, gpointer); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_LDLOC_P) LDLOC(p, gpointer); MINT_IN_BREAK;
+
+ MINT_IN_CASE(MINT_LDLOC_VT)
+ sp->data.p = vt_sp;
+ i32 = READ32(ip + 2);
+ memcpy(sp->data.p, locals + * (guint16 *)(ip + 1), i32);
+ vt_sp += (i32 + 7) & ~7;
+ ip += 4;
+ ++sp;
+ MINT_IN_BREAK;
- sp++;
- break;
- }
- case CEE_CLT_UN: {
- gint32 result;
- ++ip;
- sp -= 2;
-
- if (sp->type == VAL_I32)
- result = (guint32)sp [0].data.i < (mono_u)GET_NATI (sp [1]);
- else if (sp->type == VAL_I64)
- result = (guint64)sp [0].data.l < (guint64)sp [1].data.l;
- else if (sp->type == VAL_DOUBLE)
- result = isnan (sp [0].data.f) || isnan (sp [1].data.f);
- else
- result = (mono_u)GET_NATI (sp [0]) < (mono_u)GET_NATI (sp [1]);
- sp->type = VAL_I32;
- sp->data.i = result;
+ MINT_IN_CASE(MINT_LDLOCA_S)
+ sp->data.p = locals + * (guint16 *)(ip + 1);
+ ip += 2;
+ ++sp;
+ MINT_IN_BREAK;
- sp++;
- break;
- }
- case CEE_LDFTN:
- case CEE_LDVIRTFTN: {
- int virtual = *ip == CEE_LDVIRTFTN;
- MonoMethod *m;
- guint32 token;
- ++ip;
- token = read32 (ip);
- ip += 4;
-
- if (frame->method->wrapper_type != MONO_WRAPPER_NONE)
- m = (MonoMethod *)mono_method_get_wrapper_data (frame->method, token);
- else
- m = mono_get_method (image, token, NULL);
-
- if (!m)
- THROW_EX (mono_get_exception_missing_method (), ip - 5);
- if (virtual) {
- --sp;
- if (!sp->data.p)
- THROW_EX (mono_get_exception_null_reference (), ip - 5);
-
- m = get_virtual_method (domain, m, sp);
- }
- sp->type = VAL_NATI;
- sp->data.p = mono_create_method_pointer (m);
- sp->data.vt.klass = NULL;
- ++sp;
- break;
- }
- case CEE_UNUSED56: ves_abort(); break;
- case CEE_LDARG: {
- guint32 arg_pos;
- ++ip;
- arg_pos = read16 (ip);
- ip += 2;
- vt_alloc (ARG_TYPE (signature, arg_pos), sp, signature->pinvoke);
- stackval_from_data (ARG_TYPE (signature, arg_pos), sp, ARG_POS (arg_pos), signature->pinvoke);
- ++sp;
- break;
- }
- case CEE_LDARGA: {
- MonoType *t;
- MonoClass *c;
- guint32 anum;
-
- ++ip;
- anum = read16 (ip);
- ip += 2;
- t = ARG_TYPE (signature, anum);
- c = mono_class_from_mono_type (t);
- sp->data.vt.klass = c;
- sp->data.vt.vt = ARG_POS (anum);
-
- if (c->valuetype)
- sp->type = VAL_VALUETA;
- else
- sp->type = VAL_TP;
-
- ++sp;
- break;
- }
- case CEE_STARG: {
- guint32 arg_pos;
- ++ip;
- arg_pos = read16 (ip);
- ip += 2;
- --sp;
- stackval_to_data (ARG_TYPE (signature, arg_pos), sp, ARG_POS (arg_pos), signature->pinvoke);
- vt_free (sp);
- break;
- }
- case CEE_LDLOC: {
- guint32 loc_pos;
- ++ip;
- loc_pos = read16 (ip);
- ip += 2;
- vt_alloc (LOCAL_TYPE (header, loc_pos), sp, FALSE);
- stackval_from_data (LOCAL_TYPE (header, loc_pos), sp, LOCAL_POS (loc_pos), FALSE);
- ++sp;
- break;
- }
- case CEE_LDLOCA: {
- MonoType *t;
- MonoClass *c;
- guint32 loc_pos;
-
- ++ip;
- loc_pos = read16 (ip);
- ip += 2;
- t = LOCAL_TYPE (header, loc_pos);
- c = mono_class_from_mono_type (t);
- sp->data.vt.vt = LOCAL_POS (loc_pos);
- sp->data.vt.klass = c;
-
- if (c->valuetype)
- sp->type = VAL_VALUETA;
- else
- sp->type = VAL_TP;
-
- ++sp;
- break;
- }
- case CEE_STLOC: {
- guint32 loc_pos;
- ++ip;
- loc_pos = read16 (ip);
- ip += 2;
- --sp;
- stackval_to_data (LOCAL_TYPE (header, loc_pos), sp, LOCAL_POS (loc_pos), FALSE);
- vt_free (sp);
- break;
- }
- case CEE_LOCALLOC:
- --sp;
- if (sp != frame->stack)
- THROW_EX (mono_get_exception_execution_engine (NULL), ip - 1);
- ++ip;
- sp->data.p = alloca (sp->data.i);
- sp->type = VAL_TP;
- sp++;
- break;
- case CEE_UNUSED57: ves_abort(); break;
- case CEE_ENDFILTER: ves_abort(); break;
- case CEE_UNALIGNED_:
- ++ip;
- unaligned_address = 1;
- break;
- case CEE_VOLATILE_:
- ++ip;
- volatile_address = 1;
- break;
- case CEE_TAIL_:
- ++ip;
- tail_recursion = 1;
- break;
- case CEE_INITOBJ: {
- guint32 token;
- ++ip;
- token = read32 (ip);
- ip += 4;
- /*
- * we ignore the value of token (I think we can as unspecified
- * behavior described in Partition II, 3.5).
- */
- --sp;
- g_assert (sp->type == VAL_VALUETA || sp->type == VAL_TP);
- memset (sp->data.vt.vt, 0, mono_class_value_size (sp->data.vt.klass, NULL));
- break;
- }
- case CEE_UNUSED68: ves_abort(); break;
- case CEE_CPBLK:
- sp -= 3;
- if (!sp [0].data.p || !sp [1].data.p)
- THROW_EX (mono_get_exception_null_reference(), ip - 1);
- ++ip;
- /* FIXME: value and size may be int64... */
- memcpy (sp [0].data.p, sp [1].data.p, sp [2].data.i);
- break;
- case CEE_INITBLK:
- sp -= 3;
- if (!sp [0].data.p)
- THROW_EX (mono_get_exception_null_reference(), ip - 1);
- ++ip;
- /* FIXME: value and size may be int64... */
- memset (sp [0].data.p, sp [1].data.i, sp [2].data.i);
- break;
- case CEE_UNUSED69: ves_abort(); break;
- case CEE_RETHROW:
- /*
- * need to clarify what this should actually do:
- * start the search from the last found handler in
- * this method or continue in the caller or what.
- * Also, do we need to run finally/fault handlers after a retrow?
- * Well, this implementation will follow the usual search
- * for an handler, considering the current ip as throw spot.
- * We need to NULL frame->ex_handler for the later code to
- * actually run the new found handler.
- */
- frame->ex_handler = NULL;
- THROW_EX (frame->ex, ip - 1);
- break;
- case CEE_UNUSED: ves_abort(); break;
- case CEE_SIZEOF: {
- guint32 token;
- int align;
- ++ip;
- token = read32 (ip);
- ip += 4;
- if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC) {
- MonoType *type = mono_type_create_from_typespec (image, token);
- sp->data.i = mono_type_size (type, &align);
- mono_metadata_free_type (type);
- } else {
- MonoClass *szclass = mono_class_get (image, token);
- mono_class_init (szclass);
- if (!szclass->valuetype)
- THROW_EX (mono_exception_from_name (mono_defaults.corlib, "System", "InvalidProgramException"), ip - 5);
- sp->data.i = mono_class_value_size (szclass, &align);
- }
- sp->type = VAL_I32;
- ++sp;
- break;
- }
- case CEE_REFANYTYPE: ves_abort(); break;
- case CEE_UNUSED52:
- case CEE_UNUSED53:
- case CEE_UNUSED54:
- case CEE_UNUSED55:
- case CEE_UNUSED70:
- default:
- g_error ("Unimplemented opcode: 0xFE %02x at 0x%x\n", *ip, ip-header->code);
- }
- continue;
- DEFAULT;
+#define STLOC(datamem, argtype) \
+ --sp; \
+ * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp->data.datamem; \
+ ip += 2;
+
+ MINT_IN_CASE(MINT_STLOC_I1) STLOC(i, gint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STLOC_U1) STLOC(i, guint8); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STLOC_I2) STLOC(i, gint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STLOC_U2) STLOC(i, guint16); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STLOC_I4) STLOC(i, gint32); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STLOC_I8) STLOC(l, gint64); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STLOC_R4) STLOC(f, float); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STLOC_R8) STLOC(f, double); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STLOC_O) STLOC(p, gpointer); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STLOC_P) STLOC(p, gpointer); MINT_IN_BREAK;
+
+#define STLOC_NP(datamem, argtype) \
+ * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp [-1].data.datamem; \
+ ip += 2;
+
+ MINT_IN_CASE(MINT_STLOC_NP_I4) STLOC_NP(i, gint32); MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_STLOC_NP_O) STLOC_NP(p, gpointer); MINT_IN_BREAK;
+
+ MINT_IN_CASE(MINT_STLOC_VT)
+ i32 = READ32(ip + 2);
+ --sp;
+ memcpy(locals + * (guint16 *)(ip + 1), sp->data.p, i32);
+ vt_sp -= (i32 + 7) & ~7;
+ ip += 4;
+ MINT_IN_BREAK;
+
+ MINT_IN_CASE(MINT_LOCALLOC)
+ if (sp != frame->stack + 1) /*FIX?*/
+ THROW_EX (mono_get_exception_execution_engine (NULL), ip);
+ sp [-1].data.p = alloca (sp [-1].data.i);
+ ++ip;
+ MINT_IN_BREAK;
+#if 0
+ MINT_IN_CASE(MINT_ENDFILTER) ves_abort(); MINT_IN_BREAK;
+#endif
+ MINT_IN_CASE(MINT_INITOBJ)
+ --sp;
+ memset (sp->data.vt, 0, READ32(ip + 1));
+ ip += 3;
+ MINT_IN_BREAK;
+ MINT_IN_CASE(MINT_CPBLK)
+ sp -= 3;
+ if (!sp [0].data.p || !sp [1].data.p)
+ THROW_EX (mono_get_exception_null_reference(), ip - 1);
+ ++ip;
+ /* FIXME: value and size may be int64... */
+ memcpy (sp [0].data.p, sp [1].data.p, sp [2].data.i);
+ MINT_IN_BREAK;
+#if 0
+ MINT_IN_CASE(MINT_CONSTRAINED_) {
+ guint32 token;
+ /* FIXME: implement */
+ ++ip;
+ token = READ32 (ip);
+ ip += 2;
+ MINT_IN_BREAK;
+ }
+#endif
+ MINT_IN_CASE(MINT_INITBLK)
+ sp -= 3;
+ if (!sp [0].data.p)
+ THROW_EX (mono_get_exception_null_reference(), ip - 1);
+ ++ip;
+ /* FIXME: value and size may be int64... */
+ memset (sp [0].data.p, sp [1].data.i, sp [2].data.i);
+ MINT_IN_BREAK;
+#if 0
+ MINT_IN_CASE(MINT_NO_)
+ /* FIXME: implement */
+ ip += 2;
+ MINT_IN_BREAK;
+#endif
+ MINT_IN_CASE(MINT_RETHROW)
+ /*
+ * need to clarify what this should actually do:
+ * start the search from the last found handler in
+ * this method or continue in the caller or what.
+ * Also, do we need to run finally/fault handlers after a retrow?
+ * Well, this implementation will follow the usual search
+ * for an handler, considering the current ip as throw spot.
+ * We need to NULL frame->ex_handler for the later code to
+ * actually run the new found handler.
+ */
+ frame->ex_handler = NULL;
+ THROW_EX (frame->ex, ip - 1);
+ MINT_IN_BREAK;
+ MINT_IN_DEFAULT
+ g_print ("Unimplemented opcode: %04x %s at 0x%x\n", *ip, mono_interp_opname[*ip], ip-rtm->code);
+ THROW_EX (mono_get_exception_execution_engine ("Unimplemented opcode"), ip);
}
}
int i;
guint32 ip_offset;
MonoInvocation *inv;
- MonoMethodHeader *hd;
MonoExceptionClause *clause;
/*char *message;*/
MonoObject *ex_obj;
#if DEBUG_INTERP
if (tracing)
- g_print ("* Handling exception '%s' at IL_%04x\n", mono_object_class (frame->ex)->name, frame->ip - header->code);
+ g_print ("* Handling exception '%s' at IL_%04x\n",
+ frame->ex == NULL ? "** Unknown **" : mono_object_class (frame->ex)->name,
+ rtm == NULL ? 0 : frame->ip - rtm->code);
#endif
if (die_on_exception)
goto die_on_ex;
-
+
for (inv = frame; inv; inv = inv->parent) {
- if (inv->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
+ MonoMethod *method;
+ if (inv->runtime_method == NULL)
+ continue;
+ method = inv->runtime_method->method;
+ if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
+ continue;
+ if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))
continue;
- if (inv->method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))
+ if (inv->ip == NULL)
continue;
- hd = ((MonoMethodNormal*)inv->method)->header;
- ip_offset = inv->ip - hd->code;
- for (i = 0; i < hd->num_clauses; ++i) {
- clause = &hd->clauses [i];
+ ip_offset = inv->ip - inv->runtime_method->code;
+ inv->ex_handler = NULL; /* clear this in case we are trhowing an exception while handling one - this one wins */
+ for (i = 0; i < inv->runtime_method->num_clauses; ++i) {
+ clause = &inv->runtime_method->clauses [i];
if (clause->flags <= 1 && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
if (!clause->flags) {
- if (mono_object_isinst ((MonoObject*)frame->ex, mono_class_get (inv->method->klass->image, clause->token_or_filter))) {
+ if (mono_object_isinst ((MonoObject*)frame->ex, clause->data.catch_class)) {
/*
* OK, we found an handler, now we need to execute the finally
* and fault blocks before branching to the handler code.
inv->ex_handler = clause;
#if DEBUG_INTERP
if (tracing)
- g_print ("* Found handler at '%s'\n", inv->method->name);
+ g_print ("* Found handler at '%s'\n", method->name);
#endif
- /*
- * It seems that if the catch handler is found in the same method,
- * it gets executed before the finally handler.
- */
- if (inv == frame)
- goto handle_fault;
- else
- goto handle_finally;
+ goto handle_finally;
}
} else {
/* FIXME: handle filter clauses */
int i;
guint32 ip_offset;
MonoExceptionClause *clause;
+ GSList *old_list = finally_ips;
+ MonoMethod *method = frame->runtime_method->method;
+ MonoMethodHeader *header = mono_method_get_header (method);
#if DEBUG_INTERP
if (tracing)
- g_print ("* Handle finally\n");
+ g_print ("* Handle finally IL_%04x\n", endfinally_ip == NULL ? 0 : endfinally_ip - rtm->code);
#endif
- if ((frame->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
- || (frame->method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))) {
- DEBUG_LEAVE ();
- return;
+ if (rtm == NULL || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
+ || (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))) {
+ goto exit_frame;
}
- ip_offset = frame->ip - header->code;
+ ip_offset = frame->ip - rtm->code;
- for (i = 0; i < header->num_clauses; ++i) {
- clause = &header->clauses [i];
- if (clause == frame->ex_handler)
+ if (endfinally_ip != NULL)
+ finally_ips = g_slist_prepend(finally_ips, (void *)endfinally_ip);
+ for (i = 0; i < header->num_clauses; ++i)
+ if (frame->ex_handler == &rtm->clauses [i])
break;
- if (MONO_OFFSET_IN_CLAUSE (clause, ip_offset) && !(MONO_OFFSET_IN_CLAUSE (clause, endfinally_ip - header->code))) {
+ while (i > 0) {
+ --i;
+ clause = &rtm->clauses [i];
+ if (MONO_OFFSET_IN_CLAUSE (clause, ip_offset) && (endfinally_ip == NULL || !(MONO_OFFSET_IN_CLAUSE (clause, endfinally_ip - rtm->code)))) {
if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
- ip = header->code + clause->handler_offset;
- finally_ips = g_slist_append (finally_ips, (gpointer) ip);
+ ip = rtm->code + clause->handler_offset;
+ finally_ips = g_slist_prepend (finally_ips, (gpointer) ip);
#if DEBUG_INTERP
if (tracing)
g_print ("* Found finally at IL_%04x with exception: %s\n", clause->handler_offset, frame->ex? "yes": "no");
}
}
}
- if (finally_ips) {
+
+ endfinally_ip = NULL;
+
+ if (old_list != finally_ips && finally_ips) {
ip = finally_ips->data;
finally_ips = g_slist_remove (finally_ips, ip);
+ sp = frame->stack; /* spec says stack should be empty at endfinally so it should be at the start too */
goto main_loop;
}
*/
if (frame->ex)
goto handle_fault;
- ip = endfinally_ip;
- goto main_loop;
+ ves_abort();
}
handle_fault:
{
int i;
guint32 ip_offset;
MonoExceptionClause *clause;
+ MonoMethodHeader *header = mono_method_get_header (frame->runtime_method->method);
#if DEBUG_INTERP
if (tracing)
g_print ("* Handle fault\n");
#endif
- ip_offset = frame->ip - header->code;
+ ip_offset = frame->ip - rtm->code;
for (i = 0; i < header->num_clauses; ++i) {
- clause = &header->clauses [i];
- if (clause->flags == 3 && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
- ip = header->code + clause->handler_offset;
+ clause = &rtm->clauses [i];
+ if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
+ ip = rtm->code + clause->handler_offset;
#if DEBUG_INTERP
if (tracing)
g_print ("* Executing handler at IL_%04x\n", clause->handler_offset);
if (tracing)
g_print ("* Executing handler at IL_%04x\n", frame->ex_handler->handler_offset);
#endif
- ip = header->code + frame->ex_handler->handler_offset;
+ ip = rtm->code + frame->ex_handler->handler_offset;
sp = frame->stack;
- sp->type = VAL_OBJ;
+ vt_sp = (char *)sp + rtm->stack_size;
sp->data.p = frame->ex;
++sp;
goto main_loop;
}
- if (!frame->parent)
- goto die_on_ex;
- DEBUG_LEAVE ();
+ goto exit_frame;
+ }
+exit_frame:
+ DEBUG_LEAVE ();
+}
+
+void
+ves_exec_method (MonoInvocation *frame)
+{
+ ThreadContext *context = TlsGetValue (thread_context_id);
+ ThreadContext context_struct;
+ jmp_buf env;
+
+ frame->ex = NULL;
+
+ if (setjmp(env)) {
+ mono_unhandled_exception ((MonoObject*)frame->ex);
return;
}
-
+ if (context == NULL) {
+ context = &context_struct;
+ context_struct.domain = mono_domain_get ();
+ context_struct.base_frame = frame;
+ context_struct.current_frame = NULL;
+ context_struct.env_frame = frame;
+ context_struct.current_env = &env;
+ context_struct.search_for_handler = 0;
+ context_struct.managed_code = 0;
+ TlsSetValue (thread_context_id, context);
+ }
+ frame->ip = NULL;
+ frame->parent = context->current_frame;
+ frame->runtime_method = mono_interp_get_runtime_method (frame->method);
+ context->managed_code = 1;
+ ves_exec_method_with_context(frame, context);
+ context->managed_code = 0;
+ if (frame->ex) {
+ if (context != &context_struct && context->current_env) {
+ context->env_frame->ex = frame->ex;
+ longjmp (*context->current_env, 1);
+ }
+ else
+ mono_unhandled_exception ((MonoObject*)frame->ex);
+ }
+ if (context->base_frame == frame)
+ TlsSetValue (thread_context_id, NULL);
+ else
+ context->current_frame = frame->parent;
}
static int
ves_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
{
- MonoImage *image = assembly->image;
- MonoCLIImageInfo *iinfo;
+ MonoImage *image = mono_assembly_get_image (assembly);
MonoMethod *method;
MonoObject *exc = NULL;
int rval;
- iinfo = image->image_info;
- method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL);
+ method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
if (!method)
- g_error ("No entry point method found in %s", image->name);
+ g_error ("No entry point method found in %s", mono_image_get_filename (image));
rval = mono_runtime_run_main (method, argc, argv, &exc);
+ if (exc != NULL)
+ mono_unhandled_exception (exc);
return rval;
}
}
#endif
-static MonoException * segv_exception = NULL;
+static void
+add_signal_handler (int signo, void (*handler)(int))
+{
+#ifdef PLATFORM_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)
{
- signal (signum, segv_handler);
+ ThreadContext *context = TlsGetValue (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 = TlsGetValue (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 = TlsGetValue (thread_context_id);
+ MonoException *abrt_exception;
+
+ if (context == NULL)
+ return;
+ abrt_exception = mono_get_exception_execution_engine ("Abort (SIGABRT).");
+ mono_raise_exception (abrt_exception);
+}
+
+static void
+thread_abort_handler (int signum)
+{
+ ThreadContext *context = TlsGetValue (thread_context_id);
+ MonoException *exc;
+
+ if (context == NULL)
+ return;
+
+ exc = mono_thread_request_interruption (context->managed_code);
+ if (exc) mono_raise_exception (exc);
+}
+
static MonoBoolean
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 = TlsGetValue (thread_context_id);
+ MonoInvocation *inv = context->current_frame;
+ 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)
- *method = NULL;
+ *method = inv == NULL ? NULL : mono_method_get_object (context->domain, inv->runtime_method->method, NULL);
if (line)
*line = 0;
- if (column)
- *column = 0;
- if (file)
- *file = mono_string_new (mono_domain_get (), "unknown");
+ if (need_file_info) {
+ if (column)
+ *column = 0;
+ if (file)
+ *file = mono_string_new (mono_domain_get (), "unknown");
+ }
return TRUE;
}
static MonoArray *
ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
{
- return NULL;
+ MonoDomain *domain = mono_domain_get ();
+ MonoArray *res;
+ MonoArray *ta = exc->trace_ips;
+ int i, len;
+
+ if (ta == NULL) {
+ /* Exception is not thrown yet */
+ return mono_array_new (domain, mono_defaults.stack_frame_class, 0);
+ }
+
+ len = mono_array_length (ta);
+
+ res = mono_array_new (domain, mono_defaults.stack_frame_class, len > skip ? len - skip : 0);
+
+ for (i = skip; i < len / 2; i++) {
+ MonoStackFrame *sf = (MonoStackFrame *)mono_object_new (domain, mono_defaults.stack_frame_class);
+ 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 (domain, rtm->method, NULL);
+ 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 = filename? mono_string_new (domain, filename): NULL;
+ sf->column = 0;
+
+ g_free (filename);
+ }
+#endif
+
+ mono_array_set (res, gpointer, i, sf);
+ }
+
+ return res;
+}
+
+static MonoObject *
+ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
+ MonoReflectionMethod *info)
+{
+ MonoClass *delegate_class = mono_class_from_mono_type (type->type);
+ MonoObject *delegate;
+
+ mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
+
+ delegate = mono_object_new (mono_object_domain (type), delegate_class);
+
+ interp_delegate_ctor (mono_object_domain (type), delegate, target, mono_interp_get_runtime_method (info->method));
+
+ return delegate;
}
+
typedef struct
{
MonoDomain *domain;
{
MainThreadArgs *main_args=(MainThreadArgs *)user_data;
MonoAssembly *assembly;
- char *error;
- if (main_args->enable_debugging)
+ if (main_args->enable_debugging) {
mono_debug_init (MONO_DEBUG_FORMAT_MONO);
+ mono_debug_init_1 (main_args->domain);
+ }
assembly = mono_domain_assembly_open (main_args->domain,
main_args->file);
#ifdef RUN_TEST
test_load_class (assembly->image);
#else
- error = mono_verify_corlib ();
- if (error) {
- fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
- exit (1);
- }
- segv_exception = mono_get_exception_null_reference ();
- segv_exception->message = mono_string_new (main_args->domain, "Segmentation fault");
- signal (SIGSEGV, segv_handler);
ves_exec (main_args->domain, assembly, main_args->argc, main_args->argv);
#endif
static void
mono_runtime_install_handlers (void)
{
- /* FIXME: anything to do here? */
+ add_signal_handler (SIGSEGV, segv_handler);
+ add_signal_handler (SIGINT, quit_handler);
+ add_signal_handler (SIGABRT, abrt_handler);
+ add_signal_handler (mono_thread_get_abort_signal (), thread_abort_handler);
+}
+
+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);
+}
+
+MonoDomain *
+mono_interp_init(const char *file)
+{
+ MonoDomain *domain;
+
+ g_set_prgname (file);
+ mono_set_rootdir ();
+
+ g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
+ g_log_set_fatal_mask (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR);
+
+ if (!g_thread_supported ())
+ g_thread_init (NULL);
+
+ thread_context_id = TlsAlloc ();
+ TlsSetValue (thread_context_id, NULL);
+ InitializeCriticalSection (&runtime_method_lookup_section);
+ InitializeCriticalSection (&create_method_pointer_mutex);
+
+ mono_runtime_install_handlers ();
+ mono_interp_transform_init ();
+ mono_install_compile_method (mono_create_method_pointer);
+ mono_install_runtime_invoke (interp_mono_runtime_invoke);
+ mono_install_remoting_trampoline (interp_create_remoting_trampoline);
+ mono_install_trampoline (interp_create_trampoline);
+
+ mono_install_handler (interp_ex_handler);
+ mono_install_stack_walk (interp_walk_stack);
+ 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 (domain, NULL, NULL);
+
+
+ mono_thread_attach (domain);
+ return domain;
}
int
-main (int argc, char *argv [])
+mono_main (int argc, char *argv [])
{
MonoDomain *domain;
- int retval = 0, i, ocount = 0;
+ int retval = 0, i;
char *file, *config_file = NULL;
int enable_debugging = FALSE;
MainThreadArgs main_args;
-
+ const char *error;
+
+ setlocale (LC_ALL, "");
if (argc < 2)
usage ();
+ MONO_GC_PRE_INIT ();
+
for (i = 1; i < argc && argv [i][0] == '-'; i++){
if (strcmp (argv [i], "--trace") == 0)
global_tracing = 1;
global_no_pointers = 1;
if (strcmp (argv [i], "--traceops") == 0)
global_tracing = 2;
+ if (strcmp (argv [i], "--traceopt") == 0)
+ ++mono_interp_traceopt;
if (strcmp (argv [i], "--dieonex") == 0) {
die_on_exception = 1;
enable_debugging = 1;
mono_print_vtable = TRUE;
if (strcmp (argv [i], "--profile") == 0)
mono_profiler_load (NULL);
- if (strcmp (argv [i], "--opcode-count") == 0)
- ocount = 1;
if (strcmp (argv [i], "--config") == 0)
config_file = argv [++i];
if (strcmp (argv [i], "--workers") == 0) {
g_error ("Invalid method name '%s'", argv [i]);
db_methods = g_list_append (db_methods, desc);
}
+ if (strcmp (argv [i], "--nested") == 0)
+ nested_trace = 1;
#endif
}
if (!file)
usage ();
- g_set_prgname (file);
- mono_set_rootdir ();
+ domain = mono_interp_init(file);
mono_config_parse (config_file);
-
- g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
- g_log_set_fatal_mask (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR);
-
- mono_init_icall ();
- 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);
-
- frame_thread_id = TlsAlloc ();
- TlsSetValue (frame_thread_id, NULL);
-
- mono_install_compile_method (mono_create_method_pointer);
- mono_install_runtime_invoke (interp_mono_runtime_invoke);
- mono_install_remoting_trampoline (interp_create_remoting_trampoline);
-
- mono_install_handler (interp_ex_handler);
- mono_install_stack_walk (interp_walk_stack);
- InitializeCriticalSection (&metadata_lock);
- domain = mono_init (file);
- mono_runtime_init (domain, NULL, NULL);
+ error = mono_check_corlib_version ();
+ if (error) {
+ fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
+ fprintf (stderr, "Download a newer corlib at http://www.go-mono.com/daily.\n");
+ exit (1);
+ }
main_args.domain=domain;
main_args.file=file;
mono_runtime_exec_managed_code (domain, main_thread_handler,
&main_args);
-
- mono_profiler_shutdown ();
-
- mono_runtime_cleanup (domain);
- mono_domain_unload (domain, TRUE);
+
+ quit_function (domain, NULL);
/* Get the return value from System.Environment.ExitCode */
retval=mono_environment_exitcode_get ();
-#if DEBUG_INTERP
- if (ocount) {
- fprintf (stderr, "opcode count: %ld\n", opcode_count);
- fprintf (stderr, "fcall count: %ld\n", fcall_count);
- }
+#if COUNT_OPS
+ for (i = 0; i < 512; i++)
+ if (opcode_counts[i] != 0)
+ printf("%s %d\n", mono_interp_opname[i], opcode_counts[i]);
#endif
return retval;
}