[runtime] Call error_init instead of mono_error_init (#4425)
[mono.git] / mono / mini / interpreter / interp.c
index 7684052260be089b64856eda816a1cdcc484d038..2ec010502b821001ece92d2ae5d052dd1a40c8b4 100644 (file)
@@ -58,6 +58,7 @@
 #include <mono/metadata/mono-debug.h>
 
 #include "interp.h"
+#include "interp-internals.h"
 #include "mintops.h"
 #include "hacks.h"
 
@@ -258,7 +259,7 @@ RuntimeMethod*
 mono_interp_get_runtime_method (MonoDomain *domain, MonoMethod *method, MonoError *error)
 {
        RuntimeMethod *rtm;
-       mono_error_init (error);
+       error_init (error);
 
        mono_os_mutex_lock (&runtime_method_lookup_section);
        if ((rtm = mono_internal_hash_table_lookup (&domain->jit_code_hash, method))) {
@@ -305,6 +306,8 @@ get_virtual_method (MonoDomain *domain, RuntimeMethod *runtime_method, MonoObjec
                return ret;
        }
 
+       mono_class_setup_vtable (obj->vtable->klass);
+
        int slot = mono_method_get_vtable_slot (m);
        if (mono_class_is_interface (m->klass)) {
                g_assert (obj->vtable->klass != m->klass);
@@ -1212,7 +1215,7 @@ get_trace_ips (MonoDomain *domain, MonoInvocation *top)
 #endif
 
 MonoObject*
-interp_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
+mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
 {
        MonoInvocation frame;
        ThreadContext * volatile context = mono_native_tls_get_value (thread_context_id);
@@ -1227,7 +1230,7 @@ interp_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
        MonoInvocation *old_frame = NULL;
        jmp_buf env;
 
-       mono_error_init (error);
+       error_init (error);
 
        frame.ex = NULL;
 
@@ -1463,8 +1466,32 @@ static mono_mutex_t create_method_pointer_mutex;
 
 static GHashTable *method_pointer_hash = NULL;
 
+static MonoMethod *method_pointers [2] = {0};
+
+static MonoObject *
+mp_tramp_0 (MonoObject *this_obj, void **params, MonoObject **exc, void *compiled_method) {
+       MonoError error;
+       void *params_real[] = {this_obj, &params, &exc, &compiled_method};
+       MonoObject *ret = mono_interp_runtime_invoke (method_pointers [0], NULL, params_real, NULL, &error);
+       mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+       return ret;
+}
+
+static MonoObject *
+mp_tramp_1 (MonoObject *this_obj, void **params, MonoObject **exc, void *compiled_method) {
+       MonoError error;
+       void *params_real[] = {this_obj, &params, &exc, &compiled_method};
+       MonoObject *ret = mono_interp_runtime_invoke (method_pointers [1], NULL, params_real, NULL, &error);
+       mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+       return ret;
+}
+
+gpointer *mp_tramps[] = {(gpointer) mp_tramp_0, (gpointer) mp_tramp_1};
+
+static int tramps_used = 0;
+
 gpointer
-interp_create_method_pointer (MonoMethod *method, MonoError *error)
+mono_interp_create_method_pointer (MonoMethod *method, MonoError *error)
 {
        gpointer addr;
        MonoJitInfo *ji;
@@ -1494,10 +1521,13 @@ interp_create_method_pointer (MonoMethod *method, MonoError *error)
                mono_jit_info_table_add (mono_get_root_domain (), ji);
        }               
        else {
-               g_error ("FIXME: not available? figure out new API");
-#if 0
-               addr = mono_arch_create_method_pointer (method);
-#endif
+               g_assert (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE);
+               g_assert (tramps_used < 2);
+
+               /* FIXME: needs locking */
+               method_pointers [tramps_used] = method;
+               addr = mp_tramps [tramps_used];
+               tramps_used++;
        }
 
        g_hash_table_insert (method_pointer_hash, method, addr);
@@ -1791,7 +1821,9 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                        if (csignature->hasthis)
                                --sp;
                        child_frame.stack_args = sp;
-                       if (csignature->hasthis && mono_object_is_transparent_proxy (sp->data.p)) {
+
+                       /* `this' can be NULL for string:.ctor */
+                       if (csignature->hasthis && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
                                child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                        } else if (child_frame.runtime_method->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
@@ -1876,7 +1908,9 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                        if (child_frame.runtime_method->hasthis)
                                --sp;
                        child_frame.stack_args = sp;
-                       if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype && mono_object_is_transparent_proxy (sp->data.p)) {
+
+                       /* `this' can be NULL for string:.ctor */
+                       if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
                                child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                        }
@@ -1951,7 +1985,9 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                        child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
 
                        if (this_arg->vtable->klass->valuetype && child_frame.runtime_method->valuetype) {
-                               sp->data.p = (char *) this_arg + sizeof (MonoObject);
+                               /* unbox */
+                               gpointer *unboxed = mono_object_unbox (this_arg);
+                               stackval_from_data (&this_arg->vtable->klass->byval_arg, sp, (char *) unboxed, FALSE);
                        }
 
                        ves_exec_method_with_context (&child_frame, context);
@@ -1996,7 +2032,8 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                        child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
 
                        if (this_arg->vtable->klass->valuetype && child_frame.runtime_method->valuetype) {
-                               sp->data.p = (char *) this_arg + sizeof (MonoObject);
+                               gpointer *unboxed = mono_object_unbox (this_arg);
+                               stackval_from_data (&this_arg->vtable->klass->byval_arg, sp, (char *) unboxed, FALSE);
                        }
 
                        ves_exec_method_with_context (&child_frame, context);
@@ -2772,6 +2809,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                                                mono_thread_interruption_checkpoint ();
                                        sp->data.p = o;
                                } else {
+                                       sp->data.p = NULL;
                                        child_frame.retval = &retval;
                                }
                        }
@@ -3211,7 +3249,8 @@ array_constructed:
                MINT_IN_CASE(MINT_LDELEM_I)  /* fall through */
                MINT_IN_CASE(MINT_LDELEM_R4) /* fall through */
                MINT_IN_CASE(MINT_LDELEM_R8) /* fall through */
-               MINT_IN_CASE(MINT_LDELEM_REF) {
+               MINT_IN_CASE(MINT_LDELEM_REF) /* fall through */
+               MINT_IN_CASE(MINT_LDELEM_VT) {
                        MonoArray *o;
                        mono_u aindex;
 
@@ -3262,6 +3301,16 @@ array_constructed:
                        case MINT_LDELEM_REF:
                                sp [0].data.p = mono_array_get (o, gpointer, aindex);
                                break;
+                       case MINT_LDELEM_VT: {
+                               MonoClass *klass_vt = rtm->data_items [*(guint16 *) (ip + 1)];
+                               i32 = READ32 (ip + 2);
+                               char *src_addr = mono_array_addr_with_size ((MonoArray *) o, i32, aindex);
+                               sp [0].data.vt = vt_sp;
+                               stackval_from_data (&klass_vt->byval_arg, sp, src_addr, FALSE);
+                               vt_sp += (i32 + 7) & ~7;
+                               ip += 3;
+                               break;
+                       }
                        default:
                                ves_abort();
                        }
@@ -3277,7 +3326,8 @@ array_constructed:
                MINT_IN_CASE(MINT_STELEM_I8) /* fall through */
                MINT_IN_CASE(MINT_STELEM_R4) /* fall through */
                MINT_IN_CASE(MINT_STELEM_R8) /* fall through */
-               MINT_IN_CASE(MINT_STELEM_REF) {
+               MINT_IN_CASE(MINT_STELEM_REF) /* fall through */
+               MINT_IN_CASE(MINT_STELEM_VT) {
                        mono_u aindex;
 
                        sp -= 3;
@@ -3318,7 +3368,18 @@ array_constructed:
                                if (sp [2].data.p && !isinst_obj)
                                        THROW_EX (mono_get_exception_array_type_mismatch (), ip);
                                mono_array_set ((MonoArray *)o, gpointer, aindex, sp [2].data.p);
-                       } break;
+                               break;
+                       }
+                       case MINT_STELEM_VT: {
+                               MonoClass *klass_vt = rtm->data_items [*(guint16 *) (ip + 1)];
+                               i32 = READ32 (ip + 2);
+                               char *dst_addr = mono_array_addr_with_size ((MonoArray *) o, i32, aindex);
+
+                               stackval_to_data (&klass_vt->byval_arg, &sp [2], dst_addr, FALSE);
+                               vt_sp -= (i32 + 7) & ~7;
+                               ip += 3;
+                               break;
+                       }
                        default:
                                ves_abort();
                        }
@@ -4324,6 +4385,7 @@ interp_regression_step (MonoImage *image, int verbose, int *total_run, int *tota
 
        g_timer_start (timer);
        for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
+               MonoObject *exc = NULL;
                MonoError error;
                MonoMethod *method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
                if (!method) {
@@ -4346,14 +4408,43 @@ interp_regression_step (MonoImage *image, int verbose, int *total_run, int *tota
                        } else {
                                filter = strcmp (method->name, name) == 0;
                        }
-               } else { // no filter
+               } else { /* no filter, check for `Category' attribute on method */
                        filter = TRUE;
+                       MonoCustomAttrInfo* ainfo = mono_custom_attrs_from_method_checked (method, &error);
+                       mono_error_cleanup (&error);
+
+                       if (ainfo) {
+                               int j;
+                               for (j = 0; j < ainfo->num_attrs && filter; ++j) {
+                                       MonoCustomAttrEntry *centry = &ainfo->attrs [j];
+                                       if (centry->ctor == NULL)
+                                               continue;
+
+                                       MonoClass *klass = centry->ctor->klass;
+                                       if (strcmp (klass->name, "CategoryAttribute"))
+                                               continue;
+
+                                       MonoObject *obj = mono_custom_attrs_get_attr_checked (ainfo, klass, &error);
+                                       /* FIXME: there is an ordering problem if there're multiple attributes, do this instead:
+                                        * MonoObject *obj = create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, &error); */
+                                       mono_error_cleanup (&error);
+                                       MonoMethod *getter = mono_class_get_method_from_name (klass, "get_Category", -1);
+                                       MonoObject *str = mono_interp_runtime_invoke (getter, obj, NULL, &exc, &error);
+                                       mono_error_cleanup (&error);
+                                       char *utf8_str = mono_string_to_utf8_checked ((MonoString *) str, &error);
+                                       mono_error_cleanup (&error);
+                                       if (!strcmp (utf8_str, "!INTERPRETER")) {
+                                               g_print ("skip %s...\n", method->name);
+                                               filter = FALSE;
+                                       }
+                               }
+                       }
                }
                if (strncmp (method->name, "test_", 5) == 0 && filter) {
                        MonoError interp_error;
                        MonoObject *exc = NULL;
 
-                       result_obj = interp_mono_runtime_invoke (method, NULL, NULL, &exc, &interp_error);
+                       result_obj = mono_interp_runtime_invoke (method, NULL, NULL, &exc, &interp_error);
                        if (!mono_error_ok (&interp_error)) {
                                cfailed++;
                                g_print ("Test '%s' execution failed.\n", method->name);
@@ -4417,7 +4508,7 @@ interp_regression (MonoImage *image, int verbose, int *total_run)
 }
 
 int
-interp_regression_list (int verbose, int count, char *images [])
+mono_interp_regression_list (int verbose, int count, char *images [])
 {
        int i, total, total_run, run;