[reflection] Use mono_module_get_object_handle everywhere (#4010)
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Wed, 30 Nov 2016 17:20:30 +0000 (12:20 -0500)
committerGitHub <noreply@github.com>
Wed, 30 Nov 2016 17:20:30 +0000 (12:20 -0500)
* [reflection] Refactor managed object caching

Split up all the mono_XXX_get_object_checked functions into a generic
cache check and a specific construction function that's called if
there's a cache miss.

* [reflection] Add mono_assembly_get_object_handle

* [reflection] Add mono_module_get_object_handle

* [reflection] Use mono_module_get_object_handle everywhere

instead of mono_module_get_object_checked.

Also implement mono_module_file_get_object_handle instead of mono_module_file_get_object_checked

mono/metadata/custom-attrs.c
mono/metadata/icall-def.h
mono/metadata/icall.c
mono/metadata/object-internals.h
mono/metadata/reflection-cache.h
mono/metadata/reflection-internals.h
mono/metadata/reflection.c
mono/metadata/sre.c

index a290bce42da2c6f9fb0761633426b6fd997cfe7c..46c8ba4f1640831814a2583aed99009b32776a8a 100644 (file)
@@ -16,7 +16,6 @@
 #include "mono/metadata/gc-internals.h"
 #include "mono/metadata/mono-endian.h"
 #include "mono/metadata/object-internals.h"
-#include "mono/metadata/reflection-cache.h"
 #include "mono/metadata/custom-attrs-internals.h"
 #include "mono/metadata/sre-internals.h"
 #include "mono/metadata/reflection-internals.h"
index 7b6d6cd0f0e79d684089ac1f74ddffead341ad58..1889ed36f6cb1f3ed941a801e1ab8ef5fe8fa842 100644 (file)
@@ -503,11 +503,11 @@ ICALL(ASSEM_2, "GetCallingAssembly", ves_icall_System_Reflection_Assembly_GetCal
 ICALL(ASSEM_3, "GetEntryAssembly", ves_icall_System_Reflection_Assembly_GetEntryAssembly)
 ICALL(ASSEM_4, "GetExecutingAssembly", ves_icall_System_Reflection_Assembly_GetExecutingAssembly)
 ICALL(ASSEM_5, "GetFilesInternal", ves_icall_System_Reflection_Assembly_GetFilesInternal)
-ICALL(ASSEM_6, "GetManifestModuleInternal", ves_icall_System_Reflection_Assembly_GetManifestModuleInternal)
-ICALL(ASSEM_7, "GetManifestResourceInfoInternal", ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal)
-ICALL(ASSEM_8, "GetManifestResourceInternal", ves_icall_System_Reflection_Assembly_GetManifestResourceInternal)
+HANDLES(ICALL(ASSEM_6, "GetManifestModuleInternal", ves_icall_System_Reflection_Assembly_GetManifestModuleInternal))
+HANDLES(ICALL(ASSEM_7, "GetManifestResourceInfoInternal", ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal))
+HANDLES(ICALL(ASSEM_8, "GetManifestResourceInternal", ves_icall_System_Reflection_Assembly_GetManifestResourceInternal))
 ICALL(ASSEM_9, "GetManifestResourceNames", ves_icall_System_Reflection_Assembly_GetManifestResourceNames)
-ICALL(ASSEM_10, "GetModulesInternal", ves_icall_System_Reflection_Assembly_GetModulesInternal)
+HANDLES(ICALL(ASSEM_10, "GetModulesInternal", ves_icall_System_Reflection_Assembly_GetModulesInternal))
 //ICALL(ASSEM_11, "GetNamespaces", ves_icall_System_Reflection_Assembly_GetNamespaces)
 HANDLES(ICALL(ASSEM_13, "GetTypes", ves_icall_System_Reflection_Assembly_GetTypes))
 HANDLES(ICALL(ASSEM_14, "InternalGetAssemblyName", ves_icall_System_Reflection_Assembly_InternalGetAssemblyName))
@@ -806,7 +806,7 @@ ICALL(RTH_5, "GetElementType", ves_icall_RuntimeTypeHandle_GetElementType)
 ICALL(RTH_19, "GetGenericParameterInfo", ves_icall_RuntimeTypeHandle_GetGenericParameterInfo)
 ICALL(RTH_6, "GetGenericTypeDefinition_impl", ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl)
 ICALL(RTH_7, "GetMetadataToken", ves_icall_reflection_get_token)
-ICALL(RTH_8, "GetModule", ves_icall_RuntimeTypeHandle_GetModule)
+HANDLES(ICALL(RTH_8, "GetModule", ves_icall_RuntimeTypeHandle_GetModule))
 ICALL(RTH_9, "HasInstantiation", ves_icall_RuntimeTypeHandle_HasInstantiation)
 ICALL(RTH_10, "IsArray", ves_icall_RuntimeTypeHandle_IsArray)
 ICALL(RTH_11, "IsByRef", ves_icall_RuntimeTypeHandle_IsByRef)
index 8ad0c616b962a609932579699f018406426b7dff..de0582b7cc1cf8f5f649054f9fc32d3f36bc231e 100644 (file)
@@ -2605,15 +2605,14 @@ ves_icall_reflection_get_token (MonoObject* obj)
        return result;
 }
 
-ICALL_EXPORT MonoReflectionModule*
-ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
+ICALL_EXPORT MonoReflectionModuleHandle
+ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionTypeHandle type, MonoError *error)
 {
-       MonoError error;
-       MonoReflectionModule *result = NULL;
-       MonoClass *klass = mono_class_from_mono_type (type->type);
-       result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
-       mono_error_set_pending_exception (&error);
-       return result;
+       mono_error_init (error);
+       MonoDomain *domain = MONO_HANDLE_DOMAIN (type);
+       MonoType *t = MONO_HANDLE_GETVAL (type, type);
+       MonoClass *klass = mono_class_from_mono_type (t);
+       return mono_module_get_object_handle (domain, klass->image, error);
 }
 
 ICALL_EXPORT MonoReflectionAssembly*
@@ -4608,15 +4607,13 @@ leave:
        return res;
 }
 
-ICALL_EXPORT MonoReflectionModule*
-ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly
+ICALL_EXPORT MonoReflectionModuleHandle
+ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssemblyHandle assembly, MonoError *error
 {
-       MonoError error;
-       MonoReflectionModule *result = NULL;
-       result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
-       if (!mono_error_ok (&error))
-               mono_error_set_pending_exception (&error);
-       return result;
+       mono_error_init (error);
+       MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly);
+       MonoAssembly *a = MONO_HANDLE_GETVAL (assembly, assembly);
+       return mono_module_get_object_handle (domain, a->image, error);
 }
 
 ICALL_EXPORT MonoArray*
@@ -4724,23 +4721,24 @@ g_concat_dir_and_file (const char *dir, const char *file)
 }
 
 ICALL_EXPORT void *
-ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module
+ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, gint32 *size, MonoReflectionModuleHandleOut ref_module, MonoError *error
 {
-       MonoError error;
-       MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
+       mono_error_init (error);
+       MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
+       MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
+       MonoTableInfo *table = &assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
        guint32 i;
        guint32 cols [MONO_MANIFEST_SIZE];
        guint32 impl, file_idx;
        const char *val;
        MonoImage *module;
 
-       char *n = mono_string_to_utf8_checked (name, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       char *n = mono_string_handle_to_utf8 (name, error);
+       return_val_if_nok (error, NULL);
 
        for (i = 0; i < table->rows; ++i) {
                mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
-               val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
+               val = mono_metadata_string_heap (assembly->image, cols [MONO_MANIFEST_NAME]);
                if (strcmp (val, n) == 0)
                        break;
        }
@@ -4757,82 +4755,87 @@ ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflection
                g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
                file_idx = impl >> MONO_IMPLEMENTATION_BITS;
 
-               module = mono_image_load_file_for_image_checked (assembly->assembly->image, file_idx, &error);
-               if (mono_error_set_pending_exception (&error) || !module)
+               module = mono_image_load_file_for_image_checked (assembly->image, file_idx, error);
+               if (!is_ok (error) || !module)
                        return NULL;
        }
        else
-               module = assembly->assembly->image;
+               module = assembly->image;
 
        
-       MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
-       if (mono_error_set_pending_exception (&error))
+       MonoReflectionModuleHandle rm = mono_module_get_object_handle (domain, module, error);
+       if (!is_ok (error))
                return NULL;
-       mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
+       MONO_HANDLE_ASSIGN (ref_module, rm);
 
        return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
 }
 
-ICALL_EXPORT gboolean
-ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
+static gboolean
+get_manifest_resource_info_internal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, MonoManifestResourceInfoHandle info, MonoError *error)
 {
-       MonoError error;
-       MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
+       HANDLE_FUNCTION_ENTER ();
+       MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
+       MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
+       MonoTableInfo *table = &assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
        int i;
        guint32 cols [MONO_MANIFEST_SIZE];
        guint32 file_cols [MONO_FILE_SIZE];
        const char *val;
        char *n;
 
-       n = mono_string_to_utf8_checked (name, &error);
-       if (mono_error_set_pending_exception (&error))
-               return FALSE;
+       gboolean result = FALSE;
+       
+       n = mono_string_handle_to_utf8 (name, error);
+       if (!is_ok (error))
+               goto leave;
+
        for (i = 0; i < table->rows; ++i) {
                mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
-               val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
+               val = mono_metadata_string_heap (assembly->image, cols [MONO_MANIFEST_NAME]);
                if (strcmp (val, n) == 0)
                        break;
        }
        g_free (n);
        if (i == table->rows)
-               return FALSE;
+               goto leave;
 
        if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
-               info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
+               MONO_HANDLE_SETVAL (info, location, guint32, RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST);
        }
        else {
                switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
                case MONO_IMPLEMENTATION_FILE:
                        i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
-                       table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
+                       table = &assembly->image->tables [MONO_TABLE_FILE];
                        mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
-                       val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
-                       MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
+                       val = mono_metadata_string_heap (assembly->image, file_cols [MONO_FILE_NAME]);
+                       MONO_HANDLE_SET (info, filename, mono_string_new_handle (domain, val, error));
                        if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
-                               info->location = 0;
+                               MONO_HANDLE_SETVAL (info, location, guint32, 0);
                        else
-                               info->location = RESOURCE_LOCATION_EMBEDDED;
+                               MONO_HANDLE_SETVAL (info, location, guint32, RESOURCE_LOCATION_EMBEDDED);
                        break;
 
                case MONO_IMPLEMENTATION_ASSEMBLYREF:
                        i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
-                       mono_assembly_load_reference (assembly->assembly->image, i - 1);
-                       if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
-                               mono_error_set_assembly_load (&error, NULL, "Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
-                               mono_error_set_pending_exception (&error);
-                               return FALSE;
-                       }
-                       MonoReflectionAssembly *assm_obj;
-                       assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
-                       if (!assm_obj) {
-                               mono_error_set_pending_exception (&error);
-                               return FALSE;
+                       mono_assembly_load_reference (assembly->image, i - 1);
+                       if (assembly->image->references [i - 1] == REFERENCE_MISSING) {
+                               mono_error_set_assembly_load (error, NULL, "Assembly %d referenced from assembly %s not found ", i - 1, assembly->image->name);
+                               goto leave;
                        }
-                       MONO_OBJECT_SETREF (info, assembly, assm_obj);
+                       MonoReflectionAssemblyHandle assm_obj = mono_assembly_get_object_handle (mono_domain_get (), assembly->image->references [i - 1], error);
+                       if (!is_ok (error))
+                               goto leave;
+                       MONO_HANDLE_SET (info, assembly, assm_obj);
 
                        /* Obtain info recursively */
-                       ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
-                       info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
+                       get_manifest_resource_info_internal (assm_obj, name, info, error);
+                       if (!is_ok (error))
+                               goto leave;
+                       guint32 location = MONO_HANDLE_GETVAL (info, location);
+                       location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
+                       MONO_HANDLE_SETVAL (info, location, guint32, location);
                        break;
 
                case MONO_IMPLEMENTATION_EXP_TYPE:
@@ -4841,7 +4844,16 @@ ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflec
                }
        }
 
-       return TRUE;
+       result = TRUE;
+leave:
+       HANDLE_FUNCTION_RETURN_VAL (result);
+}
+
+ICALL_EXPORT gboolean
+ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, MonoManifestResourceInfoHandle info_h, MonoError *error)
+{
+       mono_error_init (error);
+       return get_manifest_resource_info_internal (assembly_h, name, info_h, error);
 }
 
 ICALL_EXPORT MonoObject*
@@ -4899,22 +4911,71 @@ ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *a
        return (MonoObject*)result;
 }
 
-ICALL_EXPORT MonoArray*
-ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
+static gboolean
+add_module_to_modules_array (MonoDomain *domain, MonoArrayHandle dest, int *dest_idx, MonoImage* module, MonoError *error)
 {
-       MonoError error;
+       HANDLE_FUNCTION_ENTER ();
+       mono_error_init (error);
+       if (module) {
+               MonoReflectionModuleHandle rm = mono_module_get_object_handle (domain, module, error);
+               if (!is_ok (error))
+                       goto leave;
+               
+               MONO_HANDLE_ARRAY_SETREF (dest, *dest_idx, rm);
+               ++(*dest_idx);
+       }
+
+leave:
+       HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
+}
+
+static gboolean
+add_file_to_modules_array (MonoDomain *domain, MonoArrayHandle dest, int dest_idx, MonoImage *image, MonoTableInfo *table, int table_idx,  MonoError *error)
+{
+       HANDLE_FUNCTION_ENTER ();
+       mono_error_init (error);
+
+       guint32 cols [MONO_FILE_SIZE];
+       mono_metadata_decode_row (table, table_idx, cols, MONO_FILE_SIZE);
+       if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
+               MonoReflectionModuleHandle rm = mono_module_file_get_object_handle (domain, image, table_idx, error);
+               if (!is_ok (error))
+                       goto leave;
+               MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, rm);
+       } else {
+               MonoImage *m = mono_image_load_file_for_image_checked (image, table_idx + 1, error);
+               if (!is_ok (error))
+                       goto leave;
+               if (!m) {
+                       const char *filename = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
+                       mono_error_set_assembly_load (error, g_strdup (filename), "%s", "");
+                       goto leave;
+               }
+               MonoReflectionModuleHandle rm = mono_module_get_object_handle (domain, m, error);
+               if (!is_ok (error))
+                       goto leave;
+               MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, rm);
+       }
+
+leave:
+       HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
+}
+
+ICALL_EXPORT MonoArrayHandle
+ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssemblyHandle assembly_h, MonoError *error)
+{
+       mono_error_init (error);
        MonoDomain *domain = mono_domain_get();
-       MonoArray *res;
+       MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
        MonoClass *klass;
        int i, j, file_count = 0;
        MonoImage **modules;
        guint32 module_count, real_module_count;
        MonoTableInfo *table;
-       guint32 cols [MONO_FILE_SIZE];
-       MonoImage *image = assembly->assembly->image;
+       MonoImage *image = assembly->image;
 
        g_assert (image != NULL);
-       g_assert (!assembly_is_dynamic (assembly->assembly));
+       g_assert (!assembly_is_dynamic (assembly));
 
        table = &image->tables [MONO_TABLE_FILE];
        file_count = table->rows;
@@ -4928,51 +4989,29 @@ ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly
                        real_module_count ++;
 
        klass = mono_class_get_module_class ();
-       res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       MonoArrayHandle res = mono_array_new_handle (domain, klass, 1 + real_module_count + file_count, error);
+       if (!is_ok (error))
+               goto fail;
 
-       MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       MonoReflectionModuleHandle image_obj = mono_module_get_object_handle (domain, image, error);
+       if (!is_ok (error))
+               goto fail;
+
+       MONO_HANDLE_ARRAY_SETREF (res, 0, image_obj);
 
-       mono_array_setref (res, 0, image_obj);
        j = 1;
        for (i = 0; i < module_count; ++i)
-               if (modules [i]) {
-                       MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
-                       if (mono_error_set_pending_exception (&error))
-                               return NULL;
-                       mono_array_setref (res, j, rm);
-                       ++j;
-               }
+               if (!add_module_to_modules_array (domain, res, &j, modules[i], error))
+                       goto fail;
 
        for (i = 0; i < file_count; ++i, ++j) {
-               mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
-               if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
-                       MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
-                       if (mono_error_set_pending_exception (&error))
-                               return NULL;
-                       mono_array_setref (res, j, rm);
-               }
-               else {
-                       MonoImage *m = mono_image_load_file_for_image_checked (image, i + 1, &error);
-                       if (mono_error_set_pending_exception (&error))
-                               return NULL;
-                       if (!m) {
-                               const char *filename = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
-                               mono_error_set_assembly_load (&error, g_strdup (filename), "%s", "");
-                               mono_error_set_pending_exception (&error);
-                               return NULL;
-                       }
-                       MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
-                       if (mono_error_set_pending_exception (&error))
-                               return NULL;
-                       mono_array_setref (res, j, rm);
-               }
+               if (!add_file_to_modules_array (domain, res, j, image, table, i, error))
+                       goto fail;
        }
 
        return res;
+fail:
+       return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
 }
 
 ICALL_EXPORT MonoReflectionMethod*
index 581ceeb2eca916502828e914fe12d10f33a51643..3764e4a9f330cca44797ce0ebf9c862be1de79df 100644 (file)
@@ -1310,6 +1310,9 @@ typedef struct {
        guint32 location;
 } MonoManifestResourceInfo;
 
+/* Safely access System.Reflection.ManifestResourceInfo from native code */
+TYPED_HANDLE_DECL (MonoManifestResourceInfo);
+
 /* A boxed IntPtr */
 typedef struct {
        MonoObject object;
index ec4d722fb89cd724f960592fe0e7f303193b0ca7..8f68929c2a376556a5f3d57f80c2302975c2882b 100644 (file)
@@ -7,8 +7,10 @@
 
 #include <glib.h>
 #include <mono/metadata/domain-internals.h>
+#include <mono/metadata/handle.h>
 #include <mono/metadata/mono-hash.h>
 #include <mono/metadata/mempool.h>
+#include <mono/utils/mono-error-internals.h>
 
 /*
  * We need to return always the same object for MethodInfo, FieldInfo etc..
@@ -38,43 +40,120 @@ reflected_hash (gconstpointer a);
 #define FREE_REFENTRY(entry)
 #endif
 
+static inline MonoObject*
+cache_object (MonoDomain *domain, MonoClass *klass, gpointer item, MonoObject* o)
+{
+       MonoObject *obj;
+       ReflectedEntry pe;
+       pe.item = item;
+       pe.refclass = klass;
+       mono_domain_lock (domain);
+       if (!domain->refobject_hash)
+               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");
 
-#define CACHE_OBJECT(t,p,o,k)  \
-       do {    \
-               t _obj; \
-        ReflectedEntry pe; \
-        pe.item = (p); \
-        pe.refclass = (k); \
-        mono_domain_lock (domain); \
-               if (!domain->refobject_hash)    \
-                       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");  \
-        _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
-        if (!_obj) { \
-                   ReflectedEntry *e = ALLOC_REFENTRY;         \
-                   e->item = (p);      \
-                   e->refclass = (k);  \
-                   mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
-            _obj = o; \
-        } \
-               mono_domain_unlock (domain);    \
-        return _obj; \
-       } while (0)
-
-#define CHECK_OBJECT(t,p,k)    \
-       do {    \
-               t _obj; \
-               ReflectedEntry e;       \
-               e.item = (p);   \
-               e.refclass = (k);       \
-               mono_domain_lock (domain);      \
-               if (!domain->refobject_hash)    \
-                       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");  \
-               if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
-                       mono_domain_unlock (domain);    \
-                       return _obj;    \
-               }       \
-        mono_domain_unlock (domain); \
-       } while (0)
+       obj = (MonoObject*) mono_g_hash_table_lookup (domain->refobject_hash, &pe);
+       if (obj == NULL) {
+               ReflectedEntry *e = ALLOC_REFENTRY;
+               e->item = item;
+               e->refclass = klass;
+               mono_g_hash_table_insert (domain->refobject_hash, e, o);
+               obj = o;
+       }
+       mono_domain_unlock (domain);
+       return obj;
+}
+
+
+static inline MonoObjectHandle
+cache_object_handle (MonoDomain *domain, MonoClass *klass, gpointer item, MonoObjectHandle o)
+{
+       ReflectedEntry pe;
+       pe.item = item;
+       pe.refclass = klass;
+       mono_domain_lock (domain);
+       if (!domain->refobject_hash)
+               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");
+
+       MonoObjectHandle obj = MONO_HANDLE_NEW (MonoObject, mono_g_hash_table_lookup (domain->refobject_hash, &pe));
+       if (MONO_HANDLE_IS_NULL (obj)) {
+               ReflectedEntry *e = ALLOC_REFENTRY;
+               e->item = item;
+               e->refclass = klass;
+               mono_g_hash_table_insert (domain->refobject_hash, e, MONO_HANDLE_RAW (o));
+               MONO_HANDLE_ASSIGN (obj, o);
+       }
+       mono_domain_unlock (domain);
+       return obj;
+}
+
+
+#define CACHE_OBJECT(t,p,o,k) ((t) (cache_object (domain, (k), (p), (o))))
+
+
+static inline MonoObject*
+check_object (MonoDomain* domain, MonoClass *klass, gpointer item)
+{
+       ReflectedEntry e;
+       e.item = item;
+       e.refclass = klass;
+       mono_domain_lock (domain);
+       if (!domain->refobject_hash)
+               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");
+       MonoObject *obj = (MonoObject*) mono_g_hash_table_lookup (domain->refobject_hash, &e);
+       mono_domain_unlock (domain);
+       return obj;
+}
+
+static inline MonoObjectHandle
+check_object_handle (MonoDomain* domain, MonoClass *klass, gpointer item)
+{
+       ReflectedEntry e;
+       e.item = item;
+       e.refclass = klass;
+       mono_domain_lock (domain);
+       if (!domain->refobject_hash)
+               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");
+       MonoObjectHandle obj = MONO_HANDLE_NEW (MonoObject, mono_g_hash_table_lookup (domain->refobject_hash, &e));
+       mono_domain_unlock (domain);
+       return obj;
+}
+
+
+typedef MonoObject* (*ReflectionCacheConstructFunc) (MonoDomain*, MonoClass*, gpointer, gpointer, MonoError *);
+
+typedef MonoObjectHandle (*ReflectionCacheConstructFunc_handle) (MonoDomain*, MonoClass*, gpointer, gpointer, MonoError *);
+
+
+static inline MonoObject*
+check_or_construct (MonoDomain *domain, MonoClass *klass, gpointer item, gpointer user_data, MonoError *error, ReflectionCacheConstructFunc construct)
+{
+       mono_error_init (error);
+       MonoObject *obj = check_object (domain, klass, item);
+       if (obj)
+               return obj;
+       obj = construct (domain, klass, item, user_data, error);
+       return_val_if_nok (error, NULL);
+       /* note no caching if there was an error in construction */
+       return cache_object (domain, klass, item, obj);
+}
+
+static inline MonoObjectHandle
+check_or_construct_handle (MonoDomain *domain, MonoClass *klass, gpointer item, gpointer user_data, MonoError *error, ReflectionCacheConstructFunc_handle construct)
+{
+       mono_error_init (error);
+       MonoObjectHandle obj = check_object_handle (domain, klass, item);
+       if (!MONO_HANDLE_IS_NULL (obj))
+               return obj;
+       MONO_HANDLE_ASSIGN (obj, construct (domain, klass, item, user_data, error));
+       return_val_if_nok (error, NULL);
+       /* note no caching if there was an error in construction */
+       return cache_object_handle (domain, klass, item, obj);
+}
+
+
+#define CHECK_OR_CONSTRUCT(t,p,k,construct,ud) ((t) check_or_construct (domain, (k), (p), (ud), error, (ReflectionCacheConstructFunc) (construct)))
+
+#define CHECK_OR_CONSTRUCT_HANDLE(t,p,k,construct,ud) ((t) check_or_construct_handle (domain, (k), (p), (ud), error, (ReflectionCacheConstructFunc_handle) (construct)))
 
 
 #endif /*__MONO_METADATA_REFLECTION_CACHE_H__*/
index f65158bf7b09a00db47539b2fe6f3561399212f9..022963d56319f6f30bc020e47c11fd3c218177fb 100644 (file)
@@ -67,6 +67,9 @@ mono_find_dynamic_image_owner (void *ptr);
 MonoReflectionAssembly*
 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error);
 
+MonoReflectionAssemblyHandle
+mono_assembly_get_object_handle (MonoDomain *domain, MonoAssembly *assembly, MonoError *error);
+
 MonoReflectionType*
 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error);
 
@@ -85,11 +88,11 @@ mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProp
 MonoReflectionEvent*
 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error);
 
-MonoReflectionModule*
-mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error);
+MonoReflectionModuleHandle
+mono_module_get_object_handle (MonoDomain *domain, MonoImage *image, MonoError *error);
 
-MonoReflectionModule*
-mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error);
+MonoReflectionModuleHandle
+mono_module_file_get_object_handle (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error);
 
 MonoReflectionMethodBody*
 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error);
index 3e42a8e4a6720cb305c4fa19295f137e3c2328fd..28817a3311438815a1a8583fd60ae57dcc7b9452 100644 (file)
@@ -199,14 +199,39 @@ mono_reflection_cleanup_domain (MonoDomain *domain)
 MonoReflectionAssembly*
 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoError error;
-       MonoReflectionAssembly *result;
-       result = mono_assembly_get_object_checked (domain, assembly, &error);
+       MonoReflectionAssemblyHandle result = mono_assembly_get_object_handle (domain, assembly, &error);
        mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
-       return result;
+       HANDLE_FUNCTION_RETURN_OBJ (result);
+}
+
+static MonoReflectionAssemblyHandle
+assembly_object_construct (MonoDomain *domain, MonoClass *unused_klass, MonoAssembly *assembly, gpointer user_data, MonoError *error)
+{
+       mono_error_init (error);
+       MonoReflectionAssemblyHandle res = MONO_HANDLE_NEW (MonoReflectionAssembly, mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error));
+       return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE));
+       MONO_HANDLE_SETVAL (res, assembly, MonoAssembly*, assembly);
+       return res;
+}
+
+/*
+ * mono_assembly_get_object_handle:
+ * @domain: an app domain
+ * @assembly: an assembly
+ *
+ * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
+ */
+MonoReflectionAssemblyHandle
+mono_assembly_get_object_handle (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
+{
+       mono_error_init (error);
+       return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionAssemblyHandle, assembly, NULL, assembly_object_construct, NULL);
 }
+
 /*
- * mono_assembly_get_object_checked:
+ * mono_assembly_get_object_handle:
  * @domain: an app domain
  * @assembly: an assembly
  *
@@ -215,17 +240,10 @@ mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
 MonoReflectionAssembly*
 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
 {
-       MonoReflectionAssembly *res;
-       
+       HANDLE_FUNCTION_ENTER ();
        mono_error_init (error);
-
-       CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
-       res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
-       if (!res)
-               return NULL;
-       res->assembly = assembly;
-
-       CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
+       MonoReflectionAssemblyHandle result = mono_assembly_get_object_handle (domain, assembly, error);
+       HANDLE_FUNCTION_RETURN_OBJ (result);
 }
 
 
@@ -233,69 +251,82 @@ mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, Mo
 MonoReflectionModule*   
 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoError error;
-       MonoReflectionModule *result;
-       result = mono_module_get_object_checked (domain, image, &error);
+       MonoReflectionModuleHandle result = mono_module_get_object_handle (domain, image, &error);
        mono_error_cleanup (&error);
-       return result;
+       HANDLE_FUNCTION_RETURN_OBJ (result);
 }
 
-MonoReflectionModule*
-mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
+static MonoReflectionModuleHandle
+module_object_construct (MonoDomain *domain, MonoClass *unused_klass, MonoImage *image, gpointer user_data, MonoError *error)
 {
-       MonoReflectionModule *res;
        char* basename;
        
        mono_error_init (error);
-       CHECK_OBJECT (MonoReflectionModule *, image, NULL);
-       res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
-       if (!res)
-               return NULL;
+       MonoReflectionModuleHandle res = MONO_HANDLE_NEW (MonoReflectionModule, mono_object_new_checked (domain, mono_class_get_mono_module_class (), error));
+       if (!is_ok (error))
+               goto fail;
 
-       res->image = image;
-       MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
-       if (!assm_obj)
-               return NULL;
-       MONO_OBJECT_SETREF (res, assembly, assm_obj);
+       MONO_HANDLE_SETVAL (res, image, MonoImage *, image);
+       MonoReflectionAssemblyHandle assm_obj = mono_assembly_get_object_handle (domain, image->assembly, error);
+       if (!is_ok (error))
+               goto fail;
+       MONO_HANDLE_SET (res, assembly, assm_obj);
 
-       MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
+       MONO_HANDLE_SET (res, fqname, mono_string_new_handle (domain, image->name, error));
+       if (!is_ok (error))
+               goto fail;
        basename = g_path_get_basename (image->name);
-       MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
-       MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
-       
+       MONO_HANDLE_SET (res, name, mono_string_new_handle (domain, basename, error));
+       if (!is_ok (error))
+               goto fail;
+       MONO_HANDLE_SET (res, scopename, mono_string_new_handle (domain, image->module_name, error));
+       if (!is_ok (error))
+               goto fail;
+
        g_free (basename);
 
+       guint32 token = 0;
        if (image->assembly->image == image) {
-               res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
+               token  = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
        } else {
                int i;
-               res->token = 0;
                if (image->assembly->image->modules) {
                        for (i = 0; i < image->assembly->image->module_count; i++) {
                                if (image->assembly->image->modules [i] == image)
-                                       res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
+                                       token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
                        }
-                       g_assert (res->token);
+                       g_assert (token != 0);
                }
        }
+       MONO_HANDLE_SETVAL (res, token, guint32, token);
 
-       CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
+       return res;
+fail:
+       return MONO_HANDLE_CAST (MonoReflectionModule, NULL_HANDLE);
+}
+
+MonoReflectionModuleHandle
+mono_module_get_object_handle (MonoDomain *domain, MonoImage *image, MonoError *error)
+{
+       mono_error_init (error);
+       return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionModuleHandle, image, NULL, module_object_construct, NULL);
 }
 
 MonoReflectionModule*
 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoError error;
-       MonoReflectionModule *result;
-       result = mono_module_file_get_object_checked (domain, image, table_index, &error);
+       MonoReflectionModuleHandle result = mono_module_file_get_object_handle (domain, image, table_index, &error);
        mono_error_cleanup (&error);
-       return result;
+       HANDLE_FUNCTION_RETURN_OBJ (result);
 }
 
-MonoReflectionModule*
-mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
+MonoReflectionModuleHandle
+mono_module_file_get_object_handle (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
 {
-       MonoReflectionModule *res;
        MonoTableInfo *table;
        guint32 cols [MONO_FILE_SIZE];
        const char *name;
@@ -304,19 +335,19 @@ mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int t
        
        mono_error_init (error);
 
-       res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
-       if (!res)
-               return NULL;
+       MonoReflectionModuleHandle res = MONO_HANDLE_NEW (MonoReflectionModule, mono_object_new_checked (domain, mono_class_get_mono_module_class (), error));
+       if (!is_ok (error))
+               goto fail;
 
        table = &image->tables [MONO_TABLE_FILE];
        g_assert (table_index < table->rows);
        mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
 
-       res->image = NULL;
-       MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
-       if (!assm_obj)
-               return NULL;
-       MONO_OBJECT_SETREF (res, assembly, assm_obj);
+       MONO_HANDLE_SETVAL (res, image, MonoImage*, NULL);
+       MonoReflectionAssemblyHandle assm_obj = mono_assembly_get_object_handle (domain, image->assembly, error);
+       if (!is_ok (error))
+               goto fail;
+       MONO_HANDLE_SET (res, assembly, assm_obj);
        name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
 
        /* Check whenever the row has a corresponding row in the moduleref table */
@@ -325,16 +356,24 @@ mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int t
                name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
                val = mono_metadata_string_heap (image, name_idx);
                if (strcmp (val, name) == 0)
-                       res->image = image->modules [i];
+                       MONO_HANDLE_SETVAL (res, image, MonoImage*, image->modules [i]);
        }
 
-       MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
-       MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
-       MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
-       res->is_resource = cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA;
-       res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
+       MONO_HANDLE_SET (res, fqname, mono_string_new_handle (domain, name, error));
+       if (!is_ok (error))
+               goto fail;
+       MONO_HANDLE_SET (res, name, mono_string_new_handle (domain, name, error));
+       if (!is_ok (error))
+               goto fail;
+       MONO_HANDLE_SET (res, scopename, mono_string_new_handle (domain, name, error));
+       if (!is_ok (error))
+               goto fail;
+       MONO_HANDLE_SETVAL (res, is_resource, MonoBoolean, cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA);
+       MONO_HANDLE_SETVAL (res, token, guint32, mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1));
 
        return res;
+fail:
+       return MONO_HANDLE_CAST (MonoReflectionModule, NULL_HANDLE);
 }
 
 static MonoType*
@@ -406,6 +445,7 @@ mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *err
 
        mono_error_init (error);
 
+       g_assert (type != NULL);
        klass = mono_class_from_mono_type (type);
 
        /*we must avoid using @type as it might have come
@@ -515,19 +555,11 @@ mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refcl
        return ret;
 }
 
-/*
- * mono_method_get_object_checked:
- * @domain: an app domain
- * @method: a method
- * @refclass: the reflected type (can be NULL)
- * @error: set on error.
- *
- * Return an System.Reflection.MonoMethod object representing the method @method.
- * Returns NULL and sets @error on error.
- */
-MonoReflectionMethod*
-mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
+static MonoReflectionMethod*
+method_object_construct (MonoDomain *domain, MonoClass *refclass, MonoMethod *method, gpointer user_data, MonoError *error)
 {
+       mono_error_init (error);
+       g_assert (refclass != NULL);
        /*
         * We use the same C representation for methods and constructors, but the type 
         * name in C# is different.
@@ -538,10 +570,6 @@ mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClas
 
        mono_error_init (error);
 
-       if (!refclass)
-               refclass = method->klass;
-
-       CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
        if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
                klass = mono_class_get_mono_cmethod_class ();
        }
@@ -559,13 +587,33 @@ mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClas
 
        MONO_OBJECT_SETREF (ret, reftype, rt);
 
-       CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
+       return ret;
 
 leave:
        g_assert (!mono_error_ok (error));
        return NULL;
 }
 
+/*
+ * mono_method_get_object_checked:
+ * @domain: an app domain
+ * @method: a method
+ * @refclass: the reflected type (can be NULL)
+ * @error: set on error.
+ *
+ * Return an System.Reflection.MonoMethod object representing the method @method.
+ * Returns NULL and sets @error on error.
+ */
+MonoReflectionMethod*
+mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
+{
+       mono_error_init (error);
+       if (!refclass)
+               refclass = method->klass;
+
+       return CHECK_OR_CONSTRUCT (MonoReflectionMethod*, method, refclass, method_object_construct, NULL);
+}
+
 /*
  * mono_method_clear_object:
  *
@@ -610,25 +658,14 @@ mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *fie
        return result;
 }
 
-/*
- * mono_field_get_object_checked:
- * @domain: an app domain
- * @klass: a type
- * @field: a field
- * @error: set on error
- *
- * Return an System.Reflection.MonoField object representing the field @field
- * in class @klass. On error, returns NULL and sets @error.
- */
-MonoReflectionField*
-mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
+static MonoReflectionField*
+field_object_construct (MonoDomain *domain, MonoClass *klass, MonoClassField *field, gpointer user_data, MonoError *error)
 {
        MonoReflectionType *rt;
        MonoReflectionField *res;
 
        mono_error_init (error);
 
-       CHECK_OBJECT (MonoReflectionField *, field, klass);
        res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
        if (!res)
                return NULL;
@@ -644,7 +681,24 @@ mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassFi
                MONO_OBJECT_SETREF (res, type, rt);
        }
        res->attrs = mono_field_get_flags (field);
-       CACHE_OBJECT (MonoReflectionField *, field, res, klass);
+       return res;
+}
+
+/*
+ * mono_field_get_object_checked:
+ * @domain: an app domain
+ * @klass: a type
+ * @field: a field
+ * @error: set on error
+ *
+ * Return an System.Reflection.MonoField object representing the field @field
+ * in class @klass. On error, returns NULL and sets @error.
+ */
+MonoReflectionField*
+mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
+{
+       mono_error_init (error);
+       return CHECK_OR_CONSTRUCT (MonoReflectionField*, field, klass, field_object_construct, NULL);
 }
 
 /*
@@ -666,6 +720,21 @@ mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *pr
        return result;
 }
 
+static MonoReflectionProperty*
+property_object_construct (MonoDomain *domain, MonoClass *klass, MonoProperty *property, gpointer user_data, MonoError *error)
+{
+       MonoReflectionProperty *res;
+
+       mono_error_init (error);
+
+       res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
+       if (!res)
+               return NULL;
+       res->klass = klass;
+       res->property = property;
+       return res;
+}
+
 /**
  * mono_property_get_object:
  * @domain: an app domain
@@ -679,17 +748,8 @@ mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *pr
 MonoReflectionProperty*
 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
 {
-       MonoReflectionProperty *res;
-
        mono_error_init (error);
-
-       CHECK_OBJECT (MonoReflectionProperty *, property, klass);
-       res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
-       if (!res)
-               return NULL;
-       res->klass = klass;
-       res->property = property;
-       CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
+       return CHECK_OR_CONSTRUCT (MonoReflectionProperty*, property, klass, property_object_construct, NULL);
 }
 
 /*
@@ -711,6 +771,20 @@ mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
        return result;
 }
 
+static MonoReflectionEvent*
+event_object_construct (MonoDomain *domain, MonoClass *klass, MonoEvent *event, gpointer user_data, MonoError *error)
+{
+       MonoReflectionMonoEvent *mono_event;
+
+       mono_error_init (error);
+       mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
+       if (!mono_event)
+               return NULL;
+       mono_event->klass = klass;
+       mono_event->event = event;
+       return &mono_event->object;
+}
+
 /**
  * mono_event_get_object_checked:
  * @domain: an app domain
@@ -724,18 +798,8 @@ mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
 MonoReflectionEvent*
 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
 {
-       MonoReflectionEvent *res;
-       MonoReflectionMonoEvent *mono_event;
-
        mono_error_init (error);
-       CHECK_OBJECT (MonoReflectionEvent *, event, klass);
-       mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
-       if (!mono_event)
-               return NULL;
-       mono_event->klass = klass;
-       mono_event->event = event;
-       res = (MonoReflectionEvent*)mono_event;
-       CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
+       return CHECK_OR_CONSTRUCT (MonoReflectionEvent*, event, klass, event_object_construct, NULL);
 }
 
 /**
@@ -802,19 +866,15 @@ get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
        return *reflection_missing;
 }
 
-/*
- * mono_param_get_objects:
- * @domain: an app domain
- * @method: a method
- *
- * Return an System.Reflection.ParameterInfo array object representing the parameters
- * in the method @method.
- */
-MonoArray*
-mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
+static MonoArray*
+param_objects_construct (MonoDomain *domain, MonoClass *refclass, MonoMethodSignature **addr_of_sig, gpointer user_data, MonoError *error)
 {
        static MonoClass *System_Reflection_ParameterInfo;
        static MonoClass *System_Reflection_ParameterInfo_array;
+
+       MonoMethod *method = (MonoMethod*)user_data;
+       MonoMethodSignature *sig = *addr_of_sig; /* see note in mono_param_get_objects_internal */
+
        MonoArray *res = NULL;
        MonoReflectionMethod *member = NULL;
        MonoReflectionParameter *param = NULL;
@@ -824,7 +884,6 @@ mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoCla
        MonoObject *dbnull = NULL;
        MonoObject *missing = NULL;
        MonoMarshalSpec **mspecs = NULL;
-       MonoMethodSignature *sig = NULL;
        MonoVTable *pinfo_vtable;
        MonoReflectionType *rt;
        int i;
@@ -833,35 +892,12 @@ mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoCla
        
        if (!System_Reflection_ParameterInfo_array) {
                MonoClass *klass;
-
                klass = mono_class_get_mono_parameter_info_class ();
-
-               mono_memory_barrier ();
                System_Reflection_ParameterInfo = klass; 
-
-       
                klass = mono_array_class_get (klass, 1);
-               mono_memory_barrier ();
                System_Reflection_ParameterInfo_array = klass;
        }
 
-       sig = mono_method_signature_checked (method, error);
-       if (!mono_error_ok (error))
-               goto leave;
-
-       if (!sig->param_count) {
-               res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
-               if (!res)
-                       goto leave;
-
-               return res;
-       }
-
-       /* Note: the cache is based on the address of the signature into the method
-        * since we already cache MethodInfos with the method as keys.
-        */
-       CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
-
        member = mono_method_get_object_checked (domain, method, refclass, error);
        if (!member)
                goto leave;
@@ -968,7 +1004,40 @@ leave:
        if (!is_ok (error))
                return NULL;
        
-       CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
+       return res;
+}
+
+/*
+ * mono_param_get_objects:
+ * @domain: an app domain
+ * @method: a method
+ *
+ * Return an System.Reflection.ParameterInfo array object representing the parameters
+ * in the method @method.
+ */
+MonoArray*
+mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
+{
+       mono_error_init (error);
+
+       MonoMethodSignature *sig = mono_method_signature_checked (method, error);
+       if (!mono_error_ok (error))
+               goto leave;
+
+       if (!sig->param_count) {
+               MonoArray *res = mono_array_new_checked (domain, mono_class_get_mono_parameter_info_class (), 0, error);
+               if (!res)
+                       goto leave;
+
+               return res;
+       }
+
+       /* Note: the cache is based on the address of the signature into the method
+        * since we already cache MethodInfos with the method as keys.
+        */
+       return CHECK_OR_CONSTRUCT (MonoArray*, &method->signature, refclass, param_objects_construct, method);
+leave:
+       return NULL;
 }
 
 MonoArray*
@@ -996,17 +1065,8 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
        return result;
 }
 
-/**
- * mono_method_body_get_object_checked:
- * @domain: an app domain
- * @method: a method
- * @error: set on error
- *
- * Return an System.Reflection.MethodBody object representing the
- * method @method.  On failure, returns NULL and sets @error.
- */
-MonoReflectionMethodBody*
-mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
+static MonoReflectionMethodBody*
+method_body_object_construct (MonoDomain *domain, MonoClass *unused_class, MonoMethod *method, gpointer user_data, MonoError *error)
 {
        MonoReflectionMethodBody *ret;
        MonoMethodHeader *header;
@@ -1025,8 +1085,6 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
                return NULL;
        }
 
-       CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
-
        if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
                (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
            (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
@@ -1124,14 +1182,28 @@ mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, Mon
        }
 
        mono_metadata_free_mh (header);
-       CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
        return ret;
-
 fail:
        mono_metadata_free_mh (header);
        return NULL;
 }
 
+/**
+ * mono_method_body_get_object_checked:
+ * @domain: an app domain
+ * @method: a method
+ * @error: set on error
+ *
+ * Return an System.Reflection.MethodBody object representing the
+ * method @method.  On failure, returns NULL and sets @error.
+ */
+MonoReflectionMethodBody*
+mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
+{
+       mono_error_init (error);
+       return CHECK_OR_CONSTRUCT (MonoReflectionMethodBody *, method, NULL, method_body_object_construct, NULL);
+}
+
 /**
  * mono_get_dbnull_object:
  * @domain: Domain where the object lives
index 7c2117a7a3eb1a13b097b658a3aa9cb48ccf6a43..d189c4a03172d91d46dddf26aa2586bb676e703f 100644 (file)
@@ -1304,13 +1304,13 @@ mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
 static gpointer
 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
 {
-       CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
+       return CACHE_OBJECT (MonoReflectionAssembly *, assembly, &res->object, NULL);
 }
 
 static gpointer
 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
 {
-       CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
+       return CACHE_OBJECT (MonoReflectionModuleBuilder *, module, &res->module.obj, NULL);
 }
 
 static gboolean