* Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
* Copyright 2004-2009 Novell, Inc (http://www.novell.com)
* Copyright 2011-2012 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
#include <string.h>
#include <sys/stat.h>
-#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/gc-internals.h>
#include <mono/utils/atomic.h>
#include <mono/utils/mono-compiler.h>
-#include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-logger-internals.h>
#include <mono/utils/mono-membar.h>
#include <mono/utils/mono-counters.h>
#include <mono/utils/hazard-pointer.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/exception.h>
#include <mono/metadata/metadata-internals.h>
-#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/gc-internals.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/mono-debug-debugger.h>
#include <mono/metadata/mono-config.h>
MonoJitInfoTable *
mono_jit_info_table_new (MonoDomain *domain)
{
- MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
+ MonoJitInfoTable *table = (MonoJitInfoTable *)g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
table->domain = domain;
table->num_chunks = 1;
for (i = 0; i < num_chunks; ++i) {
MonoJitInfoTableChunk *chunk = table->chunks [i];
- int num_elements;
- int j;
+ MonoJitInfo *tombstone;
if (--chunk->refcount > 0)
continue;
- num_elements = chunk->num_elements;
- for (j = 0; j < num_elements; ++j) {
- MonoJitInfo *ji = chunk->data [j];
-
- if (IS_JIT_INFO_TOMBSTONE (ji))
- g_free (ji);
+ for (tombstone = chunk->next_tombstone; tombstone; ) {
+ MonoJitInfo *next = tombstone->n.next_tombstone;
+ g_free (tombstone);
+ tombstone = next;
}
g_free (chunk);
while (left < right) {
int pos = (left + right) / 2;
- MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
+ MonoJitInfo *ji = (MonoJitInfo *)get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
if (addr < code_end)
MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
while (pos < chunk->num_elements) {
- ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
+ ji = (MonoJitInfo *)get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
++pos;
table by a hazard pointer and make sure that the pointer is
still there after we've made it hazardous, we don't have to
worry about the writer freeing the table. */
- table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
+ table = (MonoJitInfoTable *)get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
ji = jit_info_table_find (table, hp, (gint8*)addr);
if (hp)
/* Maybe its an AOT module */
if (try_aot && mono_get_root_domain () && mono_get_root_domain ()->aot_modules) {
- table = get_hazardous_pointer ((gpointer volatile*)&mono_get_root_domain ()->aot_modules, hp, JIT_INFO_TABLE_HAZARD_INDEX);
+ table = (MonoJitInfoTable *)get_hazardous_pointer ((gpointer volatile*)&mono_get_root_domain ()->aot_modules, hp, JIT_INFO_TABLE_HAZARD_INDEX);
module_ji = jit_info_table_find (table, hp, (gint8*)addr);
if (module_ji)
ji = jit_info_find_in_aot_func (domain, module_ji->d.image, addr);
return ji;
}
+/**
+ * mono_jit_info_table_find:
+ * @domain: Domain that you want to look up
+ * @addr: Points to an address with JITed code.
+ *
+ * Use this function to obtain a `MonoJitInfo*` object that can be used to get
+ * some statistics. You should provide both the @domain on which you will be
+ * performing the probe, and an address. Since application domains can share code
+ * the same address can be in use by multiple domains at once.
+ *
+ * This does not return any results for trampolines.
+ *
+ * Returns: NULL if the address does not belong to JITed code (it might be native
+ * code or a trampoline) or a valid pointer to a `MonoJitInfo*`.
+ */
MonoJitInfo*
mono_jit_info_table_find (MonoDomain *domain, char *addr)
{
g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
for (j = 0; j < chunk->num_elements; ++j) {
- MonoJitInfo *this = chunk->data [j];
+ MonoJitInfo *this_ji = chunk->data [j];
MonoJitInfo *next;
- g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
+ g_assert ((gint8*)this_ji->code_start + this_ji->code_size <= chunk->last_code_end);
if (j < chunk->num_elements - 1)
next = chunk->data [j + 1];
} else
return;
- g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
+ g_assert ((gint8*)this_ji->code_start + this_ji->code_size <= (gint8*)next->code_start + next->code_size);
}
}
}
int required_size;
int num_chunks;
int new_chunk, new_element;
- MonoJitInfoTable *new;
+ MonoJitInfoTable *result;
/* number of needed places for elements needed */
required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
}
g_assert (num_chunks > 0);
- new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
- new->domain = old->domain;
- new->num_chunks = num_chunks;
+ result = (MonoJitInfoTable *)g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
+ result->domain = old->domain;
+ result->num_chunks = num_chunks;
for (i = 0; i < num_chunks; ++i)
- new->chunks [i] = jit_info_table_new_chunk ();
+ result->chunks [i] = jit_info_table_new_chunk ();
new_chunk = 0;
new_element = 0;
for (j = 0; j < chunk_num_elements; ++j) {
if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
g_assert (new_chunk < num_chunks);
- new->chunks [new_chunk]->data [new_element] = chunk->data [j];
+ result->chunks [new_chunk]->data [new_element] = chunk->data [j];
if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
- new->chunks [new_chunk]->num_elements = new_element;
+ result->chunks [new_chunk]->num_elements = new_element;
++new_chunk;
new_element = 0;
}
if (new_chunk < num_chunks) {
g_assert (new_chunk == num_chunks - 1);
- new->chunks [new_chunk]->num_elements = new_element;
- g_assert (new->chunks [new_chunk]->num_elements > 0);
+ result->chunks [new_chunk]->num_elements = new_element;
+ g_assert (result->chunks [new_chunk]->num_elements > 0);
}
for (i = 0; i < num_chunks; ++i) {
- MonoJitInfoTableChunk *chunk = new->chunks [i];
+ MonoJitInfoTableChunk *chunk = result->chunks [i];
MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
- new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
+ result->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
}
- return new;
+ return result;
}
static void
static MonoJitInfoTable*
jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
{
- MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
+ MonoJitInfoTable *new_table = (MonoJitInfoTable *)g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
+ sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
int i, j;
static MonoJitInfoTableChunk*
jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
{
- MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
+ MonoJitInfoTableChunk *result = jit_info_table_new_chunk ();
int i, j;
j = 0;
for (i = 0; i < old->num_elements; ++i) {
if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
- new->data [j++] = old->data [i];
+ result->data [j++] = old->data [i];
}
- new->num_elements = j;
- if (new->num_elements > 0)
- new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
+ result->num_elements = j;
+ if (result->num_elements > 0)
+ result->last_code_end = (gint8*)result->data [j - 1]->code_start + result->data [j - 1]->code_size;
else
- new->last_code_end = old->last_code_end;
+ result->last_code_end = old->last_code_end;
- return new;
+ return result;
}
static MonoJitInfoTable*
jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
{
- MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
+ MonoJitInfoTable *new_table = (MonoJitInfoTable *)g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
+ sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
int i, j;
*table_ptr = new_table;
mono_memory_barrier ();
domain->num_jit_info_tables++;
- mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)mono_jit_info_table_free, TRUE, FALSE);
+ mono_thread_hazardous_try_free (table, (MonoHazardousFreeFunc)mono_jit_info_table_free);
table = new_table;
goto restart;
}
static MonoJitInfo*
-mono_jit_info_make_tombstone (MonoJitInfo *ji)
+mono_jit_info_make_tombstone (MonoJitInfoTableChunk *chunk, MonoJitInfo *ji)
{
MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
tombstone->code_start = ji->code_start;
tombstone->code_size = ji->code_size;
tombstone->d.method = JIT_INFO_TOMBSTONE_MARKER;
+ tombstone->n.next_tombstone = chunk->next_tombstone;
+ chunk->next_tombstone = tombstone;
return tombstone;
}
if (domain->num_jit_info_tables <= 1) {
/* Can it actually happen that we only have one table
but ji is still hazardous? */
- mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE);
+ mono_thread_hazardous_try_free (ji, g_free);
} else {
domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
}
gpointer start = ji->code_start;
int chunk_pos, pos;
- chunk_pos = jit_info_table_index (table, start);
+ chunk_pos = jit_info_table_index (table, (gint8 *)start);
g_assert (chunk_pos < table->num_chunks);
- pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
+ pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, (gint8 *)start);
do {
chunk = table->chunks [chunk_pos];
found:
g_assert (chunk->data [pos] == ji);
- chunk->data [pos] = mono_jit_info_make_tombstone (ji);
+ chunk->data [pos] = mono_jit_info_make_tombstone (chunk, ji);
/* Debugging code, should be removed. */
//jit_info_table_check (table);
ji->has_thunk_info = 1;
}
+/**
+ * mono_jit_info_get_code_start:
+ * @ji: the JIT information handle
+ *
+ * Use this function to get the starting address for the method described by
+ * the @ji object. You can use this plus the `mono_jit_info_get_code_size`
+ * to determine the start and end of the native code.
+ *
+ * Returns: Starting address with the native code.
+ */
gpointer
mono_jit_info_get_code_start (MonoJitInfo* ji)
{
return ji->code_start;
}
+/**
+ * mono_jit_info_get_code_size:
+ * @ji: the JIT information handle
+ *
+ * Use this function to get the code size for the method described by
+ * the @ji object. You can use this plus the `mono_jit_info_get_code_start`
+ * to determine the start and end of the native code.
+ *
+ * Returns: Starting address with the native code.
+ */
int
mono_jit_info_get_code_size (MonoJitInfo* ji)
{
return ji->code_size;
}
+/**
+ * mono_jit_info_get_method:
+ * @ji: the JIT information handle
+ *
+ * Use this function to get the `MonoMethod *` that backs
+ * the @ji object.
+ *
+ * Returns: The MonoMethod that represents the code tracked
+ * by @ji.
+ */
MonoMethod*
mono_jit_info_get_method (MonoJitInfo* ji)
{
{
MonoJitInfo *info = (MonoJitInfo*)value;
- return (gpointer*)&info->next_jit_code_hash;
+ return (gpointer*)&info->n.next_jit_code_hash;
}
void