2003-02-02 Martin Baulig <martin@ximian.com>
[mono.git] / mono / metadata / object.c
index e146496bc6964f82ede8643175d8f1cfeaa8cdd4..2c5d43b9e2e5dc62162dd5326acb6e242d943ed1 100644 (file)
 #include <mono/metadata/tokentype.h>
 #include <mono/metadata/loader.h>
 #include <mono/metadata/object.h>
-#include <mono/metadata/gc.h>
+#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/exception.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/threadpool.h>
+#include <mono/metadata/marshal.h>
 #include "mono/metadata/debug-helpers.h"
-#if HAVE_BOEHM_GC
-#include <gc/gc.h>
-#endif
+#include "mono/metadata/marshal.h"
+#include <mono/metadata/threads.h>
+#include <mono/metadata/environment.h>
+#include "mono/metadata/profiler-private.h"
+#include <mono/os/gc_wrapper.h>
+
+/* 
+ * enable to get a good speedup: we still need to figure out
+ * how the sync structure is freed.
+ */
+#define CREATION_SPEEDUP 0
 
 void
 mono_runtime_object_init (MonoObject *this)
@@ -46,7 +56,7 @@ mono_runtime_object_init (MonoObject *this)
 }
 
 /*
- * runtime_class_init:
+ * mono_runtime_class_init:
  * @klass: klass that needs to be initialized
  *
  * This routine calls the class constructor for @class.
@@ -55,17 +65,37 @@ void
 mono_runtime_class_init (MonoClass *klass)
 {
        int i;
+       MonoException *exc = NULL;
+       MonoException *exc_to_throw;
+       MonoMethod *method;
+       gchar *full_name;
 
        for (i = 0; i < klass->method.count; ++i) {
-               MonoMethod *method = klass->methods [i];
+               method = klass->methods [i];
                if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
                    (strcmp (".cctor", method->name) == 0)) {
-                       mono_runtime_invoke (method, NULL, NULL, NULL);
+                       mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
+                       if (exc != NULL)
+                               break;
                        return;
                }
        }
 
-       /* No class constructor found */
+       if (exc == NULL ||
+           (klass->image == mono_defaults.corlib &&            
+            !strcmp (klass->name_space, "System") &&
+            !strcmp (klass->name, "TypeInitializationException")))
+               return; /* No static constructor found or avoid infinite loop */
+
+       if (klass->name_space && *klass->name_space)
+               full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
+       else
+               full_name = g_strdup (klass->name);
+
+       exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
+       g_free (full_name);
+
+       mono_raise_exception (exc_to_throw);
 }
 
 static gpointer
@@ -148,10 +178,6 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
        if (vt && vt->domain == domain)
                return vt;
 
-       /* can interfaces have static fields? */
-       if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
-               g_assert_not_reached ();
-
        mono_domain_lock (domain);
        if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
                mono_domain_unlock (domain);
@@ -171,7 +197,7 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
 
        if (class->class_size) {
 #if HAVE_BOEHM_GC
-               vt->data = GC_malloc (class->class_size + 8);
+               vt->data = GC_MALLOC (class->class_size + 8);
                /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
                /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
                mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
@@ -189,8 +215,13 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
                if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
                        MonoClass *fklass = mono_class_from_mono_type (field->type);
                        t = (char*)vt->data + field->offset;
-                       g_assert (fklass->valuetype);
-                       memcpy (t, field->data, mono_class_value_size (fklass, NULL));
+                       if (fklass->valuetype) {
+                               memcpy (t, field->data, mono_class_value_size (fklass, NULL));
+                       } else {
+                               /* it's a pointer type: add check */
+                               g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
+                               *t = *(gpointer*)field->data;
+                       }
                        continue;
                }
                if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
@@ -241,8 +272,19 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
                        break;
                }
                case MONO_TYPE_STRING: {
-                       /*gpointer *val = (gpointer*)t;
-                       *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);*/
+                       gpointer *val = (gpointer*)t;
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+                       gunichar2 *copy = g_malloc (len);
+                       int j;
+                       for (j = 0; j < len/2; j++) {
+                               copy [j] = read16 (p);
+                               p += 2;
+                       }
+                       *val = mono_string_new_utf16 (domain, copy, len/2);
+                       g_free (copy);
+#else
+                       *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
+#endif
                        break;
                }
                case MONO_TYPE_CLASS:
@@ -268,6 +310,14 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
                }
        }
 
+       /* 
+        * arch_create_jit_trampoline () can recursively call this function again
+        * because it compiles icall methods right away.
+        */
+       mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
+       if (!class->cached_vtable)
+               class->cached_vtable = vt;
+
        /* initialize vtable */
        for (i = 0; i < class->vtable_size; ++i) {
                MonoMethod *cm;
@@ -276,10 +326,6 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
                        vt->vtable [i] = arch_create_jit_trampoline (cm);
        }
 
-       mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
-       if (!class->cached_vtable)
-               class->cached_vtable = vt;
-
        mono_domain_unlock (domain);
 
        /* make sure the the parent is initialized */
@@ -333,19 +379,195 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
        return pvt;
 }
 
-static MonoInvokeFunc default_mono_runtime_invoke = NULL;
+/*
+ * Retrieve the MonoMethod that would to be called on obj if obj is passed as
+ * the instance of a callvirt of method.
+ */
+MonoMethod*
+mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
+       MonoClass *klass;
+       MonoMethod **vtable;
+       gboolean is_proxy;
+       MonoMethod *res;
+
+       if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL))
+                       return method;
+
+       klass = mono_object_class (obj);
+       if (klass == mono_defaults.transparent_proxy_class) {
+               klass = ((MonoTransparentProxy *)obj)->klass;
+               is_proxy = TRUE;
+       } else {
+               is_proxy = FALSE;
+       }
+       vtable = klass->vtable;
+
+       if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+               res = vtable [method->klass->interface_id + method->slot];
+       } else {
+               res = vtable [method->slot];
+       }
+       g_assert (res);
+
+       if (is_proxy)
+               return mono_marshal_get_remoting_invoke (res);
+       
+       return res;
+}
+
+static MonoObject*
+dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
+{
+       g_error ("runtime invoke called on uninitialized runtime");
+       return NULL;
+}
+
+static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
 
 MonoObject*
 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
 {
-       if (!default_mono_runtime_invoke) {
-               g_error ("runtime invoke called on uninitialized runtime");
-               return NULL;
+       return default_mono_runtime_invoke (method, obj, params, exc);
+}
+
+static void
+set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
+       int t;
+       if (type->byref) {
+               gpointer *p = (gpointer*)dest;
+               *p = value;
+               return;
+       }
+       t = type->type;
+handle_enum:
+       switch (t) {
+       case MONO_TYPE_BOOLEAN:
+       case MONO_TYPE_I1:
+       case MONO_TYPE_U1: {
+               guint8 *p = (guint8*)dest;
+               *p = *(guint8*)value;
+               return;
+       }
+       case MONO_TYPE_I2:
+       case MONO_TYPE_U2:
+       case MONO_TYPE_CHAR: {
+               guint16 *p = (guint16*)dest;
+               *p = *(guint16*)value;
+               return;
+       }
+#if SIZEOF_VOID_P == 4
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
+#endif
+       case MONO_TYPE_I4:
+       case MONO_TYPE_U4: {
+               gint32 *p = (gint32*)dest;
+               *p = *(gint32*)value;
+               return;
+       }
+#if SIZEOF_VOID_P == 8
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
+#endif
+       case MONO_TYPE_I8:
+       case MONO_TYPE_U8: {
+               gint64 *p = (gint64*)dest;
+               *p = *(gint64*)value;
+               return;
+       }
+       case MONO_TYPE_R4: {
+               float *p = (float*)dest;
+               *p = *(float*)value;
+               return;
        }
+       case MONO_TYPE_R8: {
+               double *p = (double*)dest;
+               *p = *(double*)value;
+               return;
+       }
+       case MONO_TYPE_STRING:
+       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_CLASS:
+       case MONO_TYPE_OBJECT:
+       case MONO_TYPE_ARRAY:
+       case MONO_TYPE_PTR: {
+               gpointer *p = (gpointer*)dest;
+               *p = deref_pointer? *(gpointer*)value: value;
+               return;
+       }
+       case MONO_TYPE_VALUETYPE:
+               if (type->data.klass->enumtype) {
+                       t = type->data.klass->enum_basetype->type;
+                       goto handle_enum;
+               } else {
+                       int size;
+                       size = mono_class_value_size (type->data.klass, NULL);
+                       memcpy (dest, value, size);
+               }
+               return;
+       default:
+               g_warning ("got type %x", type->type);
+               g_assert_not_reached ();
+       }
+}
 
-       return default_mono_runtime_invoke (method, obj, params, exc);
+void
+mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
+{
+       void *dest;
+
+       g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
+
+       dest = (char*)obj + field->offset;
+       set_value (field->type, dest, value, FALSE);
 }
 
+void
+mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
+{
+       void *dest;
+
+       g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
+
+       dest = (char*)vt->data + field->offset;
+       set_value (field->type, dest, value, FALSE);
+}
+
+void
+mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
+{
+       void *src;
+
+       g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
+
+       src = (char*)obj + field->offset;
+       set_value (field->type, value, src, TRUE);
+}
+
+void
+mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
+{
+       void *src;
+
+       g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
+
+       src = (char*)vt->data + field->offset;
+       set_value (field->type, value, src, TRUE);
+}
+
+void
+mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
+{
+       default_mono_runtime_invoke (prop->set, obj, params, exc);
+}
+
+MonoObject*
+mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
+{
+       return default_mono_runtime_invoke (prop->get, obj, params, exc);
+}
+
+
 MonoMethod *
 mono_get_delegate_invoke (MonoClass *klass)
 {
@@ -411,10 +633,12 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
                        MonoString *arg = mono_string_new (domain, argv [i]);
                        mono_array_set (args, gpointer, i, arg);
                }
+       } else {
+               args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
        }
        
        mono_assembly_set_main (method->klass->image->assembly);
-       
+
        return mono_runtime_exec_main (method, args, exc);
 }
 
@@ -433,24 +657,45 @@ mono_unhandled_exception (MonoObject *exc)
                                             "UnhandledException");
        g_assert (field);
 
-       delegate = *(MonoObject **)(((char *)domain->domain) + field->offset); 
+       if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
+               delegate = *(MonoObject **)(((char *)domain->domain) + field->offset); 
 
-       if (!delegate) {
-               mono_print_unhandled_exception (exc);
-       } else {
-               MonoObject *e = NULL;
-               gpointer pa [2];
+               if (!delegate) {
+                       mono_print_unhandled_exception (exc);
+               } else {
+                       MonoObject *e = NULL;
+                       gpointer pa [2];
 
-               /* fixme: pass useful arguments */
-               pa [0] = NULL;
-               pa [1] = NULL;
-               mono_runtime_delegate_invoke (delegate, pa, &e);
-              
-               if (e)
-                       g_warning ("exception inside UnhandledException handler!");
+                       /* fixme: pass useful arguments */
+                       pa [0] = NULL;
+                       pa [1] = NULL;
+                       mono_runtime_delegate_invoke (delegate, pa, &e);
+                       
+                       if (e)
+                               g_warning ("exception inside UnhandledException handler!");
+               }
        }
 }
 
+/*
+ * Launch a new thread to start all setup that requires managed code
+ * to be executed.
+ *
+ * main_func is called back from the thread with main_args as the
+ * parameter.  The callback function is expected to start Main()
+ * eventually.  This function then waits for all managed threads to
+ * finish.
+ */
+void
+mono_runtime_exec_managed_code (MonoDomain *domain,
+                               MonoMainThreadFunc main_func,
+                               gpointer main_args)
+{
+       mono_thread_create (domain, main_func, main_args);
+
+       mono_thread_manage ();
+}
+
 /*
  * Execute a standard Main() method (args doesn't contain the
  * executable name).
@@ -458,11 +703,21 @@ mono_unhandled_exception (MonoObject *exc)
 int
 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
 {
+       MonoDomain *domain;
        gpointer pa [1];
+       MonoObject *res;
        int rval;
 
+       g_assert (args);
+
        pa [0] = args;
 
+       domain = mono_object_domain (args);
+       if (!domain->entry_assembly) {
+               domain->entry_assembly = method->klass->image->assembly;
+               ves_icall_System_AppDomainSetup_InitAppDomainSetup (domain->setup);
+       }
+
        /* FIXME: check signature of method */
        if (method->signature->ret->type == MONO_TYPE_I4) {
                MonoObject *res;
@@ -471,12 +726,21 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
                        rval = *(guint32 *)((char *)res + sizeof (MonoObject));
                else
                        rval = -1;
+
+               mono_environment_exitcode_set (rval);
        } else {
                mono_runtime_invoke (method, NULL, pa, exc);
                if (!exc || !*exc)
                        rval = 0;
-               else
+               else {
+                       /* If the return type of Main is void, only
+                        * set the exitcode if an exception was thrown
+                        * (we don't want to blow away an
+                        * explicitly-set exit code)
+                        */
                        rval = -1;
+                       mono_environment_exitcode_set (rval);
+               }
        }
 
        return rval;
@@ -485,7 +749,7 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
 void
 mono_install_runtime_invoke (MonoInvokeFunc func)
 {
-       default_mono_runtime_invoke = func;
+       default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
 }
 
 MonoObject*
@@ -516,12 +780,15 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                        case MONO_TYPE_I4:
                        case MONO_TYPE_U8:
                        case MONO_TYPE_I8:
+                       case MONO_TYPE_R4:
+                       case MONO_TYPE_R8:
                        case MONO_TYPE_VALUETYPE:
                                pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
                                break;
                        case MONO_TYPE_STRING:
                        case MONO_TYPE_OBJECT:
                        case MONO_TYPE_CLASS:
+                       case MONO_TYPE_ARRAY:
                        case MONO_TYPE_SZARRAY:
                                pa [i] = (char *)(((gpointer *)params->vector)[i]);
                                break;
@@ -532,7 +799,8 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
        }
 
        if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
-               obj = mono_object_new (mono_domain_get (), method->klass);
+               if (!obj)
+                       obj = mono_object_new (mono_domain_get (), method->klass);
                mono_runtime_invoke (method, obj, pa, exc);
                return obj;
        } else
@@ -553,11 +821,13 @@ mono_object_allocate (size_t size)
 {
 #if HAVE_BOEHM_GC
        /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
-       void *o = GC_malloc (size);
+       void *o = GC_MALLOC (size);
 #else
        void *o = calloc (1, size);
 #endif
 
+       mono_stats.new_object_count++;
+
        return o;
 }
 
@@ -605,13 +875,12 @@ mono_object_new_specific (MonoVTable *vtable)
 {
        MonoObject *o;
 
-       mono_stats.new_object_count++;
-
        o = mono_object_allocate (vtable->klass->instance_size);
        o->vtable = vtable;
        if (vtable->klass->has_finalize)
                mono_object_register_finalizer (o);
        
+       mono_profiler_allocation (o, vtable->klass);
        return o;
 }
 
@@ -648,6 +917,7 @@ mono_object_clone (MonoObject *obj)
 
        size = obj->vtable->klass->instance_size;
        o = mono_object_allocate (size);
+       mono_profiler_allocation (o, obj->vtable->klass);
 
        memcpy (o, obj, size);
 
@@ -670,6 +940,8 @@ mono_array_clone (MonoArray *array)
        guint32 *sizes;
        MonoClass *klass = array->obj.vtable->klass;
 
+       MONO_ARCH_SAVE_REGS;
+
        if (array->bounds == NULL) {
                size = mono_array_length (array);
                o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
@@ -727,7 +999,7 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
                len = lengths [0];
        } else {
        #if HAVE_BOEHM_GC
-               bounds = GC_malloc (sizeof (MonoArrayBounds) * array_class->rank);
+               bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
        #else
                bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
        #endif
@@ -756,6 +1028,8 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
        array->bounds = bounds;
        array->max_length = len;
 
+       mono_profiler_allocation (o, array_class);
+
        return array;
 }
 
@@ -794,7 +1068,17 @@ mono_array_new_specific (MonoVTable *vtable, guint32 n)
        gsize byte_len;
 
        byte_len = n * mono_array_element_size (vtable->klass);
+#if CREATION_SPEEDUP
+       if (vtable->klass->element_class->byval_arg.type >= MONO_TYPE_BOOLEAN && vtable->klass->element_class->byval_arg.type <= MONO_TYPE_R4) {
+               o = GC_MALLOC_ATOMIC (sizeof (MonoArray) + byte_len);
+               o->synchronisation = 0;
+               memset (((MonoArray*)o)->vector, 0, byte_len);
+       } else {
+               o = mono_object_allocate (sizeof (MonoArray) + byte_len);
+       }
+#else
        o = mono_object_allocate (sizeof (MonoArray) + byte_len);
+#endif
        if (!o)
                G_BREAKPOINT ();
        o->vtable = vtable;
@@ -802,6 +1086,7 @@ mono_array_new_specific (MonoVTable *vtable, guint32 n)
        ao = (MonoArray *)o;
        ao->bounds = NULL;
        ao->max_length = n;
+       mono_profiler_allocation (o, vtable->klass);
 
        return ao;
 }
@@ -838,12 +1123,8 @@ mono_string_new_size (MonoDomain *domain, gint32 len)
 {
        MonoString *s;
 
-       /* 
-        * enable to get a good speedup: we still need to figure out
-        * how the sync structure is freed.
-        */
-#if 0
-       s = GC_malloc_atomic (sizeof (MonoString) + ((len + 1) * 2));
+#if CREATION_SPEEDUP
+       s = GC_MALLOC_ATOMIC (sizeof (MonoString) + ((len + 1) * 2));
        s->object.synchronisation = 0;
        mono_string_chars (s) [len] = 0;
 #else
@@ -854,6 +1135,7 @@ mono_string_new_size (MonoDomain *domain, gint32 len)
 
        s->object.vtable = mono_class_vtable (domain, mono_defaults.string_class);
        s->length = len;
+       mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
 
        return s;
 }
@@ -950,6 +1232,7 @@ mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
        size = mono_class_instance_size (class);
        res = mono_object_allocate (size);
        res->vtable = mono_class_vtable (domain, class);
+       mono_profiler_allocation (res, class);
 
        size = size - sizeof (MonoObject);
 
@@ -1011,8 +1294,8 @@ mono_object_isinst (MonoObject *obj, MonoClass *klass)
                }
                if (klass->rank) {
                        if (oklass->rank == klass->rank && 
-                           (oklass->element_class->baseval - klass->element_class->baseval) <= 
-                           klass->element_class->diffval)
+                           (oklass->cast_class->baseval - klass->cast_class->baseval) <= 
+                           klass->cast_class->diffval)
                                return obj;
                        
                } else if ((oklass->baseval - klass->baseval) <= klass->diffval)
@@ -1101,8 +1384,11 @@ mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
        const char *str, *sig;
        MonoString *o;
        size_t len2;
-               
-       sig = str = mono_metadata_user_string (image, idx);
+
+       if (image->assembly->dynamic)
+               return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
+       else
+               sig = str = mono_metadata_user_string (image, idx);
 
        mono_domain_lock (domain);
        if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
@@ -1185,6 +1471,23 @@ mono_string_to_utf16 (MonoString *s)
        return (gunichar2 *)(as);
 }
 
+/*
+ * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
+ */
+MonoString *
+mono_string_from_utf16 (gunichar2 *data)
+{
+       MonoDomain *domain = mono_domain_get ();
+       int len = 0;
+
+       if (!data)
+               return NULL;
+
+       while (data [len]) len++;
+
+       return mono_string_new_utf16 (domain, data, len);
+}
+
 static void
 default_ex_handler (MonoException *ex)
 {
@@ -1375,27 +1678,49 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
 void
 mono_print_unhandled_exception (MonoObject *exc)
 {
-       char *message = g_strdup ("");
-       char *trace = g_strdup ("");
+       char *message = (char *) "";
        MonoString *str; 
+       MonoMethod *method;
+       MonoClass *klass;
+       gboolean free_message = FALSE;
+       gint i;
 
        if (mono_object_isinst (exc, mono_defaults.exception_class)) {
-               if ((str = ((MonoException *)exc)->message))
+               klass = exc->vtable->klass;
+               method = NULL;
+               while (klass && method == NULL) {
+                       for (i = 0; i < klass->method.count; ++i) {
+                               method = klass->methods [i];
+                               if (!strcmp ("ToString", method->name) &&
+                                   method->signature->param_count == 0 &&
+                                   method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
+                                   method->flags & METHOD_ATTRIBUTE_PUBLIC) {
+                                       break;
+                               }
+                               method = NULL;
+                       }
+                       
+                       if (method == NULL)
+                               klass = klass->parent;
+               }
+
+               g_assert (method);
+
+               str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
+               if (str) {
                        message = mono_string_to_utf8 (str);
-               if ((str = ((MonoException *)exc)->stack_trace))
-                       trace = mono_string_to_utf8 (str);
+                       free_message = TRUE;
+               }
        }                               
 
-       g_warning ("unhandled exception %s.%s: \"%s\"", exc->vtable->klass->name_space, 
-                  exc->vtable->klass->name, message);
+       /*
+        * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space, 
+        *         exc->vtable->klass->name, message);
+        */
+       g_printerr ("\nUnhandled Exception: %s\n", message);
        
-       if (trace) {
-               g_printerr (trace);
-               g_printerr ("\n");
-       }
-
-       g_free (message);
-       g_free (trace);
+       if (free_message)
+               g_free (message);
 }
 
 /**
@@ -1423,12 +1748,13 @@ mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
 
        if ((ji = mono_jit_info_table_find (domain, addr))) {
                method = ji->method;
-               delegate->method_info = mono_method_get_object (domain, method);
+               delegate->method_info = mono_method_get_object (domain, method, NULL);
        }
 
        if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
                g_assert (method);
-               delegate->method_ptr = arch_create_remoting_trampoline (method);
+               method = mono_marshal_get_remoting_invoke (method);
+               delegate->method_ptr = mono_compile_method (method);
                delegate->target = target;
        } else {
                delegate->method_ptr = addr;
@@ -1453,10 +1779,10 @@ mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *
        msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class); 
        
        if (invoke) {
-               mono_message_init (domain, msg, mono_method_get_object (domain, invoke), NULL);
+               mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
                count =  sig->param_count - 2;
        } else {
-               mono_message_init (domain, msg, mono_method_get_object (domain, method), NULL);
+               mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
                count =  sig->param_count;
        }
 
@@ -1499,10 +1825,12 @@ void
 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
 {
        MonoMethodSignature *sig = method->signature;
-       int i, j, type, size, align;
+       int i, j, type, size;
        
        for (i = 0, j = 0; i < sig->param_count; i++) {
-               MonoType *pt = mono_get_param_info (sig, i, &size, &align);
+               MonoType *pt = sig->params [i];
+
+               size = mono_type_stack_size (pt, NULL);
 
                if (pt->byref) {
                        char *arg = mono_array_get (out_args, gpointer, j);
@@ -1543,6 +1871,122 @@ mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoAr
        }
 }
 
+/**
+ * mono_load_remote_field:
+ * @this: pointer to an object
+ * @klass: klass of the object containing @field
+ * @field: the field to load
+ * @res: a storage to store the result
+ *
+ * This method is called by the runtime on attempts to load fields of
+ * transparent proxy objects. @this points to such TP, @klass is the class of
+ * the object containing @field. @res is a storage location which can be
+ * used to store the result.
+ *
+ * Returns: an address pointing to the value of field.
+ */
+gpointer
+mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
+{
+       static MonoMethod *getter = NULL;
+       MonoDomain *domain = mono_domain_get ();
+       MonoClass *field_class;
+       MonoMethodMessage *msg;
+       MonoArray *out_args;
+       MonoObject *exc;
+       gpointer tmp;
+
+       g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
+
+       if (!res)
+               res = &tmp;
+
+       if (!getter) {
+               int i;
+
+               for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
+                       MonoMethod *cm = mono_defaults.object_class->methods [i];
+              
+                       if (!strcmp (cm->name, "FieldGetter")) {
+                               getter = cm;
+                               break;
+                       }
+               }
+               g_assert (getter);
+       }
+       
+       field_class = mono_class_from_mono_type (field->type);
 
+       msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
+       out_args = mono_array_new (domain, mono_defaults.object_class, 1);
+       mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
 
+       mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
+       mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
+
+       mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)this)->rp, msg, &exc, &out_args);
+
+       *res = mono_array_get (out_args, MonoObject *, 0);
+
+       if (field_class->valuetype) {
+               return ((char *)*res) + sizeof (MonoObject);
+       } else
+               return res;
+}
+
+/**
+ * mono_store_remote_field:
+ * @this: pointer to an object
+ * @klass: klass of the object containing @field
+ * @field: the field to load
+ * @val: the value/object to store
+ *
+ * This method is called by the runtime on attempts to store fields of
+ * transparent proxy objects. @this points to such TP, @klass is the class of
+ * the object containing @field. @val is the new value to store in @field.
+ */
+void
+mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
+{
+       static MonoMethod *setter = NULL;
+       MonoDomain *domain = mono_domain_get ();
+       MonoClass *field_class;
+       MonoMethodMessage *msg;
+       MonoArray *out_args;
+       MonoObject *exc;
+       MonoObject *arg;
+
+       g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
+
+       if (!setter) {
+               int i;
+
+               for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
+                       MonoMethod *cm = mono_defaults.object_class->methods [i];
+              
+                       if (!strcmp (cm->name, "FieldSetter")) {
+                               setter = cm;
+                               break;
+                       }
+               }
+               g_assert (setter);
+       }
+
+       field_class = mono_class_from_mono_type (field->type);
+
+       if (field_class->valuetype)
+               arg = mono_value_box (domain, field_class, val);
+       else 
+               arg = *((MonoObject **)val);
+               
+
+       msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
+       mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
+
+       mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
+       mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
+       mono_array_set (msg->args, gpointer, 2, arg);
+
+       mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)this)->rp, msg, &exc, &out_args);
+}