* class.c (mono_method_set_generic_container): New accessor function.
(mono_method_get_generic_container): Ditto.
* class-internals.h (struct _MonoMethod): Remove rarely used
'generic_container' field, store it in the property hash instead. Add
'is_generic' boolean field instead.
* image.c (mono_image_init): Initialize property_hash.
(mono_image_close): Destroy property_hash.
* metadata-internals.h (struct _MonoImage): Add 'property_hash' hash table to
hold rarely used fields of runtime structures belonging to this image.
* class.c loader.c verify.c icall.c reflection.c: Use the new accessor functions
to get/set method->generic_container.
svn path=/trunk/mono/; revision=104056
2008-05-26 Zoltan Varga <vargaz@gmail.com>
+ * class.c (mono_method_set_generic_container): New accessor function.
+ (mono_method_get_generic_container): Ditto.
+
+ * class-internals.h (struct _MonoMethod): Remove rarely used
+ 'generic_container' field, store it in the property hash instead. Add
+ 'is_generic' boolean field instead.
+
+ * image.c (mono_image_init): Initialize property_hash.
+ (mono_image_close): Destroy property_hash.
+
+ * metadata-internals.h (struct _MonoImage): Add 'property_hash' hash table to
+ hold rarely used fields of runtime structures belonging to this image.
+
+ * class.c loader.c verify.c icall.c reflection.c: Use the new accessor functions
+ to get/set method->generic_container.
+
* loader.c (mono_get_method_from_token): Avoid loading the method header for
generic methods.
MONO_REMOTING_TARGET_COMINTEROP
} MonoRemotingTarget;
+#define MONO_METHOD_PROP_GENERIC_CONTAINER 0
+
struct _MonoMethod {
guint16 flags; /* method flags */
guint16 iflags; /* method implementation flags */
guint32 token;
MonoClass *klass;
MonoMethodSignature *signature;
- MonoGenericContainer *generic_container;
/* name is useful mostly for debugging */
const char *name;
/* this is used by the inlining algorithm */
unsigned int string_ctor:1;
unsigned int save_lmf:1;
unsigned int dynamic:1; /* created & destroyed during runtime */
+ unsigned int is_generic:1; /* whenever this is a generic method definition */
unsigned int is_inflated:1; /* whether we're a MonoMethodInflated */
unsigned int skip_visibility:1; /* whenever to skip JIT visibility checks */
unsigned int verification_success:1; /* whether this method has been verified successfully.*/
- signed int slot : 19;
+ signed int slot : 18;
+
+ /*
+ * If is_generic is TRUE, the generic_container is stored in image->property_hash,
+ * using the key MONO_METHOD_PROP_GENERIC_CONTAINER.
+ */
};
struct _MonoMethodNormal {
MonoGenericContext*
mono_method_get_context (MonoMethod *method) MONO_INTERNAL;
+/* Used by monodis, thus cannot be MONO_INTERNAL */
+MonoGenericContainer*
+mono_method_get_generic_container (MonoMethod *method);
+
MonoGenericContext*
mono_generic_class_get_context (MonoGenericClass *gclass) MONO_INTERNAL;
MonoClass*
mono_generic_class_get_class (MonoGenericClass *gclass) MONO_INTERNAL;
+void
+mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container) MONO_INTERNAL;
+
MonoMethod*
mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context);
method = imethod->declaring;
}
- if (!method->generic_container && !method->klass->generic_container)
+ if (!method->is_generic && !method->klass->generic_container)
return method;
/*
* everything should behave like a regular type or method.
*
*/
- is_mb_open = method->generic_container && /* This is a generic method definition */
+ is_mb_open = method->is_generic &&
method->klass->image->dynamic && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
- context->method_inst == method->generic_container->context.method_inst; /* and it's been instantiated with its own arguments. */
+ context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
iresult = g_new0 (MonoMethodInflated, 1);
iresult->context = *context;
iresult->declaring = method;
iresult->is_mb_open = is_mb_open;
- if (!context->method_inst && method->generic_container)
- iresult->context.method_inst = method->generic_container->context.method_inst;
+ if (!context->method_inst && method->is_generic)
+ iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
mono_loader_lock ();
cached = mono_method_inflated_lookup (iresult, FALSE);
}
result = (MonoMethod *) iresult;
- result->is_inflated = 1;
+ result->is_inflated = TRUE;
+ result->is_generic = FALSE;
result->signature = NULL;
- if (context->method_inst)
- result->generic_container = NULL;
+ if (!context->method_inst) {
+ /* Set the generic_container of the result to the generic_container of method */
+ MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
- /* Due to the memcpy above, !context->method_inst => result->generic_container == method->generic_container */
+ if (generic_container) {
+ result->is_generic = 1;
+ mono_method_set_generic_container (result, generic_container);
+ }
+ }
if (!klass_hint || !klass_hint->generic_class ||
klass_hint->generic_class->container_class != method->klass ||
return &imethod->context;
}
+/*
+ * mono_method_get_generic_container:
+ *
+ * Returns the generic container of METHOD, which should be a generic method definition.
+ * Returns NULL if METHOD is not a generic method definition.
+ * LOCKING: Acquires the loader lock.
+ */
+MonoGenericContainer*
+mono_method_get_generic_container (MonoMethod *method)
+{
+ MonoGenericContainer *container;
+
+ if (!method->is_generic)
+ return NULL;
+
+ mono_loader_lock ();
+ container = mono_property_hash_lookup (method->klass->image->property_hash, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
+ mono_loader_unlock ();
+ g_assert (container);
+
+ return container;
+}
+
+/*
+ * mono_method_set_generic_container:
+ *
+ * Sets the generic container of METHOD to CONTAINER.
+ * LOCKING: Acquires the loader lock.
+ */
+void
+mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
+{
+ g_assert (method->is_generic);
+
+ mono_loader_lock ();
+ mono_property_hash_insert (method->klass->image->property_hash, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
+ mono_loader_unlock ();
+}
+
/**
* mono_class_find_enum_basetype:
* @class: The enum class
MONO_ARCH_SAVE_REGS;
- if (method->method->generic_container)
+ if (method->method->is_generic)
return method;
if (!method->method->is_inflated)
result = imethod->declaring;
/* Not a generic method. */
- if (!result->generic_container)
+ if (!result->is_generic)
return NULL;
if (method->method->klass->image->dynamic) {
{
MONO_ARCH_SAVE_REGS;
- return method->method->generic_container != NULL;
+ return method->method->is_generic;
}
static MonoArray*
res = mono_array_new (domain, mono_defaults.monotype_class, count);
for (i = 0; i < count; i++) {
- MonoGenericParam *param = &method->method->generic_container->type_params [i];
+ MonoGenericContainer *container = mono_method_get_generic_container (method->method);
+ MonoGenericParam *param = &container->type_params [i];
MonoClass *pklass = mono_class_from_generic_parameter (
param, method->method->klass->image, TRUE);
mono_array_setref (res, i,
image->memberref_signatures = g_hash_table_new (NULL, NULL);
image->helper_signatures = g_hash_table_new (g_str_hash, g_str_equal);
image->method_signatures = g_hash_table_new (NULL, NULL);
+
+ image->property_hash = mono_property_hash_new ();
}
#if G_BYTE_ORDER != G_LITTLE_ENDIAN
if (image->rgctx_template_hash)
g_hash_table_destroy (image->rgctx_template_hash);
+ if (image->property_hash)
+ mono_property_hash_destroy (image->property_hash);
+
if (image->interface_bitset) {
mono_unload_interface_ids (image->interface_bitset);
mono_bitset_free (image->interface_bitset);
container = klass->generic_container;
generic_container = mono_metadata_load_generic_params (image, token, container);
if (generic_container) {
+ result->is_generic = TRUE;
generic_container->owner.method = result;
mono_metadata_load_generic_param_constraints (image, token, generic_container);
piinfo->piflags = mono_metadata_decode_row_col (&tables [MONO_TABLE_IMPLMAP], piinfo->implmap_idx - 1, MONO_IMPLMAP_FLAGS);
}
- result->generic_container = generic_container;
+ if (generic_container)
+ mono_method_set_generic_container (result, generic_container);
return result;
}
MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
int i;
+ mono_loader_lock ();
+ mono_property_hash_remove_object (method->klass->image->property_hash, method);
+ mono_loader_unlock ();
+
g_free ((char*)method->name);
if (mw->method.header) {
g_free ((char*)mw->method.header->code);
sig = mono_metadata_blob_heap (img, mono_metadata_decode_row_col (&img->tables [MONO_TABLE_METHOD], idx - 1, MONO_METHOD_SIGNATURE));
g_assert (!m->klass->generic_class);
- container = m->generic_container;
+ container = mono_method_get_generic_container (m);
if (!container)
container = m->klass->generic_container;
g_assert (loc);
- mn->header = mono_metadata_parse_mh_full (img, method->generic_container, loc);
+ mn->header = mono_metadata_parse_mh_full (img, mono_method_get_generic_container (method), loc);
mono_loader_unlock ();
return mn->header;
#include "mono/utils/mono-compiler.h"
#include "mono/utils/mono-dl.h"
#include "mono/utils/monobitset.h"
+#include "mono/utils/mono-property-hash.h"
#define MONO_SECMAN_FLAG_INIT(x) (x & 0x2)
#define MONO_SECMAN_FLAG_GET_VALUE(x) (x & 0x1)
*/
GHashTable *generic_class_cache;
+ /* Contains rarely used fields of runtime structures belonging to this image */
+ MonoPropertyHash *property_hash;
+
void *reflection_info;
/*
int count = mono_array_length (rmb->generic_params);
MonoGenericContainer *container;
- m->generic_container = container = rmb->generic_container;
+ container = rmb->generic_container;
+ if (container) {
+ m->is_generic = TRUE;
+ mono_method_set_generic_container (m, container);
+ }
container->type_argc = count;
container->type_params = g_new0 (MonoGenericParam, count);
container->owner.method = m;
imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
}
- if (method->generic_container && method->klass->image->dynamic) {
+ if (method->is_generic && method->klass->image->dynamic) {
MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
mono_loader_lock ();
{
MonoMethodInflated *gmethod = (MonoMethodInflated *)method;
MonoGenericInst *ginst = gmethod->context.method_inst;
- MonoGenericContainer *gc = gmethod->declaring->generic_container;
+ MonoGenericContainer *gc = mono_method_get_generic_container (gmethod->declaring);
if (!gc) /*non-generic inflated method - it's part of a generic type */
return TRUE;
return is_valid_generic_instantiation (gc, &gmethod->context, ginst);
if (ctx.signature->is_inflated)
ctx.generic_context = generic_context = mono_method_get_context (method);
- if (!generic_context && (method->klass->generic_container || method->generic_container)) {
- if (method->generic_container)
- ctx.generic_context = generic_context = &method->generic_container->context;
+ if (!generic_context && (method->klass->generic_container || method->is_generic)) {
+ if (method->is_generic)
+ ctx.generic_context = generic_context = &(mono_method_get_generic_container (method)->context);
else
ctx.generic_context = generic_context = &method->klass->generic_container->context;
}