remove GenericVectorTests from rsp (#17366)
[mono-project.git] / mono / metadata / reflection-cache.h
blob6a792961c988feecc205322b6f2ef59b32a6d0de
1 /**
2 * \file
3 * Copyright 2016 Microsoft
4 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
5 */
6 #ifndef __MONO_METADATA_REFLECTION_CACHE_H__
7 #define __MONO_METADATA_REFLECTION_CACHE_H__
9 #include <glib.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.
22 typedef struct {
23 gpointer item;
24 MonoClass *refclass;
25 } ReflectedEntry;
27 gboolean
28 mono_reflected_equal (gconstpointer a, gconstpointer b);
30 guint
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);
38 else
39 return (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry));
42 static inline void
43 free_reflected_entry (ReflectedEntry *entry)
45 if (!mono_gc_is_moving ())
46 g_free (entry);
49 static inline MonoObject*
50 cache_object (MonoDomain *domain, MonoClass *klass, gpointer item, MonoObject* o)
52 MonoObject *obj;
53 ReflectedEntry pe;
54 pe.item = item;
55 pe.refclass = klass;
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);
62 if (obj == NULL) {
63 ReflectedEntry *e = alloc_reflected_entry (domain);
64 e->item = item;
65 e->refclass = klass;
66 mono_conc_g_hash_table_insert (domain->refobject_hash, e, o);
67 obj = o;
69 mono_domain_unlock (domain);
70 return obj;
74 static inline MonoObjectHandle
75 cache_object_handle (MonoDomain *domain, MonoClass *klass, gpointer item, MonoObjectHandle o)
77 ReflectedEntry pe;
78 pe.item = item;
79 pe.refclass = klass;
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);
88 e->item = item;
89 e->refclass = klass;
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);
94 return obj;
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)
103 ReflectedEntry e;
104 e.item = item;
105 e.refclass = klass;
106 MonoConcGHashTable *hash = domain->refobject_hash;
107 if (!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)
119 error_init (error);
120 MonoObjectHandle obj = check_object_handle (domain, klass, item);
121 if (!MONO_HANDLE_IS_NULL (obj))
122 return 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))
126 return 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__*/