The new argument controls what should happen when the given token is already
present.
In some situations it's expected that we either see the same object, or we
unconditionally want to replace it (for example if we previously registered a
TypeBuilder or a MethodBuilder, after the type or method is created, we will
re-register the RuntimeType or MonoMethod in its place). In other cases (for
example when a module references a MonoMethod from a different assembly), we
may still call `mono_image_create_token()` multiple times but we expect to see
the same MonoMethod object.
+typedef enum {
+ MONO_DYN_IMAGE_TOK_NEW, /* assert if same token is registered already */
+ MONO_DYN_IMAGE_TOK_SAME_OK, /* allow collision only with the same object */
+ MONO_DYN_IMAGE_TOK_REPLACE, /* keep the new object, always */
+} MonoDynamicImageTokCollision;
+
void
mono_dynamic_images_init (void);
void
void
mono_dynamic_images_init (void);
void
-mono_dynamic_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObjectHandle obj);
+mono_dynamic_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObjectHandle obj, int tok_collision);
gboolean
mono_dynamic_image_is_valid_token (MonoDynamicImage *image, guint32 token);
gboolean
mono_dynamic_image_is_valid_token (MonoDynamicImage *image, guint32 token);
* the Module.ResolveXXXToken () methods to work.
*/
void
* the Module.ResolveXXXToken () methods to work.
*/
void
-mono_dynamic_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObjectHandle obj)
+mono_dynamic_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObjectHandle obj, int how_collide)
{
MONO_REQ_GC_UNSAFE_MODE;
{
MONO_REQ_GC_UNSAFE_MODE;
+ g_assert (!MONO_HANDLE_IS_NULL (obj));
dynamic_image_lock (assembly);
dynamic_image_lock (assembly);
+ MonoObject *prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
+ if (prev) {
+ switch (how_collide) {
+ case MONO_DYN_IMAGE_TOK_NEW:
+ g_assert_not_reached ();
+ case MONO_DYN_IMAGE_TOK_SAME_OK:
+ g_assert (prev == MONO_HANDLE_RAW (obj));
+ break;
+ case MONO_DYN_IMAGE_TOK_REPLACE:
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), MONO_HANDLE_RAW (obj));
dynamic_image_unlock (assembly);
}
#else
void
mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), MONO_HANDLE_RAW (obj));
dynamic_image_unlock (assembly);
}
#else
void
-mono_dynamic_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObjectHandle obj)
+mono_dynamic_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObjectHandle obj, int how_collide)
if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
(type->type != MONO_TYPE_MVAR)) {
token = MONO_TYPEDEFORREF_TYPEDEF | (MONO_HANDLE_GETVAL (tb, table_idx) << MONO_TYPEDEFORREF_BITS);
if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
(type->type != MONO_TYPE_MVAR)) {
token = MONO_TYPEDEFORREF_TYPEDEF | (MONO_HANDLE_GETVAL (tb, table_idx) << MONO_TYPEDEFORREF_BITS);
- mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, tb));
+ /* This function is called multiple times from sre and sre-save, so same object is okay */
+ mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, tb), MONO_DYN_IMAGE_TOK_SAME_OK);
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 ++;
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_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, tb));
+
+
+ if (!MONO_HANDLE_IS_NULL (tb)) {
+ /* This function is called multiple times from sre and sre-save, so same object is okay */
+ mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, tb), MONO_DYN_IMAGE_TOK_SAME_OK);
+ }
+
leave:
HANDLE_FUNCTION_RETURN_VAL (token);
}
leave:
HANDLE_FUNCTION_RETURN_VAL (token);
}
}
token = MONO_TOKEN_STRING | idx;
}
token = MONO_TOKEN_STRING | idx;
- mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, str));
+ mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, str), MONO_DYN_IMAGE_TOK_NEW);
leave:
HANDLE_FUNCTION_RETURN_VAL (token);
leave:
HANDLE_FUNCTION_RETURN_VAL (token);
g_error ("requested method token for %s\n", klass->name);
}
g_error ("requested method token for %s\n", klass->name);
}
- mono_dynamic_image_register_token (assembly, token, obj);
+ mono_dynamic_image_register_token (assembly, token, obj, MONO_DYN_IMAGE_TOK_NEW);
return token;
fail:
g_assert (!mono_error_ok (error));
return token;
fail:
g_assert (!mono_error_ok (error));
+ /* This function is called from ModuleBuilder:getToken multiple times for the same objects */
+ int how_collide = MONO_DYN_IMAGE_TOK_SAME_OK;
+
if (strcmp (klass->name, "RuntimeType") == 0) {
MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, obj), error);
return_val_if_nok (error, 0);
MonoClass *mc = mono_class_from_mono_type (type);
token = mono_metadata_token_from_dor (
mono_dynimage_encode_typedef_or_ref_full (assembly, type, !mono_class_is_gtd (mc) || create_open_instance));
if (strcmp (klass->name, "RuntimeType") == 0) {
MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, obj), error);
return_val_if_nok (error, 0);
MonoClass *mc = mono_class_from_mono_type (type);
token = mono_metadata_token_from_dor (
mono_dynimage_encode_typedef_or_ref_full (assembly, type, !mono_class_is_gtd (mc) || create_open_instance));
+ /* If it's a RuntimeType now, we could have registered a
+ * TypeBuilder for it before, so replacing is okay. */
+ how_collide = MONO_DYN_IMAGE_TOK_REPLACE;
} else if (strcmp (klass->name, "MonoCMethod") == 0 ||
strcmp (klass->name, "MonoMethod") == 0) {
MonoReflectionMethodHandle m = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
} else if (strcmp (klass->name, "MonoCMethod") == 0 ||
strcmp (klass->name, "MonoMethod") == 0) {
MonoReflectionMethodHandle m = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
* FIXME: do the equivalent for Fields.
*/
token = method->token;
* FIXME: do the equivalent for Fields.
*/
token = method->token;
+ how_collide = MONO_DYN_IMAGE_TOK_REPLACE;
} else {
/*
* Each token should have a unique index, but the indexes are
} else {
/*
* Each token should have a unique index, but the indexes are
*/
method_table_idx --;
token = MONO_TOKEN_METHOD_DEF | method_table_idx;
*/
method_table_idx --;
token = MONO_TOKEN_METHOD_DEF | method_table_idx;
+ how_collide = MONO_DYN_IMAGE_TOK_NEW;
}
} else {
token = mono_image_get_methodref_token (assembly, method, create_open_instance);
}
} else {
token = mono_image_get_methodref_token (assembly, method, create_open_instance);
static guint32 field_table_idx = 0xffffff;
field_table_idx --;
token = MONO_TOKEN_FIELD_DEF | field_table_idx;
static guint32 field_table_idx = 0xffffff;
field_table_idx --;
token = MONO_TOKEN_FIELD_DEF | field_table_idx;
+ how_collide = MONO_DYN_IMAGE_TOK_NEW;
} else {
token = mono_image_get_fieldref_token (assembly, obj, field);
}
} else {
token = mono_image_get_fieldref_token (assembly, obj, field);
}
- mono_dynamic_image_register_token (assembly, token, obj);
+ mono_dynamic_image_register_token (assembly, token, obj, how_collide);
*/
mono_image_append_class_to_reflection_info_set (klass);
*/
mono_image_append_class_to_reflection_info_set (klass);
- mono_dynamic_image_register_token (dynamic_image, MONO_TOKEN_TYPE_DEF | table_idx, MONO_HANDLE_CAST (MonoObject, ref_tb));
+ mono_dynamic_image_register_token (dynamic_image, MONO_TOKEN_TYPE_DEF | table_idx, MONO_HANDLE_CAST (MonoObject, ref_tb), MONO_DYN_IMAGE_TOK_NEW);
if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
(!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
(!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilderHandle mb, MonoObjectHandle obj, guint32 token, MonoError *error)
{
error_init (error);
ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilderHandle mb, MonoObjectHandle obj, guint32 token, MonoError *error)
{
error_init (error);
- mono_dynamic_image_register_token (MONO_HANDLE_GETVAL (mb, dynamic_image), token, obj);
+ /* This function may be called by ModuleBuilder.FixupTokens to update
+ * an existing token, so replace is okay here. */
+ mono_dynamic_image_register_token (MONO_HANDLE_GETVAL (mb, dynamic_image), token, obj, MONO_DYN_IMAGE_TOK_REPLACE);