[msvc] Update csproj files (#4740)
[mono.git] / mono / metadata / reflection-cache.h
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__
8
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>
15
16 /*
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.
20  */
21
22 typedef struct {
23         gpointer item;
24         MonoClass *refclass;
25 } ReflectedEntry;
26
27 gboolean
28 reflected_equal (gconstpointer a, gconstpointer b);
29
30 guint
31 reflected_hash (gconstpointer a);
32
33 #ifdef HAVE_BOEHM_GC
34 /* ReflectedEntry doesn't need to be GC tracked */
35 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
36 #define FREE_REFENTRY(entry) g_free ((entry))
37 #define REFENTRY_REQUIRES_CLEANUP
38 #else
39 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
40 /* FIXME: */
41 #define FREE_REFENTRY(entry)
42 #endif
43
44 static inline MonoObject*
45 cache_object (MonoDomain *domain, MonoClass *klass, gpointer item, MonoObject* o)
46 {
47         MonoObject *obj;
48         ReflectedEntry pe;
49         pe.item = item;
50         pe.refclass = klass;
51         mono_domain_lock (domain);
52         if (!domain->refobject_hash)
53                 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");
54
55         obj = (MonoObject*) mono_g_hash_table_lookup (domain->refobject_hash, &pe);
56         if (obj == NULL) {
57                 ReflectedEntry *e = ALLOC_REFENTRY;
58                 e->item = item;
59                 e->refclass = klass;
60                 mono_g_hash_table_insert (domain->refobject_hash, e, o);
61                 obj = o;
62         }
63         mono_domain_unlock (domain);
64         return obj;
65 }
66
67
68 static inline MonoObjectHandle
69 cache_object_handle (MonoDomain *domain, MonoClass *klass, gpointer item, MonoObjectHandle o)
70 {
71         ReflectedEntry pe;
72         pe.item = item;
73         pe.refclass = klass;
74         mono_domain_lock (domain);
75         if (!domain->refobject_hash)
76                 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");
77
78         MonoObjectHandle obj = MONO_HANDLE_NEW (MonoObject, mono_g_hash_table_lookup (domain->refobject_hash, &pe));
79         if (MONO_HANDLE_IS_NULL (obj)) {
80                 ReflectedEntry *e = ALLOC_REFENTRY;
81                 e->item = item;
82                 e->refclass = klass;
83                 mono_g_hash_table_insert (domain->refobject_hash, e, MONO_HANDLE_RAW (o));
84                 MONO_HANDLE_ASSIGN (obj, o);
85         }
86         mono_domain_unlock (domain);
87         return obj;
88 }
89
90 #define CACHE_OBJECT(t,p,o,k) ((t) (cache_object (domain, (k), (p), (o))))
91 #define CACHE_OBJECT_HANDLE(t,p,o,k) ((t) (cache_object_handle (domain, (k), (p), (o))))
92
93 static inline MonoObjectHandle
94 check_object_handle (MonoDomain* domain, MonoClass *klass, gpointer item)
95 {
96         ReflectedEntry e;
97         e.item = item;
98         e.refclass = klass;
99         mono_domain_lock (domain);
100         if (!domain->refobject_hash)
101                 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");
102         MonoObjectHandle obj = MONO_HANDLE_NEW (MonoObject, mono_g_hash_table_lookup (domain->refobject_hash, &e));
103         mono_domain_unlock (domain);
104         return obj;
105 }
106
107
108 typedef MonoObjectHandle (*ReflectionCacheConstructFunc_handle) (MonoDomain*, MonoClass*, gpointer, gpointer, MonoError *);
109
110 static inline MonoObjectHandle
111 check_or_construct_handle (MonoDomain *domain, MonoClass *klass, gpointer item, gpointer user_data, MonoError *error, ReflectionCacheConstructFunc_handle construct)
112 {
113         error_init (error);
114         MonoObjectHandle obj = check_object_handle (domain, klass, item);
115         if (!MONO_HANDLE_IS_NULL (obj))
116                 return obj;
117         MONO_HANDLE_ASSIGN (obj, construct (domain, klass, item, user_data, error));
118         return_val_if_nok (error, NULL);
119         /* note no caching if there was an error in construction */
120         return cache_object_handle (domain, klass, item, obj);
121 }
122
123
124 #define CHECK_OR_CONSTRUCT_HANDLE(t,p,k,construct,ud) ((t) check_or_construct_handle (domain, (k), (p), (ud), error, (ReflectionCacheConstructFunc_handle) (construct)))
125
126
127 #endif /*__MONO_METADATA_REFLECTION_CACHE_H__*/