2002-03-12 Dietmar Maurer <dietmar@ximian.com>
authorDietmar Maurer <dietmar@mono-cvs.ximian.com>
Tue, 12 Mar 2002 12:40:51 +0000 (12:40 -0000)
committerDietmar Maurer <dietmar@mono-cvs.ximian.com>
Tue, 12 Mar 2002 12:40:51 +0000 (12:40 -0000)
* class.c (class_compute_field_layout): separate computation of
static field layout

svn path=/trunk/mono/; revision=3067

mono/metadata/ChangeLog
mono/metadata/class.c
mono/metadata/class.h
mono/metadata/metadata.c
mono/tests/delegate.cs

index fd1b0d2983f054b2b049714e90c05beee47bfa48..ab4dd7c37c1adfa6e156013510114a4b97745b11 100644 (file)
@@ -1,3 +1,8 @@
+2002-03-12  Dietmar Maurer  <dietmar@ximian.com>
+
+       * class.c (class_compute_field_layout): separate computation of 
+       static field layout
+
 2002-03-12  Dan Lewis <dihlewis@yahoo.co.uk>
 
        * icall.c: added System.Buffer support.
index 188f532fcac47592885ed901c42cc115d1d17df2..9e91bc120ab694cad45abbded35a5f2b780f05ea 100644 (file)
@@ -150,33 +150,84 @@ class_compute_field_layout (MonoClass *class)
                        G_BREAKPOINT ();
        }
        /*
-        * Compute field layout and total size.
+        * Compute field layout and total size (not considering static fields)
         */
-       switch (layout){
+       switch (layout) {
        case TYPE_ATTRIBUTE_AUTO_LAYOUT:
        case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
                for (i = 0; i < top; i++){
                        int size, align;
                        
+                       if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
+                               continue;
+
                        size = mono_type_size (class->fields [i].type, &align);
-                       if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC) {
-                               class->fields [i].offset = class->class_size;
-                               class->fields [i].offset += align - 1;
-                               class->fields [i].offset &= ~(align - 1);
-                               class->class_size = class->fields [i].offset + size;
-                       } else {
-                               class->min_align = MAX (align, class->min_align);
-                               class->fields [i].offset = class->instance_size;
-                               class->fields [i].offset += align - 1;
-                               class->fields [i].offset &= ~(align - 1);
-                               class->instance_size = class->fields [i].offset + size;
-                       }
+
+                       class->min_align = MAX (align, class->min_align);
+                       class->fields [i].offset = class->instance_size;
+                       class->fields [i].offset += align - 1;
+                       class->fields [i].offset &= ~(align - 1);
+                       class->instance_size = class->fields [i].offset + size;
                }
+       
                if (class->instance_size & (class->min_align - 1)) {
                        class->instance_size += class->min_align - 1;
                        class->instance_size &= ~(class->min_align - 1);
                }
                break;
+       case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
+               for (i = 0; i < top; i++) {
+                       int size, align;
+                       int idx = class->field.first + i;
+
+                       /*
+                        * There must be info about all the fields in a type if it
+                        * uses explicit layout.
+                        */
+
+                       if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
+                               continue;
+
+                       size = mono_type_size (class->fields [i].type, &align);
+                       
+                       mono_metadata_field_info (m, idx, &class->fields [i].offset, NULL, NULL);
+                       if (class->fields [i].offset == (guint32)-1)
+                               g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, class->fields [i].name);
+                       /*
+                        * The offset is from the start of the object: this works for both
+                        * classes and valuetypes.
+                        */
+                       class->fields [i].offset += sizeof (MonoObject);
+                       /*
+                        * Calc max size.
+                        */
+                       size += class->fields [i].offset;
+                       class->instance_size = MAX (class->instance_size, size);
+               }
+               break;
+       }
+
+       class->size_inited = 1;
+
+       /*
+        * Compute static field layout and size
+        */
+       switch (layout) {
+       case TYPE_ATTRIBUTE_AUTO_LAYOUT:
+       case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
+               for (i = 0; i < top; i++){
+                       int size, align;
+                       
+                       if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
+                               continue;
+                       
+                       size = mono_type_size (class->fields [i].type, &align);
+                       class->fields [i].offset = class->class_size;
+                       class->fields [i].offset += align - 1;
+                       class->fields [i].offset &= ~(align - 1);
+                       class->class_size = class->fields [i].offset + size;
+               }
+               break;
        case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
                for (i = 0; i < top; i++){
                        int size, align;
@@ -187,27 +238,15 @@ class_compute_field_layout (MonoClass *class)
                         * uses explicit layout.
                         */
 
+                       
+                       if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
+                               continue;
+
                        size = mono_type_size (class->fields [i].type, &align);
-                       if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC) {
-                               class->fields [i].offset = class->class_size;
-                               class->fields [i].offset += align - 1;
-                               class->fields [i].offset &= ~(align - 1);
-                               class->class_size = class->fields [i].offset + size;
-                       } else {
-                               mono_metadata_field_info (m, idx, &class->fields [i].offset, NULL, NULL);
-                               if (class->fields [i].offset == (guint32)-1)
-                                               g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, class->fields [i].name);
-                               /*
-                                * The offset is from the start of the object: this works for both
-                                * classes and valuetypes.
-                                */
-                               class->fields [i].offset += sizeof (MonoObject);
-                               /*
-                                * Calc max size.
-                                */
-                               size += class->fields [i].offset;
-                               class->instance_size = MAX (class->instance_size, size);
-                       }
+                       class->fields [i].offset = class->class_size;
+                       class->fields [i].offset += align - 1;
+                       class->fields [i].offset &= ~(align - 1);
+                       class->class_size = class->fields [i].offset + size;
                }
                break;
        }
@@ -333,7 +372,13 @@ mono_class_init (MonoClass *class)
 
        if (class->inited)
                return;
-       class->inited = 1;
+
+       if (class->init_pending) {
+               /* this indicates a cyclic dependency */
+               g_error ("pending init %s.%s\n", class->name_space, class->name);
+       }
+
+       class->init_pending = 1;
 
        if (class->parent) {
                if (!class->parent->inited)
@@ -348,7 +393,7 @@ mono_class_init (MonoClass *class)
        /*
         * Computes the size used by the fields, and their locations
         */
-       if (class->field.count > 0){
+       if (!class->size_inited && class->field.count > 0){
                class->fields = g_new0 (MonoClassField, class->field.count);
                class_compute_field_layout (class);
        }
@@ -362,6 +407,8 @@ mono_class_init (MonoClass *class)
        if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
                for (i = 0; i < class->method.count; ++i)
                        class->methods [i]->slot = i;
+               class->init_pending = 0;
+               class->inited = 1;
                return;
        }
 
@@ -626,6 +673,9 @@ mono_class_init (MonoClass *class)
                }
        }
 
+       class->inited = 1;
+       class->init_pending = 0;
+
 #define GHC_SLOT 2
 
        if (!default_ghc) {
@@ -1023,8 +1073,10 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 
        //class->interfaces = mono_metadata_interfaces_from_typedef (image, type_token, &class->interface_count);
 
-       if (class->enumtype)
-               mono_class_init (class);
+       if (class->enumtype) {
+               class->fields = g_new0 (MonoClassField, class->field.count);
+               class_compute_field_layout (class);
+       } 
 
        if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
                class->nested_in = mono_class_create_from_typedef (image, type_token);
@@ -1234,7 +1286,7 @@ gint32
 mono_class_instance_size (MonoClass *klass)
 {
        
-       if (!klass->inited)
+       if (!klass->size_inited)
                mono_class_init (klass);
 
        return klass->instance_size;
index d7608ea067e1f096258469d5d2ef00f26eeae9a7..eb5eab60c7b495c09c4823be7c088d78cb4fe9ae 100644 (file)
@@ -39,6 +39,8 @@ struct _MonoClass {
 
        guint dummy           : 1; /* temorary hack */
        guint inited          : 1;
+       guint init_pending    : 1;
+       guint size_inited     : 1;
        guint valuetype       : 1; /* derives from System.ValueType */
        guint enumtype        : 1; /* derives from System.Enum */
        guint ghcimpl         : 1; /* class has its own GetHashCode impl */ 
index 3cb5d3694f395549a21faffca01c5cd75c10fe0a..d1a9aee7ba2a70dbd3c495e108bb2f52610a50de 100644 (file)
@@ -1887,6 +1887,9 @@ mono_type_size (MonoType *t, gint *align)
        case MONO_TYPE_VALUETYPE: {
                guint32 size;
 
+               if (!t->data.klass->size_inited)
+                       mono_class_init (t->data.klass);
+
                if (t->data.klass->enumtype) {
                        return mono_type_size (t->data.klass->enum_basetype, align);
                } else {
index 8d9ecd3570f832b8bf00d35866c34e56b6cf879a..683d840b06655b22f881c0d548bf332bc609490f 100644 (file)
@@ -1,8 +1,14 @@
 using System;
+using System.Runtime.InteropServices;
+
 namespace Bah {
 class Test {
+       [DllImport("cygwin1.dll", EntryPoint="puts", CharSet=CharSet.Ansi)]
+       public static extern int puts (string name);
+
        delegate void SimpleDelegate ();
        delegate string NotSimpleDelegate (int a);
+       delegate int AnotherDelegate (string s);
        
        public int data;
        
@@ -39,6 +45,20 @@ class Test {
 
                if (d.Method.Name != "F")
                        return 1;
+
+               if (d3.Method == null)
+                       return 1;
+               
+               object [] args = {3};
+               d3.DynamicInvoke (args);
+
+               AnotherDelegate d4 = new AnotherDelegate (puts);
+               if (d4.Method == null)
+                       return 1;
+
+               Console.WriteLine (d4.Method);
+               Console.WriteLine (d4.Method.Name);
+               Console.WriteLine (d4.Method.DeclaringType);
                
                return 0;
        }