+/**
+ * mono_aot_get_class_from_name:
+ *
+ * Obtains a MonoClass with a given namespace and a given name which is located in IMAGE,
+ * using a cache stored in the AOT file.
+ * Stores the resulting class in *KLASS if found, stores NULL otherwise.
+ *
+ * Returns: TRUE if the klass was found/not found in the cache, FALSE if no aot file was
+ * found.
+ */
+gboolean
+mono_aot_get_class_from_name (MonoImage *image, const char *name_space, const char *name, MonoClass **klass)
+{
+ MonoAotModule *aot_module;
+ guint16 *table, *entry;
+ guint16 table_size;
+ guint32 hash;
+ char full_name_buf [1024];
+ char *full_name;
+ const char *name2, *name_space2;
+ MonoTableInfo *t;
+ guint32 cols [MONO_TYPEDEF_SIZE];
+ GHashTable *nspace_table;
+
+ if (!aot_modules)
+ return FALSE;
+
+ mono_aot_lock ();
+
+ aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, image->assembly);
+ if (!aot_module || !aot_module->class_name_table) {
+ mono_aot_unlock ();
+ return FALSE;
+ }
+
+ *klass = NULL;
+
+ /* First look in the cache */
+ if (!aot_module->name_cache)
+ aot_module->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
+ nspace_table = g_hash_table_lookup (aot_module->name_cache, name_space);
+ if (nspace_table) {
+ *klass = g_hash_table_lookup (nspace_table, name);
+ if (*klass) {
+ mono_aot_unlock ();
+ return TRUE;
+ }
+ }
+
+ table_size = aot_module->class_name_table [0];
+ table = aot_module->class_name_table + 1;
+
+ if (name_space [0] == '\0')
+ full_name = g_strdup_printf ("%s", name);
+ else {
+ if (strlen (name_space) + strlen (name) < 1000) {
+ sprintf (full_name_buf, "%s.%s", name_space, name);
+ full_name = full_name_buf;
+ } else {
+ full_name = g_strdup_printf ("%s.%s", name_space, name);
+ }
+ }
+ hash = g_str_hash (full_name) % table_size;
+ if (full_name != full_name_buf)
+ g_free (full_name);
+
+ entry = &table [hash * 2];
+
+ if (entry [0] != 0) {
+ t = &image->tables [MONO_TABLE_TYPEDEF];
+
+ while (TRUE) {
+ guint32 index = entry [0];
+ guint32 next = entry [1];
+ guint32 token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, index);
+
+ name_table_accesses ++;
+
+ mono_metadata_decode_row (t, index - 1, cols, MONO_TYPEDEF_SIZE);
+
+ name2 = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
+ name_space2 = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
+
+ if (!strcmp (name, name2) && !strcmp (name_space, name_space2)) {
+ mono_aot_unlock ();
+ *klass = mono_class_get (image, token);
+
+ /* Add to cache */
+ if (*klass) {
+ mono_aot_lock ();
+ nspace_table = g_hash_table_lookup (aot_module->name_cache, name_space);
+ if (!nspace_table) {
+ nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (aot_module->name_cache, (char*)name_space2, nspace_table);
+ }
+ g_hash_table_insert (nspace_table, (char*)name2, *klass);
+ mono_aot_unlock ();
+ }
+ return TRUE;
+ }
+
+ if (next != 0) {
+ entry = &table [next * 2];
+ } else {
+ break;
+ }
+ }
+ }
+
+ mono_aot_unlock ();
+
+ return TRUE;
+}
+