Wed Aug 14 17:26:27 CEST 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / object.c
index ce8c5d75542159bb5cf1c1d00d10984cd44bda8f..84845dd778d076954d2f5b5be9ee85530c51c3fe 100644 (file)
@@ -243,8 +243,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:
@@ -348,6 +359,144 @@ mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **
        return default_mono_runtime_invoke (method, obj, params, exc);
 }
 
+static void
+set_value (MonoType *type, void *dest, void *value) {
+       int t;
+       if (type->byref) {
+               gpointer *p = (gpointer*)dest;
+               *p = value;
+               return;
+       }
+handle_enum:
+       t = type->type;
+       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 = 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 ();
+       }
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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)
 {
@@ -439,21 +588,23 @@ 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!");
+               }
        }
 }
 
@@ -1429,12 +1580,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;
@@ -1459,10 +1611,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;
        }
 
@@ -1551,6 +1703,125 @@ 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);
+}
+