2 * PLEASE NOTE: This is a research prototype.
5 * interp.c: Interpreter for CIL byte codes
8 * Paolo Molaro (lupus@ximian.com)
9 * Miguel de Icaza (miguel@ximian.com)
10 * Dietmar Maurer (dietmar@ximian.com)
12 * (C) 2001, 2002 Ximian, Inc.
27 #include <mono/utils/gc_wrapper.h>
33 # define alloca __builtin_alloca
37 /* trim excessive headers */
38 #include <mono/metadata/image.h>
39 #include <mono/metadata/assembly.h>
40 #include <mono/metadata/cil-coff.h>
41 #include <mono/metadata/mono-endian.h>
42 #include <mono/metadata/tabledefs.h>
43 #include <mono/metadata/tokentype.h>
44 #include <mono/metadata/loader.h>
45 #include <mono/metadata/threads.h>
46 #include <mono/metadata/threadpool.h>
47 #include <mono/metadata/profiler-private.h>
48 #include <mono/metadata/appdomain.h>
49 #include <mono/metadata/reflection.h>
50 #include <mono/metadata/reflection-internals.h>
51 #include <mono/metadata/exception.h>
52 #include <mono/metadata/verify.h>
53 #include <mono/metadata/opcodes.h>
54 #include <mono/metadata/debug-helpers.h>
55 #include <mono/metadata/mono-config.h>
56 #include <mono/metadata/marshal.h>
57 #include <mono/metadata/environment.h>
58 #include <mono/metadata/mono-debug.h>
61 #include "interp-internals.h"
65 #include <mono/mini/mini.h>
66 #include <mono/mini/jit-icalls.h>
69 /* Mingw 2.1 doesnt need this any more, but leave it in for now for older versions */
72 #define finite _finite
76 #define finite isfinite
80 #define INIT_FRAME(frame,parent_frame,method_args,method_retval,domain,mono_method,error) \
82 (frame)->parent = (parent_frame); \
83 (frame)->stack_args = (method_args); \
84 (frame)->retval = (method_retval); \
85 (frame)->runtime_method = mono_interp_get_runtime_method ((domain), (mono_method), (error)); \
88 (frame)->invoke_trap = 0; \
91 void ves_exec_method (MonoInvocation
*frame
);
93 static char* dump_stack (stackval
*stack
, stackval
*sp
);
94 static char* dump_frame (MonoInvocation
*inv
);
95 static MonoArray
*get_trace_ips (MonoDomain
*domain
, MonoInvocation
*top
);
96 static void ves_exec_method_with_context (MonoInvocation
*frame
, ThreadContext
*context
);
98 typedef void (*ICallMethod
) (MonoInvocation
*frame
);
100 static guint32 die_on_exception
= 0;
101 static MonoNativeTlsKey thread_context_id
;
103 static char* dump_args (MonoInvocation
*inv
);
105 #define DEBUG_INTERP 0
108 int mono_interp_traceopt
= 2;
109 /* If true, then we output the opcodes as we interpret them */
110 static int global_tracing
= 2;
112 static int debug_indent_level
= 0;
114 static int break_on_method
= 0;
115 static int nested_trace
= 0;
116 static GList
*db_methods
= NULL
;
123 for (h
= 0; h
< debug_indent_level
; h
++)
128 db_match_method (gpointer data
, gpointer user_data
)
130 MonoMethod
*m
= (MonoMethod
*)user_data
;
131 MonoMethodDesc
*desc
= data
;
133 if (mono_method_desc_full_match (desc
, m
))
137 static void debug_enter (MonoInvocation
*frame
, int *tracing
)
140 g_list_foreach (db_methods
, db_match_method
, (gpointer
)frame
->runtime_method
->method
);
142 *tracing
= nested_trace
? (global_tracing
= 2, 3) : 2;
146 MonoMethod
*method
= frame
->runtime_method
->method
;
147 char *mn
, *args
= dump_args (frame
);
148 debug_indent_level
++;
150 mn
= mono_method_full_name (method
, FALSE
);
151 g_print ("(%p) Entering %s (", mono_thread_internal_current (), mn
);
153 g_print ("%s)\n", args
);
156 if (mono_profiler_events
& MONO_PROFILE_ENTER_LEAVE
)
157 mono_profiler_method_enter (frame
->runtime_method
->method
);
161 #define DEBUG_LEAVE() \
164 args = dump_retval (frame); \
166 mn = mono_method_full_name (frame->runtime_method->method, FALSE); \
167 g_print ("(%p) Leaving %s", mono_thread_internal_current (), mn); \
169 g_print (" => %s\n", args); \
171 debug_indent_level--; \
172 if (tracing == 3) global_tracing = 0; \
174 if (mono_profiler_events & MONO_PROFILE_ENTER_LEAVE) \
175 mono_profiler_method_leave (frame->runtime_method->method);
179 int mono_interp_traceopt
= 0;
180 static void debug_enter (MonoInvocation
*frame
, int *tracing
)
183 #define DEBUG_LEAVE()
188 interp_ex_handler (MonoException
*ex
) {
190 ThreadContext
*context
= mono_native_tls_get_value (thread_context_id
);
194 stack_trace
= dump_frame (context
->current_frame
);
195 ex
->stack_trace
= mono_string_new (mono_domain_get(), stack_trace
);
196 g_free (stack_trace
);
197 if (context
->current_env
== NULL
|| strcmp(ex
->object
.vtable
->klass
->name
, "ExecutionEngineException") == 0) {
198 char *strace
= mono_string_to_utf8_checked (ex
->stack_trace
, &error
);
199 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
200 fprintf(stderr
, "Nothing can catch this exception: ");
201 fprintf(stderr
, "%s", ex
->object
.vtable
->klass
->name
);
202 if (ex
->message
!= NULL
) {
203 char *m
= mono_string_to_utf8_checked (ex
->message
, &error
);
204 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
205 fprintf(stderr
, ": %s", m
);
208 fprintf(stderr
, "\n%s\n", strace
);
210 if (ex
->inner_ex
!= NULL
) {
211 ex
= (MonoException
*)ex
->inner_ex
;
212 fprintf(stderr
, "Inner exception: %s", ex
->object
.vtable
->klass
->name
);
213 if (ex
->message
!= NULL
) {
214 char *m
= mono_string_to_utf8_checked (ex
->message
, &error
);
215 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
216 fprintf(stderr
, ": %s", m
);
219 strace
= mono_string_to_utf8_checked (ex
->stack_trace
, &error
);
220 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
221 fprintf(stderr
, "\n");
222 fprintf(stderr
, "%s\n", strace
);
225 /* wait for other threads to also collapse */
226 // Sleep(1000); // TODO: proper sleep
229 context
->env_frame
->ex
= ex
;
230 context
->search_for_handler
= 1;
231 longjmp (*context
->current_env
, 1);
235 ves_real_abort (int line
, MonoMethod
*mh
,
236 const unsigned short *ip
, stackval
*stack
, stackval
*sp
)
239 fprintf (stderr
, "Execution aborted in method: %s::%s\n", mh
->klass
->name
, mh
->name
);
240 fprintf (stderr
, "Line=%d IP=0x%04lx, Aborted execution\n", line
,
241 ip
-(const unsigned short *)mono_method_get_header_checked (mh
, &error
)->code
);
242 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
243 g_print ("0x%04x %02x\n",
244 ip
-(const unsigned short *)mono_method_get_header_checked (mh
, &error
)->code
, *ip
);
245 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
247 printf ("\t[%ld] 0x%08x %0.5f\n", sp
-stack
, sp
[-1].data
.i
, sp
[-1].data
.f
);
250 #define ves_abort() \
252 ves_real_abort(__LINE__, frame->runtime_method->method, ip, frame->stack, sp); \
253 THROW_EX (mono_get_exception_execution_engine (NULL), ip); \
256 static mono_mutex_t runtime_method_lookup_section
;
259 mono_interp_get_runtime_method (MonoDomain
*domain
, MonoMethod
*method
, MonoError
*error
)
264 mono_os_mutex_lock (&runtime_method_lookup_section
);
265 if ((rtm
= mono_internal_hash_table_lookup (&domain
->jit_code_hash
, method
))) {
266 mono_os_mutex_unlock (&runtime_method_lookup_section
);
269 rtm
= mono_mempool_alloc (domain
->mp
, sizeof (RuntimeMethod
));
270 memset (rtm
, 0, sizeof (*rtm
));
271 rtm
->method
= method
;
272 rtm
->param_count
= mono_method_signature (method
)->param_count
;
273 rtm
->hasthis
= mono_method_signature (method
)->hasthis
;
274 mono_internal_hash_table_insert (&domain
->jit_code_hash
, method
, rtm
);
275 mono_os_mutex_unlock (&runtime_method_lookup_section
);
281 mono_interp_create_trampoline (MonoDomain
*domain
, MonoMethod
*method
, MonoError
*error
)
283 if (method
->iflags
& METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED
)
284 method
= mono_marshal_get_synchronized_wrapper (method
);
285 return mono_interp_get_runtime_method (domain
, method
, error
);
288 static inline RuntimeMethod
*
289 get_virtual_method (MonoDomain
*domain
, RuntimeMethod
*runtime_method
, MonoObject
*obj
)
291 MonoMethod
*m
= runtime_method
->method
;
294 if ((m
->flags
& METHOD_ATTRIBUTE_FINAL
) || !(m
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
295 RuntimeMethod
*ret
= NULL
;
296 if (mono_object_is_transparent_proxy (obj
)) {
297 ret
= mono_interp_get_runtime_method (domain
, mono_marshal_get_remoting_invoke (m
), &error
);
298 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
299 } else if (m
->iflags
& METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED
) {
300 ret
= mono_interp_get_runtime_method (domain
, mono_marshal_get_synchronized_wrapper (m
), &error
);
301 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
303 ret
= runtime_method
;
308 mono_class_setup_vtable (obj
->vtable
->klass
);
310 int slot
= mono_method_get_vtable_slot (m
);
311 if (mono_class_is_interface (m
->klass
)) {
312 g_assert (obj
->vtable
->klass
!= m
->klass
);
313 /* TODO: interface offset lookup is slow, go through IMT instead */
314 gboolean non_exact_match
;
315 slot
+= mono_class_interface_offset_with_variance (obj
->vtable
->klass
, m
->klass
, &non_exact_match
);
318 MonoMethod
*virtual_method
= obj
->vtable
->klass
->vtable
[slot
];
319 if (m
->is_inflated
&& mono_method_get_context (m
)->method_inst
) {
320 MonoGenericContext context
= { NULL
, NULL
};
322 if (mono_class_is_ginst (virtual_method
->klass
))
323 context
.class_inst
= mono_class_get_generic_class (virtual_method
->klass
)->context
.class_inst
;
324 else if (mono_class_is_gtd (virtual_method
->klass
))
325 context
.class_inst
= mono_class_get_generic_container (virtual_method
->klass
)->context
.class_inst
;
326 context
.method_inst
= mono_method_get_context (m
)->method_inst
;
328 virtual_method
= mono_class_inflate_generic_method_checked (virtual_method
, &context
, &error
);
329 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
331 RuntimeMethod
*virtual_runtime_method
= mono_interp_get_runtime_method (domain
, virtual_method
, &error
);
332 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
333 return virtual_runtime_method
;
337 stackval_from_data (MonoType
*type
, stackval
*result
, char *data
, gboolean pinvoke
)
340 switch (type
->type
) {
341 case MONO_TYPE_OBJECT
:
342 case MONO_TYPE_CLASS
:
343 case MONO_TYPE_STRING
:
344 case MONO_TYPE_ARRAY
:
345 case MONO_TYPE_SZARRAY
:
350 result
->data
.p
= *(gpointer
*)data
;
353 switch (type
->type
) {
357 result
->data
.i
= *(gint8
*)data
;
360 case MONO_TYPE_BOOLEAN
:
361 result
->data
.i
= *(guint8
*)data
;
364 result
->data
.i
= *(gint16
*)data
;
368 result
->data
.i
= *(guint16
*)data
;
371 result
->data
.i
= *(gint32
*)data
;
375 result
->data
.nati
= *(mono_i
*)data
;
378 result
->data
.p
= *(gpointer
*)data
;
381 result
->data
.i
= *(guint32
*)data
;
384 result
->data
.f
= *(float*)data
;
388 result
->data
.l
= *(gint64
*)data
;
391 result
->data
.f
= *(double*)data
;
393 case MONO_TYPE_STRING
:
394 case MONO_TYPE_SZARRAY
:
395 case MONO_TYPE_CLASS
:
396 case MONO_TYPE_OBJECT
:
397 case MONO_TYPE_ARRAY
:
398 result
->data
.p
= *(gpointer
*)data
;
400 case MONO_TYPE_VALUETYPE
:
401 if (type
->data
.klass
->enumtype
) {
402 stackval_from_data (mono_class_enum_basetype (type
->data
.klass
), result
, data
, pinvoke
);
405 mono_value_copy (result
->data
.vt
, data
, type
->data
.klass
);
407 case MONO_TYPE_GENERICINST
:
408 stackval_from_data (&type
->data
.generic_class
->container_class
->byval_arg
, result
, data
, pinvoke
);
411 g_warning ("got type 0x%02x", type
->type
);
412 g_assert_not_reached ();
417 stackval_to_data (MonoType
*type
, stackval
*val
, char *data
, gboolean pinvoke
)
420 gpointer
*p
= (gpointer
*)data
;
424 /* printf ("TODAT0 %p\n", data); */
425 switch (type
->type
) {
428 guint8
*p
= (guint8
*)data
;
432 case MONO_TYPE_BOOLEAN
: {
433 guint8
*p
= (guint8
*)data
;
434 *p
= (val
->data
.i
!= 0);
439 case MONO_TYPE_CHAR
: {
440 guint16
*p
= (guint16
*)data
;
445 mono_i
*p
= (mono_i
*)data
;
446 /* In theory the value used by stloc should match the local var type
447 but in practice it sometimes doesn't (a int32 gets dup'd and stloc'd into
448 a native int - both by csc and mcs). Not sure what to do about sign extension
449 as it is outside the spec... doing the obvious */
450 *p
= (mono_i
)val
->data
.nati
;
454 mono_u
*p
= (mono_u
*)data
;
456 *p
= (mono_u
)val
->data
.nati
;
461 gint32
*p
= (gint32
*)data
;
467 gint64
*p
= (gint64
*)data
;
472 float *p
= (float*)data
;
477 double *p
= (double*)data
;
481 case MONO_TYPE_STRING
:
482 case MONO_TYPE_SZARRAY
:
483 case MONO_TYPE_CLASS
:
484 case MONO_TYPE_OBJECT
:
485 case MONO_TYPE_ARRAY
:
486 case MONO_TYPE_PTR
: {
487 gpointer
*p
= (gpointer
*)data
;
491 case MONO_TYPE_VALUETYPE
:
492 if (type
->data
.klass
->enumtype
) {
493 stackval_to_data (mono_class_enum_basetype (type
->data
.klass
), val
, data
, pinvoke
);
496 mono_value_copy (data
, val
->data
.vt
, type
->data
.klass
);
498 case MONO_TYPE_GENERICINST
:
499 stackval_to_data (&type
->data
.generic_class
->container_class
->byval_arg
, val
, data
, pinvoke
);
502 g_warning ("got type %x", type
->type
);
503 g_assert_not_reached ();
508 fill_in_trace (MonoException
*exception
, MonoInvocation
*frame
)
510 char *stack_trace
= dump_frame (frame
);
511 MonoDomain
*domain
= mono_domain_get();
512 (exception
)->stack_trace
= mono_string_new (domain
, stack_trace
);
513 (exception
)->trace_ips
= get_trace_ips (domain
, frame
);
514 g_free (stack_trace
);
517 #define FILL_IN_TRACE(exception, frame) fill_in_trace(exception, frame)
519 #define THROW_EX(exception,ex_ip) \
521 frame->ip = (ex_ip); \
522 frame->ex = (MonoException*)(exception); \
523 FILL_IN_TRACE(frame->ex, frame); \
524 goto handle_exception; \
528 ves_array_create (MonoInvocation
*frame
, MonoDomain
*domain
, MonoClass
*klass
, MonoMethodSignature
*sig
, stackval
*values
)
531 intptr_t *lower_bounds
;
536 lengths
= alloca (sizeof (uintptr_t) * klass
->rank
* 2);
537 for (i
= 0; i
< sig
->param_count
; ++i
) {
538 lengths
[i
] = values
->data
.i
;
541 if (klass
->rank
== sig
->param_count
) {
542 /* Only lengths provided. */
545 /* lower bounds are first. */
546 lower_bounds
= (intptr_t *) lengths
;
547 lengths
+= klass
->rank
;
549 obj
= (MonoObject
*) mono_array_new_full_checked (domain
, klass
, lengths
, lower_bounds
, &error
);
550 if (!mono_error_ok (&error
)) {
551 frame
->ex
= mono_error_convert_to_exception (&error
);
552 FILL_IN_TRACE (frame
->ex
, frame
);
554 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
559 ves_array_calculate_index (MonoArray
*ao
, stackval
*sp
, MonoInvocation
*frame
)
561 g_assert (!frame
->ex
);
562 MonoClass
*ac
= ((MonoObject
*) ao
)->vtable
->klass
;
566 for (gint32 i
= 0; i
< ac
->rank
; i
++) {
567 guint32 idx
= sp
[i
].data
.i
;
568 guint32 lower
= ao
->bounds
[i
].lower_bound
;
569 guint32 len
= ao
->bounds
[i
].length
;
570 if (idx
< lower
|| (idx
- lower
) >= len
) {
571 frame
->ex
= mono_get_exception_index_out_of_range ();
572 FILL_IN_TRACE (frame
->ex
, frame
);
575 pos
= (pos
* len
) + idx
- lower
;
579 if (pos
>= ao
->max_length
) {
580 frame
->ex
= mono_get_exception_index_out_of_range ();
581 FILL_IN_TRACE (frame
->ex
, frame
);
589 ves_array_set (MonoInvocation
*frame
)
591 stackval
*sp
= frame
->stack_args
+ 1;
593 MonoObject
*o
= frame
->stack_args
->data
.p
;
594 MonoArray
*ao
= (MonoArray
*) o
;
595 MonoClass
*ac
= o
->vtable
->klass
;
597 g_assert (ac
->rank
>= 1);
599 gint32 pos
= ves_array_calculate_index (ao
, sp
, frame
);
603 if (sp
[ac
->rank
].data
.p
&& !mono_object_class (o
)->element_class
->valuetype
) {
605 MonoObject
*isinst
= mono_object_isinst_checked (sp
[ac
->rank
].data
.p
, mono_object_class (o
)->element_class
, &error
);
606 mono_error_cleanup (&error
);
608 frame
->ex
= mono_get_exception_array_type_mismatch ();
609 FILL_IN_TRACE (frame
->ex
, frame
);
614 gint32 esize
= mono_array_element_size (ac
);
615 gpointer ea
= mono_array_addr_with_size (ao
, esize
, pos
);
617 MonoType
*mt
= mono_method_signature (frame
->runtime_method
->method
)->params
[ac
->rank
];
618 stackval_to_data (mt
, &sp
[ac
->rank
], ea
, FALSE
);
622 ves_array_get (MonoInvocation
*frame
)
624 stackval
*sp
= frame
->stack_args
+ 1;
626 MonoObject
*o
= frame
->stack_args
->data
.p
;
627 MonoArray
*ao
= (MonoArray
*) o
;
628 MonoClass
*ac
= o
->vtable
->klass
;
630 g_assert (ac
->rank
>= 1);
632 gint32 pos
= ves_array_calculate_index (ao
, sp
, frame
);
636 gint32 esize
= mono_array_element_size (ac
);
637 gpointer ea
= mono_array_addr_with_size (ao
, esize
, pos
);
639 MonoType
*mt
= mono_method_signature (frame
->runtime_method
->method
)->ret
;
640 stackval_from_data (mt
, frame
->retval
, ea
, FALSE
);
644 ves_array_element_address (MonoInvocation
*frame
, MonoClass
*required_type
, MonoArray
*ao
, stackval
*sp
, gboolean needs_typecheck
)
646 MonoClass
*ac
= ((MonoObject
*) ao
)->vtable
->klass
;
648 g_assert (ac
->rank
>= 1);
650 gint32 pos
= ves_array_calculate_index (ao
, sp
, frame
);
654 if (needs_typecheck
&& !mono_class_is_assignable_from (mono_object_class ((MonoObject
*) ao
)->element_class
, required_type
->element_class
)) {
655 frame
->ex
= mono_get_exception_array_type_mismatch ();
656 FILL_IN_TRACE (frame
->ex
, frame
);
659 gint32 esize
= mono_array_element_size (ac
);
660 return mono_array_addr_with_size (ao
, esize
, pos
);
664 interp_walk_stack_with_ctx (MonoInternalStackWalk func
, MonoContext
*ctx
, MonoUnwindOptions options
, void *user_data
)
667 ThreadContext
*context
= mono_native_tls_get_value (thread_context_id
);
669 MonoInvocation
*frame
= context
->current_frame
;
672 MonoStackFrameInfo fi
;
673 memset (&fi
, 0, sizeof (MonoStackFrameInfo
));
675 /* TODO: hack to make some asserts happy. */
676 fi
.ji
= (MonoJitInfo
*) frame
->runtime_method
;
678 if (frame
->runtime_method
)
679 fi
.method
= fi
.actual_method
= frame
->runtime_method
->method
;
681 if (!fi
.method
|| (fi
.method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) || (fi
.method
->iflags
& (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
| METHOD_IMPL_ATTRIBUTE_RUNTIME
))) {
683 fi
.type
= FRAME_TYPE_MANAGED_TO_NATIVE
;
685 MonoMethodHeader
*hd
= mono_method_get_header_checked (fi
.method
, &error
);
686 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
687 fi
.type
= FRAME_TYPE_MANAGED
;
688 fi
.il_offset
= frame
->ip
- (const unsigned short *) hd
->code
;
689 if (!fi
.method
->wrapper_type
)
693 if (func (&fi
, ctx
, user_data
))
695 frame
= frame
->parent
;
701 static MonoPIFunc mono_interp_enter_icall_trampoline
= NULL
;
703 struct _MethodArguments
{
712 typedef struct _MethodArguments MethodArguments
;
714 // TODO: this function is also arch dependent (register width).
715 static MethodArguments
* build_args_from_sig (MonoMethodSignature
*sig
, MonoInvocation
*frame
)
717 // TODO: don't malloc this data structure.
718 MethodArguments
*margs
= g_malloc0 (sizeof (MethodArguments
));
723 for (int i
= 0; i
< sig
->param_count
; i
++) {
724 guint32 ptype
= sig
->params
[i
]->byref
? MONO_TYPE_PTR
: sig
->params
[i
]->type
;
726 case MONO_TYPE_BOOLEAN
:
737 case MONO_TYPE_SZARRAY
:
738 case MONO_TYPE_CLASS
:
739 case MONO_TYPE_OBJECT
:
740 case MONO_TYPE_STRING
:
742 case MONO_TYPE_VALUETYPE
:
743 case MONO_TYPE_GENERICINST
:
751 g_error ("build_args_from_sig: not implemented yet (1): 0x%x\n", ptype
);
756 margs
->iargs
= g_malloc0 (sizeof (gpointer
) * margs
->ilen
);
759 margs
->fargs
= g_malloc0 (sizeof (double) * margs
->flen
);
762 g_error ("build_args_from_sig: TODO, allocate gregs: %d\n", margs
->ilen
);
765 g_error ("build_args_from_sig: TODO, allocate fregs: %d\n", margs
->flen
);
772 margs
->iargs
[0] = frame
->stack_args
->data
.p
;
776 for (int i
= 0; i
< sig
->param_count
; i
++) {
777 guint32 ptype
= sig
->params
[i
]->byref
? MONO_TYPE_PTR
: sig
->params
[i
]->type
;
779 case MONO_TYPE_BOOLEAN
:
790 case MONO_TYPE_SZARRAY
:
791 case MONO_TYPE_CLASS
:
792 case MONO_TYPE_OBJECT
:
793 case MONO_TYPE_STRING
:
795 case MONO_TYPE_VALUETYPE
:
796 case MONO_TYPE_GENERICINST
:
797 margs
->iargs
[int_i
] = frame
->stack_args
[i
].data
.p
;
799 g_print ("build_args_from_sig: margs->iargs[%d]: %p (frame @ %d)\n", int_i
, margs
->iargs
[int_i
], i
);
805 margs
->fargs
[int_f
] = frame
->stack_args
[i
].data
.f
;
809 g_error ("build_args_from_sig: not implemented yet (2): 0x%x\n", ptype
);
813 switch (sig
->ret
->type
) {
814 case MONO_TYPE_BOOLEAN
:
825 case MONO_TYPE_SZARRAY
:
826 case MONO_TYPE_CLASS
:
827 case MONO_TYPE_OBJECT
:
828 case MONO_TYPE_STRING
:
830 case MONO_TYPE_VALUETYPE
:
831 case MONO_TYPE_GENERICINST
:
832 margs
->retval
= &(frame
->retval
->data
.p
);
836 margs
->retval
= &(frame
->retval
->data
.p
);
837 margs
->is_float_ret
= 1;
840 margs
->retval
= NULL
;
843 g_error ("build_args_from_sig: ret type not implemented yet: 0x%x\n", sig
->ret
->type
);
850 ves_pinvoke_method (MonoInvocation
*frame
, MonoMethodSignature
*sig
, MonoFuncV addr
, gboolean string_ctor
, ThreadContext
*context
)
853 MonoInvocation
*old_frame
= context
->current_frame
;
854 MonoInvocation
*old_env_frame
= context
->env_frame
;
855 jmp_buf *old_env
= context
->current_env
;
858 context
->current_frame
= old_frame
;
859 context
->env_frame
= old_env_frame
;
860 context
->current_env
= old_env
;
861 context
->managed_code
= 1;
866 context
->env_frame
= frame
;
867 context
->current_env
= &env
;
869 g_assert (!frame
->runtime_method
);
870 if (!mono_interp_enter_icall_trampoline
) {
872 mono_interp_enter_icall_trampoline
= mono_arch_get_enter_icall_trampoline (&info
);
874 // mono_tramp_info_register (info, NULL);
877 MethodArguments
*margs
= build_args_from_sig (sig
, frame
);
879 g_print ("ICALL: mono_interp_enter_icall_trampoline = %p, addr = %p\n", mono_interp_enter_icall_trampoline
, addr
);
880 g_print ("margs(out): ilen=%d, flen=%d\n", margs
->ilen
, margs
->flen
);
883 context
->current_frame
= frame
;
884 context
->managed_code
= 0;
886 mono_interp_enter_icall_trampoline (addr
, margs
);
888 context
->managed_code
= 1;
889 /* domain can only be changed by native code */
890 context
->domain
= mono_domain_get ();
892 if (*mono_thread_interruption_request_flag ()) {
893 MonoException
*exc
= mono_thread_interruption_checkpoint ();
896 context
->search_for_handler
= 1;
900 if (!frame
->ex
&& !MONO_TYPE_ISSTRUCT (sig
->ret
))
901 stackval_from_data (sig
->ret
, frame
->retval
, (char*)&frame
->retval
->data
.p
, sig
->pinvoke
);
903 context
->current_frame
= old_frame
;
904 context
->env_frame
= old_env_frame
;
905 context
->current_env
= old_env
;
907 g_free (margs
->iargs
);
908 g_free (margs
->fargs
);
913 mono_interp_init_delegate (MonoDelegate
*del
)
916 del
->method
= ((RuntimeMethod
*) del
->method_ptr
)->method
;
921 * runtime specifies that the implementation of the method is automatically
922 * provided by the runtime and is primarily used for the methods of delegates.
925 ves_runtime_method (MonoInvocation
*frame
, ThreadContext
*context
)
927 MonoMethod
*method
= frame
->runtime_method
->method
;
928 const char *name
= method
->name
;
929 MonoObject
*obj
= (MonoObject
*) frame
->stack_args
->data
.p
;
930 MonoObject
*isinst_obj
;
933 mono_class_init (method
->klass
);
935 isinst_obj
= mono_object_isinst_checked (obj
, mono_defaults
.array_class
, &error
);
936 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
937 if (obj
&& isinst_obj
) {
938 if (*name
== 'S' && (strcmp (name
, "Set") == 0)) {
939 ves_array_set (frame
);
942 if (*name
== 'G' && (strcmp (name
, "Get") == 0)) {
943 ves_array_get (frame
);
948 g_error ("Don't know how to exec runtime method %s.%s::%s",
949 method
->klass
->name_space
, method
->klass
->name
,
954 dump_stack (stackval
*stack
, stackval
*sp
)
957 GString
*str
= g_string_new ("");
960 return g_string_free (str
, FALSE
);
963 g_string_append_printf (str
, "[%p (%lld)] ", s
->data
.l
, s
->data
.l
);
966 return g_string_free (str
, FALSE
);
970 dump_stackval (GString
*str
, stackval
*s
, MonoType
*type
)
972 switch (type
->type
) {
980 case MONO_TYPE_BOOLEAN
:
981 g_string_append_printf (str
, "[%d] ", s
->data
.i
);
983 case MONO_TYPE_STRING
:
984 case MONO_TYPE_SZARRAY
:
985 case MONO_TYPE_CLASS
:
986 case MONO_TYPE_OBJECT
:
987 case MONO_TYPE_ARRAY
:
991 g_string_append_printf (str
, "[%p] ", s
->data
.p
);
993 case MONO_TYPE_VALUETYPE
:
994 if (type
->data
.klass
->enumtype
)
995 g_string_append_printf (str
, "[%d] ", s
->data
.i
);
997 g_string_append_printf (str
, "[vt:%p] ", s
->data
.p
);
1001 g_string_append_printf (str
, "[%g] ", s
->data
.f
);
1006 GString
*res
= g_string_new ("");
1007 mono_type_get_desc (res
, type
, TRUE
);
1008 g_string_append_printf (str
, "[{%s} %lld/0x%0llx] ", res
->str
, s
->data
.l
, s
->data
.l
);
1009 g_string_free (res
, TRUE
);
1016 dump_args (MonoInvocation
*inv
)
1018 GString
*str
= g_string_new ("");
1020 MonoMethodSignature
*signature
= mono_method_signature (inv
->runtime_method
->method
);
1022 if (signature
->param_count
== 0 && !signature
->hasthis
)
1023 return g_string_free (str
, FALSE
);
1025 if (signature
->hasthis
) {
1026 MonoMethod
*method
= inv
->runtime_method
->method
;
1027 dump_stackval (str
, inv
->stack_args
, &method
->klass
->byval_arg
);
1030 for (i
= 0; i
< signature
->param_count
; ++i
)
1031 dump_stackval (str
, inv
->stack_args
+ (!!signature
->hasthis
) + i
, signature
->params
[i
]);
1033 return g_string_free (str
, FALSE
);
1037 dump_retval (MonoInvocation
*inv
)
1039 GString
*str
= g_string_new ("");
1040 MonoType
*ret
= mono_method_signature (inv
->runtime_method
->method
)->ret
;
1042 if (ret
->type
!= MONO_TYPE_VOID
)
1043 dump_stackval (str
, inv
->retval
, ret
);
1045 return g_string_free (str
, FALSE
);
1049 dump_frame (MonoInvocation
*inv
)
1051 GString
*str
= g_string_new ("");
1056 for (i
= 0; inv
; inv
= inv
->parent
) {
1057 if (inv
->runtime_method
!= NULL
) {
1058 MonoMethod
*method
= inv
->runtime_method
->method
;
1062 const char * opname
= "";
1064 gchar
*source
= NULL
;
1068 if ((method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) == 0 &&
1069 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
) == 0) {
1070 MonoMethodHeader
*hd
= mono_method_get_header_checked (method
, &error
);
1071 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
1075 opname
= mono_interp_opname
[*inv
->ip
];
1076 codep
= inv
->ip
- inv
->runtime_method
->code
;
1077 source
= g_strdup_printf ("%s:%d // (TODO: proper stacktrace)", method
->name
, codep
);
1082 MonoDebugSourceLocation
*minfo
= mono_debug_lookup_method (method
);
1083 source
= mono_debug_method_lookup_location (minfo
, codep
);
1087 args
= dump_args (inv
);
1088 name
= mono_method_full_name (method
, TRUE
);
1090 g_string_append_printf (str
, "#%d: 0x%05x %-10s in %s (%s) at %s\n", i
, codep
, opname
, name
, args
, source
);
1092 g_string_append_printf (str
, "#%d: 0x%05x %-10s in %s (%s)\n", i
, codep
, opname
, name
, args
);
1099 return g_string_free (str
, FALSE
);
1103 get_trace_ips (MonoDomain
*domain
, MonoInvocation
*top
)
1107 MonoInvocation
*inv
;
1110 for (i
= 0, inv
= top
; inv
; inv
= inv
->parent
)
1111 if (inv
->runtime_method
!= NULL
)
1114 res
= mono_array_new_checked (domain
, mono_defaults
.int_class
, 2 * i
, &error
);
1115 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
1117 for (i
= 0, inv
= top
; inv
; inv
= inv
->parent
)
1118 if (inv
->runtime_method
!= NULL
) {
1119 mono_array_set (res
, gpointer
, i
, inv
->runtime_method
);
1121 mono_array_set (res
, gpointer
, i
, (gpointer
)inv
->ip
);
1129 #define MYGUINT64_MAX 18446744073709551615ULL
1130 #define MYGINT64_MAX 9223372036854775807LL
1131 #define MYGINT64_MIN (-MYGINT64_MAX -1LL)
1133 #define MYGUINT32_MAX 4294967295U
1134 #define MYGINT32_MAX 2147483647
1135 #define MYGINT32_MIN (-MYGINT32_MAX -1)
1137 #define CHECK_ADD_OVERFLOW(a,b) \
1138 (gint32)(b) >= 0 ? (gint32)(MYGINT32_MAX) - (gint32)(b) < (gint32)(a) ? -1 : 0 \
1139 : (gint32)(MYGINT32_MIN) - (gint32)(b) > (gint32)(a) ? +1 : 0
1141 #define CHECK_SUB_OVERFLOW(a,b) \
1142 (gint32)(b) < 0 ? (gint32)(MYGINT32_MAX) + (gint32)(b) < (gint32)(a) ? -1 : 0 \
1143 : (gint32)(MYGINT32_MIN) + (gint32)(b) > (gint32)(a) ? +1 : 0
1145 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1146 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1148 #define CHECK_SUB_OVERFLOW_UN(a,b) \
1149 (guint32)(a) < (guint32)(b) ? -1 : 0
1151 #define CHECK_ADD_OVERFLOW64(a,b) \
1152 (gint64)(b) >= 0 ? (gint64)(MYGINT64_MAX) - (gint64)(b) < (gint64)(a) ? -1 : 0 \
1153 : (gint64)(MYGINT64_MIN) - (gint64)(b) > (gint64)(a) ? +1 : 0
1155 #define CHECK_SUB_OVERFLOW64(a,b) \
1156 (gint64)(b) < 0 ? (gint64)(MYGINT64_MAX) + (gint64)(b) < (gint64)(a) ? -1 : 0 \
1157 : (gint64)(MYGINT64_MIN) + (gint64)(b) > (gint64)(a) ? +1 : 0
1159 #define CHECK_ADD_OVERFLOW64_UN(a,b) \
1160 (guint64)(MYGUINT64_MAX) - (guint64)(b) < (guint64)(a) ? -1 : 0
1162 #define CHECK_SUB_OVERFLOW64_UN(a,b) \
1163 (guint64)(a) < (guint64)(b) ? -1 : 0
1165 #if SIZEOF_VOID_P == 4
1166 #define CHECK_ADD_OVERFLOW_NAT(a,b) CHECK_ADD_OVERFLOW(a,b)
1167 #define CHECK_ADD_OVERFLOW_NAT_UN(a,b) CHECK_ADD_OVERFLOW_UN(a,b)
1169 #define CHECK_ADD_OVERFLOW_NAT(a,b) CHECK_ADD_OVERFLOW64(a,b)
1170 #define CHECK_ADD_OVERFLOW_NAT_UN(a,b) CHECK_ADD_OVERFLOW64_UN(a,b)
1173 /* Resolves to TRUE if the operands would overflow */
1174 #define CHECK_MUL_OVERFLOW(a,b) \
1175 ((gint32)(a) == 0) || ((gint32)(b) == 0) ? 0 : \
1176 (((gint32)(a) > 0) && ((gint32)(b) == -1)) ? FALSE : \
1177 (((gint32)(a) < 0) && ((gint32)(b) == -1)) ? (a == - MYGINT32_MAX) : \
1178 (((gint32)(a) > 0) && ((gint32)(b) > 0)) ? (gint32)(a) > ((MYGINT32_MAX) / (gint32)(b)) : \
1179 (((gint32)(a) > 0) && ((gint32)(b) < 0)) ? (gint32)(a) > ((MYGINT32_MIN) / (gint32)(b)) : \
1180 (((gint32)(a) < 0) && ((gint32)(b) > 0)) ? (gint32)(a) < ((MYGINT32_MIN) / (gint32)(b)) : \
1181 (gint32)(a) < ((MYGINT32_MAX) / (gint32)(b))
1183 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1184 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1185 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1187 #define CHECK_MUL_OVERFLOW64(a,b) \
1188 ((gint64)(a) == 0) || ((gint64)(b) == 0) ? 0 : \
1189 (((gint64)(a) > 0) && ((gint64)(b) == -1)) ? FALSE : \
1190 (((gint64)(a) < 0) && ((gint64)(b) == -1)) ? (a == - MYGINT64_MAX) : \
1191 (((gint64)(a) > 0) && ((gint64)(b) > 0)) ? (gint64)(a) > ((MYGINT64_MAX) / (gint64)(b)) : \
1192 (((gint64)(a) > 0) && ((gint64)(b) < 0)) ? (gint64)(a) > ((MYGINT64_MIN) / (gint64)(b)) : \
1193 (((gint64)(a) < 0) && ((gint64)(b) > 0)) ? (gint64)(a) < ((MYGINT64_MIN) / (gint64)(b)) : \
1194 (gint64)(a) < ((MYGINT64_MAX) / (gint64)(b))
1196 #define CHECK_MUL_OVERFLOW64_UN(a,b) \
1197 ((guint64)(a) == 0) || ((guint64)(b) == 0) ? 0 : \
1198 (guint64)(b) > ((MYGUINT64_MAX) / (guint64)(a))
1200 #if SIZEOF_VOID_P == 4
1201 #define CHECK_MUL_OVERFLOW_NAT(a,b) CHECK_MUL_OVERFLOW(a,b)
1202 #define CHECK_MUL_OVERFLOW_NAT_UN(a,b) CHECK_MUL_OVERFLOW_UN(a,b)
1204 #define CHECK_MUL_OVERFLOW_NAT(a,b) CHECK_MUL_OVERFLOW64(a,b)
1205 #define CHECK_MUL_OVERFLOW_NAT_UN(a,b) CHECK_MUL_OVERFLOW64_UN(a,b)
1209 mono_interp_runtime_invoke (MonoMethod
*method
, void *obj
, void **params
, MonoObject
**exc
, MonoError
*error
)
1211 MonoInvocation frame
;
1212 ThreadContext
* volatile context
= mono_native_tls_get_value (thread_context_id
);
1213 MonoObject
*retval
= NULL
;
1214 MonoMethodSignature
*sig
= mono_method_signature (method
);
1215 MonoClass
*klass
= mono_class_from_mono_type (sig
->ret
);
1216 int i
, type
, isobject
= 0;
1219 stackval
*args
= alloca (sizeof (stackval
) * (sig
->param_count
+ !!sig
->hasthis
));
1220 ThreadContext context_struct
;
1221 MonoInvocation
*old_frame
= NULL
;
1229 if (context
!= &context_struct
) {
1230 context
->domain
= mono_domain_get ();
1231 context
->current_frame
= old_frame
;
1232 context
->managed_code
= 0;
1234 mono_native_tls_set_value (thread_context_id
, NULL
);
1236 *exc
= (MonoObject
*)frame
.ex
;
1240 if (context
== NULL
) {
1241 context
= &context_struct
;
1242 context_struct
.base_frame
= &frame
;
1243 context_struct
.current_frame
= NULL
;
1244 context_struct
.env_frame
= &frame
;
1245 context_struct
.current_env
= &env
;
1246 context_struct
.search_for_handler
= 0;
1247 context_struct
.managed_code
= 0;
1248 mono_native_tls_set_value (thread_context_id
, context
);
1251 old_frame
= context
->current_frame
;
1253 context
->domain
= mono_domain_get ();
1255 switch (sig
->ret
->type
) {
1256 case MONO_TYPE_VOID
:
1258 case MONO_TYPE_STRING
:
1259 case MONO_TYPE_OBJECT
:
1260 case MONO_TYPE_CLASS
:
1261 case MONO_TYPE_ARRAY
:
1262 case MONO_TYPE_SZARRAY
:
1265 case MONO_TYPE_VALUETYPE
:
1266 retval
= mono_object_new_checked (context
->domain
, klass
, error
);
1267 ret
= ((char*)retval
) + sizeof (MonoObject
);
1268 if (!sig
->ret
->data
.klass
->enumtype
)
1269 result
.data
.vt
= ret
;
1272 retval
= mono_object_new_checked (context
->domain
, klass
, error
);
1273 ret
= ((char*)retval
) + sizeof (MonoObject
);
1278 args
[0].data
.p
= obj
;
1280 for (i
= 0; i
< sig
->param_count
; ++i
) {
1281 int a_index
= i
+ !!sig
->hasthis
;
1282 if (sig
->params
[i
]->byref
) {
1283 args
[a_index
].data
.p
= params
[i
];
1286 type
= sig
->params
[i
]->type
;
1291 case MONO_TYPE_BOOLEAN
:
1292 args
[a_index
].data
.i
= *(MonoBoolean
*)params
[i
];
1296 case MONO_TYPE_CHAR
:
1297 args
[a_index
].data
.i
= *(gint16
*)params
[i
];
1299 #if SIZEOF_VOID_P == 4
1300 case MONO_TYPE_U
: /* use VAL_POINTER? */
1305 args
[a_index
].data
.i
= *(gint32
*)params
[i
];
1307 #if SIZEOF_VOID_P == 8
1313 args
[a_index
].data
.l
= *(gint64
*)params
[i
];
1315 case MONO_TYPE_VALUETYPE
:
1316 if (sig
->params
[i
]->data
.klass
->enumtype
) {
1317 type
= mono_class_enum_basetype (sig
->params
[i
]->data
.klass
)->type
;
1320 args
[a_index
].data
.p
= params
[i
];
1323 case MONO_TYPE_STRING
:
1324 case MONO_TYPE_CLASS
:
1325 case MONO_TYPE_ARRAY
:
1326 case MONO_TYPE_SZARRAY
:
1327 case MONO_TYPE_OBJECT
:
1328 args
[a_index
].data
.p
= params
[i
];
1331 g_error ("type 0x%x not handled in runtime invoke", sig
->params
[i
]->type
);
1335 if (method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
)
1336 method
= mono_marshal_get_native_wrapper (method
, FALSE
, FALSE
);
1337 INIT_FRAME (&frame
,context
->current_frame
,args
,&result
,mono_get_root_domain (),method
,error
);
1339 frame
.invoke_trap
= 1;
1340 context
->managed_code
= 1;
1341 ves_exec_method_with_context (&frame
, context
);
1342 context
->managed_code
= 0;
1343 if (context
== &context_struct
)
1344 mono_native_tls_set_value (thread_context_id
, NULL
);
1346 context
->current_frame
= old_frame
;
1347 if (frame
.ex
!= NULL
) {
1349 *exc
= (MonoObject
*) frame
.ex
;
1352 if (context
->current_env
!= NULL
) {
1353 context
->env_frame
->ex
= frame
.ex
;
1354 longjmp(*context
->current_env
, 1);
1357 printf("dropped exception...\n");
1359 if (sig
->ret
->type
== MONO_TYPE_VOID
&& !method
->string_ctor
)
1361 if (isobject
|| method
->string_ctor
)
1362 return result
.data
.p
;
1363 stackval_to_data (sig
->ret
, &result
, ret
, sig
->pinvoke
);
1368 do_icall (ThreadContext
*context
, int op
, stackval
*sp
, gpointer ptr
)
1370 MonoInvocation
*old_frame
= context
->current_frame
;
1371 MonoInvocation
*old_env_frame
= context
->env_frame
;
1372 jmp_buf *old_env
= context
->current_env
;
1376 context
->current_frame
= old_frame
;
1377 context
->env_frame
= old_env_frame
;
1378 context
->current_env
= old_env
;
1379 context
->managed_code
= 1;
1383 context
->env_frame
= context
->current_frame
;
1384 context
->current_env
= &env
;
1385 context
->managed_code
= 0;
1388 case MINT_ICALL_V_V
: {
1389 void (*func
)() = ptr
;
1393 case MINT_ICALL_V_P
: {
1394 gpointer (*func
)() = ptr
;
1396 sp
[-1].data
.p
= func ();
1399 case MINT_ICALL_P_V
: {
1400 void (*func
)(gpointer
) = ptr
;
1401 func (sp
[-1].data
.p
);
1405 case MINT_ICALL_P_P
: {
1406 gpointer (*func
)(gpointer
) = ptr
;
1407 sp
[-1].data
.p
= func (sp
[-1].data
.p
);
1410 case MINT_ICALL_PP_V
: {
1411 void (*func
)(gpointer
,gpointer
) = ptr
;
1413 func (sp
[0].data
.p
, sp
[1].data
.p
);
1416 case MINT_ICALL_PI_V
: {
1417 void (*func
)(gpointer
,int) = ptr
;
1419 func (sp
[0].data
.p
, sp
[1].data
.i
);
1422 case MINT_ICALL_PP_P
: {
1423 gpointer (*func
)(gpointer
,gpointer
) = ptr
;
1425 sp
[-1].data
.p
= func (sp
[-1].data
.p
, sp
[0].data
.p
);
1428 case MINT_ICALL_PI_P
: {
1429 gpointer (*func
)(gpointer
,int) = ptr
;
1431 sp
[-1].data
.p
= func (sp
[-1].data
.p
, sp
[0].data
.i
);
1434 case MINT_ICALL_PPP_V
: {
1435 void (*func
)(gpointer
,gpointer
,gpointer
) = ptr
;
1437 func (sp
[0].data
.p
, sp
[1].data
.p
, sp
[2].data
.p
);
1440 case MINT_ICALL_PPI_V
: {
1441 void (*func
)(gpointer
,gpointer
,int) = ptr
;
1443 func (sp
[0].data
.p
, sp
[1].data
.p
, sp
[2].data
.i
);
1447 g_assert_not_reached ();
1450 context
->env_frame
= old_env_frame
;
1451 context
->current_env
= old_env
;
1456 static mono_mutex_t create_method_pointer_mutex
;
1458 static GHashTable
*method_pointer_hash
= NULL
;
1460 static MonoMethod
*method_pointers
[2] = {0};
1463 mp_tramp_0 (MonoObject
*this_obj
, void **params
, MonoObject
**exc
, void *compiled_method
) {
1465 void *params_real
[] = {this_obj
, ¶ms
, &exc
, &compiled_method
};
1466 MonoObject
*ret
= mono_interp_runtime_invoke (method_pointers
[0], NULL
, params_real
, NULL
, &error
);
1467 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
1472 mp_tramp_1 (MonoObject
*this_obj
, void **params
, MonoObject
**exc
, void *compiled_method
) {
1474 void *params_real
[] = {this_obj
, ¶ms
, &exc
, &compiled_method
};
1475 MonoObject
*ret
= mono_interp_runtime_invoke (method_pointers
[1], NULL
, params_real
, NULL
, &error
);
1476 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
1480 gpointer
*mp_tramps
[] = {(gpointer
) mp_tramp_0
, (gpointer
) mp_tramp_1
};
1482 static int tramps_used
= 0;
1485 mono_interp_create_method_pointer (MonoMethod
*method
, MonoError
*error
)
1490 mono_os_mutex_lock (&create_method_pointer_mutex
);
1491 if (!method_pointer_hash
) {
1492 // FIXME: is registering method table as GC root really necessary?
1493 // MONO_GC_REGISTER_ROOT_FIXED (method_pointer_hash);
1494 method_pointer_hash
= g_hash_table_new (NULL
, NULL
);
1496 addr
= g_hash_table_lookup (method_pointer_hash
, method
);
1498 mono_os_mutex_unlock (&create_method_pointer_mutex
);
1503 * If it is a static P/Invoke method, we can just return the pointer
1504 * to the method implementation.
1506 if (method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
&& ((MonoMethodPInvoke
*) method
)->addr
) {
1507 ji
= g_new0 (MonoJitInfo
, 1);
1508 ji
->d
.method
= method
;
1510 ji
->code_start
= addr
= ((MonoMethodPInvoke
*) method
)->addr
;
1512 mono_jit_info_table_add (mono_get_root_domain (), ji
);
1515 g_assert (method
->wrapper_type
== MONO_WRAPPER_RUNTIME_INVOKE
);
1516 g_assert (tramps_used
< 2);
1518 /* FIXME: needs locking */
1519 method_pointers
[tramps_used
] = method
;
1520 addr
= mp_tramps
[tramps_used
];
1524 g_hash_table_insert (method_pointer_hash
, method
, addr
);
1525 mono_os_mutex_unlock (&create_method_pointer_mutex
);
1531 static int opcode_counts
[512];
1533 #define COUNT_OP(op) opcode_counts[op]++
1535 #define COUNT_OP(op)
1539 #define DUMP_INSTR() \
1540 if (tracing > 1) { \
1542 if (sp > frame->stack) { \
1543 ins = dump_stack (frame->stack, sp); \
1545 ins = g_strdup (""); \
1549 char *mn = mono_method_full_name (frame->runtime_method->method, FALSE); \
1550 g_print ("(%p) %s -> ", mono_thread_internal_current (), mn); \
1552 mono_interp_dis_mintop(rtm->code, ip); \
1553 g_print ("\t%d:%s\n", vt_sp - vtalloc, ins); \
1557 #define DUMP_INSTR()
1561 #define USE_COMPUTED_GOTO 1
1563 #if USE_COMPUTED_GOTO
1564 #define MINT_IN_SWITCH(op) COUNT_OP(op); goto *in_labels[op];
1565 #define MINT_IN_CASE(x) LAB_ ## x:
1567 #define MINT_IN_BREAK if (tracing > 1) goto main_loop; else { COUNT_OP(*ip); goto *in_labels[*ip]; }
1569 #define MINT_IN_BREAK { COUNT_OP(*ip); goto *in_labels[*ip]; }
1571 #define MINT_IN_DEFAULT mint_default: if (0) goto mint_default; /* make gcc shut up */
1573 #define MINT_IN_SWITCH(op) switch (op)
1574 #define MINT_IN_CASE(x) case x:
1575 #define MINT_IN_BREAK break
1576 #define MINT_IN_DEFAULT default:
1580 * Defining this causes register allocation errors in some versions of gcc:
1581 * error: unable to find a register to spill in class `SIREG'
1583 /* #define MINT_USE_DEDICATED_IP_REG */
1586 ves_exec_method_with_context (MonoInvocation
*frame
, ThreadContext
*context
)
1588 MonoInvocation child_frame
;
1589 GSList
*finally_ips
= NULL
;
1590 const unsigned short *endfinally_ip
= NULL
;
1591 #if defined(__GNUC__) && defined (i386) && defined (MINT_USE_DEDICATED_IP_REG)
1592 register const unsigned short *ip
asm ("%esi");
1594 register const unsigned short *ip
;
1596 register stackval
*sp
;
1599 gint tracing
= global_tracing
;
1600 unsigned char *vtalloc
;
1603 unsigned char *vt_sp
;
1604 unsigned char *locals
;
1606 MonoObject
*o
= NULL
;
1608 #if USE_COMPUTED_GOTO
1609 static void *in_labels
[] = {
1610 #define OPDEF(a,b,c,d) \
1612 #include "mintops.def"
1617 frame
->ex_handler
= NULL
;
1619 context
->current_frame
= frame
;
1622 debug_enter (frame
, &tracing
);
1625 if (!frame
->runtime_method
->transformed
) {
1626 context
->managed_code
= 0;
1628 char *mn
= mono_method_full_name (frame
->runtime_method
->method
, TRUE
);
1629 g_print ("(%p) Transforming %s\n", mono_thread_internal_current (), mn
);
1632 frame
->ex
= mono_interp_transform_method (frame
->runtime_method
, context
);
1633 context
->managed_code
= 1;
1641 rtm
= frame
->runtime_method
;
1642 frame
->args
= alloca (rtm
->alloca_size
);
1643 memset (frame
->args
, 0, rtm
->alloca_size
);
1645 sp
= frame
->stack
= (stackval
*)((char *)frame
->args
+ rtm
->args_size
);
1646 memset (sp
, 0, rtm
->stack_size
);
1648 vt_sp
= (unsigned char *) sp
+ rtm
->stack_size
;
1649 memset (vt_sp
, 0, rtm
->vt_stack_size
);
1654 locals
= (unsigned char *) vt_sp
+ rtm
->vt_stack_size
;
1655 memset (vt_sp
, 0, rtm
->locals_size
);
1657 child_frame
.parent
= frame
;
1663 * using while (ip < end) may result in a 15% performance drop,
1664 * but it may be useful for debug
1668 /* g_assert (sp >= frame->stack); */
1669 /* g_assert(vt_sp - vtalloc <= rtm->vt_stack_size); */
1671 MINT_IN_SWITCH (*ip
) {
1672 MINT_IN_CASE(MINT_INITLOCALS
)
1673 memset (locals
, 0, rtm
->locals_size
);
1676 MINT_IN_CASE(MINT_NOP
)
1679 MINT_IN_CASE(MINT_BREAK
)
1681 G_BREAKPOINT (); /* this is not portable... */
1683 MINT_IN_CASE(MINT_LDNULL
)
1688 MINT_IN_CASE(MINT_VTRESULT
) {
1689 int ret_size
= * (guint16
*)(ip
+ 1);
1690 unsigned char *ret_vt_sp
= vt_sp
;
1691 vt_sp
-= READ32(ip
+ 2);
1693 memmove (vt_sp
, ret_vt_sp
, ret_size
);
1694 sp
[-1].data
.p
= vt_sp
;
1695 vt_sp
+= (ret_size
+ 7) & ~7;
1700 #define LDC(n) do { sp->data.i = (n); ++ip; ++sp; } while (0)
1701 MINT_IN_CASE(MINT_LDC_I4_M1
)
1704 MINT_IN_CASE(MINT_LDC_I4_0
)
1707 MINT_IN_CASE(MINT_LDC_I4_1
)
1710 MINT_IN_CASE(MINT_LDC_I4_2
)
1713 MINT_IN_CASE(MINT_LDC_I4_3
)
1716 MINT_IN_CASE(MINT_LDC_I4_4
)
1719 MINT_IN_CASE(MINT_LDC_I4_5
)
1722 MINT_IN_CASE(MINT_LDC_I4_6
)
1725 MINT_IN_CASE(MINT_LDC_I4_7
)
1728 MINT_IN_CASE(MINT_LDC_I4_8
)
1731 MINT_IN_CASE(MINT_LDC_I4_S
)
1732 sp
->data
.i
= *(const short *)(ip
+ 1);
1736 MINT_IN_CASE(MINT_LDC_I4
)
1738 sp
->data
.i
= READ32 (ip
);
1742 MINT_IN_CASE(MINT_LDC_I8
)
1744 sp
->data
.l
= READ64 (ip
);
1748 MINT_IN_CASE(MINT_LDC_R4
) {
1752 sp
->data
.f
= * (float *)&val
;
1757 MINT_IN_CASE(MINT_LDC_R8
)
1758 sp
->data
.l
= READ64 (ip
+ 1); /* note union usage */
1762 MINT_IN_CASE(MINT_DUP
)
1767 MINT_IN_CASE(MINT_DUP_VT
)
1768 i32
= READ32 (ip
+ 1);
1770 memcpy(sp
->data
.p
, sp
[-1].data
.p
, i32
);
1771 vt_sp
+= (i32
+ 7) & ~7;
1775 MINT_IN_CASE(MINT_POP
) {
1776 guint16 u16
= (* (guint16
*)(ip
+ 1)) + 1;
1778 memmove (sp
- u16
, sp
- 1, (u16
- 1) * sizeof (stackval
));
1783 MINT_IN_CASE(MINT_JMP
) {
1784 RuntimeMethod
*new_method
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
1785 if (!new_method
->transformed
) {
1787 frame
->ex
= mono_interp_transform_method (new_method
, context
);
1792 if (new_method
->alloca_size
> rtm
->alloca_size
)
1793 g_error ("MINT_JMP to method which needs more stack space (%d > %d)", new_method
->alloca_size
, rtm
->alloca_size
);
1794 rtm
= frame
->runtime_method
= new_method
;
1795 vt_sp
= (unsigned char *) sp
+ rtm
->stack_size
;
1799 locals
= vt_sp
+ rtm
->vt_stack_size
;
1800 ip
= rtm
->new_body_start
; /* bypass storing input args from callers frame */
1803 MINT_IN_CASE(MINT_CALLI
) {
1804 MonoMethodSignature
*csignature
;
1805 stackval
*endsp
= sp
;
1809 csignature
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
1813 child_frame
.runtime_method
= sp
->data
.p
;
1816 child_frame
.retval
= sp
;
1817 /* decrement by the actual number of args */
1818 sp
-= csignature
->param_count
;
1819 if (csignature
->hasthis
)
1821 child_frame
.stack_args
= sp
;
1823 /* `this' can be NULL for string:.ctor */
1824 if (csignature
->hasthis
&& sp
->data
.p
&& mono_object_is_transparent_proxy (sp
->data
.p
)) {
1825 child_frame
.runtime_method
= mono_interp_get_runtime_method (context
->domain
, mono_marshal_get_remoting_invoke (child_frame
.runtime_method
->method
), &error
);
1826 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
1827 } else if (child_frame
.runtime_method
->method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) {
1828 child_frame
.runtime_method
= mono_interp_get_runtime_method (context
->domain
, mono_marshal_get_native_wrapper (child_frame
.runtime_method
->method
, FALSE
, FALSE
), &error
);
1829 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
1832 if (csignature
->hasthis
) {
1833 MonoObject
*this_arg
= sp
->data
.p
;
1835 if (this_arg
->vtable
->klass
->valuetype
) {
1836 gpointer
*unboxed
= mono_object_unbox (this_arg
);
1837 sp
[0].data
.p
= unboxed
;
1841 ves_exec_method_with_context (&child_frame
, context
);
1843 context
->current_frame
= frame
;
1845 if (child_frame
.ex
) {
1847 * An exception occurred, need to run finally, fault and catch handlers..
1849 frame
->ex
= child_frame
.ex
;
1850 goto handle_finally
;
1853 /* need to handle typedbyref ... */
1854 if (csignature
->ret
->type
!= MONO_TYPE_VOID
) {
1860 MINT_IN_CASE(MINT_CALLI_NAT
) {
1861 MonoMethodSignature
*csignature
;
1862 stackval
*endsp
= sp
;
1863 unsigned char *code
= NULL
;
1867 csignature
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
1872 child_frame
.runtime_method
= NULL
;
1875 child_frame
.retval
= sp
;
1876 /* decrement by the actual number of args */
1877 sp
-= csignature
->param_count
;
1878 if (csignature
->hasthis
)
1880 child_frame
.stack_args
= sp
;
1881 ves_pinvoke_method (&child_frame
, csignature
, (MonoFuncV
) code
, FALSE
, context
);
1883 context
->current_frame
= frame
;
1885 if (child_frame
.ex
) {
1887 * An exception occurred, need to run finally, fault and catch handlers..
1889 frame
->ex
= child_frame
.ex
;
1890 if (context
->search_for_handler
) {
1891 context
->search_for_handler
= 0;
1892 goto handle_exception
;
1894 goto handle_finally
;
1897 /* need to handle typedbyref ... */
1898 if (csignature
->ret
->type
!= MONO_TYPE_VOID
) {
1904 MINT_IN_CASE(MINT_CALL
) {
1905 stackval
*endsp
= sp
;
1909 child_frame
.runtime_method
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
1912 child_frame
.retval
= sp
;
1913 /* decrement by the actual number of args */
1914 sp
-= child_frame
.runtime_method
->param_count
;
1915 if (child_frame
.runtime_method
->hasthis
)
1917 child_frame
.stack_args
= sp
;
1919 /* `this' can be NULL for string:.ctor */
1920 if (child_frame
.runtime_method
->hasthis
&& !child_frame
.runtime_method
->method
->klass
->valuetype
&& sp
->data
.p
&& mono_object_is_transparent_proxy (sp
->data
.p
)) {
1921 child_frame
.runtime_method
= mono_interp_get_runtime_method (context
->domain
, mono_marshal_get_remoting_invoke (child_frame
.runtime_method
->method
), &error
);
1922 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
1924 ves_exec_method_with_context (&child_frame
, context
);
1926 context
->current_frame
= frame
;
1928 if (child_frame
.ex
) {
1930 * An exception occurred, need to run finally, fault and catch handlers..
1932 frame
->ex
= child_frame
.ex
;
1933 goto handle_finally
;
1936 /* need to handle typedbyref ... */
1941 MINT_IN_CASE(MINT_VCALL
) {
1944 child_frame
.runtime_method
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
1948 child_frame
.retval
= sp
;
1949 /* decrement by the actual number of args */
1950 sp
-= child_frame
.runtime_method
->param_count
;
1951 if (child_frame
.runtime_method
->hasthis
) {
1953 MonoObject
*this_arg
= sp
->data
.p
;
1955 THROW_EX (mono_get_exception_null_reference(), ip
- 2);
1957 child_frame
.stack_args
= sp
;
1959 if (child_frame
.runtime_method
->hasthis
&& !child_frame
.runtime_method
->method
->klass
->valuetype
&& mono_object_is_transparent_proxy (sp
->data
.p
)) {
1960 child_frame
.runtime_method
= mono_interp_get_runtime_method (context
->domain
, mono_marshal_get_remoting_invoke (child_frame
.runtime_method
->method
), &error
);
1961 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
1964 ves_exec_method_with_context (&child_frame
, context
);
1966 context
->current_frame
= frame
;
1968 if (child_frame
.ex
) {
1970 * An exception occurred, need to run finally, fault and catch handlers..
1972 frame
->ex
= child_frame
.ex
;
1973 goto handle_finally
;
1977 MINT_IN_CASE(MINT_CALLVIRT
) {
1978 stackval
*endsp
= sp
;
1979 MonoObject
*this_arg
;
1984 token
= * (unsigned short *)(ip
+ 1);
1986 child_frame
.runtime_method
= rtm
->data_items
[token
];
1988 child_frame
.retval
= sp
;
1990 /* decrement by the actual number of args */
1991 sp
-= child_frame
.runtime_method
->param_count
+ 1;
1992 child_frame
.stack_args
= sp
;
1993 this_arg
= sp
->data
.p
;
1995 THROW_EX (mono_get_exception_null_reference(), ip
- 2);
1996 child_frame
.runtime_method
= get_virtual_method (context
->domain
, child_frame
.runtime_method
, this_arg
);
1998 MonoClass
*this_class
= this_arg
->vtable
->klass
;
1999 if (this_class
->valuetype
&& child_frame
.runtime_method
->method
->klass
->valuetype
) {
2001 gpointer
*unboxed
= mono_object_unbox (this_arg
);
2002 sp
[0].data
.p
= unboxed
;
2005 ves_exec_method_with_context (&child_frame
, context
);
2007 context
->current_frame
= frame
;
2009 if (child_frame
.ex
) {
2011 * An exception occurred, need to run finally, fault and catch handlers..
2013 frame
->ex
= child_frame
.ex
;
2014 if (context
->search_for_handler
) {
2015 context
->search_for_handler
= 0;
2016 goto handle_exception
;
2018 goto handle_finally
;
2021 /* need to handle typedbyref ... */
2026 MINT_IN_CASE(MINT_VCALLVIRT
) {
2027 MonoObject
*this_arg
;
2032 token
= * (unsigned short *)(ip
+ 1);
2034 child_frame
.runtime_method
= rtm
->data_items
[token
];
2036 child_frame
.retval
= sp
;
2038 /* decrement by the actual number of args */
2039 sp
-= child_frame
.runtime_method
->param_count
+ 1;
2040 child_frame
.stack_args
= sp
;
2041 this_arg
= sp
->data
.p
;
2043 THROW_EX (mono_get_exception_null_reference(), ip
- 2);
2044 child_frame
.runtime_method
= get_virtual_method (context
->domain
, child_frame
.runtime_method
, this_arg
);
2046 MonoClass
*this_class
= this_arg
->vtable
->klass
;
2047 if (this_class
->valuetype
&& child_frame
.runtime_method
->method
->klass
->valuetype
) {
2048 gpointer
*unboxed
= mono_object_unbox (this_arg
);
2049 sp
[0].data
.p
= unboxed
;
2052 ves_exec_method_with_context (&child_frame
, context
);
2054 context
->current_frame
= frame
;
2056 if (child_frame
.ex
) {
2058 * An exception occurred, need to run finally, fault and catch handlers..
2060 frame
->ex
= child_frame
.ex
;
2061 if (context
->search_for_handler
) {
2062 context
->search_for_handler
= 0;
2063 goto handle_exception
;
2065 goto handle_finally
;
2069 MINT_IN_CASE(MINT_CALLRUN
)
2070 ves_runtime_method (frame
, context
);
2073 goto handle_exception
;
2076 MINT_IN_CASE(MINT_RET
)
2078 *frame
->retval
= *sp
;
2079 if (sp
> frame
->stack
)
2080 g_warning ("ret: more values on stack: %d", sp
-frame
->stack
);
2082 MINT_IN_CASE(MINT_RET_VOID
)
2083 if (sp
> frame
->stack
)
2084 g_warning ("ret.void: more values on stack: %d", sp
-frame
->stack
);
2086 MINT_IN_CASE(MINT_RET_VT
)
2087 i32
= READ32(ip
+ 1);
2089 memcpy(frame
->retval
->data
.p
, sp
->data
.p
, i32
);
2090 if (sp
> frame
->stack
)
2091 g_warning ("ret.vt: more values on stack: %d", sp
-frame
->stack
);
2093 MINT_IN_CASE(MINT_BR_S
)
2094 ip
+= (short) *(ip
+ 1);
2096 MINT_IN_CASE(MINT_BR
)
2097 ip
+= (gint32
) READ32(ip
+ 1);
2099 #define ZEROP_S(datamem, op) \
2101 if (sp->data.datamem op 0) \
2102 ip += * (gint16 *)(ip + 1); \
2106 #define ZEROP(datamem, op) \
2108 if (sp->data.datamem op 0) \
2109 ip += READ32(ip + 1); \
2113 MINT_IN_CASE(MINT_BRFALSE_I4_S
)
2116 MINT_IN_CASE(MINT_BRFALSE_I8_S
)
2119 MINT_IN_CASE(MINT_BRFALSE_R8_S
)
2122 MINT_IN_CASE(MINT_BRFALSE_I4
)
2125 MINT_IN_CASE(MINT_BRFALSE_I8
)
2128 MINT_IN_CASE(MINT_BRFALSE_R8
)
2131 MINT_IN_CASE(MINT_BRTRUE_I4_S
)
2134 MINT_IN_CASE(MINT_BRTRUE_I8_S
)
2137 MINT_IN_CASE(MINT_BRTRUE_R8_S
)
2140 MINT_IN_CASE(MINT_BRTRUE_I4
)
2143 MINT_IN_CASE(MINT_BRTRUE_I8
)
2146 MINT_IN_CASE(MINT_BRTRUE_R8
)
2149 #define CONDBR_S(cond) \
2152 ip += * (gint16 *)(ip + 1); \
2155 #define BRELOP_S(datamem, op) \
2156 CONDBR_S(sp[0].data.datamem op sp[1].data.datamem)
2158 #define CONDBR(cond) \
2161 ip += READ32(ip + 1); \
2165 #define BRELOP(datamem, op) \
2166 CONDBR(sp[0].data.datamem op sp[1].data.datamem)
2168 MINT_IN_CASE(MINT_BEQ_I4_S
)
2171 MINT_IN_CASE(MINT_BEQ_I8_S
)
2174 MINT_IN_CASE(MINT_BEQ_R8_S
)
2175 CONDBR_S(!isunordered (sp
[0].data
.f
, sp
[1].data
.f
) && sp
[0].data
.f
== sp
[1].data
.f
)
2177 MINT_IN_CASE(MINT_BEQ_I4
)
2180 MINT_IN_CASE(MINT_BEQ_I8
)
2183 MINT_IN_CASE(MINT_BEQ_R8
)
2184 CONDBR(!isunordered (sp
[0].data
.f
, sp
[1].data
.f
) && sp
[0].data
.f
== sp
[1].data
.f
)
2186 MINT_IN_CASE(MINT_BGE_I4_S
)
2189 MINT_IN_CASE(MINT_BGE_I8_S
)
2192 MINT_IN_CASE(MINT_BGE_R8_S
)
2193 CONDBR_S(!isunordered (sp
[0].data
.f
, sp
[1].data
.f
) && sp
[0].data
.f
>= sp
[1].data
.f
)
2195 MINT_IN_CASE(MINT_BGE_I4
)
2198 MINT_IN_CASE(MINT_BGE_I8
)
2201 MINT_IN_CASE(MINT_BGE_R8
)
2202 CONDBR(!isunordered (sp
[0].data
.f
, sp
[1].data
.f
) && sp
[0].data
.f
>= sp
[1].data
.f
)
2204 MINT_IN_CASE(MINT_BGT_I4_S
)
2207 MINT_IN_CASE(MINT_BGT_I8_S
)
2210 MINT_IN_CASE(MINT_BGT_R8_S
)
2211 CONDBR_S(!isunordered (sp
[0].data
.f
, sp
[1].data
.f
) && sp
[0].data
.f
> sp
[1].data
.f
)
2213 MINT_IN_CASE(MINT_BGT_I4
)
2216 MINT_IN_CASE(MINT_BGT_I8
)
2219 MINT_IN_CASE(MINT_BGT_R8
)
2220 CONDBR(!isunordered (sp
[0].data
.f
, sp
[1].data
.f
) && sp
[0].data
.f
> sp
[1].data
.f
)
2222 MINT_IN_CASE(MINT_BLT_I4_S
)
2225 MINT_IN_CASE(MINT_BLT_I8_S
)
2228 MINT_IN_CASE(MINT_BLT_R8_S
)
2229 CONDBR_S(!isunordered (sp
[0].data
.f
, sp
[1].data
.f
) && sp
[0].data
.f
< sp
[1].data
.f
)
2231 MINT_IN_CASE(MINT_BLT_I4
)
2234 MINT_IN_CASE(MINT_BLT_I8
)
2237 MINT_IN_CASE(MINT_BLT_R8
)
2238 CONDBR(!isunordered (sp
[0].data
.f
, sp
[1].data
.f
) && sp
[0].data
.f
< sp
[1].data
.f
)
2240 MINT_IN_CASE(MINT_BLE_I4_S
)
2243 MINT_IN_CASE(MINT_BLE_I8_S
)
2246 MINT_IN_CASE(MINT_BLE_R8_S
)
2247 CONDBR_S(!isunordered (sp
[0].data
.f
, sp
[1].data
.f
) && sp
[0].data
.f
<= sp
[1].data
.f
)
2249 MINT_IN_CASE(MINT_BLE_I4
)
2252 MINT_IN_CASE(MINT_BLE_I8
)
2255 MINT_IN_CASE(MINT_BLE_R8
)
2256 CONDBR(!isunordered (sp
[0].data
.f
, sp
[1].data
.f
) && sp
[0].data
.f
<= sp
[1].data
.f
)
2258 MINT_IN_CASE(MINT_BNE_UN_I4_S
)
2261 MINT_IN_CASE(MINT_BNE_UN_I8_S
)
2264 MINT_IN_CASE(MINT_BNE_UN_R8_S
)
2265 CONDBR_S(isunordered (sp
[0].data
.f
, sp
[1].data
.f
) || sp
[0].data
.f
!= sp
[1].data
.f
)
2267 MINT_IN_CASE(MINT_BNE_UN_I4
)
2270 MINT_IN_CASE(MINT_BNE_UN_I8
)
2273 MINT_IN_CASE(MINT_BNE_UN_R8
)
2274 CONDBR(isunordered (sp
[0].data
.f
, sp
[1].data
.f
) || sp
[0].data
.f
!= sp
[1].data
.f
)
2277 #define BRELOP_S_CAST(datamem, op, type) \
2279 if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
2280 ip += * (gint16 *)(ip + 1); \
2284 #define BRELOP_CAST(datamem, op, type) \
2286 if ((type) sp[0].data.datamem op (type) sp[1].data.datamem) \
2287 ip += READ32(ip + 1); \
2291 MINT_IN_CASE(MINT_BGE_UN_I4_S
)
2292 BRELOP_S_CAST(i
, >=, guint32
);
2294 MINT_IN_CASE(MINT_BGE_UN_I8_S
)
2295 BRELOP_S_CAST(l
, >=, guint64
);
2297 MINT_IN_CASE(MINT_BGE_UN_R8_S
)
2298 CONDBR_S(isunordered (sp
[0].data
.f
, sp
[1].data
.f
) || sp
[0].data
.f
>= sp
[1].data
.f
)
2300 MINT_IN_CASE(MINT_BGE_UN_I4
)
2301 BRELOP_CAST(i
, >=, guint32
);
2303 MINT_IN_CASE(MINT_BGE_UN_I8
)
2304 BRELOP_CAST(l
, >=, guint64
);
2306 MINT_IN_CASE(MINT_BGE_UN_R8
)
2307 CONDBR(isunordered (sp
[0].data
.f
, sp
[1].data
.f
) || sp
[0].data
.f
>= sp
[1].data
.f
)
2309 MINT_IN_CASE(MINT_BGT_UN_I4_S
)
2310 BRELOP_S_CAST(i
, >, guint32
);
2312 MINT_IN_CASE(MINT_BGT_UN_I8_S
)
2313 BRELOP_S_CAST(l
, >, guint64
);
2315 MINT_IN_CASE(MINT_BGT_UN_R8_S
)
2316 CONDBR_S(isunordered (sp
[0].data
.f
, sp
[1].data
.f
) || sp
[0].data
.f
> sp
[1].data
.f
)
2318 MINT_IN_CASE(MINT_BGT_UN_I4
)
2319 BRELOP_CAST(i
, >, guint32
);
2321 MINT_IN_CASE(MINT_BGT_UN_I8
)
2322 BRELOP_CAST(l
, >, guint64
);
2324 MINT_IN_CASE(MINT_BGT_UN_R8
)
2325 CONDBR(isunordered (sp
[0].data
.f
, sp
[1].data
.f
) || sp
[0].data
.f
> sp
[1].data
.f
)
2327 MINT_IN_CASE(MINT_BLE_UN_I4_S
)
2328 BRELOP_S_CAST(i
, <=, guint32
);
2330 MINT_IN_CASE(MINT_BLE_UN_I8_S
)
2331 BRELOP_S_CAST(l
, <=, guint64
);
2333 MINT_IN_CASE(MINT_BLE_UN_R8_S
)
2334 CONDBR_S(isunordered (sp
[0].data
.f
, sp
[1].data
.f
) || sp
[0].data
.f
<= sp
[1].data
.f
)
2336 MINT_IN_CASE(MINT_BLE_UN_I4
)
2337 BRELOP_CAST(i
, <=, guint32
);
2339 MINT_IN_CASE(MINT_BLE_UN_I8
)
2340 BRELOP_CAST(l
, <=, guint64
);
2342 MINT_IN_CASE(MINT_BLE_UN_R8
)
2343 CONDBR(isunordered (sp
[0].data
.f
, sp
[1].data
.f
) || sp
[0].data
.f
<= sp
[1].data
.f
)
2345 MINT_IN_CASE(MINT_BLT_UN_I4_S
)
2346 BRELOP_S_CAST(i
, <, guint32
);
2348 MINT_IN_CASE(MINT_BLT_UN_I8_S
)
2349 BRELOP_S_CAST(l
, <, guint64
);
2351 MINT_IN_CASE(MINT_BLT_UN_R8_S
)
2352 CONDBR_S(isunordered (sp
[0].data
.f
, sp
[1].data
.f
) || sp
[0].data
.f
< sp
[1].data
.f
)
2354 MINT_IN_CASE(MINT_BLT_UN_I4
)
2355 BRELOP_CAST(i
, <, guint32
);
2357 MINT_IN_CASE(MINT_BLT_UN_I8
)
2358 BRELOP_CAST(l
, <, guint64
);
2360 MINT_IN_CASE(MINT_BLT_UN_R8
)
2361 CONDBR(isunordered (sp
[0].data
.f
, sp
[1].data
.f
) || sp
[0].data
.f
< sp
[1].data
.f
)
2363 MINT_IN_CASE(MINT_SWITCH
) {
2365 const unsigned short *st
;
2371 if ((guint32
)sp
->data
.i
< n
) {
2373 ip
+= 2 * (guint32
)sp
->data
.i
;
2374 offset
= READ32 (ip
);
2381 MINT_IN_CASE(MINT_LDIND_I1
)
2383 sp
[-1].data
.i
= *(gint8
*)sp
[-1].data
.p
;
2385 MINT_IN_CASE(MINT_LDIND_U1
)
2387 sp
[-1].data
.i
= *(guint8
*)sp
[-1].data
.p
;
2389 MINT_IN_CASE(MINT_LDIND_I2
)
2391 sp
[-1].data
.i
= *(gint16
*)sp
[-1].data
.p
;
2393 MINT_IN_CASE(MINT_LDIND_U2
)
2395 sp
[-1].data
.i
= *(guint16
*)sp
[-1].data
.p
;
2397 MINT_IN_CASE(MINT_LDIND_I4
) /* Fall through */
2398 MINT_IN_CASE(MINT_LDIND_U4
)
2400 sp
[-1].data
.i
= *(gint32
*)sp
[-1].data
.p
;
2402 MINT_IN_CASE(MINT_LDIND_I8
)
2404 sp
[-1].data
.l
= *(gint64
*)sp
[-1].data
.p
;
2406 MINT_IN_CASE(MINT_LDIND_I
) {
2407 guint16 offset
= * (guint16
*)(ip
+ 1);
2408 sp
[-1 - offset
].data
.p
= *(gpointer
*)sp
[-1 - offset
].data
.p
;
2412 MINT_IN_CASE(MINT_LDIND_R4
)
2414 sp
[-1].data
.f
= *(gfloat
*)sp
[-1].data
.p
;
2416 MINT_IN_CASE(MINT_LDIND_R8
)
2418 sp
[-1].data
.f
= *(gdouble
*)sp
[-1].data
.p
;
2420 MINT_IN_CASE(MINT_LDIND_REF
)
2422 sp
[-1].data
.p
= *(gpointer
*)sp
[-1].data
.p
;
2424 MINT_IN_CASE(MINT_STIND_REF
)
2427 * (gpointer
*) sp
->data
.p
= sp
[1].data
.p
;
2429 MINT_IN_CASE(MINT_STIND_I1
)
2432 * (gint8
*) sp
->data
.p
= (gint8
)sp
[1].data
.i
;
2434 MINT_IN_CASE(MINT_STIND_I2
)
2437 * (gint16
*) sp
->data
.p
= (gint16
)sp
[1].data
.i
;
2439 MINT_IN_CASE(MINT_STIND_I4
)
2442 * (gint32
*) sp
->data
.p
= sp
[1].data
.i
;
2444 MINT_IN_CASE(MINT_STIND_I
)
2447 * (mono_i
*) sp
->data
.p
= (mono_i
)sp
[1].data
.p
;
2449 MINT_IN_CASE(MINT_STIND_I8
)
2452 * (gint64
*) sp
->data
.p
= sp
[1].data
.l
;
2454 MINT_IN_CASE(MINT_STIND_R4
)
2457 * (float *) sp
->data
.p
= (gfloat
)sp
[1].data
.f
;
2459 MINT_IN_CASE(MINT_STIND_R8
)
2462 * (double *) sp
->data
.p
= sp
[1].data
.f
;
2464 #define BINOP(datamem, op) \
2466 sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.datamem; \
2468 MINT_IN_CASE(MINT_ADD_I4
)
2471 MINT_IN_CASE(MINT_ADD_I8
)
2474 MINT_IN_CASE(MINT_ADD_R8
)
2477 MINT_IN_CASE(MINT_ADD1_I4
)
2481 MINT_IN_CASE(MINT_SUB_I4
)
2484 MINT_IN_CASE(MINT_SUB_I8
)
2487 MINT_IN_CASE(MINT_SUB_R8
)
2490 MINT_IN_CASE(MINT_SUB1_I4
)
2494 MINT_IN_CASE(MINT_MUL_I4
)
2497 MINT_IN_CASE(MINT_MUL_I8
)
2500 MINT_IN_CASE(MINT_MUL_R8
)
2503 MINT_IN_CASE(MINT_DIV_I4
)
2504 if (sp
[-1].data
.i
== 0)
2505 THROW_EX (mono_get_exception_divide_by_zero (), ip
);
2506 if (sp
[-1].data
.i
== (-1))
2507 THROW_EX (mono_get_exception_overflow (), ip
);
2510 MINT_IN_CASE(MINT_DIV_I8
)
2511 if (sp
[-1].data
.l
== 0)
2512 THROW_EX (mono_get_exception_divide_by_zero (), ip
);
2513 if (sp
[-1].data
.l
== (-1))
2514 THROW_EX (mono_get_exception_overflow (), ip
);
2517 MINT_IN_CASE(MINT_DIV_R8
)
2521 #define BINOP_CAST(datamem, op, type) \
2523 sp [-1].data.datamem = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
2525 MINT_IN_CASE(MINT_DIV_UN_I4
)
2526 if (sp
[-1].data
.i
== 0)
2527 THROW_EX (mono_get_exception_divide_by_zero (), ip
);
2528 BINOP_CAST(i
, /, guint32
);
2530 MINT_IN_CASE(MINT_DIV_UN_I8
)
2531 if (sp
[-1].data
.l
== 0)
2532 THROW_EX (mono_get_exception_divide_by_zero (), ip
);
2533 BINOP_CAST(l
, /, guint64
);
2535 MINT_IN_CASE(MINT_REM_I4
)
2536 if (sp
[-1].data
.i
== 0)
2537 THROW_EX (mono_get_exception_divide_by_zero (), ip
);
2538 if (sp
[-1].data
.i
== (-1))
2539 THROW_EX (mono_get_exception_overflow (), ip
);
2542 MINT_IN_CASE(MINT_REM_I8
)
2543 if (sp
[-1].data
.l
== 0)
2544 THROW_EX (mono_get_exception_divide_by_zero (), ip
);
2545 if (sp
[-1].data
.l
== (-1))
2546 THROW_EX (mono_get_exception_overflow (), ip
);
2549 MINT_IN_CASE(MINT_REM_R8
)
2550 /* FIXME: what do we actually do here? */
2552 sp
[-1].data
.f
= fmod (sp
[-1].data
.f
, sp
[0].data
.f
);
2555 MINT_IN_CASE(MINT_REM_UN_I4
)
2556 if (sp
[-1].data
.i
== 0)
2557 THROW_EX (mono_get_exception_divide_by_zero (), ip
);
2558 BINOP_CAST(i
, %, guint32
);
2560 MINT_IN_CASE(MINT_REM_UN_I8
)
2561 if (sp
[-1].data
.l
== 0)
2562 THROW_EX (mono_get_exception_divide_by_zero (), ip
);
2563 BINOP_CAST(l
, %, guint64
);
2565 MINT_IN_CASE(MINT_AND_I4
)
2568 MINT_IN_CASE(MINT_AND_I8
)
2571 MINT_IN_CASE(MINT_OR_I4
)
2574 MINT_IN_CASE(MINT_OR_I8
)
2577 MINT_IN_CASE(MINT_XOR_I4
)
2580 MINT_IN_CASE(MINT_XOR_I8
)
2584 #define SHIFTOP(datamem, op) \
2586 sp [-1].data.datamem = sp [-1].data.datamem op sp [0].data.i; \
2589 MINT_IN_CASE(MINT_SHL_I4
)
2592 MINT_IN_CASE(MINT_SHL_I8
)
2595 MINT_IN_CASE(MINT_SHR_I4
)
2598 MINT_IN_CASE(MINT_SHR_I8
)
2601 MINT_IN_CASE(MINT_SHR_UN_I4
)
2603 sp
[-1].data
.i
= (guint32
)sp
[-1].data
.i
>> sp
[0].data
.i
;
2606 MINT_IN_CASE(MINT_SHR_UN_I8
)
2608 sp
[-1].data
.l
= (guint64
)sp
[-1].data
.l
>> sp
[0].data
.i
;
2611 MINT_IN_CASE(MINT_NEG_I4
)
2612 sp
[-1].data
.i
= - sp
[-1].data
.i
;
2615 MINT_IN_CASE(MINT_NEG_I8
)
2616 sp
[-1].data
.l
= - sp
[-1].data
.l
;
2619 MINT_IN_CASE(MINT_NEG_R8
)
2620 sp
[-1].data
.f
= - sp
[-1].data
.f
;
2623 MINT_IN_CASE(MINT_NOT_I4
)
2624 sp
[-1].data
.i
= ~ sp
[-1].data
.i
;
2627 MINT_IN_CASE(MINT_NOT_I8
)
2628 sp
[-1].data
.l
= ~ sp
[-1].data
.l
;
2631 MINT_IN_CASE(MINT_CONV_I1_I4
)
2632 sp
[-1].data
.i
= (gint8
)sp
[-1].data
.i
;
2635 MINT_IN_CASE(MINT_CONV_I1_I8
)
2636 sp
[-1].data
.i
= (gint8
)sp
[-1].data
.l
;
2639 MINT_IN_CASE(MINT_CONV_I1_R8
)
2640 sp
[-1].data
.i
= (gint8
)sp
[-1].data
.f
;
2643 MINT_IN_CASE(MINT_CONV_U1_I4
)
2644 sp
[-1].data
.i
= (guint8
)sp
[-1].data
.i
;
2647 MINT_IN_CASE(MINT_CONV_U1_I8
)
2648 sp
[-1].data
.i
= (guint8
)sp
[-1].data
.l
;
2651 MINT_IN_CASE(MINT_CONV_U1_R8
)
2652 sp
[-1].data
.i
= (guint8
)sp
[-1].data
.f
;
2655 MINT_IN_CASE(MINT_CONV_I2_I4
)
2656 sp
[-1].data
.i
= (gint16
)sp
[-1].data
.i
;
2659 MINT_IN_CASE(MINT_CONV_I2_I8
)
2660 sp
[-1].data
.i
= (gint16
)sp
[-1].data
.l
;
2663 MINT_IN_CASE(MINT_CONV_I2_R8
)
2664 sp
[-1].data
.i
= (gint16
)sp
[-1].data
.f
;
2667 MINT_IN_CASE(MINT_CONV_U2_I4
)
2668 sp
[-1].data
.i
= (guint16
)sp
[-1].data
.i
;
2671 MINT_IN_CASE(MINT_CONV_U2_I8
)
2672 sp
[-1].data
.i
= (guint16
)sp
[-1].data
.l
;
2675 MINT_IN_CASE(MINT_CONV_U2_R8
)
2676 sp
[-1].data
.i
= (guint16
)sp
[-1].data
.f
;
2679 MINT_IN_CASE(MINT_CONV_I4_R8
)
2680 sp
[-1].data
.i
= (gint32
)sp
[-1].data
.f
;
2683 MINT_IN_CASE(MINT_CONV_U4_I8
)
2684 MINT_IN_CASE(MINT_CONV_I4_I8
)
2685 sp
[-1].data
.i
= (gint32
)sp
[-1].data
.l
;
2688 MINT_IN_CASE(MINT_CONV_I4_I8_SP
)
2689 sp
[-2].data
.i
= (gint32
)sp
[-2].data
.l
;
2692 MINT_IN_CASE(MINT_CONV_U4_R8
)
2693 sp
[-1].data
.i
= (guint32
)sp
[-1].data
.f
;
2696 MINT_IN_CASE(MINT_CONV_I8_I4
)
2697 sp
[-1].data
.l
= sp
[-1].data
.i
;
2700 MINT_IN_CASE(MINT_CONV_I8_I4_SP
)
2701 sp
[-2].data
.l
= sp
[-2].data
.i
;
2704 MINT_IN_CASE(MINT_CONV_I8_U4
)
2705 sp
[-1].data
.l
= (guint32
)sp
[-1].data
.i
;
2708 MINT_IN_CASE(MINT_CONV_I8_R8
)
2709 sp
[-1].data
.l
= (gint64
)sp
[-1].data
.f
;
2712 MINT_IN_CASE(MINT_CONV_R4_I4
)
2713 sp
[-1].data
.f
= (float)sp
[-1].data
.i
;
2716 MINT_IN_CASE(MINT_CONV_R4_I8
)
2717 sp
[-1].data
.f
= (float)sp
[-1].data
.l
;
2720 MINT_IN_CASE(MINT_CONV_R4_R8
)
2721 sp
[-1].data
.f
= (float)sp
[-1].data
.f
;
2724 MINT_IN_CASE(MINT_CONV_R8_I4
)
2725 sp
[-1].data
.f
= (double)sp
[-1].data
.i
;
2728 MINT_IN_CASE(MINT_CONV_R8_I8
)
2729 sp
[-1].data
.f
= (double)sp
[-1].data
.l
;
2732 MINT_IN_CASE(MINT_CONV_U8_I4
)
2733 sp
[-1].data
.l
= sp
[-1].data
.i
& 0xffffffff;
2736 MINT_IN_CASE(MINT_CONV_U8_R8
)
2737 sp
[-1].data
.l
= (guint64
)sp
[-1].data
.f
;
2740 MINT_IN_CASE(MINT_CPOBJ
) {
2741 c
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
2742 g_assert (c
->byval_arg
.type
== MONO_TYPE_VALUETYPE
);
2743 stackval_from_data (&c
->byval_arg
, &sp
[-2], sp
[-1].data
.p
, FALSE
);
2748 MINT_IN_CASE(MINT_LDOBJ
) {
2750 c
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
2753 if (c
->byval_arg
.type
== MONO_TYPE_VALUETYPE
&& !c
->enumtype
) {
2754 int size
= mono_class_value_size (c
, NULL
);
2755 sp
[-1].data
.p
= vt_sp
;
2756 vt_sp
+= (size
+ 7) & ~7;
2758 stackval_from_data (&c
->byval_arg
, &sp
[-1], p
, FALSE
);
2761 MINT_IN_CASE(MINT_LDSTR
)
2762 sp
->data
.p
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
2766 MINT_IN_CASE(MINT_NEWOBJ
) {
2767 MonoClass
*newobj_class
;
2768 MonoMethodSignature
*csig
;
2769 stackval valuetype_this
;
2775 token
= * (guint16
*)(ip
+ 1);
2778 child_frame
.ip
= NULL
;
2779 child_frame
.ex
= NULL
;
2781 child_frame
.runtime_method
= rtm
->data_items
[token
];
2782 csig
= mono_method_signature (child_frame
.runtime_method
->method
);
2783 newobj_class
= child_frame
.runtime_method
->method
->klass
;
2784 /*if (profiling_classes) {
2785 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class));
2787 g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count));
2790 if (newobj_class
->parent
== mono_defaults
.array_class
) {
2791 sp
-= csig
->param_count
;
2792 child_frame
.stack_args
= sp
;
2793 o
= ves_array_create (&child_frame
, context
->domain
, newobj_class
, csig
, sp
);
2795 THROW_EX (child_frame
.ex
, ip
);
2796 goto array_constructed
;
2799 g_assert (csig
->hasthis
);
2800 if (csig
->param_count
) {
2801 sp
-= csig
->param_count
;
2802 memmove (sp
+ 1, sp
, csig
->param_count
* sizeof (stackval
));
2804 child_frame
.stack_args
= sp
;
2807 * First arg is the object.
2809 if (newobj_class
->valuetype
) {
2810 MonoType
*t
= &newobj_class
->byval_arg
;
2811 memset (&valuetype_this
, 0, sizeof (stackval
));
2812 if (!newobj_class
->enumtype
&& (t
->type
== MONO_TYPE_VALUETYPE
|| (t
->type
== MONO_TYPE_GENERICINST
&& mono_type_generic_inst_is_valuetype (t
)))) {
2814 valuetype_this
.data
.p
= vt_sp
;
2816 sp
->data
.p
= &valuetype_this
;
2819 if (newobj_class
!= mono_defaults
.string_class
) {
2820 context
->managed_code
= 0;
2821 o
= mono_object_new_checked (context
->domain
, newobj_class
, &error
);
2822 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
2823 context
->managed_code
= 1;
2824 if (*mono_thread_interruption_request_flag ())
2825 mono_thread_interruption_checkpoint ();
2829 child_frame
.retval
= &retval
;
2833 g_assert (csig
->call_convention
== MONO_CALL_DEFAULT
);
2835 ves_exec_method_with_context (&child_frame
, context
);
2837 context
->current_frame
= frame
;
2839 if (child_frame
.ex
) {
2841 * An exception occurred, need to run finally, fault and catch handlers..
2843 frame
->ex
= child_frame
.ex
;
2844 goto handle_finally
;
2847 * a constructor returns void, but we need to return the object we created
2850 if (newobj_class
->valuetype
&& !newobj_class
->enumtype
) {
2851 *sp
= valuetype_this
;
2852 } else if (newobj_class
== mono_defaults
.string_class
) {
2860 MINT_IN_CASE(MINT_CASTCLASS
)
2861 c
= rtm
->data_items
[*(guint16
*)(ip
+ 1)];
2862 if ((o
= sp
[-1].data
.p
)) {
2863 MonoObject
*isinst_obj
= mono_object_isinst_checked (o
, c
, &error
);
2864 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
2866 THROW_EX (mono_get_exception_invalid_cast (), ip
);
2870 MINT_IN_CASE(MINT_ISINST
)
2871 c
= rtm
->data_items
[*(guint16
*)(ip
+ 1)];
2872 if ((o
= sp
[-1].data
.p
)) {
2873 MonoObject
*isinst_obj
= mono_object_isinst_checked (o
, c
, &error
);
2874 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
2876 sp
[-1].data
.p
= NULL
;
2880 MINT_IN_CASE(MINT_CONV_R_UN_I4
)
2881 sp
[-1].data
.f
= (double)(guint32
)sp
[-1].data
.i
;
2884 MINT_IN_CASE(MINT_CONV_R_UN_I8
)
2885 sp
[-1].data
.f
= (double)(guint64
)sp
[-1].data
.l
;
2888 MINT_IN_CASE(MINT_UNBOX
)
2889 c
= rtm
->data_items
[*(guint16
*)(ip
+ 1)];
2893 THROW_EX (mono_get_exception_null_reference (), ip
);
2895 MonoObject
*isinst_obj
= mono_object_isinst_checked (o
, c
, &error
);
2896 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
2897 if (!(isinst_obj
|| ((o
->vtable
->klass
->rank
== 0) && (o
->vtable
->klass
->element_class
== c
->element_class
))))
2898 THROW_EX (mono_get_exception_invalid_cast (), ip
);
2900 sp
[-1].data
.p
= mono_object_unbox (o
);
2903 MINT_IN_CASE(MINT_THROW
)
2905 frame
->ex_handler
= NULL
;
2907 sp
->data
.p
= mono_get_exception_null_reference ();
2908 THROW_EX ((MonoException
*)sp
->data
.p
, ip
);
2910 MINT_IN_CASE(MINT_LDFLDA_UNSAFE
)
2912 sp
[-1].data
.p
= (char *)o
+ * (guint16
*)(ip
+ 1);
2915 MINT_IN_CASE(MINT_LDFLDA
)
2918 THROW_EX (mono_get_exception_null_reference (), ip
);
2919 sp
[-1].data
.p
= (char *)o
+ * (guint16
*)(ip
+ 1);
2922 MINT_IN_CASE(MINT_CKNULL
)
2925 THROW_EX (mono_get_exception_null_reference (), ip
);
2929 #define LDFLD(datamem, fieldtype) \
2930 o = sp [-1].data.p; \
2932 THROW_EX (mono_get_exception_null_reference (), ip); \
2933 sp[-1].data.datamem = * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) ; \
2936 MINT_IN_CASE(MINT_LDFLD_I1
) LDFLD(i
, gint8
); MINT_IN_BREAK
;
2937 MINT_IN_CASE(MINT_LDFLD_U1
) LDFLD(i
, guint8
); MINT_IN_BREAK
;
2938 MINT_IN_CASE(MINT_LDFLD_I2
) LDFLD(i
, gint16
); MINT_IN_BREAK
;
2939 MINT_IN_CASE(MINT_LDFLD_U2
) LDFLD(i
, guint16
); MINT_IN_BREAK
;
2940 MINT_IN_CASE(MINT_LDFLD_I4
) LDFLD(i
, gint32
); MINT_IN_BREAK
;
2941 MINT_IN_CASE(MINT_LDFLD_I8
) LDFLD(l
, gint64
); MINT_IN_BREAK
;
2942 MINT_IN_CASE(MINT_LDFLD_R4
) LDFLD(f
, float); MINT_IN_BREAK
;
2943 MINT_IN_CASE(MINT_LDFLD_R8
) LDFLD(f
, double); MINT_IN_BREAK
;
2944 MINT_IN_CASE(MINT_LDFLD_O
) LDFLD(p
, gpointer
); MINT_IN_BREAK
;
2945 MINT_IN_CASE(MINT_LDFLD_P
) LDFLD(p
, gpointer
); MINT_IN_BREAK
;
2947 MINT_IN_CASE(MINT_LDFLD_VT
)
2950 THROW_EX (mono_get_exception_null_reference (), ip
);
2951 i32
= READ32(ip
+ 2);
2952 sp
[-1].data
.p
= vt_sp
;
2953 memcpy(sp
[-1].data
.p
, (char *)o
+ * (guint16
*)(ip
+ 1), i32
);
2954 vt_sp
+= (i32
+ 7) & ~7;
2958 MINT_IN_CASE(MINT_LDRMFLD
) {
2960 MonoClassField
*field
;
2965 THROW_EX (mono_get_exception_null_reference (), ip
);
2966 field
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
2968 if (mono_object_is_transparent_proxy (o
)) {
2969 MonoClass
*klass
= ((MonoTransparentProxy
*)o
)->remote_class
->proxy_class
;
2971 addr
= mono_load_remote_field_checked (o
, klass
, field
, &tmp
, &error
);
2972 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
2974 addr
= (char*)o
+ field
->offset
;
2977 stackval_from_data (field
->type
, &sp
[-1], addr
, FALSE
);
2981 MINT_IN_CASE(MINT_LDRMFLD_VT
) {
2982 MonoClassField
*field
;
2988 THROW_EX (mono_get_exception_null_reference (), ip
);
2989 field
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
2990 i32
= READ32(ip
+ 2);
2992 if (mono_object_is_transparent_proxy (o
)) {
2993 MonoClass
*klass
= ((MonoTransparentProxy
*)o
)->remote_class
->proxy_class
;
2994 addr
= mono_load_remote_field_checked (o
, klass
, field
, &tmp
, &error
);
2995 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
2997 addr
= (char*)o
+ field
->offset
;
3000 sp
[-1].data
.p
= vt_sp
;
3001 memcpy(sp
[-1].data
.p
, (char *)o
+ * (guint16
*)(ip
+ 1), i32
);
3002 vt_sp
+= (i32
+ 7) & ~7;
3003 memcpy(sp
[-1].data
.p
, addr
, i32
);
3007 #define STFLD(datamem, fieldtype) \
3008 o = sp [-2].data.p; \
3010 THROW_EX (mono_get_exception_null_reference (), ip); \
3012 * (fieldtype *)((char *)o + * (guint16 *)(ip + 1)) = sp[1].data.datamem; \
3015 MINT_IN_CASE(MINT_STFLD_I1
) STFLD(i
, gint8
); MINT_IN_BREAK
;
3016 MINT_IN_CASE(MINT_STFLD_U1
) STFLD(i
, guint8
); MINT_IN_BREAK
;
3017 MINT_IN_CASE(MINT_STFLD_I2
) STFLD(i
, gint16
); MINT_IN_BREAK
;
3018 MINT_IN_CASE(MINT_STFLD_U2
) STFLD(i
, guint16
); MINT_IN_BREAK
;
3019 MINT_IN_CASE(MINT_STFLD_I4
) STFLD(i
, gint32
); MINT_IN_BREAK
;
3020 MINT_IN_CASE(MINT_STFLD_I8
) STFLD(l
, gint64
); MINT_IN_BREAK
;
3021 MINT_IN_CASE(MINT_STFLD_R4
) STFLD(f
, float); MINT_IN_BREAK
;
3022 MINT_IN_CASE(MINT_STFLD_R8
) STFLD(f
, double); MINT_IN_BREAK
;
3023 MINT_IN_CASE(MINT_STFLD_O
) STFLD(p
, gpointer
); MINT_IN_BREAK
;
3024 MINT_IN_CASE(MINT_STFLD_P
) STFLD(p
, gpointer
); MINT_IN_BREAK
;
3026 MINT_IN_CASE(MINT_STFLD_VT
)
3029 THROW_EX (mono_get_exception_null_reference (), ip
);
3030 i32
= READ32(ip
+ 2);
3032 memcpy((char *)o
+ * (guint16
*)(ip
+ 1), sp
[1].data
.p
, i32
);
3033 vt_sp
-= (i32
+ 7) & ~7;
3037 MINT_IN_CASE(MINT_STRMFLD
) {
3038 MonoClassField
*field
;
3042 THROW_EX (mono_get_exception_null_reference (), ip
);
3044 field
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
3047 if (mono_object_is_transparent_proxy (o
)) {
3048 MonoClass
*klass
= ((MonoTransparentProxy
*)o
)->remote_class
->proxy_class
;
3049 mono_store_remote_field_checked (o
, klass
, field
, &sp
[-1].data
, &error
);
3050 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
3052 stackval_to_data (field
->type
, &sp
[-1], (char*)o
+ field
->offset
, FALSE
);
3057 MINT_IN_CASE(MINT_STRMFLD_VT
) {
3058 MonoClassField
*field
;
3062 THROW_EX (mono_get_exception_null_reference (), ip
);
3063 field
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
3064 i32
= READ32(ip
+ 2);
3067 if (mono_object_is_transparent_proxy (o
)) {
3068 MonoClass
*klass
= ((MonoTransparentProxy
*)o
)->remote_class
->proxy_class
;
3069 mono_store_remote_field_checked (o
, klass
, field
, &sp
[-1].data
, &error
);
3070 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
3072 memcpy((char*)o
+ field
->offset
, sp
[-1].data
.p
, i32
);
3075 vt_sp
-= (i32
+ 7) & ~7;
3078 MINT_IN_CASE(MINT_LDSFLDA
) {
3079 MonoClassField
*field
= rtm
->data_items
[*(guint16
*)(ip
+ 1)];
3080 sp
->data
.p
= mono_class_static_field_address (context
->domain
, field
);
3085 MINT_IN_CASE(MINT_LDSFLD
) {
3086 MonoClassField
*field
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
3087 gpointer addr
= mono_class_static_field_address (context
->domain
, field
);
3088 stackval_from_data (field
->type
, sp
, addr
, FALSE
);
3093 MINT_IN_CASE(MINT_LDSFLD_VT
) {
3094 MonoClassField
*field
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
3095 gpointer addr
= mono_class_static_field_address (context
->domain
, field
);
3096 int size
= READ32 (ip
+ 2);
3100 vt_sp
+= (size
+ 7) & ~7;
3101 stackval_from_data (field
->type
, sp
, addr
, FALSE
);
3105 MINT_IN_CASE(MINT_STSFLD
) {
3106 MonoClassField
*field
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
3107 gpointer addr
= mono_class_static_field_address (context
->domain
, field
);
3110 stackval_to_data (field
->type
, sp
, addr
, FALSE
);
3113 MINT_IN_CASE(MINT_STSFLD_VT
) {
3114 MonoClassField
*field
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
3115 gpointer addr
= mono_class_static_field_address (context
->domain
, field
);
3116 int size
= READ32 (ip
+ 2);
3120 stackval_to_data (field
->type
, sp
, addr
, FALSE
);
3121 vt_sp
-= (size
+ 7) & ~7;
3124 MINT_IN_CASE(MINT_STOBJ_VT
) {
3126 c
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
3128 size
= mono_class_value_size (c
, NULL
);
3129 memcpy(sp
[-2].data
.p
, sp
[-1].data
.p
, size
);
3130 vt_sp
-= (size
+ 7) & ~7;
3134 MINT_IN_CASE(MINT_STOBJ
) {
3136 c
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
3138 size
= mono_class_value_size (c
, NULL
);
3139 memcpy(sp
[-2].data
.p
, &sp
[-1].data
, size
);
3143 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_R8
)
3144 if (sp
[-1].data
.f
< 0 || sp
[-1].data
.f
> MYGUINT32_MAX
)
3145 THROW_EX (mono_get_exception_overflow (), ip
);
3146 sp
[-1].data
.i
= (guint32
)sp
[-1].data
.f
;
3149 MINT_IN_CASE(MINT_CONV_OVF_U8_I4
)
3150 if (sp
[-1].data
.i
< 0)
3151 THROW_EX (mono_get_exception_overflow (), ip
);
3152 sp
[-1].data
.l
= sp
[-1].data
.i
;
3155 MINT_IN_CASE(MINT_CONV_OVF_U8_I8
)
3156 if (sp
[-1].data
.l
< 0)
3157 THROW_EX (mono_get_exception_overflow (), ip
);
3160 MINT_IN_CASE(MINT_CONV_OVF_I8_U8
)
3161 if ((guint64
) sp
[-1].data
.l
> MYGINT64_MAX
)
3162 THROW_EX (mono_get_exception_overflow (), ip
);
3165 MINT_IN_CASE(MINT_CONV_OVF_U8_R8
)
3166 MINT_IN_CASE(MINT_CONV_OVF_I8_UN_R8
)
3167 if (sp
[-1].data
.f
< 0 || sp
[-1].data
.f
> MYGINT64_MAX
)
3168 THROW_EX (mono_get_exception_overflow (), ip
);
3169 sp
[-1].data
.l
= (guint64
)sp
[-1].data
.f
;
3172 MINT_IN_CASE(MINT_CONV_OVF_I8_R8
)
3173 if (sp
[-1].data
.f
< MYGINT64_MIN
|| sp
[-1].data
.f
> MYGINT64_MAX
)
3174 THROW_EX (mono_get_exception_overflow (), ip
);
3175 sp
[-1].data
.l
= (gint64
)sp
[-1].data
.f
;
3178 MINT_IN_CASE(MINT_CONV_OVF_I4_UN_I8
)
3179 if ((mono_u
)sp
[-1].data
.l
> MYGUINT32_MAX
)
3180 THROW_EX (mono_get_exception_overflow (), ip
);
3181 sp
[-1].data
.i
= (mono_u
)sp
[-1].data
.l
;
3184 MINT_IN_CASE(MINT_BOX
) {
3185 c
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
3186 guint16 offset
= * (guint16
*)(ip
+ 2);
3188 if (c
->byval_arg
.type
== MONO_TYPE_VALUETYPE
&& !c
->enumtype
) {
3189 int size
= mono_class_value_size (c
, NULL
);
3190 sp
[-1 - offset
].data
.p
= mono_value_box_checked (context
->domain
, c
, sp
[-1 - offset
].data
.p
, &error
);
3191 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
3192 size
= (size
+ 7) & ~7;
3195 stackval_to_data (&c
->byval_arg
, &sp
[-1 - offset
], (char *) &sp
[-1 - offset
], FALSE
);
3196 sp
[-1 - offset
].data
.p
= mono_value_box_checked (context
->domain
, c
, &sp
[-1 - offset
], &error
);
3197 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
3202 MINT_IN_CASE(MINT_NEWARR
)
3203 sp
[-1].data
.p
= (MonoObject
*) mono_array_new_checked (context
->domain
, rtm
->data_items
[*(guint16
*)(ip
+ 1)], sp
[-1].data
.i
, &error
);
3204 if (!mono_error_ok (&error
)) {
3205 THROW_EX (mono_error_convert_to_exception (&error
), ip
);
3207 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
3209 /*if (profiling_classes) {
3210 guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, o->vtable->klass));
3212 g_hash_table_insert (profiling_classes, o->vtable->klass, GUINT_TO_POINTER (count));
3216 MINT_IN_CASE(MINT_LDLEN
)
3219 THROW_EX (mono_get_exception_null_reference (), ip
);
3220 sp
[-1].data
.nati
= mono_array_length ((MonoArray
*)o
);
3223 MINT_IN_CASE(MINT_GETCHR
) {
3227 THROW_EX (mono_get_exception_null_reference (), ip
);
3228 i32
= sp
[-1].data
.i
;
3229 if (i32
< 0 || i32
>= mono_string_length (s
))
3230 THROW_EX (mono_get_exception_index_out_of_range (), ip
);
3232 sp
[-1].data
.i
= mono_string_chars(s
)[i32
];
3236 MINT_IN_CASE(MINT_STRLEN
)
3238 sp
[-1].data
.i
= mono_string_length ((MonoString
*)sp
[-1].data
.p
);
3240 MINT_IN_CASE(MINT_ARRAY_RANK
)
3243 THROW_EX (mono_get_exception_null_reference (), ip
);
3244 sp
[-1].data
.i
= mono_object_class (sp
[-1].data
.p
)->rank
;
3247 MINT_IN_CASE(MINT_LDELEMA
)
3248 MINT_IN_CASE(MINT_LDELEMA_TC
) {
3249 gboolean needs_typecheck
= *ip
== MINT_LDELEMA_TC
;
3251 MonoClass
*klass
= rtm
->data_items
[*(guint16
*) (ip
+ 1)];
3252 guint16 numargs
= *(guint16
*) (ip
+ 2);
3257 sp
->data
.p
= ves_array_element_address (frame
, klass
, (MonoArray
*) o
, &sp
[1], needs_typecheck
);
3259 THROW_EX (frame
->ex
, ip
);
3264 MINT_IN_CASE(MINT_LDELEM_I1
) /* fall through */
3265 MINT_IN_CASE(MINT_LDELEM_U1
) /* fall through */
3266 MINT_IN_CASE(MINT_LDELEM_I2
) /* fall through */
3267 MINT_IN_CASE(MINT_LDELEM_U2
) /* fall through */
3268 MINT_IN_CASE(MINT_LDELEM_I4
) /* fall through */
3269 MINT_IN_CASE(MINT_LDELEM_U4
) /* fall through */
3270 MINT_IN_CASE(MINT_LDELEM_I8
) /* fall through */
3271 MINT_IN_CASE(MINT_LDELEM_I
) /* fall through */
3272 MINT_IN_CASE(MINT_LDELEM_R4
) /* fall through */
3273 MINT_IN_CASE(MINT_LDELEM_R8
) /* fall through */
3274 MINT_IN_CASE(MINT_LDELEM_REF
) /* fall through */
3275 MINT_IN_CASE(MINT_LDELEM_VT
) {
3283 THROW_EX (mono_get_exception_null_reference (), ip
);
3285 aindex
= sp
[1].data
.i
;
3286 if (aindex
>= mono_array_length (o
))
3287 THROW_EX (mono_get_exception_index_out_of_range (), ip
);
3290 * FIXME: throw mono_get_exception_array_type_mismatch () if needed
3293 case MINT_LDELEM_I1
:
3294 sp
[0].data
.i
= mono_array_get (o
, gint8
, aindex
);
3296 case MINT_LDELEM_U1
:
3297 sp
[0].data
.i
= mono_array_get (o
, guint8
, aindex
);
3299 case MINT_LDELEM_I2
:
3300 sp
[0].data
.i
= mono_array_get (o
, gint16
, aindex
);
3302 case MINT_LDELEM_U2
:
3303 sp
[0].data
.i
= mono_array_get (o
, guint16
, aindex
);
3306 sp
[0].data
.nati
= mono_array_get (o
, mono_i
, aindex
);
3308 case MINT_LDELEM_I4
:
3309 sp
[0].data
.i
= mono_array_get (o
, gint32
, aindex
);
3311 case MINT_LDELEM_U4
:
3312 sp
[0].data
.i
= mono_array_get (o
, guint32
, aindex
);
3314 case MINT_LDELEM_I8
:
3315 sp
[0].data
.l
= mono_array_get (o
, guint64
, aindex
);
3317 case MINT_LDELEM_R4
:
3318 sp
[0].data
.f
= mono_array_get (o
, float, aindex
);
3320 case MINT_LDELEM_R8
:
3321 sp
[0].data
.f
= mono_array_get (o
, double, aindex
);
3323 case MINT_LDELEM_REF
:
3324 sp
[0].data
.p
= mono_array_get (o
, gpointer
, aindex
);
3326 case MINT_LDELEM_VT
: {
3327 MonoClass
*klass_vt
= rtm
->data_items
[*(guint16
*) (ip
+ 1)];
3328 i32
= READ32 (ip
+ 2);
3329 char *src_addr
= mono_array_addr_with_size ((MonoArray
*) o
, i32
, aindex
);
3330 sp
[0].data
.vt
= vt_sp
;
3331 stackval_from_data (&klass_vt
->byval_arg
, sp
, src_addr
, FALSE
);
3332 vt_sp
+= (i32
+ 7) & ~7;
3344 MINT_IN_CASE(MINT_STELEM_I
) /* fall through */
3345 MINT_IN_CASE(MINT_STELEM_I1
) /* fall through */
3346 MINT_IN_CASE(MINT_STELEM_U1
) /* fall through */
3347 MINT_IN_CASE(MINT_STELEM_I2
) /* fall through */
3348 MINT_IN_CASE(MINT_STELEM_I4
) /* fall through */
3349 MINT_IN_CASE(MINT_STELEM_I8
) /* fall through */
3350 MINT_IN_CASE(MINT_STELEM_R4
) /* fall through */
3351 MINT_IN_CASE(MINT_STELEM_R8
) /* fall through */
3352 MINT_IN_CASE(MINT_STELEM_REF
) /* fall through */
3353 MINT_IN_CASE(MINT_STELEM_VT
) {
3360 THROW_EX (mono_get_exception_null_reference (), ip
);
3362 aindex
= sp
[1].data
.i
;
3363 if (aindex
>= mono_array_length ((MonoArray
*)o
))
3364 THROW_EX (mono_get_exception_index_out_of_range (), ip
);
3368 mono_array_set ((MonoArray
*)o
, mono_i
, aindex
, sp
[2].data
.nati
);
3370 case MINT_STELEM_I1
:
3371 mono_array_set ((MonoArray
*)o
, gint8
, aindex
, sp
[2].data
.i
);
3373 case MINT_STELEM_U1
:
3374 mono_array_set ((MonoArray
*) o
, guint8
, aindex
, sp
[2].data
.i
);
3376 case MINT_STELEM_I2
:
3377 mono_array_set ((MonoArray
*)o
, gint16
, aindex
, sp
[2].data
.i
);
3379 case MINT_STELEM_I4
:
3380 mono_array_set ((MonoArray
*)o
, gint32
, aindex
, sp
[2].data
.i
);
3382 case MINT_STELEM_I8
:
3383 mono_array_set ((MonoArray
*)o
, gint64
, aindex
, sp
[2].data
.l
);
3385 case MINT_STELEM_R4
:
3386 mono_array_set ((MonoArray
*)o
, float, aindex
, sp
[2].data
.f
);
3388 case MINT_STELEM_R8
:
3389 mono_array_set ((MonoArray
*)o
, double, aindex
, sp
[2].data
.f
);
3391 case MINT_STELEM_REF
: {
3392 MonoObject
*isinst_obj
= mono_object_isinst_checked (sp
[2].data
.p
, mono_object_class (o
)->element_class
, &error
);
3393 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
3394 if (sp
[2].data
.p
&& !isinst_obj
)
3395 THROW_EX (mono_get_exception_array_type_mismatch (), ip
);
3396 mono_array_set ((MonoArray
*)o
, gpointer
, aindex
, sp
[2].data
.p
);
3399 case MINT_STELEM_VT
: {
3400 MonoClass
*klass_vt
= rtm
->data_items
[*(guint16
*) (ip
+ 1)];
3401 i32
= READ32 (ip
+ 2);
3402 char *dst_addr
= mono_array_addr_with_size ((MonoArray
*) o
, i32
, aindex
);
3404 stackval_to_data (&klass_vt
->byval_arg
, &sp
[2], dst_addr
, FALSE
);
3405 vt_sp
-= (i32
+ 7) & ~7;
3416 MINT_IN_CASE(MINT_CONV_OVF_I4_U4
)
3417 if (sp
[-1].data
.i
< 0)
3418 THROW_EX (mono_get_exception_overflow (), ip
);
3421 MINT_IN_CASE(MINT_CONV_OVF_I4_I8
)
3422 if (sp
[-1].data
.l
< MYGINT32_MIN
|| sp
[-1].data
.l
> MYGINT32_MAX
)
3423 THROW_EX (mono_get_exception_overflow (), ip
);
3424 sp
[-1].data
.i
= (gint32
) sp
[-1].data
.l
;
3427 MINT_IN_CASE(MINT_CONV_OVF_I4_U8
)
3428 if (sp
[-1].data
.l
< 0 || sp
[-1].data
.l
> MYGINT32_MAX
)
3429 THROW_EX (mono_get_exception_overflow (), ip
);
3430 sp
[-1].data
.i
= (gint32
) sp
[-1].data
.l
;
3433 MINT_IN_CASE(MINT_CONV_OVF_I4_R8
)
3434 if (sp
[-1].data
.f
< MYGINT32_MIN
|| sp
[-1].data
.f
> MYGINT32_MAX
)
3435 THROW_EX (mono_get_exception_overflow (), ip
);
3436 sp
[-1].data
.i
= (gint32
) sp
[-1].data
.f
;
3439 MINT_IN_CASE(MINT_CONV_OVF_U4_I4
)
3440 if (sp
[-1].data
.i
< 0)
3441 THROW_EX (mono_get_exception_overflow (), ip
);
3444 MINT_IN_CASE(MINT_CONV_OVF_U4_I8
)
3445 if (sp
[-1].data
.l
< 0 || sp
[-1].data
.l
> MYGUINT32_MAX
)
3446 THROW_EX (mono_get_exception_overflow (), ip
);
3447 sp
[-1].data
.i
= (guint32
) sp
[-1].data
.l
;
3450 MINT_IN_CASE(MINT_CONV_OVF_U4_R8
)
3451 if (sp
[-1].data
.f
< 0 || sp
[-1].data
.f
> MYGUINT32_MAX
)
3452 THROW_EX (mono_get_exception_overflow (), ip
);
3453 sp
[-1].data
.i
= (guint32
) sp
[-1].data
.f
;
3456 MINT_IN_CASE(MINT_CONV_OVF_I2_I4
)
3457 if (sp
[-1].data
.i
< -32768 || sp
[-1].data
.i
> 32767)
3458 THROW_EX (mono_get_exception_overflow (), ip
);
3461 MINT_IN_CASE(MINT_CONV_OVF_I2_I8
)
3462 if (sp
[-1].data
.l
< -32768 || sp
[-1].data
.l
> 32767)
3463 THROW_EX (mono_get_exception_overflow (), ip
);
3464 sp
[-1].data
.i
= (gint16
) sp
[-1].data
.l
;
3467 MINT_IN_CASE(MINT_CONV_OVF_I2_R8
)
3468 if (sp
[-1].data
.f
< -32768 || sp
[-1].data
.f
> 32767)
3469 THROW_EX (mono_get_exception_overflow (), ip
);
3470 sp
[-1].data
.i
= (gint16
) sp
[-1].data
.f
;
3473 MINT_IN_CASE(MINT_CONV_OVF_U2_I4
)
3474 if (sp
[-1].data
.i
< 0 || sp
[-1].data
.i
> 65535)
3475 THROW_EX (mono_get_exception_overflow (), ip
);
3478 MINT_IN_CASE(MINT_CONV_OVF_U2_I8
)
3479 if (sp
[-1].data
.l
< 0 || sp
[-1].data
.l
> 65535)
3480 THROW_EX (mono_get_exception_overflow (), ip
);
3481 sp
[-1].data
.i
= (guint16
) sp
[-1].data
.l
;
3484 MINT_IN_CASE(MINT_CONV_OVF_U2_R8
)
3485 if (sp
[-1].data
.f
< 0 || sp
[-1].data
.f
> 65535)
3486 THROW_EX (mono_get_exception_overflow (), ip
);
3487 sp
[-1].data
.i
= (guint16
) sp
[-1].data
.f
;
3490 MINT_IN_CASE(MINT_CONV_OVF_I1_I4
)
3491 if (sp
[-1].data
.i
< -128 || sp
[-1].data
.i
> 127)
3492 THROW_EX (mono_get_exception_overflow (), ip
);
3495 MINT_IN_CASE(MINT_CONV_OVF_I1_I8
)
3496 if (sp
[-1].data
.l
< -128 || sp
[-1].data
.l
> 127)
3497 THROW_EX (mono_get_exception_overflow (), ip
);
3498 sp
[-1].data
.i
= (gint8
) sp
[-1].data
.l
;
3501 MINT_IN_CASE(MINT_CONV_OVF_I1_R8
)
3502 if (sp
[-1].data
.f
< -128 || sp
[-1].data
.f
> 127)
3503 THROW_EX (mono_get_exception_overflow (), ip
);
3504 sp
[-1].data
.i
= (gint8
) sp
[-1].data
.f
;
3507 MINT_IN_CASE(MINT_CONV_OVF_U1_I4
)
3508 if (sp
[-1].data
.i
< 0 || sp
[-1].data
.i
> 255)
3509 THROW_EX (mono_get_exception_overflow (), ip
);
3512 MINT_IN_CASE(MINT_CONV_OVF_U1_I8
)
3513 if (sp
[-1].data
.l
< 0 || sp
[-1].data
.l
> 255)
3514 THROW_EX (mono_get_exception_overflow (), ip
);
3515 sp
[-1].data
.i
= (guint8
) sp
[-1].data
.l
;
3518 MINT_IN_CASE(MINT_CONV_OVF_U1_R8
)
3519 if (sp
[-1].data
.f
< 0 || sp
[-1].data
.f
> 255)
3520 THROW_EX (mono_get_exception_overflow (), ip
);
3521 sp
[-1].data
.i
= (guint8
) sp
[-1].data
.f
;
3525 MINT_IN_CASE(MINT_LDELEM
)
3526 MINT_IN_CASE(MINT_STELEM
)
3527 MINT_IN_CASE(MINT_UNBOX_ANY
)
3529 MINT_IN_CASE(MINT_REFANYVAL
) ves_abort(); MINT_IN_BREAK
;
3531 MINT_IN_CASE(MINT_CKFINITE
)
3532 if (!isfinite(sp
[-1].data
.f
))
3533 THROW_EX (mono_get_exception_arithmetic (), ip
);
3537 MINT_IN_CASE(MINT_MKREFANY
) ves_abort(); MINT_IN_BREAK
;
3539 MINT_IN_CASE(MINT_LDTOKEN
)
3542 * (gpointer
*)sp
->data
.p
= rtm
->data_items
[*(guint16
*)(ip
+ 1)];
3546 MINT_IN_CASE(MINT_ADD_OVF_I4
)
3547 if (CHECK_ADD_OVERFLOW (sp
[-2].data
.i
, sp
[-1].data
.i
))
3548 THROW_EX (mono_get_exception_overflow (), ip
);
3551 MINT_IN_CASE(MINT_ADD_OVF_I8
)
3552 if (CHECK_ADD_OVERFLOW64 (sp
[-2].data
.l
, sp
[-1].data
.l
))
3553 THROW_EX (mono_get_exception_overflow (), ip
);
3556 MINT_IN_CASE(MINT_ADD_OVF_UN_I4
)
3557 if (CHECK_ADD_OVERFLOW_UN (sp
[-2].data
.i
, sp
[-1].data
.i
))
3558 THROW_EX (mono_get_exception_overflow (), ip
);
3559 BINOP_CAST(i
, +, guint32
);
3561 MINT_IN_CASE(MINT_ADD_OVF_UN_I8
)
3562 if (CHECK_ADD_OVERFLOW64_UN (sp
[-2].data
.l
, sp
[-1].data
.l
))
3563 THROW_EX (mono_get_exception_overflow (), ip
);
3564 BINOP_CAST(l
, +, guint64
);
3566 MINT_IN_CASE(MINT_MUL_OVF_I4
)
3567 if (CHECK_MUL_OVERFLOW (sp
[-2].data
.i
, sp
[-1].data
.i
))
3568 THROW_EX (mono_get_exception_overflow (), ip
);
3571 MINT_IN_CASE(MINT_MUL_OVF_I8
)
3572 if (CHECK_MUL_OVERFLOW64 (sp
[-2].data
.l
, sp
[-1].data
.l
))
3573 THROW_EX (mono_get_exception_overflow (), ip
);
3576 MINT_IN_CASE(MINT_MUL_OVF_UN_I4
)
3577 if (CHECK_MUL_OVERFLOW_UN (sp
[-2].data
.i
, sp
[-1].data
.i
))
3578 THROW_EX (mono_get_exception_overflow (), ip
);
3579 BINOP_CAST(i
, *, guint32
);
3581 MINT_IN_CASE(MINT_MUL_OVF_UN_I8
)
3582 if (CHECK_MUL_OVERFLOW64_UN (sp
[-2].data
.l
, sp
[-1].data
.l
))
3583 THROW_EX (mono_get_exception_overflow (), ip
);
3584 BINOP_CAST(l
, *, guint64
);
3586 MINT_IN_CASE(MINT_SUB_OVF_I4
)
3587 if (CHECK_SUB_OVERFLOW (sp
[-2].data
.i
, sp
[-1].data
.i
))
3588 THROW_EX (mono_get_exception_overflow (), ip
);
3591 MINT_IN_CASE(MINT_SUB_OVF_I8
)
3592 if (CHECK_SUB_OVERFLOW64 (sp
[-2].data
.l
, sp
[-1].data
.l
))
3593 THROW_EX (mono_get_exception_overflow (), ip
);
3596 MINT_IN_CASE(MINT_SUB_OVF_UN_I4
)
3597 if (CHECK_SUB_OVERFLOW_UN (sp
[-2].data
.i
, sp
[-1].data
.i
))
3598 THROW_EX (mono_get_exception_overflow (), ip
);
3599 BINOP_CAST(i
, -, guint32
);
3601 MINT_IN_CASE(MINT_SUB_OVF_UN_I8
)
3602 if (CHECK_SUB_OVERFLOW64_UN (sp
[-2].data
.l
, sp
[-1].data
.l
))
3603 THROW_EX (mono_get_exception_overflow (), ip
);
3604 BINOP_CAST(l
, -, guint64
);
3606 MINT_IN_CASE(MINT_ENDFINALLY
)
3608 ip
= finally_ips
->data
;
3609 finally_ips
= g_slist_remove (finally_ips
, ip
);
3616 MINT_IN_CASE(MINT_LEAVE
) /* Fall through */
3617 MINT_IN_CASE(MINT_LEAVE_S
)
3618 while (sp
> frame
->stack
) {
3622 if (*ip
== MINT_LEAVE_S
) {
3623 ip
+= (short) *(ip
+ 1);
3625 ip
+= (gint32
) READ32 (ip
+ 1);
3628 if (frame
->ex_handler
!= NULL
&& MONO_OFFSET_IN_HANDLER(frame
->ex_handler
, frame
->ip
- rtm
->code
)) {
3629 frame
->ex_handler
= NULL
;
3632 goto handle_finally
;
3634 MINT_IN_CASE(MINT_ICALL_V_V
)
3635 MINT_IN_CASE(MINT_ICALL_V_P
)
3636 MINT_IN_CASE(MINT_ICALL_P_V
)
3637 MINT_IN_CASE(MINT_ICALL_P_P
)
3638 MINT_IN_CASE(MINT_ICALL_PP_V
)
3639 MINT_IN_CASE(MINT_ICALL_PI_V
)
3640 MINT_IN_CASE(MINT_ICALL_PP_P
)
3641 MINT_IN_CASE(MINT_ICALL_PI_P
)
3642 MINT_IN_CASE(MINT_ICALL_PPP_V
)
3643 MINT_IN_CASE(MINT_ICALL_PPI_V
)
3644 sp
= do_icall (context
, *ip
, sp
, rtm
->data_items
[*(guint16
*)(ip
+ 1)]);
3645 if (frame
->ex
!= NULL
)
3646 goto handle_exception
;
3649 MINT_IN_CASE(MINT_MONO_LDPTR
)
3650 sp
->data
.p
= rtm
->data_items
[*(guint16
*)(ip
+ 1)];
3654 MINT_IN_CASE(MINT_MONO_NEWOBJ
)
3655 sp
->data
.p
= mono_object_new_checked (context
->domain
, rtm
->data_items
[*(guint16
*)(ip
+ 1)], &error
);
3656 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
3660 MINT_IN_CASE(MINT_MONO_FREE
)
3663 g_error ("that doesn't seem right");
3664 g_free (sp
->data
.p
);
3666 MINT_IN_CASE(MINT_MONO_RETOBJ
)
3669 stackval_from_data (mono_method_signature (frame
->runtime_method
->method
)->ret
, frame
->retval
, sp
->data
.p
,
3670 mono_method_signature (frame
->runtime_method
->method
)->pinvoke
);
3671 if (sp
> frame
->stack
)
3672 g_warning ("retobj: more values on stack: %d", sp
-frame
->stack
);
3675 #define RELOP(datamem, op) \
3677 sp [-1].data.i = sp [-1].data.datamem op sp [0].data.datamem; \
3679 MINT_IN_CASE(MINT_CEQ_I4
)
3682 MINT_IN_CASE(MINT_CEQ0_I4
)
3683 sp
[-1].data
.i
= (sp
[-1].data
.i
== 0);
3686 MINT_IN_CASE(MINT_CEQ_I8
)
3689 MINT_IN_CASE(MINT_CEQ_R8
)
3691 if (isunordered (sp
[-1].data
.f
, sp
[0].data
.f
))
3694 sp
[-1].data
.i
= sp
[-1].data
.f
== sp
[0].data
.f
;
3697 MINT_IN_CASE(MINT_CGT_I4
)
3700 MINT_IN_CASE(MINT_CGT_I8
)
3703 MINT_IN_CASE(MINT_CGT_R8
)
3705 if (isunordered (sp
[-1].data
.f
, sp
[0].data
.f
))
3708 sp
[-1].data
.i
= sp
[-1].data
.f
> sp
[0].data
.f
;
3712 #define RELOP_CAST(datamem, op, type) \
3714 sp [-1].data.i = (type)sp [-1].data.datamem op (type)sp [0].data.datamem; \
3717 MINT_IN_CASE(MINT_CGT_UN_I4
)
3718 RELOP_CAST(i
, >, guint32
);
3720 MINT_IN_CASE(MINT_CGT_UN_I8
)
3721 RELOP_CAST(l
, >, guint64
);
3723 MINT_IN_CASE(MINT_CGT_UN_R8
)
3725 if (isunordered (sp
[-1].data
.f
, sp
[0].data
.f
))
3728 sp
[-1].data
.i
= sp
[-1].data
.f
> sp
[0].data
.f
;
3731 MINT_IN_CASE(MINT_CLT_I4
)
3734 MINT_IN_CASE(MINT_CLT_I8
)
3737 MINT_IN_CASE(MINT_CLT_R8
)
3739 if (isunordered (sp
[-1].data
.f
, sp
[0].data
.f
))
3742 sp
[-1].data
.i
= sp
[-1].data
.f
< sp
[0].data
.f
;
3745 MINT_IN_CASE(MINT_CLT_UN_I4
)
3746 RELOP_CAST(i
, <, guint32
);
3748 MINT_IN_CASE(MINT_CLT_UN_I8
)
3749 RELOP_CAST(l
, <, guint64
);
3751 MINT_IN_CASE(MINT_CLT_UN_R8
)
3753 if (isunordered (sp
[-1].data
.f
, sp
[0].data
.f
))
3756 sp
[-1].data
.i
= sp
[-1].data
.f
< sp
[0].data
.f
;
3759 MINT_IN_CASE(MINT_LDFTN
) {
3760 sp
->data
.p
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
3765 MINT_IN_CASE(MINT_LDVIRTFTN
) {
3766 RuntimeMethod
*m
= rtm
->data_items
[* (guint16
*)(ip
+ 1)];
3770 THROW_EX (mono_get_exception_null_reference (), ip
- 2);
3772 sp
->data
.p
= get_virtual_method (context
->domain
, m
, sp
->data
.p
);
3777 MINT_IN_CASE(MINT_LDTHISA
)
3778 g_error ("should not happen");
3779 // sp->data.p = &frame->obj;
3784 #define LDARG(datamem, argtype) \
3785 sp->data.datamem = * (argtype *)(frame->args + * (guint16 *)(ip + 1)); \
3789 MINT_IN_CASE(MINT_LDARG_I1
) LDARG(i
, gint8
); MINT_IN_BREAK
;
3790 MINT_IN_CASE(MINT_LDARG_U1
) LDARG(i
, guint8
); MINT_IN_BREAK
;
3791 MINT_IN_CASE(MINT_LDARG_I2
) LDARG(i
, gint16
); MINT_IN_BREAK
;
3792 MINT_IN_CASE(MINT_LDARG_U2
) LDARG(i
, guint16
); MINT_IN_BREAK
;
3793 MINT_IN_CASE(MINT_LDARG_I4
) LDARG(i
, gint32
); MINT_IN_BREAK
;
3794 MINT_IN_CASE(MINT_LDARG_I8
) LDARG(l
, gint64
); MINT_IN_BREAK
;
3795 MINT_IN_CASE(MINT_LDARG_R4
) LDARG(f
, float); MINT_IN_BREAK
;
3796 MINT_IN_CASE(MINT_LDARG_R8
) LDARG(f
, double); MINT_IN_BREAK
;
3797 MINT_IN_CASE(MINT_LDARG_O
) LDARG(p
, gpointer
); MINT_IN_BREAK
;
3798 MINT_IN_CASE(MINT_LDARG_P
) LDARG(p
, gpointer
); MINT_IN_BREAK
;
3800 MINT_IN_CASE(MINT_LDARG_VT
)
3802 i32
= READ32(ip
+ 2);
3803 memcpy(sp
->data
.p
, frame
->args
+ * (guint16
*)(ip
+ 1), i32
);
3804 vt_sp
+= (i32
+ 7) & ~7;
3809 #define STARG(datamem, argtype) \
3811 * (argtype *)(frame->args + * (guint16 *)(ip + 1)) = sp->data.datamem; \
3814 MINT_IN_CASE(MINT_STARG_I1
) STARG(i
, gint8
); MINT_IN_BREAK
;
3815 MINT_IN_CASE(MINT_STARG_U1
) STARG(i
, guint8
); MINT_IN_BREAK
;
3816 MINT_IN_CASE(MINT_STARG_I2
) STARG(i
, gint16
); MINT_IN_BREAK
;
3817 MINT_IN_CASE(MINT_STARG_U2
) STARG(i
, guint16
); MINT_IN_BREAK
;
3818 MINT_IN_CASE(MINT_STARG_I4
) STARG(i
, gint32
); MINT_IN_BREAK
;
3819 MINT_IN_CASE(MINT_STARG_I8
) STARG(l
, gint64
); MINT_IN_BREAK
;
3820 MINT_IN_CASE(MINT_STARG_R4
) STARG(f
, float); MINT_IN_BREAK
;
3821 MINT_IN_CASE(MINT_STARG_R8
) STARG(f
, double); MINT_IN_BREAK
;
3822 MINT_IN_CASE(MINT_STARG_O
) STARG(p
, gpointer
); MINT_IN_BREAK
;
3823 MINT_IN_CASE(MINT_STARG_P
) STARG(p
, gpointer
); MINT_IN_BREAK
;
3825 MINT_IN_CASE(MINT_STARG_VT
)
3826 i32
= READ32(ip
+ 2);
3828 memcpy(frame
->args
+ * (guint16
*)(ip
+ 1), sp
->data
.p
, i32
);
3829 vt_sp
-= (i32
+ 7) & ~7;
3833 #define STINARG(datamem, argtype) \
3835 int n = * (guint16 *)(ip + 1); \
3836 * (argtype *)(frame->args + rtm->arg_offsets [n]) = frame->stack_args [n].data.datamem; \
3840 MINT_IN_CASE(MINT_STINARG_I1
) STINARG(i
, gint8
); MINT_IN_BREAK
;
3841 MINT_IN_CASE(MINT_STINARG_U1
) STINARG(i
, guint8
); MINT_IN_BREAK
;
3842 MINT_IN_CASE(MINT_STINARG_I2
) STINARG(i
, gint16
); MINT_IN_BREAK
;
3843 MINT_IN_CASE(MINT_STINARG_U2
) STINARG(i
, guint16
); MINT_IN_BREAK
;
3844 MINT_IN_CASE(MINT_STINARG_I4
) STINARG(i
, gint32
); MINT_IN_BREAK
;
3845 MINT_IN_CASE(MINT_STINARG_I8
) STINARG(l
, gint64
); MINT_IN_BREAK
;
3846 MINT_IN_CASE(MINT_STINARG_R4
) STINARG(f
, float); MINT_IN_BREAK
;
3847 MINT_IN_CASE(MINT_STINARG_R8
) STINARG(f
, double); MINT_IN_BREAK
;
3848 MINT_IN_CASE(MINT_STINARG_O
) STINARG(p
, gpointer
); MINT_IN_BREAK
;
3849 MINT_IN_CASE(MINT_STINARG_P
) STINARG(p
, gpointer
); MINT_IN_BREAK
;
3851 MINT_IN_CASE(MINT_STINARG_VT
) {
3852 int n
= * (guint16
*)(ip
+ 1);
3853 i32
= READ32(ip
+ 2);
3854 memcpy (frame
->args
+ rtm
->arg_offsets
[n
], frame
->stack_args
[n
].data
.p
, i32
);
3859 MINT_IN_CASE(MINT_LDARGA
)
3860 sp
->data
.p
= frame
->args
+ * (guint16
*)(ip
+ 1);
3865 #define LDLOC(datamem, argtype) \
3866 sp->data.datamem = * (argtype *)(locals + * (guint16 *)(ip + 1)); \
3870 MINT_IN_CASE(MINT_LDLOC_I1
) LDLOC(i
, gint8
); MINT_IN_BREAK
;
3871 MINT_IN_CASE(MINT_LDLOC_U1
) LDLOC(i
, guint8
); MINT_IN_BREAK
;
3872 MINT_IN_CASE(MINT_LDLOC_I2
) LDLOC(i
, gint16
); MINT_IN_BREAK
;
3873 MINT_IN_CASE(MINT_LDLOC_U2
) LDLOC(i
, guint16
); MINT_IN_BREAK
;
3874 MINT_IN_CASE(MINT_LDLOC_I4
) LDLOC(i
, gint32
); MINT_IN_BREAK
;
3875 MINT_IN_CASE(MINT_LDLOC_I8
) LDLOC(l
, gint64
); MINT_IN_BREAK
;
3876 MINT_IN_CASE(MINT_LDLOC_R4
) LDLOC(f
, float); MINT_IN_BREAK
;
3877 MINT_IN_CASE(MINT_LDLOC_R8
) LDLOC(f
, double); MINT_IN_BREAK
;
3878 MINT_IN_CASE(MINT_LDLOC_O
) LDLOC(p
, gpointer
); MINT_IN_BREAK
;
3879 MINT_IN_CASE(MINT_LDLOC_P
) LDLOC(p
, gpointer
); MINT_IN_BREAK
;
3881 MINT_IN_CASE(MINT_LDLOC_VT
)
3883 i32
= READ32(ip
+ 2);
3884 memcpy(sp
->data
.p
, locals
+ * (guint16
*)(ip
+ 1), i32
);
3885 vt_sp
+= (i32
+ 7) & ~7;
3890 MINT_IN_CASE(MINT_LDLOCA_S
)
3891 sp
->data
.p
= locals
+ * (guint16
*)(ip
+ 1);
3896 #define STLOC(datamem, argtype) \
3898 * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp->data.datamem; \
3901 MINT_IN_CASE(MINT_STLOC_I1
) STLOC(i
, gint8
); MINT_IN_BREAK
;
3902 MINT_IN_CASE(MINT_STLOC_U1
) STLOC(i
, guint8
); MINT_IN_BREAK
;
3903 MINT_IN_CASE(MINT_STLOC_I2
) STLOC(i
, gint16
); MINT_IN_BREAK
;
3904 MINT_IN_CASE(MINT_STLOC_U2
) STLOC(i
, guint16
); MINT_IN_BREAK
;
3905 MINT_IN_CASE(MINT_STLOC_I4
) STLOC(i
, gint32
); MINT_IN_BREAK
;
3906 MINT_IN_CASE(MINT_STLOC_I8
) STLOC(l
, gint64
); MINT_IN_BREAK
;
3907 MINT_IN_CASE(MINT_STLOC_R4
) STLOC(f
, float); MINT_IN_BREAK
;
3908 MINT_IN_CASE(MINT_STLOC_R8
) STLOC(f
, double); MINT_IN_BREAK
;
3909 MINT_IN_CASE(MINT_STLOC_O
) STLOC(p
, gpointer
); MINT_IN_BREAK
;
3910 MINT_IN_CASE(MINT_STLOC_P
) STLOC(p
, gpointer
); MINT_IN_BREAK
;
3912 #define STLOC_NP(datamem, argtype) \
3913 * (argtype *)(locals + * (guint16 *)(ip + 1)) = sp [-1].data.datamem; \
3916 MINT_IN_CASE(MINT_STLOC_NP_I4
) STLOC_NP(i
, gint32
); MINT_IN_BREAK
;
3917 MINT_IN_CASE(MINT_STLOC_NP_O
) STLOC_NP(p
, gpointer
); MINT_IN_BREAK
;
3919 MINT_IN_CASE(MINT_STLOC_VT
)
3920 i32
= READ32(ip
+ 2);
3922 memcpy(locals
+ * (guint16
*)(ip
+ 1), sp
->data
.p
, i32
);
3923 vt_sp
-= (i32
+ 7) & ~7;
3927 MINT_IN_CASE(MINT_LOCALLOC
) {
3928 if (sp
!= frame
->stack
+ 1) /*FIX?*/
3929 THROW_EX (mono_get_exception_execution_engine (NULL
), ip
);
3931 int len
= sp
[-1].data
.i
;
3932 sp
[-1].data
.p
= alloca (len
);
3933 MonoMethodHeader
*header
= mono_method_get_header_checked (frame
->runtime_method
->method
, &error
);
3934 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
3935 if (header
->init_locals
)
3936 memset (sp
[-1].data
.p
, 0, len
);
3941 MINT_IN_CASE(MINT_ENDFILTER
) ves_abort(); MINT_IN_BREAK
;
3943 MINT_IN_CASE(MINT_INITOBJ
)
3945 memset (sp
->data
.vt
, 0, READ32(ip
+ 1));
3948 MINT_IN_CASE(MINT_CPBLK
)
3950 if (!sp
[0].data
.p
|| !sp
[1].data
.p
)
3951 THROW_EX (mono_get_exception_null_reference(), ip
- 1);
3953 /* FIXME: value and size may be int64... */
3954 memcpy (sp
[0].data
.p
, sp
[1].data
.p
, sp
[2].data
.i
);
3957 MINT_IN_CASE(MINT_CONSTRAINED_
) {
3959 /* FIXME: implement */
3961 token
= READ32 (ip
);
3966 MINT_IN_CASE(MINT_INITBLK
)
3969 THROW_EX (mono_get_exception_null_reference(), ip
- 1);
3971 /* FIXME: value and size may be int64... */
3972 memset (sp
[0].data
.p
, sp
[1].data
.i
, sp
[2].data
.i
);
3975 MINT_IN_CASE(MINT_NO_
)
3976 /* FIXME: implement */
3980 MINT_IN_CASE(MINT_RETHROW
)
3982 * need to clarify what this should actually do:
3983 * start the search from the last found handler in
3984 * this method or continue in the caller or what.
3985 * Also, do we need to run finally/fault handlers after a retrow?
3986 * Well, this implementation will follow the usual search
3987 * for an handler, considering the current ip as throw spot.
3988 * We need to NULL frame->ex_handler for the later code to
3989 * actually run the new found handler.
3991 frame
->ex_handler
= NULL
;
3992 THROW_EX (frame
->ex
, ip
- 1);
3995 g_print ("Unimplemented opcode: %04x %s at 0x%x\n", *ip
, mono_interp_opname
[*ip
], ip
-rtm
->code
);
3996 THROW_EX (mono_get_exception_execution_engine ("Unimplemented opcode"), ip
);
4000 g_assert_not_reached ();
4002 * Exception handling code.
4003 * The exception object is stored in frame->ex.
4010 MonoInvocation
*inv
;
4011 MonoExceptionClause
*clause
;
4017 g_print ("* Handling exception '%s' at IL_%04x\n",
4018 frame
->ex
== NULL
? "** Unknown **" : mono_object_class (frame
->ex
)->name
,
4019 rtm
== NULL
? 0 : frame
->ip
- rtm
->code
);
4021 if (die_on_exception
)
4024 for (inv
= frame
; inv
; inv
= inv
->parent
) {
4026 if (inv
->runtime_method
== NULL
)
4028 method
= inv
->runtime_method
->method
;
4029 if (method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
)
4031 if (method
->iflags
& (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
| METHOD_IMPL_ATTRIBUTE_RUNTIME
))
4033 if (inv
->ip
== NULL
)
4035 ip_offset
= inv
->ip
- inv
->runtime_method
->code
;
4036 inv
->ex_handler
= NULL
; /* clear this in case we are trhowing an exception while handling one - this one wins */
4037 for (i
= 0; i
< inv
->runtime_method
->num_clauses
; ++i
) {
4038 clause
= &inv
->runtime_method
->clauses
[i
];
4039 if (clause
->flags
<= 1 && MONO_OFFSET_IN_CLAUSE (clause
, ip_offset
)) {
4040 if (!clause
->flags
) {
4041 MonoObject
*isinst_obj
= mono_object_isinst_checked ((MonoObject
*)frame
->ex
, clause
->data
.catch_class
, &error
);
4042 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
4045 * OK, we found an handler, now we need to execute the finally
4046 * and fault blocks before branching to the handler code.
4048 inv
->ex_handler
= clause
;
4051 g_print ("* Found handler at '%s'\n", method
->name
);
4053 goto handle_finally
;
4056 g_error ("FIXME: handle filter clause");
4062 * If we get here, no handler was found: print a stack trace.
4064 for (inv
= frame
; inv
; inv
= inv
->parent
) {
4065 if (inv
->invoke_trap
)
4066 goto handle_finally
;
4069 ex_obj
= (MonoObject
*)frame
->ex
;
4070 mono_unhandled_exception (ex_obj
);
4077 MonoExceptionClause
*clause
;
4078 GSList
*old_list
= finally_ips
;
4079 MonoMethod
*method
= frame
->runtime_method
->method
;
4080 MonoMethodHeader
*header
= mono_method_get_header_checked (method
, &error
);
4081 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
4085 g_print ("* Handle finally IL_%04x\n", endfinally_ip
== NULL
? 0 : endfinally_ip
- rtm
->code
);
4087 if (rtm
== NULL
|| (method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
)
4088 || (method
->iflags
& (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
| METHOD_IMPL_ATTRIBUTE_RUNTIME
))) {
4091 ip_offset
= frame
->ip
- rtm
->code
;
4093 if (endfinally_ip
!= NULL
)
4094 finally_ips
= g_slist_prepend(finally_ips
, (void *)endfinally_ip
);
4095 for (i
= 0; i
< header
->num_clauses
; ++i
)
4096 if (frame
->ex_handler
== &rtm
->clauses
[i
])
4100 clause
= &rtm
->clauses
[i
];
4101 if (MONO_OFFSET_IN_CLAUSE (clause
, ip_offset
) && (endfinally_ip
== NULL
|| !(MONO_OFFSET_IN_CLAUSE (clause
, endfinally_ip
- rtm
->code
)))) {
4102 if (clause
->flags
== MONO_EXCEPTION_CLAUSE_FINALLY
) {
4103 ip
= rtm
->code
+ clause
->handler_offset
;
4104 finally_ips
= g_slist_prepend (finally_ips
, (gpointer
) ip
);
4107 g_print ("* Found finally at IL_%04x with exception: %s\n", clause
->handler_offset
, frame
->ex
? "yes": "no");
4113 endfinally_ip
= NULL
;
4115 if (old_list
!= finally_ips
&& finally_ips
) {
4116 ip
= finally_ips
->data
;
4117 finally_ips
= g_slist_remove (finally_ips
, ip
);
4118 sp
= frame
->stack
; /* spec says stack should be empty at endfinally so it should be at the start too */
4123 * If an exception is set, we need to execute the fault handler, too,
4124 * otherwise, we continue normally.
4134 MonoExceptionClause
*clause
;
4135 MonoMethod
*method
= frame
->runtime_method
->method
;
4136 MonoMethodHeader
*header
= mono_method_get_header_checked (method
, &error
);
4137 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
4141 g_print ("* Handle fault\n");
4143 ip_offset
= frame
->ip
- rtm
->code
;
4144 for (i
= 0; i
< header
->num_clauses
; ++i
) {
4145 clause
= &rtm
->clauses
[i
];
4146 if (clause
->flags
== MONO_EXCEPTION_CLAUSE_FAULT
&& MONO_OFFSET_IN_CLAUSE (clause
, ip_offset
)) {
4147 ip
= rtm
->code
+ clause
->handler_offset
;
4150 g_print ("* Executing handler at IL_%04x\n", clause
->handler_offset
);
4156 * If the handler for the exception was found in this method, we jump
4157 * to it right away, otherwise we return and let the caller run
4158 * the finally, fault and catch blocks.
4159 * This same code should be present in the endfault opcode, but it
4160 * is corrently not assigned in the ECMA specs: LAMESPEC.
4162 if (frame
->ex_handler
) {
4165 g_print ("* Executing handler at IL_%04x\n", frame
->ex_handler
->handler_offset
);
4167 ip
= rtm
->code
+ frame
->ex_handler
->handler_offset
;
4169 vt_sp
= (unsigned char *) sp
+ rtm
->stack_size
;
4170 sp
->data
.p
= frame
->ex
;
4181 ves_exec_method (MonoInvocation
*frame
)
4183 ThreadContext
*context
= mono_native_tls_get_value (thread_context_id
);
4184 ThreadContext context_struct
;
4191 mono_unhandled_exception ((MonoObject
*)frame
->ex
);
4194 if (context
== NULL
) {
4195 context
= &context_struct
;
4196 context_struct
.domain
= mono_domain_get ();
4197 context_struct
.base_frame
= frame
;
4198 context_struct
.current_frame
= NULL
;
4199 context_struct
.env_frame
= frame
;
4200 context_struct
.current_env
= &env
;
4201 context_struct
.search_for_handler
= 0;
4202 context_struct
.managed_code
= 0;
4203 mono_native_tls_set_value (thread_context_id
, context
);
4206 frame
->parent
= context
->current_frame
;
4207 frame
->runtime_method
= mono_interp_get_runtime_method (context
->domain
, frame
->method
, &error
);
4208 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
4209 context
->managed_code
= 1;
4210 ves_exec_method_with_context (frame
, context
);
4211 context
->managed_code
= 0;
4213 if (context
!= &context_struct
&& context
->current_env
) {
4214 context
->env_frame
->ex
= frame
->ex
;
4215 longjmp (*context
->current_env
, 1);
4218 mono_unhandled_exception ((MonoObject
*)frame
->ex
);
4220 if (context
->base_frame
== frame
)
4221 mono_native_tls_set_value (thread_context_id
, NULL
);
4223 context
->current_frame
= frame
->parent
;
4227 ves_exec (MonoDomain
*domain
, MonoAssembly
*assembly
, int argc
, char *argv
[])
4229 MonoImage
*image
= mono_assembly_get_image (assembly
);
4234 method
= mono_get_method_checked (image
, mono_image_get_entry_point (image
), NULL
, NULL
, &error
);
4235 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
4238 g_error ("No entry point method found in %s", mono_image_get_filename (image
));
4240 rval
= mono_runtime_run_main_checked (method
, argc
, argv
, &error
);
4241 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
4249 "mint %s, the Mono ECMA CLI interpreter, (C) 2001, 2002 Ximian, Inc.\n\n"
4250 "Usage is: mint [options] executable args...\n\n", VERSION
);
4252 "Runtime Debugging:\n"
4257 " --noptr\t\t\tdon't print pointer addresses in trace output\n"
4260 " --traceclassinit\n"
4263 " --debug method_name\n"
4270 " --config filename load the specified config file instead of the default\n"
4271 " --workers n maximum number of worker threads\n"
4277 interp_ves_icall_get_frame_info (gint32 skip
, MonoBoolean need_file_info
,
4278 MonoReflectionMethod
**method
,
4279 gint32
*iloffset
, gint32
*native_offset
,
4280 MonoString
**file
, gint32
*line
, gint32
*column
)
4282 ThreadContext
*context
= mono_native_tls_get_value (thread_context_id
);
4283 MonoInvocation
*inv
= context
->current_frame
;
4287 for (i
= 0; inv
&& i
< skip
; inv
= inv
->parent
)
4288 if (inv
->runtime_method
!= NULL
)
4299 *method
= mono_method_get_object_checked (context
->domain
, inv
->runtime_method
->method
, NULL
, &error
);
4300 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
4305 if (need_file_info
) {
4309 *file
= mono_string_new (mono_domain_get (), "unknown");
4316 interp_ves_icall_get_trace (MonoException
*exc
, gint32 skip
, MonoBoolean need_file_info
)
4318 MonoDomain
*domain
= mono_domain_get ();
4320 MonoArray
*ta
= exc
->trace_ips
;
4325 /* Exception is not thrown yet */
4326 MonoArray
*array
= mono_array_new_checked (domain
, mono_defaults
.stack_frame_class
, 0, &error
);
4327 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
4331 len
= mono_array_length (ta
);
4333 res
= mono_array_new_checked (domain
, mono_defaults
.stack_frame_class
, len
> skip
? len
- skip
: 0, &error
);
4334 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
4336 for (i
= skip
; i
< len
/ 2; i
++) {
4337 MonoStackFrame
*sf
= (MonoStackFrame
*)mono_object_new_checked (domain
, mono_defaults
.stack_frame_class
, &error
);
4338 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
4339 gushort
*ip
= mono_array_get (ta
, gpointer
, 2 * i
+ 1);
4340 RuntimeMethod
*rtm
= mono_array_get (ta
, gpointer
, 2 * i
);
4343 sf
->method
= mono_method_get_object_checked (domain
, rtm
->method
, NULL
, &error
);
4344 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
4345 sf
->native_offset
= ip
- rtm
->code
;
4349 sf
->il_offset
= mono_debug_il_offset_from_address (ji
->method
, sf
->native_offset
, domain
);
4351 if (need_file_info
) {
4354 filename
= mono_debug_source_location_from_address (ji
->method
, sf
->native_offset
, &sf
->line
, domain
);
4356 sf
->filename
= filename
? mono_string_new (domain
, filename
): NULL
;
4363 mono_array_set (res
, gpointer
, i
, sf
);
4372 mono_native_tls_alloc (&thread_context_id
, NULL
);
4373 mono_native_tls_set_value (thread_context_id
, NULL
);
4374 mono_os_mutex_init_recursive (&runtime_method_lookup_section
);
4375 mono_os_mutex_init_recursive (&create_method_pointer_mutex
);
4377 mono_interp_transform_init ();
4380 typedef int (*TestMethod
) (void);
4383 interp_regression_step (MonoImage
*image
, int verbose
, int *total_run
, int *total
, GTimer
*timer
, MonoDomain
*domain
)
4385 int result
, expected
, failed
, cfailed
, run
;
4386 double elapsed
, transform_time
;
4388 MonoObject
*result_obj
;
4389 static gboolean filter_method_init
= FALSE
;
4390 static const char *filter_method
= NULL
;
4392 g_print ("Test run: image=%s\n", mono_image_get_filename (image
));
4393 cfailed
= failed
= run
= 0;
4394 transform_time
= elapsed
= 0.0;
4397 /* fixme: ugly hack - delete all previously compiled methods */
4398 if (domain_jit_info (domain
)) {
4399 g_hash_table_destroy (domain_jit_info (domain
)->jit_trampoline_hash
);
4400 domain_jit_info (domain
)->jit_trampoline_hash
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
4401 mono_internal_hash_table_destroy (&(domain
->jit_code_hash
));
4402 mono_jit_code_hash_init (&(domain
->jit_code_hash
));
4406 g_timer_start (timer
);
4407 for (i
= 0; i
< mono_image_get_table_rows (image
, MONO_TABLE_METHOD
); ++i
) {
4408 MonoObject
*exc
= NULL
;
4410 MonoMethod
*method
= mono_get_method_checked (image
, MONO_TOKEN_METHOD_DEF
| (i
+ 1), NULL
, NULL
, &error
);
4412 mono_error_cleanup (&error
); /* FIXME don't swallow the error */
4416 if (!filter_method_init
) {
4417 filter_method
= g_getenv ("INTERP_FILTER_METHOD");
4418 filter_method_init
= TRUE
;
4420 gboolean filter
= FALSE
;
4421 if (filter_method
) {
4422 const char *name
= filter_method
;
4424 if ((strchr (name
, '.') > name
) || strchr (name
, ':')) {
4425 MonoMethodDesc
*desc
= mono_method_desc_new (name
, TRUE
);
4426 filter
= mono_method_desc_full_match (desc
, method
);
4427 mono_method_desc_free (desc
);
4429 filter
= strcmp (method
->name
, name
) == 0;
4431 } else { /* no filter, check for `Category' attribute on method */
4433 MonoCustomAttrInfo
* ainfo
= mono_custom_attrs_from_method_checked (method
, &error
);
4434 mono_error_cleanup (&error
);
4438 for (j
= 0; j
< ainfo
->num_attrs
&& filter
; ++j
) {
4439 MonoCustomAttrEntry
*centry
= &ainfo
->attrs
[j
];
4440 if (centry
->ctor
== NULL
)
4443 MonoClass
*klass
= centry
->ctor
->klass
;
4444 if (strcmp (klass
->name
, "CategoryAttribute"))
4447 MonoObject
*obj
= mono_custom_attrs_get_attr_checked (ainfo
, klass
, &error
);
4448 /* FIXME: there is an ordering problem if there're multiple attributes, do this instead:
4449 * MonoObject *obj = create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, &error); */
4450 mono_error_cleanup (&error
);
4451 MonoMethod
*getter
= mono_class_get_method_from_name (klass
, "get_Category", -1);
4452 MonoObject
*str
= mono_interp_runtime_invoke (getter
, obj
, NULL
, &exc
, &error
);
4453 mono_error_cleanup (&error
);
4454 char *utf8_str
= mono_string_to_utf8_checked ((MonoString
*) str
, &error
);
4455 mono_error_cleanup (&error
);
4456 if (!strcmp (utf8_str
, "!INTERPRETER")) {
4457 g_print ("skip %s...\n", method
->name
);
4463 if (strncmp (method
->name
, "test_", 5) == 0 && filter
) {
4464 MonoError interp_error
;
4465 MonoObject
*exc
= NULL
;
4467 result_obj
= mono_interp_runtime_invoke (method
, NULL
, NULL
, &exc
, &interp_error
);
4468 if (!mono_error_ok (&interp_error
)) {
4470 g_print ("Test '%s' execution failed.\n", method
->name
);
4471 } else if (exc
!= NULL
) {
4472 g_print ("Exception in Test '%s' occured:\n", method
->name
);
4473 mono_object_describe (exc
);
4477 result
= *(gint32
*) mono_object_unbox (result_obj
);
4478 expected
= atoi (method
->name
+ 5); // FIXME: oh no.
4481 if (result
!= expected
) {
4483 g_print ("Test '%s' failed result (got %d, expected %d).\n", method
->name
, result
, expected
);
4488 g_timer_stop (timer
);
4489 elapsed
= g_timer_elapsed (timer
, NULL
);
4490 if (failed
> 0 || cfailed
> 0){
4491 g_print ("Results: total tests: %d, failed: %d, cfailed: %d (pass: %.2f%%)\n",
4492 run
, failed
, cfailed
, 100.0*(run
-failed
-cfailed
)/run
);
4494 g_print ("Results: total tests: %d, all pass \n", run
);
4497 g_print ("Elapsed time: %f secs (%f, %f)\n\n", elapsed
,
4498 elapsed
- transform_time
, transform_time
);
4499 *total
+= failed
+ cfailed
;
4503 interp_regression (MonoImage
*image
, int verbose
, int *total_run
)
4506 GTimer
*timer
= g_timer_new ();
4507 MonoDomain
*domain
= mono_domain_get ();
4511 /* load the metadata */
4512 for (i
= 0; i
< mono_image_get_table_rows (image
, MONO_TABLE_METHOD
); ++i
) {
4514 method
= mono_get_method_checked (image
, MONO_TOKEN_METHOD_DEF
| (i
+ 1), NULL
, NULL
, &error
);
4516 mono_error_cleanup (&error
);
4519 mono_class_init (method
->klass
);
4524 interp_regression_step (image
, verbose
, total_run
, &total
, timer
, domain
);
4526 g_timer_destroy (timer
);
4531 mono_interp_regression_list (int verbose
, int count
, char *images
[])
4533 int i
, total
, total_run
, run
;
4535 total_run
= total
= 0;
4536 for (i
= 0; i
< count
; ++i
) {
4537 MonoAssembly
*ass
= mono_assembly_open (images
[i
], NULL
);
4539 g_warning ("failed to load assembly: %s", images
[i
]);
4542 total
+= interp_regression (mono_assembly_get_image (ass
), verbose
, &run
);
4546 g_print ("Overall results: tests: %d, failed: %d (pass: %.2f%%)\n", total_run
, total
, 100.0*(total_run
-total
)/total_run
);
4548 g_print ("Overall results: tests: %d, 100%% pass\n", total_run
);