static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
-#endif
-
static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
+static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
+#endif
+
static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
-static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
static gboolean is_sre_field_builder (MonoClass *class);
static gboolean is_sr_mono_method (MonoClass *class);
static gboolean is_sr_mono_cmethod (MonoClass *class);
+static gboolean is_sr_mono_generic_method (MonoClass *class);
+static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
static gboolean is_sr_mono_field (MonoClass *class);
+static gboolean is_sr_mono_property (MonoClass *class);
+static gboolean is_sre_method_on_tb_inst (MonoClass *class);
+static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
}
#endif
+/*
+ * mono_class_get_ref_info:
+ *
+ * Return the type builder/generic param builder corresponding to KLASS, if it exists.
+ */
+gpointer
+mono_class_get_ref_info (MonoClass *klass)
+{
+ if (klass->ref_info_handle == 0)
+ return NULL;
+ else
+ return mono_gchandle_get_target (klass->ref_info_handle);
+}
+
+void
+mono_class_set_ref_info (MonoClass *klass, gpointer obj)
+{
+ klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
+ g_assert (klass->ref_info_handle != 0);
+}
+
+void
+mono_class_free_ref_info (MonoClass *klass)
+{
+ if (klass->ref_info_handle) {
+ mono_gchandle_free (klass->ref_info_handle);
+ klass->ref_info_handle = 0;
+ }
+}
+
static void
encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
{
}
}
+#ifndef DISABLE_REFLECTION_EMIT
static void
reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
{
rmb->refs = NULL;
}
-#ifndef DISABLE_REFLECTION_EMIT
static void
reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
{
values [MONO_METHODIMPL_DECLARATION] = tok;
}
+#ifndef DISABLE_REFLECTION_EMIT
static void
mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
{
mono_image_basic_method (&rmb, assembly);
mb->table_idx = *rmb.table_idx;
}
+#endif
static char*
type_get_fully_qualified_name (MonoType *type)
* PROPERTY (rows already preallocated in _get_type_info ())
* METHOD (method info already done with the generic method code)
* METHODSEMANTICS
+ * CONSTANT
*/
table = &assembly->tables [MONO_TABLE_PROPERTY];
pb->table_idx = table->next_idx ++;
values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
}
+ if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
+ guint32 field_type = 0;
+ table = &assembly->tables [MONO_TABLE_CONSTANT];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_CONSTANT_SIZE;
+ values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
+ values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
+ values [MONO_CONSTANT_TYPE] = field_type;
+ values [MONO_CONSTANT_PADDING] = 0;
+ }
}
static void
/* FIXME: track where gen_params should be freed and remove the GC root as well */
MOVING_GC_REGISTER (&entry->gparam);
entry->gparam = gparam;
-
+
g_ptr_array_add (assembly->gen_params, entry);
}
*/
if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
(type->type != MONO_TYPE_MVAR)) {
- MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
- mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
+ mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
return token;
}
token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
table->next_idx ++;
- mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
+ mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
return token;
}
}
#ifndef DISABLE_REFLECTION_EMIT
-/*
- * Insert a memberef row into the metadata: the token that point to the memberref
- * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
- * mono_image_get_fieldref_token()).
- * The sig param is an index to an already built signature.
- */
static guint32
-mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
+mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
{
MonoDynamicTable *table;
guint32 *values;
guint32 token, pclass;
- guint32 parent;
- parent = mono_image_typedef_or_ref (assembly, type);
switch (parent & MONO_TYPEDEFORREF_MASK) {
case MONO_TYPEDEFORREF_TYPEREF:
pclass = MONO_MEMBERREF_PARENT_TYPEREF;
return token;
}
+/*
+ * Insert a memberef row into the metadata: the token that point to the memberref
+ * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
+ * mono_image_get_fieldref_token()).
+ * The sig param is an index to an already built signature.
+ */
+static guint32
+mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
+{
+ guint32 parent = mono_image_typedef_or_ref (assembly, type);
+ return mono_image_add_memberef_row (assembly, parent, name, sig);
+}
+
+
static guint32
mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
{
static guint32
mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
{
- guint32 token;
+ guint32 token, parent, sig;
ReflectionMethodBuilder rmb;
char *name;
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
if (token)
*/
if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
- token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
- name, method_builder_encode_signature (assembly, &rmb));
+
+ sig = method_builder_encode_signature (assembly, &rmb);
+
+ if (tb->generic_params)
+ parent = create_generic_typespec (assembly, tb);
+ else
+ parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
+
+ token = mono_image_add_memberef_row (assembly, parent, name, sig);
g_free (name);
g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
{
guint32 token;
-
+
if (mb->generic_params && create_methodspec)
return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
static guint32
mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
{
- guint32 token;
+ guint32 token, parent, sig;
ReflectionMethodBuilder rmb;
char *name;
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
if (token)
return token;
+ g_assert (tb->generic_params);
+
reflection_methodbuilder_from_ctor_builder (&rmb, mb);
+ parent = create_generic_typespec (assembly, tb);
name = mono_string_to_utf8 (rmb.name);
- token = mono_image_get_memberref_token (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type),
- name, method_builder_encode_signature (assembly, &rmb));
+ sig = method_builder_encode_signature (assembly, &rmb);
+
+ token = mono_image_add_memberef_row (assembly, parent, name, sig);
g_free (name);
mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
klass = method->klass;
+ if (m->method_args == NULL)
+ return method;
+
if (method->is_inflated)
method = ((MonoMethodInflated *) method)->declaring;
m->table_idx = am->token & 0xffffff;
return am->token;
}
-#endif
/*
* Insert into the metadata tables all the info about the TypeBuilder tb.
}
}
}
+#endif
static void
collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
MonoGenericInst *ginst;
MonoArray *type_args;
int i;
+ MonoObject *tb;
g_assert (0); /*This code path should not be taken anymore, all MGC instantiation must happen in managed code*/
#endif
res->type.type = geninst;
- g_assert (gklass->reflection_info);
- g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
- MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
+ tb = mono_class_get_ref_info (gklass);
+ g_assert (tb);
+ g_assert (!strcmp (tb->vtable->klass->name, "TypeBuilder"));
+ MONO_OBJECT_SETREF (res, generic_type, tb);
ginst = klass->generic_class->context.class_inst;
type_args = mono_array_new (domain, mono_defaults.systemtype_class, ginst->type_argc);
mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
}
- if (klass->reflection_info && !klass->wastypebuilder) {
+ if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
gboolean is_type_done = TRUE;
/* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
* We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
if (is_type_done && !type->byref) {
mono_domain_unlock (domain);
mono_loader_unlock ();
- return klass->reflection_info;
+ return mono_class_get_ref_info (klass);
}
}
// FIXME: Get rid of this, do it in the icalls for Type
return;
}
-static MonoObject *
+MonoObject *
mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
{
void *retval;
token = mono_class_get_event_token (p->event);
} else if (strcmp (klass->name, "ParameterInfo") == 0) {
MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
+ MonoClass *member_class = mono_object_class (p->MemberImpl);
+ g_assert (mono_class_is_reflection_method_or_constructor (member_class));
token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
} else if (strcmp (klass->name, "Module") == 0) {
cinfo = mono_custom_attrs_from_method (rmethod->method);
} else if (strcmp ("ParameterInfo", klass->name) == 0) {
MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
- MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
- cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
+ MonoClass *member_class = mono_object_class (param->MemberImpl);
+ if (mono_class_is_reflection_method_or_constructor (member_class)) {
+ MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
+ cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
+ } else if (is_sr_mono_property (member_class)) {
+ MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
+ MonoMethod *method;
+ if (!(method = prop->property->get))
+ method = prop->property->set;
+ g_assert (method);
+
+ cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
+ } else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
+ MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
+ cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
+ } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
+ MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
+ MonoMethod *method = NULL;
+ if (is_sre_ctor_builder (mono_object_class (c->cb)))
+ method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
+ else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
+ method = ((MonoReflectionMethod *)c->cb)->method;
+ else
+ g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
+
+ cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
+ } else {
+ char *type_name = mono_type_get_full_name (member_class);
+ char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
+ MonoException *ex = mono_get_exception_not_supported (msg);
+ g_free (type_name);
+ g_free (msg);
+ mono_raise_exception (ex);
+ }
} else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
}
+static gboolean
+is_sr_mono_generic_method (MonoClass *class)
+{
+ check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
+}
+
+static gboolean
+is_sr_mono_generic_cmethod (MonoClass *class)
+{
+ check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
+}
+
static gboolean
is_sr_mono_field (MonoClass *class)
{
check_corlib_type_cached (class, "System.Reflection", "MonoField");
}
+static gboolean
+is_sr_mono_property (MonoClass *class)
+{
+ check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
+}
+
+static gboolean
+is_sre_method_on_tb_inst (MonoClass *class)
+{
+ check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
+}
+
+static gboolean
+is_sre_ctor_on_tb_inst (MonoClass *class)
+{
+ check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
+}
+
+gboolean
+mono_class_is_reflection_method_or_constructor (MonoClass *class)
+{
+ return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
+}
MonoType*
mono_reflection_type_get_handle (MonoReflectionType* ref)
klass->element_class = klass;
- if (klass->reflection_info == NULL) {
+ if (mono_class_get_ref_info (klass) == NULL) {
- MOVING_GC_REGISTER (&klass->reflection_info);
- klass->reflection_info = tb;
+ mono_class_set_ref_info (klass, tb);
/* Put into cache so mono_class_get () will find it.
Skip nested types as those should not be available on the global scope. */
g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
}
} else {
- g_assert (klass->reflection_info == tb);
+ g_assert (mono_class_get_ref_info (klass) == tb);
}
mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
}
if (klass->wastypebuilder) {
- tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
+ tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
is_dynamic = TRUE;
}
static void
ensure_runtime_vtable (MonoClass *klass)
{
- MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
int i, num, j;
if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
g_assert (klass->image->dynamic);
- if (!klass->reflection_info)
+ if (!mono_class_get_ref_info (klass))
return;
- g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
+ g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
- tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
+ tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
onum = 0;
if (tb->methods) {
static void
typebuilder_setup_fields (MonoClass *klass, MonoError *error)
{
- MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
MonoReflectionFieldBuilder *fb;
MonoClassField *field;
MonoImage *image = klass->image;
static void
typebuilder_setup_properties (MonoClass *klass, MonoError *error)
{
- MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
MonoReflectionPropertyBuilder *pb;
MonoImage *image = klass->image;
MonoProperty *properties;
static void
typebuilder_setup_events (MonoClass *klass, MonoError *error)
{
- MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
MonoReflectionEventBuilder *eb;
MonoImage *image = klass->image;
MonoEvent *events;
gparam->type.type = &pklass->byval_arg;
- MOVING_GC_REGISTER (&pklass->reflection_info);
- pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
+ mono_class_set_ref_info (pklass, gparam);
mono_image_lock (image);
image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
mono_image_unlock (image);
static void
ensure_complete_type (MonoClass *klass)
{
- if (klass->image->dynamic && !klass->wastypebuilder) {
- MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
+ MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
mono_metadata_free_type (type);
}
*handle_class = mono_defaults.methodhandle_class;
+ } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
+ MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
+ MonoType *mtype;
+ MonoClass *klass;
+ MonoMethod *method;
+ gpointer iter;
+ char *name;
+
+ mtype = mono_reflection_type_get_handle (m->parent);
+ klass = mono_class_from_mono_type (mtype);
+
+ /* Find the method */
+
+ name = mono_string_to_utf8 (m->name);
+ iter = NULL;
+ while ((method = mono_class_get_methods (klass, &iter))) {
+ if (!strcmp (method->name, name))
+ break;
+ }
+ g_free (name);
+
+ // FIXME:
+ g_assert (method);
+ // FIXME: Check parameters/return value etc. match
+
+ result = method;
+ *handle_class = mono_defaults.methodhandle_class;
} else if (is_sre_array (mono_object_get_class(obj)) ||
is_sre_byref (mono_object_get_class(obj)) ||
is_sre_pointer (mono_object_get_class(obj))) {
/*
* The result of mono_type_get_object () might be a System.MonoType but we
- * need a TypeBuilder so use klass->reflection_info.
+ * need a TypeBuilder so use mono_class_get_ref_info (klass).
*/
- g_assert (klass->reflection_info);
- g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
+ g_assert (mono_class_get_ref_info (klass));
+ g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
- res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
+ res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
if (exc)
return FALSE;
else