2006-06-08 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / class.c
index e99c185248303f33f76c0f9c2b2d699765fcb19c..2242760ba601fb5413a43c5d70c684848ebd2afa 100644 (file)
@@ -4,14 +4,8 @@
  * Author:
  *   Miguel de Icaza (miguel@ximian.com)
  *
- * (C) 2001 Ximian, Inc.
+ * (C) 2001-2006 Novell, Inc.
  *
- * Possible Optimizations:
- *     in mono_class_create, do not allocate the class right away,
- *     but wait until you know the size of the FieldMap, so that
- *     the class embeds directly the FieldMap after the vtable.
- *
- * 
  */
 #include <config.h>
 #include <glib.h>
@@ -35,6 +29,7 @@
 #include <mono/metadata/exception.h>
 #include <mono/metadata/security-manager.h>
 #include <mono/os/gc_wrapper.h>
+#include <mono/utils/mono-counters.h>
 
 MonoStats mono_stats;
 
@@ -47,6 +42,16 @@ static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedCl
 void (*mono_debugger_start_class_init_func) (MonoClass *klass) = NULL;
 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
 
+/*
+ * mono_class_from_typeref:
+ * @image: a MonoImage
+ * @type_token: a TypeRef token
+ *
+ * Creates the MonoClass* structure representing the type defined by
+ * the typeref token valid inside @image.
+ * Returns: the MonoClass* representing the typeref token, NULL ifcould
+ * not be loaded.
+ */
 MonoClass *
 mono_class_from_typeref (MonoImage *image, guint32 type_token)
 {
@@ -70,7 +75,19 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token)
                /* a typedef in disguise */
                return mono_class_from_name (image, nspace, name);
        case MONO_RESOLTION_SCOPE_MODULEREF:
-               return mono_class_from_name (image->modules [idx - 1], nspace, name);
+               if (image->modules [idx-1])
+                       return mono_class_from_name (image->modules [idx - 1], nspace, name);
+               else {
+                       char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
+                       char *human_name;
+                       
+                       human_name = mono_stringify_assembly_name (&image->assembly->aname);
+                       mono_loader_set_error_type_load (msg, human_name);
+                       g_free (msg);
+                       g_free (human_name);
+               
+                       return NULL;
+               }
        case MONO_RESOLTION_SCOPE_TYPEREF: {
                MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
                GList *tmp;
@@ -109,8 +126,19 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token)
        /* If this assert fails, it probably means that you haven't installed an assembly load/search hook */
        g_assert (references == image->references);
        g_assert (references [idx - 1]);
-       if (references [idx - 1] == (gpointer)-1)
+
+       /* If the assembly did not load, register this as a type load exception */
+       if (references [idx - 1] == REFERENCE_MISSING){
+               MonoAssemblyName aname;
+               char *human_name;
+               
+               mono_assembly_get_assemblyref (image, idx - 1, &aname);
+               human_name = mono_stringify_assembly_name (&aname);
+               mono_loader_set_error_assembly_load (human_name, image->assembly->ref_only);
+               g_free (human_name);
+               
                return NULL;
+       }
 
        return mono_class_from_name (references [idx - 1]->image, nspace, name);
 }
@@ -352,6 +380,12 @@ mono_type_get_full_name (MonoClass *class)
        return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
 }
 
+/**
+ * mono_type_get_name:
+ * @type: a type
+ *
+ * Returns: the string representation for type as it would be represented in IL code.
+ */
 char*
 mono_type_get_name (MonoType *type)
 {
@@ -373,6 +407,14 @@ mono_type_get_underlying_type (MonoType *type)
        return type;
 }
 
+/*
+ * mono_class_is_open_constructed_type:
+ * @type: a type
+ *
+ * Returns TRUE if type represents a generics open constructed type
+ * (not all the type parameters required for the instantiation have
+ * been provided).
+ */
 gboolean
 mono_class_is_open_constructed_type (MonoType *t)
 {
@@ -493,8 +535,11 @@ inflate_generic_type (MonoType *type, MonoGenericContext *context)
                MonoType *nt;
                if (!gclass->inst->is_open)
                        return NULL;
+               gclass = inflate_generic_class (gclass, context);
+               if (gclass == type->data.generic_class)
+                       return NULL;
                nt = dup_type (type, type);
-               nt->data.generic_class = inflate_generic_class (gclass, context);
+               nt->data.generic_class = gclass;
                return nt;
        }
        case MONO_TYPE_CLASS:
@@ -505,9 +550,9 @@ inflate_generic_type (MonoType *type, MonoGenericContext *context)
 
                if (!klass->generic_container)
                        return NULL;
-
                gclass = inflate_generic_class (klass->generic_container->context.gclass, context);
-
+               if (gclass == klass->generic_container->context.gclass)
+                       return NULL;
                nt = dup_type (type, type);
                nt->type = MONO_TYPE_GENERICINST;
                nt->data.generic_class = gclass;
@@ -527,6 +572,15 @@ mono_get_inflated_generic_class (MonoGenericClass *gclass)
        return (MonoInflatedGenericClass *) gclass;
 }
 
+/*
+ * mono_class_inflate_generic_type:
+ * @type: a type
+ * @context: a generics context
+ *
+ * Instantiate the generic type @type, using the generics context @context.
+ *
+ * Returns: the instantiated type
+ */
 MonoType*
 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
 {
@@ -539,65 +593,19 @@ mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
        return inflated;
 }
 
-MonoMethodSignature*
-mono_class_inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, MonoGenericContext *context)
-{
-       MonoMethodSignature *res;
-       gboolean is_open;
-       int i;
-
-       if (!context)
-               return sig;
-
-       res = mono_metadata_signature_alloc (image, sig->param_count);
-       res->ret = mono_class_inflate_generic_type (sig->ret, context);
-       is_open = mono_class_is_open_constructed_type (res->ret);
-       for (i = 0; i < sig->param_count; ++i) {
-               res->params [i] = mono_class_inflate_generic_type (sig->params [i], context);
-               if (!is_open)
-                       is_open = mono_class_is_open_constructed_type (res->params [i]);
-       }
-       res->hasthis = sig->hasthis;
-       res->explicit_this = sig->explicit_this;
-       res->call_convention = sig->call_convention;
-       res->pinvoke = sig->pinvoke;
-       res->generic_param_count = sig->generic_param_count;
-       res->sentinelpos = sig->sentinelpos;
-       res->has_type_parameters = is_open;
-       res->is_inflated = 1;
-       return res;
-}
-
-static MonoMethodHeader*
-inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context)
-{
-       MonoMethodHeader *res;
-       int i;
-       res = g_malloc0 (sizeof (MonoMethodHeader) + sizeof (gpointer) * header->num_locals);
-       res->code = header->code;
-       res->code_size = header->code_size;
-       res->max_stack = header->max_stack;
-       res->num_clauses = header->num_clauses;
-       res->init_locals = header->init_locals;
-       res->num_locals = header->num_locals;
-       res->clauses = header->clauses;
-       for (i = 0; i < header->num_locals; ++i)
-               res->locals [i] = mono_class_inflate_generic_type (header->locals [i], context);
-       return res;
-}
-
 static MonoGenericContext *
 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with)
 {
        MonoGenericClass *gclass = NULL;
        MonoGenericMethod *gmethod = NULL;
+       MonoGenericContext *res;
 
        if (context->gclass)
                gclass = inflate_generic_class (context->gclass, inflate_with);
 
        if (context->gmethod) {
                MonoGenericInst *ninst = mono_metadata_inflate_generic_inst (context->gmethod->inst, inflate_with);
-               if (ninst == context->gmethod->inst) {
+               if (gclass == context->gclass && ninst == context->gmethod->inst) {
                        gmethod = context->gmethod;
                } else {
                        gmethod = g_new0 (MonoGenericMethod, 1);
@@ -605,17 +613,12 @@ inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflat
                        gmethod->container = context->container;
                        gmethod->inst = ninst;
                }
-       } else if (inflate_with->gmethod) {
-               gmethod = inflate_with->gmethod;
-               /* See mini/jit-icalls.c:helper_compile_generic_method for the rationale to the
-                  first part of this assert. */
-               g_assert (!(gclass && gclass->inst->is_open) || gmethod->container->parent == context->container);
        }
 
        if (gclass == context->gclass && gmethod == context->gmethod)
                return context;
 
-       MonoGenericContext *res = g_new0 (MonoGenericContext, 1);
+       res = g_new0 (MonoGenericContext, 1);
 
        res->container = gmethod ? gmethod->container : context->container;
        res->gclass = gclass;
@@ -624,6 +627,21 @@ inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflat
        return res;
 }
 
+/*
+ * mono_class_inflate_generic_method:
+ * @method: a generic method
+ * @context: a generics context
+ *
+ * Instantiate the generic method @method using the generics context @context.
+ *
+ * Returns: the new instantiated method
+ */
+MonoMethod *
+mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
+{
+       return mono_class_inflate_generic_method_full (method, NULL, context);
+}
+
 /**
  * mono_class_inflate_generic_method:
  *
@@ -632,37 +650,67 @@ inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflat
  *         Use mono_get_inflated_method (), mono_method_signature () and mono_method_get_header () to get the correct values.
  */
 MonoMethod*
-mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
+mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
 {
-       MonoMethodInflated *result;
-       MonoGenericContainer *container = context ? context->container : NULL;
+       MonoMethod *result;
+       MonoMethodInflated *iresult;
        MonoMethodSignature *sig;
 
        /* The `method' has already been instantiated before -> we need to create a new context. */
-       sig = mono_method_signature_full (method, container);
-       if (method->is_inflated || sig->is_inflated) {
+       while (method->is_inflated) {
                MonoMethodInflated *imethod = (MonoMethodInflated *) method;
-
                context = inflate_generic_context (imethod->context, context);
+               if (context == imethod->context)
+                       return method;
                method = imethod->declaring;
        }
 
+       if (!method->generic_container && !method->klass->generic_container)
+               return method;
+
        mono_stats.inflated_method_count++;
+       iresult = g_new0 (MonoMethodInflated, 1);
 
-       /* Just create a copy, but don't actually inflate the method for performance reasons. */
-       result = g_new0 (MonoMethodInflated, 1);
-       if (sig->pinvoke)
-               result->method.pinvoke = *(MonoMethodPInvoke*)method;
-       else
-               result->method.normal = *(MonoMethodNormal*)method;
-       result->method.method.is_inflated = 1;
-       result->context = context;
-       result->declaring = method;
+       sig = mono_method_signature (method);
+       if (sig->pinvoke) {
+               iresult->method.pinvoke = *(MonoMethodPInvoke*)method;
+       } else {
+               iresult->method.normal = *(MonoMethodNormal*)method;
+               iresult->method.normal.header = NULL;
+       }
+
+       result = (MonoMethod *) iresult;
+       result->is_inflated = 1;
+       result->signature = NULL;
+       iresult->context = context;
+       iresult->declaring = method;
+
+       if (!klass_hint || !klass_hint->generic_class ||
+           klass_hint->generic_class->container_class != method->klass ||
+           klass_hint->generic_class->inst != context->gclass->inst)
+               klass_hint = NULL;
+
+       if (method->klass->generic_container)
+               result->klass = klass_hint;
+
+       if (!result->klass) {
+               MonoType *inflated = inflate_generic_type (&method->klass->byval_arg, context);
+               result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
+       }
+
+       if (method->generic_container && !context->gmethod) {
+               MonoGenericMethod *gmethod = g_memdup (method->generic_container->context.gmethod, sizeof (*gmethod));
+               gmethod->generic_class = result->klass->generic_class;
 
-       if (result->method.method.klass->generic_class)
-               result->method.method.klass = result->method.method.klass->generic_class->container_class;
+               context = g_new0 (MonoGenericContext, 1);
+               context->container = method->generic_container;
+               context->gclass = result->klass->generic_class;
+               context->gmethod = gmethod;
 
-       return (MonoMethod *) result;
+               iresult->context = context;
+       }
+
+       return result;
 }
 
 /**
@@ -671,41 +719,12 @@ mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *conte
  * For performance reasons, mono_class_inflate_generic_method() does not actually instantiate the
  * method, it just "prepares" it for that.  If you really need to fully instantiate the method
  * (including its signature and header), call this method.
+ * FIXME: Martin? this description looks completely wrong.
  */
 MonoMethod *
 mono_get_inflated_method (MonoMethod *method)
 {
-       MonoMethodInflated *imethod, *res;
-       MonoMethodHeader *mh;
-       MonoType *dtype;
-       MonoClass *rklass;
-
-       if (!method->is_inflated)
-               return method;
-
-       imethod = (MonoMethodInflated *) method;
-       if (imethod->inflated)
-               return (MonoMethod *) imethod->inflated;
-
-       mono_stats.inflated_method_count_2++;
-       mono_stats.generics_metadata_size +=
-               sizeof (MonoMethodInflated) - sizeof (MonoMethodNormal);
-
-       res = g_new0 (MonoMethodInflated, 1);
-       *res = *imethod;
-       res->inflated = imethod->inflated = res;
-
-       mh = mono_method_get_header (method);
-       if (mh)
-               res->method.normal.header = inflate_generic_header (mh, imethod->context);
-
-       dtype = mono_class_inflate_generic_type (&method->klass->byval_arg, imethod->context);
-       rklass = res->method.method.klass = mono_class_from_mono_type (dtype);
-
-       res->method.method.signature = mono_class_inflate_generic_signature (
-               method->klass->image, mono_method_signature (method), imethod->context);
-
-       return (MonoMethod *) res;
+       return method;
 }
 
 /** 
@@ -768,16 +787,17 @@ mono_class_find_enum_basetype (MonoClass *class)
  * @class: The class to initialize
  *
  * Initializes the class->fields.
- * Assumes the loader lock is held.
+ * LOCKING: Assumes the loader lock is held.
  */
 static void
 mono_class_setup_fields (MonoClass *class)
 {
        MonoImage *m = class->image; 
-       const int top = class->field.count;
+       int top = class->field.count;
        guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
        MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
-       int i, blittable = TRUE, real_size = 0;
+       int i, blittable = TRUE;
+       guint32 real_size = 0;
        guint32 packing_size = 0;
        gboolean explicit_size;
        MonoClassField *field;
@@ -787,13 +807,18 @@ mono_class_setup_fields (MonoClass *class)
        if (class->size_inited)
                return;
 
-       if (class->inited)
-               mono_class_init (class);
+       if (class->generic_class) {
+               MonoClass *gklass = class->generic_class->container_class;
+               mono_class_setup_fields (gklass);
+               top = gklass->field.count;
+       }
 
        class->instance_size = 0;
        class->class_size = 0;
 
        if (class->parent) {
+               /* For generic instances, class->parent might not have been initialized */
+               mono_class_init (class->parent);
                if (!class->parent->size_inited)
                        mono_class_setup_fields (class->parent);
                class->instance_size += class->parent->instance_size;
@@ -879,12 +904,14 @@ mono_class_setup_fields (MonoClass *class)
                        field->type = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
                        if (!field->type) {
                                mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
-                               continue;
+                               break;
                        }
                        if (mono_field_is_deleted (field))
                                continue;
                        if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
-                               mono_metadata_field_info (m, idx, &field->offset, NULL, NULL);
+                               guint32 offset;
+                               mono_metadata_field_info (m, idx, &offset, NULL, NULL);
+                               field->offset = offset;
                                if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
                                        g_warning ("%s not initialized correctly (missing field layout info for %s)",
                                                   class->name, field->name);
@@ -931,6 +958,8 @@ mono_class_setup_fields (MonoClass *class)
                class->instance_size = MAX (real_size, class->instance_size);
        }
 
+       if (class->exception_type)
+               return;
        mono_class_layout_fields (class);
 }
 
@@ -938,7 +967,7 @@ mono_class_setup_fields (MonoClass *class)
  * mono_class_setup_fields_locking:
  * @class: The class to initialize
  *
- * Initializes the class->fields.
+ * Initializes the class->fields array of fields.
  * Aquires the loader lock.
  */
 static void
@@ -969,9 +998,24 @@ mono_class_has_references (MonoClass *klass)
 }
 
 /* useful until we keep track of gc-references in corlib etc. */
+#ifdef HAVE_SGEN_GC
+#define IS_GC_REFERENCE(t) FALSE
+#else
 #define IS_GC_REFERENCE(t) ((t)->type == MONO_TYPE_U || (t)->type == MONO_TYPE_I || (t)->type == MONO_TYPE_PTR)
+#endif
 
 /*
+ * mono_class_layout_fields:
+ * @class: a class
+ *
+ * Compute the placement of fields inside an object or struct, according to
+ * the layout rules and set the following fields in @class:
+ *  - has_references (if the class contains instance references firled or structs that contain references)
+ *  - has_static_refs (same, but for static fields)
+ *  - instance_size (size of the object in memory)
+ *  - class_size (size needed for the static fields)
+ *  - size_inited (flag set when the instance_size is set)
+ *
  * LOCKING: this is supposed to be called with the loader lock held.
  */
 void
@@ -1182,10 +1226,13 @@ mono_class_layout_fields (MonoClass *class)
 
 /*
  * mono_class_setup_methods:
+ * @class: a class
  *
  *   Initializes the 'methods' array in the klass.
  * Calling this method should be avoided if possible since it allocates a lot 
  * of long-living MonoMethod structures.
+ * Methods belonging to an interface are assigned a sequential slot starting
+ * from 0.
  */
 void
 mono_class_setup_methods (MonoClass *class)
@@ -1278,37 +1325,52 @@ mono_class_setup_properties (MonoClass *class)
        mono_loader_unlock ();
 }
 
+/*
+ * LOCKING: assumes the loader lock is held.
+ */
 static void
 inflate_event (MonoClass *class, MonoEvent *event, MonoInflatedGenericClass *gclass)
 {
        event->parent = class;
 
        if (event->add) {
-               MonoMethod *inflated = mono_class_inflate_generic_method (
-                       event->add, gclass->generic_class.context);
+               MonoMethod *inflated = mono_class_inflate_generic_method_full (
+                       event->add, class, gclass->generic_class.context);
 
                event->add = mono_get_inflated_method (inflated);
        }
 
        if (event->remove) {
-               MonoMethod *inflated = mono_class_inflate_generic_method (
-                       event->remove, gclass->generic_class.context);
+               MonoMethod *inflated = mono_class_inflate_generic_method_full (
+                       event->remove, class, gclass->generic_class.context);
 
                event->remove = mono_get_inflated_method (inflated);
        }
 
        if (event->raise) {
-               MonoMethod *inflated = mono_class_inflate_generic_method (
-                       event->raise, gclass->generic_class.context);
+               MonoMethod *inflated = mono_class_inflate_generic_method_full (
+                       event->raise, class, gclass->generic_class.context);
 
                event->raise = mono_get_inflated_method (inflated);
        }
 
        if (event->other) {
-               MonoMethod *inflated = mono_class_inflate_generic_method (
-                       event->other, gclass->generic_class.context);
-
-               event->other = mono_get_inflated_method (inflated);
+               MonoMethod **om = event->other;
+               int count = 0;
+               while (*om) {
+                       count++;
+                       om++;
+               }
+               om = event->other;
+               event->other = g_new0 (MonoMethod*, count + 1);
+               count = 0;
+               while (*om) {
+                       MonoMethod *inflated = mono_class_inflate_generic_method_full (
+                               *om, class, gclass->generic_class.context);
+
+                       event->other [count++] = mono_get_inflated_method (inflated);
+                       om++;
+               }
        }
 }
 
@@ -1385,13 +1447,15 @@ mono_class_setup_events (MonoClass *class)
                                int n = 0;
 
                                if (event->other == NULL) {
-                                       event->other = g_new0 (MonoMethod*, 1);
+                                       event->other = g_new0 (MonoMethod*, 2);
                                } else {
                                        while (event->other [n])
                                                n++;
-                                       event->other = g_realloc (event->other, (n + 1) * sizeof (MonoMethod*));
+                                       event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
                                }
                                event->other [n] = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
+                               /* NULL terminated */
+                               event->other [n + 1] = NULL;
                                break;
                        }
                        default:
@@ -1405,49 +1469,84 @@ mono_class_setup_events (MonoClass *class)
        mono_loader_unlock ();
 }
 
+/*
+ * Global pool of interface IDs, represented as a bitset.
+ * LOCKING: this is supposed to be accessed with the loader lock held.
+ */
+static MonoBitSet *global_interface_bitset = NULL;
+
+/*
+ * mono_unload_interface_ids:
+ * @bitset: bit set of interface IDs
+ *
+ * When an image is unloaded, the interface IDs associated with
+ * the image are put back in the global pool of IDs so the numbers
+ * can be reused.
+ */
+void
+mono_unload_interface_ids (MonoBitSet *bitset)
+{
+       mono_loader_lock ();
+       mono_bitset_sub (global_interface_bitset, bitset);
+       mono_loader_unlock ();
+}
+
+/*
+ * mono_get_unique_iid:
+ * @class: interface
+ *
+ * Assign a unique integer ID to the interface represented by @class.
+ * The ID will positive and as small as possible.
+ * LOCKING: this is supposed to be called with the loader lock held.
+ * Returns: the new ID.
+ */
 static guint
 mono_get_unique_iid (MonoClass *class)
 {
-       static GHashTable *iid_hash = NULL;
-       static guint iid = 0;
-       char *str, *type_name;
-       gpointer value;
-       int generic_id;
+       int iid;
        
        g_assert (MONO_CLASS_IS_INTERFACE (class));
 
-       mono_loader_lock ();
-
-       if (!iid_hash)
-               iid_hash = g_hash_table_new (g_str_hash, g_str_equal);
-
-       if (class->generic_class && !class->generic_class->inst->is_open) {
-               generic_id = class->generic_class->inst->id;
-               g_assert (generic_id != 0);
-       } else
-               generic_id = 0;
-
-       type_name = mono_type_full_name (&class->byval_arg);
-       str = g_strdup_printf ("%s|%s|%d", class->image->name, type_name, generic_id);
-       g_free (type_name);
-
-       if (g_hash_table_lookup_extended (iid_hash, str, NULL, &value)) {
-               mono_loader_unlock ();
-               if (mono_print_vtable)
-                       printf ("Interface: reusing id %d for %s\n", iid, str);
-               g_free (str);
-               return GPOINTER_TO_INT (value);
+       if (!global_interface_bitset) {
+               global_interface_bitset = mono_bitset_new (128, 0);
+       }
+
+       iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
+       if (iid < 0) {
+               int old_size = mono_bitset_size (global_interface_bitset);
+               MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
+               mono_bitset_free (global_interface_bitset);
+               global_interface_bitset = new_set;
+               iid = old_size;
+       }
+       mono_bitset_set (global_interface_bitset, iid);
+       /* set the bit also in the per-image set */
+       if (class->image->interface_bitset) {
+               if (iid >= mono_bitset_size (class->image->interface_bitset)) {
+                       MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
+                       mono_bitset_free (class->image->interface_bitset);
+                       class->image->interface_bitset = new_set;
+               }
        } else {
-               if (mono_print_vtable)
-                       printf ("Interface: assigned id %d to %s\n", iid, str);
-               g_hash_table_insert (iid_hash, str, GINT_TO_POINTER (iid));
-               ++iid;
+               class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
        }
+       mono_bitset_set (class->image->interface_bitset, iid);
 
-       mono_loader_unlock ();
+       if (mono_print_vtable) {
+               int generic_id;
+               char *type_name = mono_type_full_name (&class->byval_arg);
+               if (class->generic_class && !class->generic_class->inst->is_open) {
+                       generic_id = class->generic_class->inst->id;
+                       g_assert (generic_id != 0);
+               } else {
+                       generic_id = 0;
+               }
+               printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
+               g_free (type_name);
+       }
 
        g_assert (iid <= 65535);
-       return iid - 1;
+       return iid;
 }
 
 static void
@@ -1544,6 +1643,9 @@ cache_interface_offsets (int max_iid, int *data)
        return cached;
 }
 
+/*
+ * LOCKING: this is supposed to be called with the loader lock held.
+ */
 static int
 setup_interface_offsets (MonoClass *class, int cur_slot)
 {
@@ -1581,7 +1683,7 @@ setup_interface_offsets (MonoClass *class, int cur_slot)
        }
        class->max_interface_id = max_iid;
        /* compute vtable offset for interfaces */
-       class->interface_offsets = g_malloc (sizeof (gpointer) * (max_iid + 1));
+       class->interface_offsets = g_malloc (sizeof (int) * (max_iid + 1));
 
        for (i = 0; i <= max_iid; i++)
                class->interface_offsets [i] = -1;
@@ -1624,34 +1726,17 @@ setup_interface_offsets (MonoClass *class, int cur_slot)
        return cur_slot;
 }
 
-static void
-setup_generic_vtable (MonoClass *class)
+/*
+ * Setup interface offsets for interfaces. Used by Ref.Emit.
+ */
+void
+mono_class_setup_interface_offsets (MonoClass *class)
 {
-       MonoClass *gklass;
-       int i;
-
-       gklass = class->generic_class->container_class;
-
-       mono_class_init (gklass);
-       class->vtable_size = gklass->vtable_size;
-
-       class->vtable = g_new0 (MonoMethod*, class->vtable_size);
-       memcpy (class->vtable, gklass->vtable,  sizeof (MonoMethod*) * class->vtable_size);
-
-       for (i = 0; i < class->vtable_size; i++) {
-               MonoMethod *m = class->vtable [i];
-
-               if (!m)
-                       continue;
+       mono_loader_lock ();
 
-               m = mono_class_inflate_generic_method (m, class->generic_class->context);
-               class->vtable [i] = m;
-       }
+       setup_interface_offsets (class, 0);
 
-       class->max_interface_id = gklass->max_interface_id;
-       class->interface_offsets = g_new0 (gint, gklass->max_interface_id + 1);
-       memcpy (class->interface_offsets, gklass->interface_offsets,
-               sizeof (gint) * (gklass->max_interface_id + 1));
+       mono_loader_unlock ();
 }
 
 void
@@ -1661,6 +1746,7 @@ mono_class_setup_vtable (MonoClass *class)
        MonoGenericContext *context;
        guint32 type_token;
        int onum = 0;
+       gboolean ok = TRUE;
 
        if (class->vtable)
                return;
@@ -1678,12 +1764,6 @@ mono_class_setup_vtable (MonoClass *class)
        }
 
        if (class->generic_class) {
-               if (class->generic_class->inst->is_open) {
-                       setup_generic_vtable (class);
-                       mono_loader_unlock ();
-                       return;
-               }
-
                context = class->generic_class->context;
                type_token = class->generic_class->container_class->type_token;
        } else {
@@ -1693,13 +1773,19 @@ mono_class_setup_vtable (MonoClass *class)
 
        if (class->image->dynamic)
                mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
-       else
-               mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
+       else {
+               /* The following call fails if there are missing methods in the type */
+               ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
+       }
 
-       mono_class_setup_vtable_general (class, overrides, onum);
+       if (ok)
+               mono_class_setup_vtable_general (class, overrides, onum);
+               
        g_free (overrides);
 
        mono_loader_unlock ();
+
+       return;
 }
 
 /*
@@ -1718,11 +1804,6 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
        if (class->vtable)
                return;
 
-       if (class->generic_class && class->generic_class->inst->is_open) {
-               setup_generic_vtable (class);
-               return;
-       }
-
        ifaces = mono_class_get_implemented_interfaces (class);
        if (ifaces) {
                for (i = 0; i < ifaces->len; i++) {
@@ -1994,10 +2075,21 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                                int j;
                                for (j = 0; j < k->method.count; ++j) {
                                        MonoMethod *m1 = k->methods [j];
+                                       MonoMethodSignature *cmsig, *m1sig;
+
                                        if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
                                                continue;
+
+                                       cmsig = mono_method_signature (cm);
+                                       m1sig = mono_method_signature (m1);
+
+                                       if (!cmsig || !m1sig) {
+                                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                                               return;
+                                       }
+
                                        if (!strcmp(cm->name, m1->name) && 
-                                           mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (m1))) {
+                                           mono_metadata_signature_equal (cmsig, m1sig)) {
 
                                                /* CAS - SecurityAction.InheritanceDemand */
                                                if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
@@ -2063,7 +2155,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
        } else
                class->vtable_size = cur_slot;
 
-       class->vtable = g_malloc0 (sizeof (gpointer) * class->vtable_size);
+       class->vtable = mono_mempool_alloc0 (class->image->mempool, sizeof (gpointer) * class->vtable_size);
        memcpy (class->vtable, vtable,  sizeof (gpointer) * class->vtable_size);
 
        if (mono_print_vtable) {
@@ -2110,6 +2202,46 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
        }
 }
 
+static MonoMethod *default_ghc = NULL;
+static MonoMethod *default_finalize = NULL;
+static int finalize_slot = -1;
+static int ghc_slot = -1;
+
+static void
+initialize_object_slots (MonoClass *class)
+{
+       int i;
+       if (default_ghc)
+               return;
+       if (class == mono_defaults.object_class) { 
+               mono_class_setup_vtable (class);                       
+               for (i = 0; i < class->vtable_size; ++i) {
+                       MonoMethod *cm = class->vtable [i];
+       
+                       if (!strcmp (cm->name, "GetHashCode"))
+                               ghc_slot = i;
+                       else if (!strcmp (cm->name, "Finalize"))
+                               finalize_slot = i;
+               }
+
+               g_assert (ghc_slot > 0);
+               default_ghc = class->vtable [ghc_slot];
+
+               g_assert (finalize_slot > 0);
+               default_finalize = class->vtable [finalize_slot];
+       }
+}
+
+static GList*
+g_list_prepend_mempool (GList* l, MonoMemPool* mp, gpointer datum)
+{
+       GList* n = mono_mempool_alloc (mp, sizeof (GList));
+       n->next = l;
+       n->prev = NULL;
+       n->data = datum;
+       return n;
+}
+
 /**
  * mono_class_init:
  * @class: the class to initialize
@@ -2117,23 +2249,23 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
  * compute the instance_size, class_size and other infos that cannot be 
  * computed at mono_class_get() time. Also compute a generic vtable and 
  * the method slot numbers. We use this infos later to create a domain
- * specific vtable.  
+ * specific vtable.
+ *
+ * Returns TRUE on success or FALSE if there was a problem in loading
+ * the type (incorrect assemblies, missing assemblies, methods, etc). 
  */
-void
+gboolean
 mono_class_init (MonoClass *class)
 {
        int i;
-       static MonoMethod *default_ghc = NULL;
-       static MonoMethod *default_finalize = NULL;
-       static int finalize_slot = -1;
-       static int ghc_slot = -1;
        MonoCachedClassInfo cached_info;
        gboolean has_cached_info;
-
+       int class_init_ok = TRUE;
+       
        g_assert (class);
 
        if (class->inited)
-               return;
+               return TRUE;
 
        /*g_print ("Init class %s\n", class->name);*/
 
@@ -2143,7 +2275,7 @@ mono_class_init (MonoClass *class)
        if (class->inited) {
                mono_loader_unlock ();
                /* Somebody might have gotten in before us */
-               return;
+               return TRUE;
        }
 
        if (class->init_pending) {
@@ -2187,8 +2319,8 @@ mono_class_init (MonoClass *class)
                class->methods = g_new0 (MonoMethod *, class->method.count);
 
                for (i = 0; i < class->method.count; i++) {
-                       MonoMethod *inflated = mono_class_inflate_generic_method (
-                               gklass->methods [i], gclass->generic_class.context);
+                       MonoMethod *inflated = mono_class_inflate_generic_method_full (
+                               gklass->methods [i], class, gclass->generic_class.context);
 
                        class->methods [i] = mono_get_inflated_method (inflated);
                }
@@ -2202,11 +2334,11 @@ mono_class_init (MonoClass *class)
                        *prop = gklass->properties [i];
 
                        if (prop->get)
-                               prop->get = mono_class_inflate_generic_method (
-                                       prop->get, gclass->generic_class.context);
+                               prop->get = mono_class_inflate_generic_method_full (
+                                       prop->get, class, gclass->generic_class.context);
                        if (prop->set)
-                               prop->set = mono_class_inflate_generic_method (
-                                       prop->set, gclass->generic_class.context);
+                               prop->set = mono_class_inflate_generic_method_full (
+                                       prop->set, class, gclass->generic_class.context);
 
                        prop->parent = class;
                }
@@ -2226,7 +2358,7 @@ mono_class_init (MonoClass *class)
                        guint32 cols [MONO_NESTED_CLASS_SIZE];
                        mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
                        nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
-                       class->nested_classes = g_list_prepend (class->nested_classes, nclass);
+                       class->nested_classes = g_list_prepend_mempool (class->nested_classes, class->image->mempool, nclass);
 
                        i = mono_metadata_nesting_typedef (class->image, class->type_token, i + 1);
                }
@@ -2245,8 +2377,14 @@ mono_class_init (MonoClass *class)
                class->has_static_refs = cached_info.has_static_refs;
        }
        else
-               if (!class->size_inited)
+               if (!class->size_inited){
                        mono_class_setup_fields (class);
+                       if (class->exception_type || mono_loader_get_last_error ()){
+                               class_init_ok = FALSE;
+                               goto leave;
+                       }
+               }
+                               
 
        /* initialize method pointers */
        if (class->rank) {
@@ -2259,14 +2397,14 @@ mono_class_init (MonoClass *class)
                for (i = 0; i < class->rank; ++i)
                        sig->params [i] = &mono_defaults.int32_class->byval_arg;
 
-               ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1);
+               ctor = (MonoMethod *) mono_mempool_alloc0 (class->image->mempool, sizeof (MonoMethodPInvoke));
                ctor->klass = class;
                ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
                ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
                ctor->signature = sig;
                ctor->name = ".ctor";
                ctor->slot = -1;
-               class->methods = g_new (MonoMethod*, class->method.count);
+               class->methods = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoMethod*) * class->method.count);
                class->methods [0] = ctor;
                if (class->rank > 1) {
                        sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
@@ -2275,7 +2413,7 @@ mono_class_init (MonoClass *class)
                        for (i = 0; i < class->rank * 2; ++i)
                                sig->params [i] = &mono_defaults.int32_class->byval_arg;
 
-                       ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1);
+                       ctor = (MonoMethod *) mono_mempool_alloc0 (class->image->mempool, sizeof (MonoMethodPInvoke));
                        ctor->klass = class;
                        ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
                        ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
@@ -2288,41 +2426,8 @@ mono_class_init (MonoClass *class)
 
        mono_class_setup_supertypes (class);
 
-       if (!default_ghc) {
-               if (class == mono_defaults.object_class) { 
-                       mono_class_setup_vtable (class);                       
-                       for (i = 0; i < class->vtable_size; ++i) {
-                               MonoMethod *cm = class->vtable [i];
-              
-                               if (!strcmp (cm->name, "GetHashCode")) {
-                                       ghc_slot = i;
-                                       break;
-                               }
-                       }
-
-                       g_assert (ghc_slot > 0);
-
-                       default_ghc = class->vtable [ghc_slot];
-               }
-       }
-
-       if (!default_finalize) {
-               if (class == mono_defaults.object_class) { 
-                       mono_class_setup_vtable (class);                       
-                       for (i = 0; i < class->vtable_size; ++i) {
-                               MonoMethod *cm = class->vtable [i];
-              
-                               if (!strcmp (cm->name, "Finalize")) {
-                                       finalize_slot = i;
-                                       break;
-                               }
-                       }
-
-                       g_assert (finalize_slot > 0);
-
-                       default_finalize = class->vtable [finalize_slot];
-               }
-       }
+       if (!default_ghc)
+               initialize_object_slots (class);
 
        /*
         * If possible, avoid the creation of the generic vtable by requesting
@@ -2345,7 +2450,12 @@ mono_class_init (MonoClass *class)
        }
        else {
                mono_class_setup_vtable (class);
-       
+
+               if (class->exception_type || mono_loader_get_last_error ()){
+                       class_init_ok = FALSE;
+                       goto leave;
+               }
+
                class->ghcimpl = 1;
                if (class->parent) { 
                        MonoMethod *cmethod = class->vtable [ghc_slot];
@@ -2377,11 +2487,6 @@ mono_class_init (MonoClass *class)
                }
        }
 
-       class->inited = 1;
-       class->init_pending = 0;
-       
-       mono_loader_unlock ();
-
        if (MONO_CLASS_IS_INTERFACE (class)) {
                /* 
                 * class->interface_offsets is needed for the castclass/isinst code, so
@@ -2390,8 +2495,16 @@ mono_class_init (MonoClass *class)
                setup_interface_offsets (class, 0);
        }
 
+ leave:
+       class->inited = 1;
+       class->init_pending = 0;
+
+       mono_loader_unlock ();
+
        if (mono_debugger_class_init_func)
                mono_debugger_class_init_func (class);
+
+       return class_init_ok;
 }
 
 /*
@@ -2584,6 +2697,16 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
 }
 
 /*
+ * mono_class_setup_supertypes:
+ * @class: a class
+ *
+ * Build the data structure needed to make fast type checks work.
+ * This currently sets two fields in @class:
+ *  - idepth: distance between @class and System.Object in the type
+ *    hierarchy + 1
+ *  - supertypes: array of classes: each element has a class in the hierarchy
+ *    starting from @class up to System.Object
+ * 
  * LOCKING: this assumes the loader lock is held
  */
 void
@@ -2602,7 +2725,7 @@ mono_class_setup_supertypes (MonoClass *class)
                class->idepth = 1;
 
        ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
-       class->supertypes = g_new0 (MonoClass *, ms);
+       class->supertypes = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClass *) * ms);
 
        if (class->parent) {
                class->supertypes [class->idepth - 1] = class;
@@ -2676,8 +2799,12 @@ mono_get_shared_generic_class (MonoGenericContainer *container, gboolean is_dyna
 }
 
 /**
- * @image: context where the image is created
+ * mono_class_create_from_typedef:
+ * @image: image where the token is valid
  * @type_token:  typedef token
+ *
+ * Create the MonoClass* representing the specified type token.
+ * @type_token must be a TypeDef token.
  */
 static MonoClass *
 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
@@ -2708,7 +2835,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
        nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
 
-       class = g_malloc0 (sizeof (MonoClass));
+       class = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
 
        class->name = name;
        class->name_space = nspace;
@@ -2733,6 +2860,11 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        if (cols [MONO_TYPEDEF_EXTENDS]) {
                parent = mono_class_get_full (
                        image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]), context);
+               if (parent == NULL){
+                       g_hash_table_remove (image->class_cache, GUINT_TO_POINTER (type_token));
+                       mono_loader_unlock ();
+                       return NULL;
+               }
        }
 
        /* do this early so it's available for interfaces in setup_mono_type () */
@@ -2741,6 +2873,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 
        mono_class_setup_parent (class, parent);
 
+       /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
        mono_class_setup_mono_type (class);
 
        if (!class->enumtype) {
@@ -2752,10 +2885,11 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 
        if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
                class->unicode = 1;
-       /* fixme: maybe we must set this on windows 
+
+#if PLATFORM_WIN32
        if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
                class->unicode = 1;
-       */
+#endif
 
        class->cast_class = class->element_class = class;
 
@@ -2839,9 +2973,11 @@ mono_class_create_generic (MonoInflatedGenericClass *gclass)
        MonoClass *klass, *gklass;
        int i;
 
-       if (gclass->is_initialized)
+       mono_loader_lock ();
+       if (gclass->is_initialized) {
+               mono_loader_unlock ();
                return;
-       gclass->is_initialized = TRUE;
+       }
 
        if (!gclass->klass)
                gclass->klass = g_malloc0 (sizeof (MonoClass));
@@ -2849,7 +2985,16 @@ mono_class_create_generic (MonoInflatedGenericClass *gclass)
 
        gklass = gclass->generic_class.container_class;
 
-       klass->nested_in = gklass->nested_in;
+       if (gklass->nested_in) {
+               /* 
+                * FIXME: the nested type context should include everything the
+                * nesting context should have, but it may also have additional
+                * generic parameters...
+                */
+               MonoType *inflated = mono_class_inflate_generic_type (
+                       &gklass->nested_in->byval_arg, gclass->generic_class.context);
+               klass->nested_in = mono_class_from_mono_type (inflated);
+       }
 
        klass->name = gklass->name;
        klass->name_space = gklass->name_space;
@@ -2899,12 +3044,7 @@ mono_class_create_generic (MonoInflatedGenericClass *gclass)
                i = mono_metadata_nesting_typedef (klass->image, gklass->type_token, i + 1);
        }
 
-       if (gclass->generic_class.is_dynamic) {
-               MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *) gclass;
-
-               if (dgclass->parent)
-                       klass->parent = mono_class_from_mono_type (dgclass->parent);
-       } else if (gklass->parent) {
+       if (gklass->parent) {
                MonoType *inflated = mono_class_inflate_generic_type (
                        &gklass->parent->byval_arg, gclass->generic_class.context);
 
@@ -2916,6 +3056,8 @@ mono_class_create_generic (MonoInflatedGenericClass *gclass)
 
        if (MONO_CLASS_IS_INTERFACE (klass))
                setup_interface_offsets (klass, 0);
+       gclass->is_initialized = TRUE;
+       mono_loader_unlock ();
 }
 
 MonoClass *
@@ -2983,22 +3125,28 @@ mono_ptr_class_get (MonoType *type)
 {
        MonoClass *result;
        MonoClass *el_class;
-       static GHashTable *ptr_hash = NULL;
+       MonoImage *image;
+       char *name;
+
+       el_class = mono_class_from_mono_type (type);
+       image = el_class->image;
 
        mono_loader_lock ();
 
-       if (!ptr_hash)
-               ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
-       el_class = mono_class_from_mono_type (type);
-       if ((result = g_hash_table_lookup (ptr_hash, el_class))) {
+       if (!image->ptr_cache)
+               image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
+
+       if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
                mono_loader_unlock ();
                return result;
        }
-       result = g_new0 (MonoClass, 1);
+       result = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
 
        result->parent = NULL; /* no parent for PTR types */
        result->name_space = el_class->name_space;
-       result->name = g_strdup_printf ("%s*", el_class->name);
+       name = g_strdup_printf ("%s*", el_class->name);
+       result->name = mono_mempool_strdup (image->mempool, name);
+       g_free (name);
        result->image = el_class->image;
        result->inited = TRUE;
        result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
@@ -3014,7 +3162,7 @@ mono_ptr_class_get (MonoType *type)
 
        mono_class_setup_supertypes (result);
 
-       g_hash_table_insert (ptr_hash, el_class, result);
+       g_hash_table_insert (image->ptr_cache, el_class, result);
 
        mono_loader_unlock ();
 
@@ -3027,6 +3175,8 @@ mono_fnptr_class_get (MonoMethodSignature *sig)
        MonoClass *result;
        static GHashTable *ptr_hash = NULL;
 
+       /* FIXME: These should be allocate from a mempool as well, but which one ? */
+
        mono_loader_lock ();
 
        if (!ptr_hash)
@@ -3041,7 +3191,7 @@ mono_fnptr_class_get (MonoMethodSignature *sig)
        result->parent = NULL; /* no parent for PTR types */
        result->name_space = "System";
        result->name = "MonoFNPtrFakeClass";
-       result->image = NULL; /* need to fix... */
+       result->image = mono_defaults.corlib; /* need to fix... */
        result->inited = TRUE;
        result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
        /* Can pointers get boxed? */
@@ -3173,6 +3323,9 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
 
        mono_loader_lock ();
 
+       if (!image->array_cache)
+               image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
+
        if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
                for (; list; list = list->next) {
                        class = list->data;
@@ -3205,7 +3358,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
                        mono_class_init (parent);
        }
 
-       class = g_malloc0 (sizeof (MonoClass));
+       class = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
 
        class->image = image;
        class->name_space = eclass->name_space;
@@ -3217,7 +3370,8 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
                memset (name + nsize + 1, ',', rank - 1);
        name [nsize + rank] = ']';
        name [nsize + rank + 1] = 0;
-       class->name = name;
+       class->name = mono_mempool_strdup (image->mempool, name);
+       g_free (name);
        class->type_token = 0;
        /* all arrays are marked serializable and sealed, bug #42779 */
        class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED |
@@ -3242,7 +3396,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
        class->element_class = eclass;
 
        if ((rank > 1) || bounded) {
-               MonoArrayType *at = g_new0 (MonoArrayType, 1);
+               MonoArrayType *at = mono_mempool_alloc0 (image->mempool, sizeof (MonoArrayType));
                class->byval_arg.type = MONO_TYPE_ARRAY;
                class->byval_arg.data.array = at;
                at->eklass = eclass;
@@ -3465,12 +3619,6 @@ mono_class_get_event_token (MonoEvent *event)
        return 0;
 }
 
-void *
-mono_vtable_get_static_field_data (MonoVTable *vt)
-{
-       return vt->data;
-}
-
 MonoProperty*
 mono_class_get_property_from_name (MonoClass *klass, const char *name)
 {
@@ -3641,6 +3789,10 @@ MonoClass *
 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
 {
        MonoClass *class = mono_class_get (image, type_token);
+
+       if (!image->dynamic && ((type_token & 0xff000000) == MONO_TOKEN_TYPE_DEF))
+               return class;
+
        if (class && context && (context->gclass || context->gmethod)) {
                MonoType *inflated = inflate_generic_type (&class->byval_arg, context);
                if (inflated)
@@ -3823,6 +3975,17 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name
                        if (nested)
                                return return_nested_in (class, nested);
                        return class;
+               } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
+                       MonoAssembly **references = image->references;
+                       if (!references [idx - 1])
+                               mono_assembly_load_reference (image, idx - 1);
+                       g_assert (references == image->references);
+                       g_assert (references [idx - 1]);
+                       if (references [idx - 1] == (gpointer)-1)
+                               return NULL;                    
+                       else
+                               /* FIXME: Cycle detection */
+                               return mono_class_from_name (references [idx - 1]->image, name_space, name);
                } else {
                        g_error ("not yet implemented");
                }
@@ -3840,7 +4003,6 @@ gboolean
 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
                           gboolean check_interfaces)
 {
- again:
        g_assert (klassc->idepth > 0);
        if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
                if ((klassc->interface_id <= klass->max_interface_id) &&
@@ -3866,18 +4028,6 @@ mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
        if (klassc == mono_defaults.object_class)
                return TRUE;
 
-       if (klass->generic_class && klass->generic_class->is_dynamic) {
-               MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *) klass->generic_class;
-
-               if (!dgclass->parent)
-                       return FALSE;
-
-               if (mono_metadata_type_equal (dgclass->parent, &klassc->byval_arg))
-                       return TRUE;
-               klass = mono_class_from_mono_type (dgclass->parent);
-               goto again;
-       }
-       
        return FALSE;
 }
 
@@ -3967,22 +4117,9 @@ MonoMethod*
 mono_class_get_finalizer (MonoClass *klass)
 {
        MonoCachedClassInfo cached_info;
-       static int finalize_slot = -1;
-
-       if (finalize_slot < 0) {
-               int i;
-               MonoClass* obj_class = mono_get_object_class ();
-               mono_class_setup_vtable (obj_class);
-               for (i = 0; i < obj_class->vtable_size; ++i) {
-                       MonoMethod *cm = obj_class->vtable [i];
-              
-                       if (!strcmp (mono_method_get_name (cm), "Finalize")) {
-                               finalize_slot = i;
-                               break;
-                       }
-               }
-       }
 
+       if (!klass->inited)
+               mono_class_init (klass);
        if (!klass->has_finalize)
                return NULL;
 
@@ -4916,6 +5053,37 @@ mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
        return TRUE;
 }
 
+/**
+ * mono_classes_init:
+ *
+ * Initialize the resources used by this module.
+ */
+void
+mono_classes_init (void)
+{
+}
+
+/**
+ * mono_classes_cleanup:
+ *
+ * Free the resources used by this module.
+ */
+void
+mono_classes_cleanup (void)
+{
+       IOffsetInfo *cached_info, *next;
+
+       if (global_interface_bitset)
+               mono_bitset_free (global_interface_bitset);
+
+       for (cached_info = cached_offset_info; cached_info;) {
+               next = cached_info->next;
+
+               g_free (cached_info);
+               cached_info = next;
+       }
+}
+
 /**
  * mono_class_get_exception_for_failure:
  * @klass: class in which the failure was detected
@@ -4946,8 +5114,19 @@ mono_class_get_exception_for_failure (MonoClass *klass)
        }
        case MONO_EXCEPTION_TYPE_LOAD:
                return mono_exception_from_name (mono_defaults.corlib, "System", "TypeLoadException");
-       /* TODO - handle other class related failures */
-       default:
+
+       default: {
+               MonoLoaderError *error;
+               MonoException *ex;
+               
+               error = mono_loader_get_last_error ();
+               if (error != NULL){
+                       ex = mono_loader_error_prepare_exception (error);
+                       return ex;
+               }
+               
+               /* TODO - handle other class related failures */
                return NULL;
        }
+       }
 }