3 * Copyright 2016 Microsoft
4 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
6 #ifndef __MONO_METADATA_REFLECTION_CACHE_H__
7 #define __MONO_METADATA_REFLECTION_CACHE_H__
10 #include <mono/metadata/domain-internals.h>
11 #include <mono/metadata/handle.h>
12 #include <mono/metadata/mono-hash.h>
13 #include <mono/metadata/mempool.h>
14 #include <mono/utils/mono-error-internals.h>
17 * We need to return always the same object for MethodInfo, FieldInfo etc..
18 * but we need to consider the reflected type.
19 * type uses a different hash, since it uses custom hash/equal functions.
28 mono_reflected_equal (gconstpointer a
, gconstpointer b
);
31 mono_reflected_hash (gconstpointer a
);
33 static inline ReflectedEntry
*
34 alloc_reflected_entry (MonoDomain
*domain
)
36 if (!mono_gc_is_moving ())
37 return g_new0 (ReflectedEntry
, 1);
39 return (ReflectedEntry
*)mono_mempool_alloc (domain
->mp
, sizeof (ReflectedEntry
));
43 free_reflected_entry (ReflectedEntry
*entry
)
45 if (!mono_gc_is_moving ())
49 static inline MonoObject
*
50 cache_object (MonoDomain
*domain
, MonoClass
*klass
, gpointer item
, MonoObject
* o
)
57 mono_domain_lock (domain
);
58 if (!domain
->refobject_hash
)
59 domain
->refobject_hash
= mono_conc_g_hash_table_new_type (mono_reflected_hash
, mono_reflected_equal
, MONO_HASH_VALUE_GC
, MONO_ROOT_SOURCE_DOMAIN
, domain
, "Domain Reflection Object Table");
61 obj
= (MonoObject
*) mono_conc_g_hash_table_lookup (domain
->refobject_hash
, &pe
);
63 ReflectedEntry
*e
= alloc_reflected_entry (domain
);
66 mono_conc_g_hash_table_insert (domain
->refobject_hash
, e
, o
);
69 mono_domain_unlock (domain
);
74 static inline MonoObjectHandle
75 cache_object_handle (MonoDomain
*domain
, MonoClass
*klass
, gpointer item
, MonoObjectHandle o
)
81 mono_domain_lock (domain
);
82 if (!domain
->refobject_hash
)
83 domain
->refobject_hash
= mono_conc_g_hash_table_new_type (mono_reflected_hash
, mono_reflected_equal
, MONO_HASH_VALUE_GC
, MONO_ROOT_SOURCE_DOMAIN
, domain
, "Domain Reflection Object Table");
85 MonoObjectHandle obj
= MONO_HANDLE_NEW (MonoObject
, (MonoObject
*)mono_conc_g_hash_table_lookup (domain
->refobject_hash
, &pe
));
86 if (MONO_HANDLE_IS_NULL (obj
)) {
87 ReflectedEntry
*e
= alloc_reflected_entry (domain
);
90 mono_conc_g_hash_table_insert (domain
->refobject_hash
, e
, MONO_HANDLE_RAW (o
));
91 MONO_HANDLE_ASSIGN (obj
, o
);
93 mono_domain_unlock (domain
);
97 #define CACHE_OBJECT(t,p,o,k) ((t) (cache_object (domain, (k), (p), (o))))
98 #define CACHE_OBJECT_HANDLE(t,p,o,k) (MONO_HANDLE_CAST (t, cache_object_handle (domain, (k), (p), (o))))
100 static inline MonoObjectHandle
101 check_object_handle (MonoDomain
* domain
, MonoClass
*klass
, gpointer item
)
106 MonoConcGHashTable
*hash
= domain
->refobject_hash
;
108 return MONO_HANDLE_NEW (MonoObject
, NULL
);
110 return MONO_HANDLE_NEW (MonoObject
, (MonoObject
*)mono_conc_g_hash_table_lookup (hash
, &e
));
114 typedef MonoObjectHandle (*ReflectionCacheConstructFunc_handle
) (MonoDomain
*, MonoClass
*, gpointer
, gpointer
, MonoError
*);
116 static inline MonoObjectHandle
117 check_or_construct_handle (MonoDomain
*domain
, MonoClass
*klass
, gpointer item
, gpointer user_data
, MonoError
*error
, ReflectionCacheConstructFunc_handle construct
)
120 MonoObjectHandle obj
= check_object_handle (domain
, klass
, item
);
121 if (!MONO_HANDLE_IS_NULL (obj
))
123 MONO_HANDLE_ASSIGN (obj
, construct (domain
, klass
, item
, user_data
, error
));
124 return_val_if_nok (error
, NULL_HANDLE
);
125 if (MONO_HANDLE_IS_NULL (obj
))
127 /* note no caching if there was an error in construction */
128 return cache_object_handle (domain
, klass
, item
, obj
);
131 #define CHECK_OR_CONSTRUCT_HANDLE(t,p,k,construct,ud) \
132 (MONO_HANDLE_CAST (t, check_or_construct_handle ( \
133 domain, (k), (p), (ud), error, (ReflectionCacheConstructFunc_handle) (construct))))
135 #endif /*__MONO_METADATA_REFLECTION_CACHE_H__*/