PageRenderTime 58ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/mono/metadata/domain.c

https://bitbucket.org/danipen/mono
C | 2701 lines | 1847 code | 474 blank | 380 comment | 305 complexity | e460b1959b4e67183c0fd03c10e88161 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * domain.c: MonoDomain functions
  3. *
  4. * Author:
  5. * Dietmar Maurer (dietmar@ximian.com)
  6. * Patrik Torstensson
  7. *
  8. * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  9. * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  10. * Copyright 2011-2012 Xamarin, Inc (http://www.xamarin.com)
  11. */
  12. #include <config.h>
  13. #include <glib.h>
  14. #include <string.h>
  15. #include <sys/stat.h>
  16. #include <mono/metadata/gc-internal.h>
  17. #include <mono/utils/mono-compiler.h>
  18. #include <mono/utils/mono-logger-internal.h>
  19. #include <mono/utils/mono-membar.h>
  20. #include <mono/utils/mono-counters.h>
  21. #include <mono/utils/hazard-pointer.h>
  22. #include <mono/utils/mono-tls.h>
  23. #include <mono/metadata/object.h>
  24. #include <mono/metadata/object-internals.h>
  25. #include <mono/metadata/domain-internals.h>
  26. #include <mono/metadata/class-internals.h>
  27. #include <mono/metadata/assembly.h>
  28. #include <mono/metadata/exception.h>
  29. #include <mono/metadata/metadata-internals.h>
  30. #include <mono/metadata/gc-internal.h>
  31. #include <mono/metadata/appdomain.h>
  32. #include <mono/metadata/mono-debug-debugger.h>
  33. #include <mono/metadata/mono-config.h>
  34. #include <mono/metadata/threads-types.h>
  35. #include <metadata/threads.h>
  36. #include <metadata/profiler-private.h>
  37. #include <mono/metadata/coree.h>
  38. /* #define DEBUG_DOMAIN_UNLOAD */
  39. /* we need to use both the Tls* functions and __thread because
  40. * some archs may generate faster jit code with one meachanism
  41. * or the other (we used to do it because tls slots were GC-tracked,
  42. * but we can't depend on this).
  43. */
  44. static MonoNativeTlsKey appdomain_thread_id;
  45. #ifdef MONO_HAVE_FAST_TLS
  46. MONO_FAST_TLS_DECLARE(tls_appdomain);
  47. #define GET_APPDOMAIN() ((MonoDomain*)MONO_FAST_TLS_GET(tls_appdomain))
  48. #define SET_APPDOMAIN(x) do { \
  49. MONO_FAST_TLS_SET (tls_appdomain,x); \
  50. mono_native_tls_set_value (appdomain_thread_id, x); \
  51. mono_gc_set_current_thread_appdomain (x); \
  52. } while (FALSE)
  53. #else /* !MONO_HAVE_FAST_TLS */
  54. #define GET_APPDOMAIN() ((MonoDomain *)mono_native_tls_get_value (appdomain_thread_id))
  55. #define SET_APPDOMAIN(x) do { \
  56. mono_native_tls_set_value (appdomain_thread_id, x); \
  57. mono_gc_set_current_thread_appdomain (x); \
  58. } while (FALSE)
  59. #endif
  60. #define GET_APPCONTEXT() (mono_thread_internal_current ()->current_appcontext)
  61. #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_internal_current (), current_appcontext, (x))
  62. static guint16 appdomain_list_size = 0;
  63. static guint16 appdomain_next = 0;
  64. static MonoDomain **appdomains_list = NULL;
  65. static MonoImage *exe_image;
  66. gboolean mono_dont_free_domains;
  67. #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
  68. #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
  69. static CRITICAL_SECTION appdomains_mutex;
  70. static MonoDomain *mono_root_domain = NULL;
  71. /* some statistics */
  72. static int max_domain_code_size = 0;
  73. static int max_domain_code_alloc = 0;
  74. static int total_domain_code_alloc = 0;
  75. /* AppConfigInfo: Information about runtime versions supported by an
  76. * aplication.
  77. */
  78. typedef struct {
  79. GSList *supported_runtimes;
  80. char *required_runtime;
  81. int configuration_count;
  82. int startup_count;
  83. } AppConfigInfo;
  84. /*
  85. * AotModuleInfo: Contains information about AOT modules.
  86. */
  87. typedef struct {
  88. MonoImage *image;
  89. gpointer start, end;
  90. } AotModuleInfo;
  91. static const MonoRuntimeInfo *current_runtime = NULL;
  92. static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
  93. /*
  94. * Contains information about AOT loaded code.
  95. */
  96. static MonoAotModuleInfoTable *aot_modules = NULL;
  97. /* This is the list of runtime versions supported by this JIT.
  98. */
  99. static const MonoRuntimeInfo supported_runtimes[] = {
  100. {"v2.0.50215","2.0", { {2,0,0,0}, { 8,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
  101. {"v2.0.50727","2.0", { {2,0,0,0}, { 8,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
  102. {"v4.0.30319","4.5", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
  103. {"v4.0.30128","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
  104. {"v4.0.20506","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
  105. {"moonlight", "2.1", { {2,0,5,0}, { 9,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
  106. };
  107. /* The stable runtime version */
  108. #define DEFAULT_RUNTIME_VERSION "v2.0.50727"
  109. /* Callbacks installed by the JIT */
  110. static MonoCreateDomainFunc create_domain_hook;
  111. static MonoFreeDomainFunc free_domain_hook;
  112. /* This is intentionally not in the header file, so people don't misuse it. */
  113. extern void _mono_debug_init_corlib (MonoDomain *domain);
  114. static void
  115. get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
  116. static const MonoRuntimeInfo*
  117. get_runtime_by_version (const char *version);
  118. static MonoImage*
  119. mono_jit_info_find_aot_module (guint8* addr);
  120. MonoNativeTlsKey
  121. mono_domain_get_tls_key (void)
  122. {
  123. return appdomain_thread_id;
  124. }
  125. gint32
  126. mono_domain_get_tls_offset (void)
  127. {
  128. int offset = -1;
  129. MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
  130. /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
  131. : "=r" (offset));*/
  132. return offset;
  133. }
  134. #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
  135. #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
  136. #define JIT_INFO_TABLE_FILLED_NUM_ELEMENTS (MONO_JIT_INFO_TABLE_CHUNK_SIZE * JIT_INFO_TABLE_FILL_RATIO_NOM / JIT_INFO_TABLE_FILL_RATIO_DENOM)
  137. #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
  138. #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
  139. #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL)
  140. #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == JIT_INFO_TOMBSTONE_MARKER)
  141. #define JIT_INFO_TABLE_HAZARD_INDEX 0
  142. #define JIT_INFO_HAZARD_INDEX 1
  143. static int
  144. jit_info_table_num_elements (MonoJitInfoTable *table)
  145. {
  146. int i;
  147. int num_elements = 0;
  148. for (i = 0; i < table->num_chunks; ++i) {
  149. MonoJitInfoTableChunk *chunk = table->chunks [i];
  150. int chunk_num_elements = chunk->num_elements;
  151. int j;
  152. for (j = 0; j < chunk_num_elements; ++j) {
  153. if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
  154. ++num_elements;
  155. }
  156. }
  157. return num_elements;
  158. }
  159. static MonoJitInfoTableChunk*
  160. jit_info_table_new_chunk (void)
  161. {
  162. MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
  163. chunk->refcount = 1;
  164. return chunk;
  165. }
  166. static MonoJitInfoTable *
  167. jit_info_table_new (MonoDomain *domain)
  168. {
  169. MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
  170. table->domain = domain;
  171. table->num_chunks = 1;
  172. table->chunks [0] = jit_info_table_new_chunk ();
  173. return table;
  174. }
  175. static void
  176. jit_info_table_free (MonoJitInfoTable *table)
  177. {
  178. int i;
  179. int num_chunks = table->num_chunks;
  180. MonoDomain *domain = table->domain;
  181. mono_domain_lock (domain);
  182. table->domain->num_jit_info_tables--;
  183. if (table->domain->num_jit_info_tables <= 1) {
  184. GSList *list;
  185. for (list = table->domain->jit_info_free_queue; list; list = list->next)
  186. g_free (list->data);
  187. g_slist_free (table->domain->jit_info_free_queue);
  188. table->domain->jit_info_free_queue = NULL;
  189. }
  190. /* At this point we assume that there are no other threads
  191. still accessing the table, so we don't have to worry about
  192. hazardous pointers. */
  193. for (i = 0; i < num_chunks; ++i) {
  194. MonoJitInfoTableChunk *chunk = table->chunks [i];
  195. int num_elements;
  196. int j;
  197. if (--chunk->refcount > 0)
  198. continue;
  199. num_elements = chunk->num_elements;
  200. for (j = 0; j < num_elements; ++j) {
  201. MonoJitInfo *ji = chunk->data [j];
  202. if (IS_JIT_INFO_TOMBSTONE (ji))
  203. g_free (ji);
  204. }
  205. g_free (chunk);
  206. }
  207. mono_domain_unlock (domain);
  208. g_free (table);
  209. }
  210. /* The jit_info_table is sorted in ascending order by the end
  211. * addresses of the compiled methods. The reason why we have to do
  212. * this is that once we introduce tombstones, it becomes possible for
  213. * code ranges to overlap, and if we sort by code start and insert at
  214. * the back of the table, we cannot guarantee that we won't overlook
  215. * an entry.
  216. *
  217. * There are actually two possible ways to do the sorting and
  218. * inserting which work with our lock-free mechanism:
  219. *
  220. * 1. Sort by start address and insert at the front. When looking for
  221. * an entry, find the last one with a start address lower than the one
  222. * you're looking for, then work your way to the front of the table.
  223. *
  224. * 2. Sort by end address and insert at the back. When looking for an
  225. * entry, find the first one with an end address higher than the one
  226. * you're looking for, then work your way to the end of the table.
  227. *
  228. * We chose the latter out of convenience.
  229. */
  230. static int
  231. jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
  232. {
  233. int left = 0, right = table->num_chunks;
  234. g_assert (left < right);
  235. do {
  236. int pos = (left + right) / 2;
  237. MonoJitInfoTableChunk *chunk = table->chunks [pos];
  238. if (addr < chunk->last_code_end)
  239. right = pos;
  240. else
  241. left = pos + 1;
  242. } while (left < right);
  243. g_assert (left == right);
  244. if (left >= table->num_chunks)
  245. return table->num_chunks - 1;
  246. return left;
  247. }
  248. static int
  249. jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
  250. {
  251. int left = 0, right = chunk->num_elements;
  252. while (left < right) {
  253. int pos = (left + right) / 2;
  254. MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
  255. gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
  256. if (addr < code_end)
  257. right = pos;
  258. else
  259. left = pos + 1;
  260. }
  261. g_assert (left == right);
  262. return left;
  263. }
  264. MonoJitInfo*
  265. mono_jit_info_table_find (MonoDomain *domain, char *addr)
  266. {
  267. MonoJitInfoTable *table;
  268. MonoJitInfo *ji;
  269. int chunk_pos, pos;
  270. MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
  271. MonoImage *image;
  272. ++mono_stats.jit_info_table_lookup_count;
  273. /* First we have to get the domain's jit_info_table. This is
  274. complicated by the fact that a writer might substitute a
  275. new table and free the old one. What the writer guarantees
  276. us is that it looks at the hazard pointers after it has
  277. changed the jit_info_table pointer. So, if we guard the
  278. table by a hazard pointer and make sure that the pointer is
  279. still there after we've made it hazardous, we don't have to
  280. worry about the writer freeing the table. */
  281. table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
  282. chunk_pos = jit_info_table_index (table, (gint8*)addr);
  283. g_assert (chunk_pos < table->num_chunks);
  284. pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
  285. /* We now have a position that's very close to that of the
  286. first element whose end address is higher than the one
  287. we're looking for. If we don't have the exact position,
  288. then we have a position below that one, so we'll just
  289. search upward until we find our element. */
  290. do {
  291. MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
  292. while (pos < chunk->num_elements) {
  293. ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
  294. ++pos;
  295. if (IS_JIT_INFO_TOMBSTONE (ji)) {
  296. mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
  297. continue;
  298. }
  299. if ((gint8*)addr >= (gint8*)ji->code_start
  300. && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
  301. mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
  302. mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
  303. return ji;
  304. }
  305. /* If we find a non-tombstone element which is already
  306. beyond what we're looking for, we have to end the
  307. search. */
  308. if ((gint8*)addr < (gint8*)ji->code_start)
  309. goto not_found;
  310. }
  311. ++chunk_pos;
  312. pos = 0;
  313. } while (chunk_pos < table->num_chunks);
  314. not_found:
  315. if (!hp)
  316. return NULL;
  317. mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
  318. mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
  319. ji = NULL;
  320. /* Maybe its an AOT module */
  321. image = mono_jit_info_find_aot_module ((guint8*)addr);
  322. if (image)
  323. ji = jit_info_find_in_aot_func (domain, image, addr);
  324. return ji;
  325. }
  326. static G_GNUC_UNUSED void
  327. jit_info_table_check (MonoJitInfoTable *table)
  328. {
  329. int i;
  330. for (i = 0; i < table->num_chunks; ++i) {
  331. MonoJitInfoTableChunk *chunk = table->chunks [i];
  332. int j;
  333. g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
  334. if (chunk->refcount > 10)
  335. printf("warning: chunk refcount is %d\n", chunk->refcount);
  336. g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
  337. for (j = 0; j < chunk->num_elements; ++j) {
  338. MonoJitInfo *this = chunk->data [j];
  339. MonoJitInfo *next;
  340. g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
  341. if (j < chunk->num_elements - 1)
  342. next = chunk->data [j + 1];
  343. else if (i < table->num_chunks - 1) {
  344. int k;
  345. for (k = i + 1; k < table->num_chunks; ++k)
  346. if (table->chunks [k]->num_elements > 0)
  347. break;
  348. if (k >= table->num_chunks)
  349. return;
  350. g_assert (table->chunks [k]->num_elements > 0);
  351. next = table->chunks [k]->data [0];
  352. } else
  353. return;
  354. g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
  355. }
  356. }
  357. }
  358. static MonoJitInfoTable*
  359. jit_info_table_realloc (MonoJitInfoTable *old)
  360. {
  361. int i;
  362. int num_elements = jit_info_table_num_elements (old);
  363. int required_size;
  364. int num_chunks;
  365. int new_chunk, new_element;
  366. MonoJitInfoTable *new;
  367. /* number of needed places for elements needed */
  368. required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
  369. num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
  370. if (num_chunks == 0) {
  371. g_assert (num_elements == 0);
  372. return jit_info_table_new (old->domain);
  373. }
  374. g_assert (num_chunks > 0);
  375. new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
  376. new->domain = old->domain;
  377. new->num_chunks = num_chunks;
  378. for (i = 0; i < num_chunks; ++i)
  379. new->chunks [i] = jit_info_table_new_chunk ();
  380. new_chunk = 0;
  381. new_element = 0;
  382. for (i = 0; i < old->num_chunks; ++i) {
  383. MonoJitInfoTableChunk *chunk = old->chunks [i];
  384. int chunk_num_elements = chunk->num_elements;
  385. int j;
  386. for (j = 0; j < chunk_num_elements; ++j) {
  387. if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
  388. g_assert (new_chunk < num_chunks);
  389. new->chunks [new_chunk]->data [new_element] = chunk->data [j];
  390. if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
  391. new->chunks [new_chunk]->num_elements = new_element;
  392. ++new_chunk;
  393. new_element = 0;
  394. }
  395. }
  396. }
  397. }
  398. if (new_chunk < num_chunks) {
  399. g_assert (new_chunk == num_chunks - 1);
  400. new->chunks [new_chunk]->num_elements = new_element;
  401. g_assert (new->chunks [new_chunk]->num_elements > 0);
  402. }
  403. for (i = 0; i < num_chunks; ++i) {
  404. MonoJitInfoTableChunk *chunk = new->chunks [i];
  405. MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
  406. new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
  407. }
  408. return new;
  409. }
  410. static void
  411. jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
  412. {
  413. MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
  414. MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
  415. g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
  416. new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
  417. new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
  418. memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
  419. memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
  420. new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
  421. + new1->data [new1->num_elements - 1]->code_size;
  422. new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
  423. + new2->data [new2->num_elements - 1]->code_size;
  424. *new1p = new1;
  425. *new2p = new2;
  426. }
  427. static MonoJitInfoTable*
  428. jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
  429. {
  430. MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
  431. + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
  432. int i, j;
  433. new_table->domain = table->domain;
  434. new_table->num_chunks = table->num_chunks + 1;
  435. j = 0;
  436. for (i = 0; i < table->num_chunks; ++i) {
  437. if (table->chunks [i] == chunk) {
  438. jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
  439. j += 2;
  440. } else {
  441. new_table->chunks [j] = table->chunks [i];
  442. ++new_table->chunks [j]->refcount;
  443. ++j;
  444. }
  445. }
  446. g_assert (j == new_table->num_chunks);
  447. return new_table;
  448. }
  449. static MonoJitInfoTableChunk*
  450. jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
  451. {
  452. MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
  453. int i, j;
  454. j = 0;
  455. for (i = 0; i < old->num_elements; ++i) {
  456. if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
  457. new->data [j++] = old->data [i];
  458. }
  459. new->num_elements = j;
  460. if (new->num_elements > 0)
  461. new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
  462. else
  463. new->last_code_end = old->last_code_end;
  464. return new;
  465. }
  466. static MonoJitInfoTable*
  467. jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
  468. {
  469. MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
  470. + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
  471. int i, j;
  472. new_table->domain = table->domain;
  473. new_table->num_chunks = table->num_chunks;
  474. j = 0;
  475. for (i = 0; i < table->num_chunks; ++i) {
  476. if (table->chunks [i] == chunk)
  477. new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
  478. else {
  479. new_table->chunks [j] = table->chunks [i];
  480. ++new_table->chunks [j]->refcount;
  481. ++j;
  482. }
  483. }
  484. g_assert (j == new_table->num_chunks);
  485. return new_table;
  486. }
  487. /* As we add an element to the table the case can arise that the chunk
  488. * to which we need to add is already full. In that case we have to
  489. * allocate a new table and do something about that chunk. We have
  490. * several strategies:
  491. *
  492. * If the number of elements in the table is below the low watermark
  493. * or above the high watermark, we reallocate the whole table.
  494. * Otherwise we only concern ourselves with the overflowing chunk:
  495. *
  496. * If there are no tombstones in the chunk then we split the chunk in
  497. * two, each half full.
  498. *
  499. * If the chunk does contain tombstones, we just make a new copy of
  500. * the chunk without the tombstones, which will have room for at least
  501. * the one element we have to add.
  502. */
  503. static MonoJitInfoTable*
  504. jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
  505. {
  506. int num_elements = jit_info_table_num_elements (table);
  507. int i;
  508. if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
  509. || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
  510. //printf ("reallocing table\n");
  511. return jit_info_table_realloc (table);
  512. }
  513. /* count the number of non-tombstone elements in the chunk */
  514. num_elements = 0;
  515. for (i = 0; i < chunk->num_elements; ++i) {
  516. if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
  517. ++num_elements;
  518. }
  519. if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
  520. //printf ("splitting chunk\n");
  521. return jit_info_table_copy_and_split_chunk (table, chunk);
  522. }
  523. //printf ("purifying chunk\n");
  524. return jit_info_table_copy_and_purify_chunk (table, chunk);
  525. }
  526. /* We add elements to the table by first making space for them by
  527. * shifting the elements at the back to the right, one at a time.
  528. * This results in duplicate entries during the process, but during
  529. * all the time the table is in a sorted state. Also, when an element
  530. * is replaced by another one, the element that replaces it has an end
  531. * address that is equal to or lower than that of the replaced
  532. * element. That property is necessary to guarantee that when
  533. * searching for an element we end up at a position not higher than
  534. * the one we're looking for (i.e. we either find the element directly
  535. * or we end up to the left of it).
  536. */
  537. void
  538. mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
  539. {
  540. MonoJitInfoTable *table;
  541. int chunk_pos, pos;
  542. MonoJitInfoTableChunk *chunk;
  543. int num_elements;
  544. int i;
  545. g_assert (ji->method != NULL);
  546. mono_domain_lock (domain);
  547. ++mono_stats.jit_info_table_insert_count;
  548. table = domain->jit_info_table;
  549. restart:
  550. chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
  551. g_assert (chunk_pos < table->num_chunks);
  552. chunk = table->chunks [chunk_pos];
  553. if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
  554. MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
  555. /* Debugging code, should be removed. */
  556. //jit_info_table_check (new_table);
  557. domain->jit_info_table = new_table;
  558. mono_memory_barrier ();
  559. domain->num_jit_info_tables++;
  560. mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free, TRUE, FALSE);
  561. table = new_table;
  562. goto restart;
  563. }
  564. /* Debugging code, should be removed. */
  565. //jit_info_table_check (table);
  566. num_elements = chunk->num_elements;
  567. pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
  568. /* First we need to size up the chunk by one, by copying the
  569. last item, or inserting the first one, if the table is
  570. empty. */
  571. if (num_elements > 0)
  572. chunk->data [num_elements] = chunk->data [num_elements - 1];
  573. else
  574. chunk->data [0] = ji;
  575. mono_memory_write_barrier ();
  576. chunk->num_elements = ++num_elements;
  577. /* Shift the elements up one by one. */
  578. for (i = num_elements - 2; i >= pos; --i) {
  579. mono_memory_write_barrier ();
  580. chunk->data [i + 1] = chunk->data [i];
  581. }
  582. /* Now we have room and can insert the new item. */
  583. mono_memory_write_barrier ();
  584. chunk->data [pos] = ji;
  585. /* Set the high code end address chunk entry. */
  586. chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
  587. + chunk->data [chunk->num_elements - 1]->code_size;
  588. /* Debugging code, should be removed. */
  589. //jit_info_table_check (table);
  590. mono_domain_unlock (domain);
  591. }
  592. static MonoJitInfo*
  593. mono_jit_info_make_tombstone (MonoJitInfo *ji)
  594. {
  595. MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
  596. tombstone->code_start = ji->code_start;
  597. tombstone->code_size = ji->code_size;
  598. tombstone->method = JIT_INFO_TOMBSTONE_MARKER;
  599. return tombstone;
  600. }
  601. /*
  602. * LOCKING: domain lock
  603. */
  604. static void
  605. mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
  606. {
  607. if (domain->num_jit_info_tables <= 1) {
  608. /* Can it actually happen that we only have one table
  609. but ji is still hazardous? */
  610. mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE);
  611. } else {
  612. domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
  613. }
  614. }
  615. void
  616. mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
  617. {
  618. MonoJitInfoTable *table;
  619. MonoJitInfoTableChunk *chunk;
  620. gpointer start = ji->code_start;
  621. int chunk_pos, pos;
  622. mono_domain_lock (domain);
  623. table = domain->jit_info_table;
  624. ++mono_stats.jit_info_table_remove_count;
  625. chunk_pos = jit_info_table_index (table, start);
  626. g_assert (chunk_pos < table->num_chunks);
  627. pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
  628. do {
  629. chunk = table->chunks [chunk_pos];
  630. while (pos < chunk->num_elements) {
  631. if (chunk->data [pos] == ji)
  632. goto found;
  633. g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
  634. g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
  635. <= (guint8*)ji->code_start + ji->code_size);
  636. ++pos;
  637. }
  638. ++chunk_pos;
  639. pos = 0;
  640. } while (chunk_pos < table->num_chunks);
  641. found:
  642. g_assert (chunk->data [pos] == ji);
  643. chunk->data [pos] = mono_jit_info_make_tombstone (ji);
  644. /* Debugging code, should be removed. */
  645. //jit_info_table_check (table);
  646. mono_jit_info_free_or_queue (domain, ji);
  647. mono_domain_unlock (domain);
  648. }
  649. static MonoAotModuleInfoTable*
  650. mono_aot_module_info_table_new (void)
  651. {
  652. return g_array_new (FALSE, FALSE, sizeof (gpointer));
  653. }
  654. static int
  655. aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
  656. {
  657. int left = 0, right = table->len;
  658. while (left < right) {
  659. int pos = (left + right) / 2;
  660. AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
  661. char *start = ainfo->start;
  662. char *end = ainfo->end;
  663. if (addr < start)
  664. right = pos;
  665. else if (addr >= end)
  666. left = pos + 1;
  667. else
  668. return pos;
  669. }
  670. return left;
  671. }
  672. void
  673. mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
  674. {
  675. AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
  676. int pos;
  677. ainfo->image = image;
  678. ainfo->start = start;
  679. ainfo->end = end;
  680. mono_appdomains_lock ();
  681. if (!aot_modules)
  682. aot_modules = mono_aot_module_info_table_new ();
  683. pos = aot_info_table_index (aot_modules, start);
  684. g_array_insert_val (aot_modules, pos, ainfo);
  685. mono_appdomains_unlock ();
  686. }
  687. static MonoImage*
  688. mono_jit_info_find_aot_module (guint8* addr)
  689. {
  690. guint left = 0, right;
  691. if (!aot_modules)
  692. return NULL;
  693. mono_appdomains_lock ();
  694. right = aot_modules->len;
  695. while (left < right) {
  696. guint pos = (left + right) / 2;
  697. AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
  698. if (addr < (guint8*)ai->start)
  699. right = pos;
  700. else if (addr >= (guint8*)ai->end)
  701. left = pos + 1;
  702. else {
  703. mono_appdomains_unlock ();
  704. return ai->image;
  705. }
  706. }
  707. mono_appdomains_unlock ();
  708. return NULL;
  709. }
  710. void
  711. mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
  712. {
  713. jit_info_find_in_aot_func = func;
  714. }
  715. gpointer
  716. mono_jit_info_get_code_start (MonoJitInfo* ji)
  717. {
  718. return ji->code_start;
  719. }
  720. int
  721. mono_jit_info_get_code_size (MonoJitInfo* ji)
  722. {
  723. return ji->code_size;
  724. }
  725. MonoMethod*
  726. mono_jit_info_get_method (MonoJitInfo* ji)
  727. {
  728. return ji->method;
  729. }
  730. static gpointer
  731. jit_info_key_extract (gpointer value)
  732. {
  733. MonoJitInfo *info = (MonoJitInfo*)value;
  734. return info->method;
  735. }
  736. static gpointer*
  737. jit_info_next_value (gpointer value)
  738. {
  739. MonoJitInfo *info = (MonoJitInfo*)value;
  740. return (gpointer*)&info->next_jit_code_hash;
  741. }
  742. void
  743. mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
  744. {
  745. mono_internal_hash_table_init (jit_code_hash,
  746. mono_aligned_addr_hash,
  747. jit_info_key_extract,
  748. jit_info_next_value);
  749. }
  750. MonoGenericJitInfo*
  751. mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
  752. {
  753. if (ji->has_generic_jit_info)
  754. return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
  755. else
  756. return NULL;
  757. }
  758. /*
  759. * mono_jit_info_get_generic_sharing_context:
  760. * @ji: a jit info
  761. *
  762. * Returns the jit info's generic sharing context, or NULL if it
  763. * doesn't have one.
  764. */
  765. MonoGenericSharingContext*
  766. mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
  767. {
  768. MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
  769. if (gi)
  770. return gi->generic_sharing_context;
  771. else
  772. return NULL;
  773. }
  774. /*
  775. * mono_jit_info_set_generic_sharing_context:
  776. * @ji: a jit info
  777. * @gsctx: a generic sharing context
  778. *
  779. * Sets the jit info's generic sharing context. The jit info must
  780. * have memory allocated for the context.
  781. */
  782. void
  783. mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
  784. {
  785. MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
  786. g_assert (gi);
  787. gi->generic_sharing_context = gsctx;
  788. }
  789. MonoTryBlockHoleTableJitInfo*
  790. mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji)
  791. {
  792. if (ji->has_try_block_holes) {
  793. char *ptr = (char*)&ji->clauses [ji->num_clauses];
  794. if (ji->has_generic_jit_info)
  795. ptr += sizeof (MonoGenericJitInfo);
  796. return (MonoTryBlockHoleTableJitInfo*)ptr;
  797. } else {
  798. return NULL;
  799. }
  800. }
  801. MonoArchEHJitInfo*
  802. mono_jit_info_get_arch_eh_info (MonoJitInfo *ji)
  803. {
  804. if (ji->has_arch_eh_info) {
  805. char *ptr = (char*)&ji->clauses [ji->num_clauses];
  806. if (ji->has_generic_jit_info)
  807. ptr += sizeof (MonoGenericJitInfo);
  808. if (ji->has_try_block_holes)
  809. ptr += sizeof (MonoTryBlockHoleTableJitInfo);
  810. return (MonoArchEHJitInfo*)ptr;
  811. } else {
  812. return NULL;
  813. }
  814. }
  815. MonoMethodCasInfo*
  816. mono_jit_info_get_cas_info (MonoJitInfo *ji)
  817. {
  818. if (ji->has_cas_info) {
  819. char *ptr = (char*)&ji->clauses [ji->num_clauses];
  820. if (ji->has_generic_jit_info)
  821. ptr += sizeof (MonoGenericJitInfo);
  822. if (ji->has_try_block_holes)
  823. ptr += sizeof (MonoTryBlockHoleTableJitInfo);
  824. if (ji->has_arch_eh_info)
  825. ptr += sizeof (MonoArchEHJitInfo);
  826. return (MonoMethodCasInfo*)ptr;
  827. } else {
  828. return NULL;
  829. }
  830. }
  831. void
  832. mono_install_create_domain_hook (MonoCreateDomainFunc func)
  833. {
  834. create_domain_hook = func;
  835. }
  836. void
  837. mono_install_free_domain_hook (MonoFreeDomainFunc func)
  838. {
  839. free_domain_hook = func;
  840. }
  841. /**
  842. * mono_string_equal:
  843. * @s1: First string to compare
  844. * @s2: Second string to compare
  845. *
  846. * Returns FALSE if the strings differ.
  847. */
  848. gboolean
  849. mono_string_equal (MonoString *s1, MonoString *s2)
  850. {
  851. int l1 = mono_string_length (s1);
  852. int l2 = mono_string_length (s2);
  853. if (s1 == s2)
  854. return TRUE;
  855. if (l1 != l2)
  856. return FALSE;
  857. return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
  858. }
  859. /**
  860. * mono_string_hash:
  861. * @s: the string to hash
  862. *
  863. * Returns the hash for the string.
  864. */
  865. guint
  866. mono_string_hash (MonoString *s)
  867. {
  868. const guint16 *p = mono_string_chars (s);
  869. int i, len = mono_string_length (s);
  870. guint h = 0;
  871. for (i = 0; i < len; i++) {
  872. h = (h << 5) - h + *p;
  873. p++;
  874. }
  875. return h;
  876. }
  877. static gboolean
  878. mono_ptrarray_equal (gpointer *s1, gpointer *s2)
  879. {
  880. int len = GPOINTER_TO_INT (s1 [0]);
  881. if (len != GPOINTER_TO_INT (s2 [0]))
  882. return FALSE;
  883. return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
  884. }
  885. static guint
  886. mono_ptrarray_hash (gpointer *s)
  887. {
  888. int i;
  889. int len = GPOINTER_TO_INT (s [0]);
  890. guint hash = 0;
  891. for (i = 1; i < len; i++)
  892. hash += GPOINTER_TO_UINT (s [i]);
  893. return hash;
  894. }
  895. /*
  896. * Allocate an id for domain and set domain->domain_id.
  897. * LOCKING: must be called while holding appdomains_mutex.
  898. * We try to assign low numbers to the domain, so it can be used
  899. * as an index in data tables to lookup domain-specific info
  900. * with minimal memory overhead. We also try not to reuse the
  901. * same id too quickly (to help debugging).
  902. */
  903. static int
  904. domain_id_alloc (MonoDomain *domain)
  905. {
  906. int id = -1, i;
  907. if (!appdomains_list) {
  908. appdomain_list_size = 2;
  909. appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
  910. }
  911. for (i = appdomain_next; i < appdomain_list_size; ++i) {
  912. if (!appdomains_list [i]) {
  913. id = i;
  914. break;
  915. }
  916. }
  917. if (id == -1) {
  918. for (i = 0; i < appdomain_next; ++i) {
  919. if (!appdomains_list [i]) {
  920. id = i;
  921. break;
  922. }
  923. }
  924. }
  925. if (id == -1) {
  926. MonoDomain **new_list;
  927. int new_size = appdomain_list_size * 2;
  928. if (new_size >= (1 << 16))
  929. g_assert_not_reached ();
  930. id = appdomain_list_size;
  931. new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
  932. memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
  933. mono_gc_free_fixed (appdomains_list);
  934. appdomains_list = new_list;
  935. appdomain_list_size = new_size;
  936. }
  937. domain->domain_id = id;
  938. appdomains_list [id] = domain;
  939. appdomain_next++;
  940. if (appdomain_next > appdomain_list_size)
  941. appdomain_next = 0;
  942. return id;
  943. }
  944. static gsize domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
  945. static gpointer domain_gc_desc = NULL;
  946. static guint32 domain_shadow_serial = 0L;
  947. MonoDomain *
  948. mono_domain_create (void)
  949. {
  950. MonoDomain *domain;
  951. guint32 shadow_serial;
  952. mono_appdomains_lock ();
  953. shadow_serial = domain_shadow_serial++;
  954. if (!domain_gc_desc) {
  955. unsigned int i, bit = 0;
  956. for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
  957. bit = i / sizeof (gpointer);
  958. domain_gc_bitmap [bit / 32] |= (gsize) 1 << (bit % 32);
  959. }
  960. domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
  961. }
  962. mono_appdomains_unlock ();
  963. #ifdef HAVE_BOEHM_GC
  964. /*
  965. * Boehm doesn't like roots inside GC allocated objects, and alloc_fixed returns
  966. * a GC_MALLOC-ed object, contrary to the api docs. This causes random crashes when
  967. * running the corlib test suite.
  968. * To solve this, we pass a NULL descriptor, and don't register roots.
  969. */
  970. domain = mono_gc_alloc_fixed (sizeof (MonoDomain), NULL);
  971. #else
  972. domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
  973. mono_gc_register_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED), G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_LAST_GC_TRACKED) - G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED), NULL);
  974. #endif
  975. domain->shadow_serial = shadow_serial;
  976. domain->domain = NULL;
  977. domain->setup = NULL;
  978. domain->friendly_name = NULL;
  979. domain->search_path = NULL;
  980. mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
  981. domain->mp = mono_mempool_new ();
  982. domain->code_mp = mono_code_manager_new ();
  983. domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
  984. domain->domain_assemblies = NULL;
  985. domain->assembly_bindings = NULL;
  986. domain->assembly_bindings_parsed = FALSE;
  987. domain->class_vtable_array = g_ptr_array_new ();
  988. domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
  989. domain->static_data_array = NULL;
  990. mono_jit_code_hash_init (&domain->jit_code_hash);
  991. domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
  992. domain->num_jit_info_tables = 1;
  993. domain->jit_info_table = jit_info_table_new (domain);
  994. domain->jit_info_free_queue = NULL;
  995. domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
  996. domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
  997. InitializeCriticalSection (&domain->lock);
  998. InitializeCriticalSection (&domain->assemblies_lock);
  999. InitializeCriticalSection (&domain->jit_code_hash_lock);
  1000. InitializeCriticalSection (&domain->finalizable_objects_hash_lock);
  1001. domain->method_rgctx_hash = NULL;
  1002. mono_appdomains_lock ();
  1003. domain_id_alloc (domain);
  1004. mono_appdomains_unlock ();
  1005. #ifndef DISABLE_PERFCOUNTERS
  1006. mono_perfcounters->loader_appdomains++;
  1007. mono_perfcounters->loader_total_appdomains++;
  1008. #endif
  1009. mono_debug_domain_create (domain);
  1010. if (create_domain_hook)
  1011. create_domain_hook (domain);
  1012. mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
  1013. return domain;
  1014. }
  1015. /**
  1016. * mono_init_internal:
  1017. *
  1018. * Creates the initial application domain and initializes the mono_defaults
  1019. * structure.
  1020. * This function is guaranteed to not run any IL code.
  1021. * If exe_filename is not NULL, the method will determine the required runtime
  1022. * from the exe configuration file or the version PE field.
  1023. * If runtime_version is not NULL, that runtime version will be used.
  1024. * Either exe_filename or runtime_version must be provided.
  1025. *
  1026. * Returns: the initial domain.
  1027. */
  1028. static MonoDomain *
  1029. mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
  1030. {
  1031. static MonoDomain *domain = NULL;
  1032. MonoAssembly *ass = NULL;
  1033. MonoImageOpenStatus status = MONO_IMAGE_OK;
  1034. const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
  1035. int n;
  1036. if (domain)
  1037. g_assert_not_reached ();
  1038. #ifdef HOST_WIN32
  1039. /* Avoid system error message boxes. */
  1040. SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  1041. #endif
  1042. #ifndef HOST_WIN32
  1043. wapi_init ();
  1044. #endif
  1045. #ifndef DISABLE_PERFCOUNTERS
  1046. mono_perfcounters_init ();
  1047. #endif
  1048. mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
  1049. mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
  1050. mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
  1051. mono_gc_base_init ();
  1052. MONO_FAST_TLS_INIT (tls_appdomain);
  1053. mono_native_tls_alloc (&appdomain_thread_id, NULL);
  1054. InitializeCriticalSection (&appdomains_mutex);
  1055. mono_metadata_init ();
  1056. mono_images_init ();
  1057. mono_assemblies_init ();
  1058. mono_classes_init ();
  1059. mono_loader_init ();
  1060. mono_reflection_init ();
  1061. /* FIXME: When should we release this memory? */
  1062. MONO_GC_REGISTER_ROOT_FIXED (appdomains_list);
  1063. domain = mono_domain_create ();
  1064. mono_root_domain = domain;
  1065. SET_APPDOMAIN (domain);
  1066. /* Get a list of runtimes supported by the exe */
  1067. if (exe_filename != NULL) {
  1068. /*
  1069. * This function will load the exe file as a MonoImage. We need to close it, but
  1070. * that would mean it would be reloaded later. So instead, we save it to
  1071. * exe_image, and close it during shutdown.
  1072. */
  1073. get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
  1074. #ifdef HOST_WIN32
  1075. if (!exe_image) {
  1076. exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
  1077. if (!exe_image)
  1078. exe_image = mono_image_open (exe_filename, NULL);
  1079. }
  1080. mono_fixup_exe_image (exe_image);
  1081. #endif
  1082. } else if (runtime_version != NULL) {
  1083. runtimes [0] = get_runtime_by_version (runtime_version);
  1084. runtimes [1] = NULL;
  1085. }
  1086. if (runtimes [0] == NULL) {
  1087. const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
  1088. runtimes [0] = default_runtime;
  1089. runtimes [1] = NULL;
  1090. g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
  1091. g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
  1092. }
  1093. /* The selected runtime will be the first one for which there is a mscrolib.dll */
  1094. for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
  1095. current_runtime = runtimes [n];
  1096. ass = mono_assembly_load_corlib (current_runtime, &status);
  1097. if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
  1098. break;
  1099. }
  1100. if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
  1101. switch (status){
  1102. case MONO_IMAGE_ERROR_ERRNO: {
  1103. char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
  1104. g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
  1105. g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
  1106. g_free (corlib_file);
  1107. break;
  1108. }
  1109. case MONO_IMAGE_IMAGE_INVALID:
  1110. g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
  1111. mono_assembly_getrootdir ());
  1112. break;
  1113. case MONO_IMAGE_MISSING_ASSEMBLYREF:
  1114. g_print ("Missing assembly reference in %s/mscorlib.dll\n",
  1115. mono_assembly_getrootdir ());
  1116. break;
  1117. case MONO_IMAGE_OK:
  1118. /* to suppress compiler warning */
  1119. break;
  1120. }
  1121. exit (1);
  1122. }
  1123. mono_defaults.corlib = mono_assembly_get_image (ass);
  1124. mono_defaults.object_class = mono_class_from_name (
  1125. mono_defaults.corlib, "System", "Object");
  1126. g_assert (mono_defaults.object_class != 0);
  1127. mono_defaults.void_class = mono_class_from_name (
  1128. mono_defaults.corlib, "System", "Void");
  1129. g_assert (mono_defaults.void_class != 0);
  1130. mono_defaults.boolean_class = mono_class_from_name (
  1131. mono_defaults.corlib, "System", "Boolean");
  1132. g_assert (mono_defaults.boolean_class != 0);
  1133. mono_defaults.byte_class = mono_class_from_name (
  1134. mono_defaults.corlib, "System", "Byte");
  1135. g_assert (mono_defaults.byte_class != 0);
  1136. mono_defaults.sbyte_class = mono_class_from_name (
  1137. mono_defaults.corlib, "System", "SByte");
  1138. g_assert (mono_defaults.sbyte_class != 0);
  1139. mono_defaults.int16_class = mono_class_from_name (
  1140. mono_defaults.corlib, "System", "Int16");
  1141. g_assert (mono_defaults.int16_class != 0);
  1142. mono_defaults.uint16_class = mono_class_from_name (
  1143. mono_defaults.corlib, "System", "UInt16");
  1144. g_assert (mono_defaults.uint16_class != 0);
  1145. mono_defaults.int32_class = mono_class_from_name (
  1146. mono_defaults.corlib, "System", "Int32");
  1147. g_assert (mono_defaults.int32_class != 0);
  1148. mono_defaults.uint32_class = mono_class_from_name (
  1149. mono_defaults.corlib, "System", "UInt32");
  1150. g_assert (mono_defaults.uint32_class != 0);
  1151. mono_defaults.uint_class = mono_class_from_name (
  1152. mono_defaults.corlib, "System", "UIntPtr");
  1153. g_assert (mono_defaults.uint_class != 0);
  1154. mono_defaults.int_class = mono_class_from_name (
  1155. mono_defaults.corlib, "System", "IntPtr");
  1156. g_assert (mono_defaults.int_class != 0);
  1157. mono_defaults.int64_class = mono_class_from_name (
  1158. mono_defaults.corlib, "System", "Int64");
  1159. g_assert (mono_defaults.int64_class != 0);
  1160. mono_defaults.uint64_class = mono_class_from_name (
  1161. mono_defaults.corlib, "System", "UInt64");
  1162. g_assert (mono_defaults.uint64_class != 0);
  1163. mono_defaults.single_class = mono_class_from_name (
  1164. mono_defaults.corlib, "System", "Single");
  1165. g_assert (mono_defaults.single_class != 0);
  1166. mono_defaults.double_class = mono_class_from_name (
  1167. mono_defaults.corlib, "System", "Double");
  1168. g_assert (mono_defaults.double_class != 0);
  1169. mono_defaults.char_class = mono_class_from_name (
  1170. mono_defaults.corlib, "System", "Char");
  1171. g_assert (mono_defaults.char_class != 0);
  1172. mono_defaults.string_class = mono_class_from_name (
  1173. mono_defaults.corlib, "System", "String");
  1174. g_assert (mono_defaults.string_class != 0);
  1175. mono_defaults.enum_class = mono_class_from_name (
  1176. mono_defaults.corlib, "System", "Enum");
  1177. g_assert (mono_defaults.enum_class != 0);
  1178. mono_defaults.array_class = mono_class_from_name (
  1179. mono_defaults.corlib, "System", "Array");
  1180. g_assert (mono_defaults.array_class != 0);
  1181. mono_defaults.delegate_class = mono_class_from_name (
  1182. mono_defaults.corlib, "System", "Delegate");
  1183. g_assert (mono_defaults.delegate_class != 0 );
  1184. mono_defaults.multicastdelegate_class = mono_class_from_name (
  1185. mono_defaults.corlib, "System", "MulticastDelegate");
  1186. g_assert (mono_defaults.multicastdelegate_class != 0 );
  1187. mono_defaults.asyncresult_class = mono_class_from_name (
  1188. mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
  1189. "AsyncResult");
  1190. g_assert (mono_defaults.asyncresult_class != 0 );
  1191. mono_defaults.manualresetevent_class = mono_class_from_name (
  1192. mono_defaults.corlib, "System.Threading", "ManualResetEvent");
  1193. g_assert (mono_defaults.manualresetevent_class != 0 );
  1194. mono_defaults.typehandle_class = mono_class_from_name (
  1195. mono_defaults.corlib, "System", "RuntimeTypeHandle");
  1196. g_assert (mono_defaults.typehandle_class != 0);
  1197. mono_defaults.methodhandle_class = mono_class_from_name (
  1198. mono_defaults.corlib, "System", "RuntimeMethodHandle");
  1199. g_assert (mono_defaults.methodhandle_class != 0);
  1200. mono_defaults.fieldhandle_class = mono_class_from_name (
  1201. mono_defaults.corlib, "System", "RuntimeFieldHandle");
  1202. g_assert (mono_defaults.fieldhandle_class != 0);
  1203. mono_defaults.systemtype_class = mono_class_from_name (
  1204. mono_defaults.corlib, "System", "Type");
  1205. g_assert (mono_defaults.systemtype_class != 0);
  1206. mono_defaults.monotype_class = mono_class_from_name (
  1207. mono_defaults.corlib, "System", "MonoType");
  1208. g_assert (mono_defaults.monotype_class != 0);
  1209. mono_defaults.exception_class = mono_class_from_name (
  1210. mono_defaults.corlib, "System", "Exception");
  1211. g_assert (mono_defaults.exception_class != 0);
  1212. mono_defaults.threadabortexception_class = mono_class_from_name (
  1213. mono_defaults.corlib, "System.Threading", "ThreadAbortException");
  1214. g_assert (mono_defaults.threadabortexception_class != 0);
  1215. mono_defaults.thread_class = mono_class_from_name (
  1216. mono_defaults.corlib, "System.Threading", "Thread");
  1217. g_assert (mono_defaults.thread_class != 0);
  1218. mono_defaults.internal_thread_class = mono_class_from_name (
  1219. mono_defaults.corlib, "System.Threading", "InternalThread");
  1220. if (!mono_defaults.internal_thread_class) {
  1221. /* This can happen with an old mscorlib */
  1222. fprintf (stderr, "Corlib too old for this runtime.\n");
  1223. fprintf (stderr, "Loaded from: %s\n",
  1224. mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown");
  1225. exit (1);
  1226. }
  1227. mono_defaults.appdomain_class = mono_class_from_name (
  1228. mono_defaults.corlib, "System", "AppDomain");
  1229. g_assert (mono_defaults.appdomain_class != 0);
  1230. #ifndef DISABLE_REMOTING
  1231. mono_defaults.transparent_proxy_class = mono_class_from_name (
  1232. mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
  1233. g_assert (mono_defaults.transparent_proxy_class != 0);
  1234. mono_defaults.real_proxy_class = mono_class_from_name (
  1235. mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
  1236. g_assert (mono_defaults.real_proxy_class != 0);
  1237. mono_defaults.marshalbyrefobject_class = mono_class_from_name (
  1238. mono_defaults.corlib, "System", "MarshalByRefObject");
  1239. g_assert (mono_defaults.marshalbyrefobject_class != 0);
  1240. mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
  1241. mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
  1242. g_assert (mono_defaults.iremotingtypeinfo_class != 0);
  1243. #endif
  1244. mono_defaults.mono_method_message_class = mono_class_from_name (
  1245. mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
  1246. g_assert (mono_defaults.mono_method_message_class != 0);
  1247. mono_defaults.field_info_class = mono_class_from_name (
  1248. mono_defaults.corlib, "System.Reflection", "FieldInfo");
  1249. g_assert (mono_defaults.field_info_class != 0);
  1250. mono_defaults.method_info_class = mono_class_from_name (
  1251. mono_defaults.corlib, "System.Reflection", "MethodInfo");
  1252. g_assert (mono_defaults.method_info_class != 0);
  1253. mono_defaults.stringbuilder_class = mono_class_from_name (
  1254. mono_defaults.corlib, "System.Text", "StringBuilder");
  1255. g_assert (mono_defaults.stringbuilder_class != 0);
  1256. mono_defaults.math_class = mono_class_from_name (
  1257. mono_defaults.corlib, "System", "Math");
  1258. g_assert (mono_defaults.math_class != 0);
  1259. mono_defaults.stack_frame_class = mono_class_from_name (
  1260. mono_defaults.corlib, "System.Diagnostics", "StackFrame");
  1261. g_assert (mono_defaults.stack_frame_class != 0);
  1262. mono_defaults.stack_trace_class = mono_class_from_name (
  1263. mono_defaults.corlib, "System.Diagnostics", "StackTrace");
  1264. g_assert (mono_defaults.stack_trace_class != 0);
  1265. mono_defaults.marshal_class = mono_class_from_name (
  1266. mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
  1267. g_assert (mono_defaults.marshal_class != 0);
  1268. mono_defaults.typed_reference_class = mono_class_from_name (
  1269. mono_defaults.corlib, "System", "TypedReference");
  1270. g_assert (mono_defaults.typed_reference_class != 0);
  1271. mono_defaults.argumenthandle_class = mono_class_from_name (
  1272. mono_defaults.corlib, "System", "RuntimeArgumentHandle");
  1273. g_assert (mono_defaults.argumenthandle_class != 0);
  1274. mono_defaults.monitor_class = mono_class_from_name (
  1275. mono_defaults.corlib, "System.Threading", "Monitor");
  1276. g_assert (mono_defaults.monitor_class != 0);
  1277. mono_defaults.runtimesecurityframe_class = mono_class_from_name (
  1278. mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
  1279. mono_defaults.executioncontext_class = mono_class_from_name (
  1280. mono_defaults.corlib, "System.Threading", "ExecutionContext");
  1281. mono_defaults.internals_visible_class = mono_class_from_name (
  1282. mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
  1283. mono_defaults.critical_finalizer_object = mono_class_from_name (
  1284. mono_defaults.corlib, "System.Runtime.ConstrainedExecution", "CriticalFinalizerObject");
  1285. /*
  1286. * mscorlib needs a little help, only now it can load its friends list (after we have
  1287. * loaded the InternalsVisibleToAttribute), load it now
  1288. */
  1289. mono_assembly_load_friends (ass);
  1290. mono_defaults.safehandle_class = mono_class_from_name (
  1291. mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
  1292. mono_defaults.handleref_class = mono_class_from_name (
  1293. mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
  1294. mono_defaults.attribute_class = mono_class_from_name (
  1295. mono_defaults.corlib, "System", "Attribute");
  1296. mono_defaults.customattribute_data_class = mono_class_from_name (
  1297. mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
  1298. /* these are initialized lazily when COM features are used */
  1299. #ifndef DISABLE_COM
  1300. mono_defaults.variant_class = NULL;
  1301. mono_defaults.com_object_class = NULL;
  1302. mono_defaults.com_interop_proxy_class = NULL;
  1303. mono_defaults.iunknown_class = NULL;
  1304. mono_defaults.idispatch_class = NULL;
  1305. #endif
  1306. mono_class_init (mono_defaults.array_class);
  1307. mono_defaults.generic_nullable_class = mono_class_from_name (
  1308. mono_defaults.corlib, "System", "Nullable`1");
  1309. mono_defaults.generic_ilist_class = mono_class_from_name (
  1310. mono_defaults.corlib, "System.Collections.Generic", "IList`1");
  1311. mono_defaults.generic_ireadonlylist_class = mono_class_from_name (
  1312. mono_defaults.corlib, "System.Collections.Generic", "IReadOnlyList`1");
  1313. domain->friendly_name = g_path_get_basename (filename);
  1314. _mono_debug_init_corlib (domain);
  1315. return domain;
  1316. }
  1317. /**
  1318. * mono_init:
  1319. *
  1320. * Creates the initial application domain and initializes the mono_defaults
  1321. * structure.
  1322. * This function is guaranteed to not run any IL code.
  1323. * The runtime is initialized using the default runtime version.
  1324. *
  1325. * Returns: the initial domain.
  1326. */
  1327. MonoDomain *
  1328. mono_init (const char *domain_name)
  1329. {
  1330. return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
  1331. }
  1332. /**
  1333. * mono_init_from_assembly:
  1334. * @domain_name: name to give to the initial domain
  1335. * @filename: filename to load on startup
  1336. *
  1337. * Used by the runtime, users should use mono_jit_init instead.
  1338. *
  1339. * Creates the initial application domain and initializes the mono_defaults
  1340. * structure.
  1341. * This function is guaranteed to not run any IL code.
  1342. * The runtime is initialized using the runtime version required by the
  1343. * provided executable. The version is determined by looking at the exe
  1344. * configuration file and the version PE field)
  1345. *
  1346. * Returns: the initial domain.
  1347. */
  1348. MonoDomain *
  1349. mono_init_

Large files files are truncated, but you can click here to view the full file