*
* Copyright 2002-2003 Ximian, Inc.
* Copyright 2003-2010 Novell, Inc.
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
*/
#define MONO_LLVM_IN_MINI 1
#include <mono/utils/mono-counters.h>
#include <mono/utils/mono-logger-internal.h>
#include <mono/utils/mono-mmap.h>
+#include <mono/utils/mono-tls.h>
#include <mono/utils/dtrace.h>
#include "mini.h"
static guint32 default_opt = 0;
static gboolean default_opt_set = FALSE;
-guint32 mono_jit_tls_id = -1;
+MonoNativeTlsKey mono_jit_tls_id;
+#ifdef MONO_HAVE_FAST_TLS
MONO_FAST_TLS_DECLARE(mono_jit_tls);
+#endif
#ifndef MONO_ARCH_MONITOR_ENTER_ADJUSTMENT
#define MONO_ARCH_MONITOR_ENTER_ADJUSTMENT 1
#endif
MonoTraceSpec *mono_jit_trace_calls = NULL;
-gboolean mono_break_on_exc = FALSE;
gboolean mono_compile_aot = FALSE;
/* If this is set, no code is generated dynamically, everything is taken from AOT files */
gboolean mono_aot_only = FALSE;
MonoDomain *domain = mono_domain_get ();
MonoDebugSourceLocation *location;
FindTrampUserData user_data;
-
+
+ if (!domain)
+ domain = mono_get_root_domain ();
+
ji = mono_jit_info_table_find (domain, ip);
if (!ji) {
user_data.ip = ip;
#endif
#endif
-guint32
+MonoNativeTlsKey
mono_get_jit_tls_key (void)
{
return mono_jit_tls_id;
#else
MonoJitTlsData *jit_tls;
- if ((jit_tls = TlsGetValue (mono_jit_tls_id)))
+ if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id)))
return jit_tls->lmf;
/*
* We do not assert here because this function can be called from
#else
MonoJitTlsData *jit_tls;
- if ((jit_tls = TlsGetValue (mono_jit_tls_id)))
+ if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id)))
return &jit_tls->lmf;
/*
mono_jit_thread_attach (NULL);
- if ((jit_tls = TlsGetValue (mono_jit_tls_id)))
+ if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id)))
return &jit_tls->lmf;
g_assert_not_reached ();
static void
mono_set_jit_tls (MonoJitTlsData *jit_tls)
{
- TlsSetValue (mono_jit_tls_id, jit_tls);
+ mono_native_tls_set_value (mono_jit_tls_id, jit_tls);
#ifdef MONO_HAVE_FAST_TLS
MONO_FAST_TLS_SET (mono_jit_tls, jit_tls);
#endif
}
-/* Called by native->managed wrappers */
-void
+/*
+ * mono_jit_thread_attach:
+ *
+ * Called by native->managed wrappers. Returns the original domain which needs to be
+ * restored, or NULL.
+ */
+MonoDomain*
mono_jit_thread_attach (MonoDomain *domain)
{
+ MonoDomain *orig;
+
if (!domain)
/*
* Happens when called from AOTed code which is only used in the root
mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
}
#else
- if (!TlsGetValue (mono_jit_tls_id)) {
+ if (!mono_native_tls_get_value (mono_jit_tls_id)) {
mono_thread_attach (domain);
mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
}
#endif
- if (mono_domain_get () != domain)
- mono_domain_set (domain, TRUE);
+ orig = mono_domain_get ();
+ if (orig != domain)
+ mono_domain_set (domain, TRUE);
+
+ return orig != domain ? orig : NULL;
}
+/* Called by native->managed wrappers */
+void
+mono_jit_set_domain (MonoDomain *domain)
+{
+ if (domain)
+ mono_domain_set (domain, TRUE);
+}
+
/**
* mono_thread_abort:
* @obj: exception object
static void
mono_thread_abort (MonoObject *obj)
{
- /* MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); */
+ /* MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); */
/* handle_remove should be eventually called for this thread, too
g_free (jit_tls);*/
(obj->vtable->klass == mono_defaults.threadabortexception_class)) {
mono_thread_exit ();
} else {
+ MonoObject *other = NULL;
+ MonoString *str = mono_object_to_string (obj, &other);
+ if (str) {
+ char *msg = mono_string_to_utf8 (str);
+ fprintf (stderr, "[ERROR] FATAL UNHANDLED EXCEPTION: %s\n", msg);
+ fflush (stderr);
+ g_free (msg);
+ }
+
exit (mono_environment_exitcode_get ());
}
}
MonoJitTlsData *jit_tls;
MonoLMF *lmf;
- jit_tls = TlsGetValue (mono_jit_tls_id);
+ jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
if (jit_tls)
return jit_tls;
#if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
/* jit_tls->lmf is unused */
MONO_FAST_TLS_SET (mono_lmf, lmf);
- mono_set_lmf_addr (&mono_lmf);
+ mono_set_lmf_addr (MONO_FAST_TLS_ADDR (mono_lmf));
#else
mono_set_lmf_addr (&jit_tls->lmf);
jit_tls->lmf = lmf;
#endif
- mono_arch_setup_jit_tls_data (jit_tls);
mono_setup_altstack (jit_tls);
return jit_tls;
*
* The current offender is mono_thread_manage which cleanup threads from the outside.
*/
- if (thread == mono_thread_internal_current ()) {
- mono_set_lmf (NULL);
+ if (thread == mono_thread_internal_current ())
mono_set_jit_tls (NULL);
+
+ /* If we attach a thread but never call into managed land, we might never get an lmf.*/
+ if (mono_get_lmf ()) {
+ mono_set_lmf (NULL);
mono_set_lmf_addr (NULL);
}
return mono_create_tls_get (cfg, mono_thread_get_tls_offset ());
}
+MonoInst*
+mono_get_lmf_intrinsic (MonoCompile* cfg)
+{
+ return mono_create_tls_get (cfg, mono_get_lmf_tls_offset ());
+}
+
void
mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
{
target = code;
} else {
/* get the trampoline to the method from the domain */
- target = mono_create_jit_trampoline (patch_info->data.method);
+ target = mono_create_jit_trampoline_in_domain (domain, patch_info->data.method);
}
break;
case MONO_PATCH_INFO_SWITCH: {
case MONO_PATCH_INFO_CLASS:
case MONO_PATCH_INFO_IMAGE:
case MONO_PATCH_INFO_FIELD:
+ case MONO_PATCH_INFO_SIGNATURE:
target = patch_info->data.target;
break;
case MONO_PATCH_INFO_IID:
break;
}
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
- target = mono_create_delegate_trampoline (patch_info->data.klass);
+ target = mono_create_delegate_trampoline (domain, patch_info->data.klass);
break;
case MONO_PATCH_INFO_SFLDA: {
MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.field->parent);
if (run_cctors)
mono_runtime_class_init (vtable);
}
- target = (char*)vtable->data + patch_info->data.field->offset;
+ target = (char*)mono_vtable_get_static_field_data (vtable) + patch_info->data.field->offset;
break;
}
case MONO_PATCH_INFO_RVA: {
case MONO_PATCH_INFO_ICALL_ADDR:
/* run_cctors == 0 -> AOT */
if (patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+ const char *exc_class;
+ const char *exc_arg;
+
if (run_cctors) {
- target = mono_lookup_pinvoke_call (patch_info->data.method, NULL, NULL);
- if (!target)
+ target = mono_lookup_pinvoke_call (patch_info->data.method, &exc_class, &exc_arg);
+ if (!target) {
+ if (mono_aot_only)
+ mono_raise_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
g_error ("Unable to resolve pinvoke method '%s' Re-run with MONO_LOG_LEVEL=debug for more information.\n", mono_method_full_name (patch_info->data.method, TRUE));
+ }
} else {
target = NULL;
}
bb->last_seq_point = ins;
}
+void
+mono_add_var_location (MonoCompile *cfg, MonoInst *var, gboolean is_reg, int reg, int offset, int from, int to)
+{
+ MonoDwarfLocListEntry *entry = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoDwarfLocListEntry));
+
+ if (is_reg)
+ g_assert (offset == 0);
+
+ entry->is_reg = is_reg;
+ entry->reg = reg;
+ entry->offset = offset;
+ entry->from = from;
+ entry->to = to;
+
+ if (var == cfg->args [0])
+ cfg->this_loclist = g_slist_append_mempool (cfg->mempool, cfg->this_loclist, entry);
+ else if (var == cfg->rgctx_var)
+ cfg->rgctx_loclist = g_slist_append_mempool (cfg->mempool, cfg->rgctx_loclist, entry);
+}
+
#ifndef DISABLE_JIT
static void
{
int i;
MonoBasicBlock *in_bb;
+ GSList *l;
for (i = 0; i < bb->in_count; ++i) {
in_bb = bb->in_bb [i];
if (in_bb->last_seq_point) {
- next [in_bb->last_seq_point->backend.size] = g_slist_append (next [in_bb->last_seq_point->backend.size], GUINT_TO_POINTER (ins->backend.size));
+ int src_index = in_bb->last_seq_point->backend.size;
+ int dst_index = ins->backend.size;
+
+ /* bb->in_bb might contain duplicates */
+ for (l = next [src_index]; l; l = l->next)
+ if (GPOINTER_TO_UINT (l->data) == dst_index)
+ break;
+ if (!l)
+ next [src_index] = g_slist_append (next [src_index], GUINT_TO_POINTER (dst_index));
} else {
/* Have to look at its predecessors */
if (depth < 5)
for (l = bb_seq_points; l; l = l->next) {
MonoInst *ins = l->data;
- if (!(ins->flags & MONO_INST_SINGLE_STEP_LOC))
+ if (ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET)
+ /* Used to implement method entry/exit events */
continue;
if (last != NULL) {
last = ins;
}
+
+ if (bb->last_ins && bb->last_ins->opcode == OP_ENDFINALLY) {
+ MonoBasicBlock *bb2;
+ MonoInst *endfinally_seq_point = NULL;
+
+ /*
+ * The ENDFINALLY branches are not represented in the cfg, so link it with all seq points starting bbs.
+ */
+ l = g_slist_last (bb->seq_points);
+ g_assert (l);
+ endfinally_seq_point = l->data;
+
+ for (bb2 = cfg->bb_entry; bb2; bb2 = bb2->next_bb) {
+ GSList *l = g_slist_last (bb2->seq_points);
+
+ if (l) {
+ MonoInst *ins = l->data;
+
+ if (!(ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET) && ins != endfinally_seq_point)
+ next [endfinally_seq_point->backend.size] = g_slist_append (next [endfinally_seq_point->backend.size], GUINT_TO_POINTER (ins->backend.size));
+ }
+ }
+ }
}
if (cfg->verbose_level > 2) {
sp->next = g_new (int, sp->next_len);
j = 0;
if (cfg->verbose_level > 2 && next [i]) {
- printf ("\t0x%x ->", sp->il_offset);
+ printf ("\tIL0x%x ->", sp->il_offset);
for (l = next [i]; l; l = l->next) {
next_index = GPOINTER_TO_UINT (l->data);
- printf (" 0x%x", info->seq_points [next_index].il_offset);
+ printf (" IL0x%x", info->seq_points [next_index].il_offset);
}
printf ("\n");
}
max_epilog_size = 0;
- code = cfg->native_code + cfg->code_len;
-
/* we always allocate code in cfg->domain->code_mp to increase locality */
cfg->code_size = cfg->code_len + max_epilog_size;
/* fixme: align to MONO_ARCH_CODE_ALIGNMENT */
nacl_allow_target_modification (TRUE);
#endif
+ g_assert (code);
memcpy (code, cfg->native_code, cfg->code_len);
#if defined(__default_codegen__)
g_free (cfg->native_code);
MonoMethodHeader *header;
MonoJitInfo *jinfo;
int num_clauses;
- int generic_info_size;
- int holes_size = 0, num_holes = 0;
+ int generic_info_size, arch_eh_info_size = 0;
+ int holes_size = 0, num_holes = 0, cas_size = 0;
+ guint32 stack_size = 0;
g_assert (method_to_compile == cfg->method);
header = cfg->header;
else
generic_info_size = 0;
+ if (cfg->arch_eh_jit_info) {
+ MonoJitArgumentInfo *arg_info;
+ MonoMethodSignature *sig = mono_method_signature (cfg->method_to_register);
+
+ /*
+ * This cannot be computed during stack walking, as
+ * mono_arch_get_argument_info () is not signal safe.
+ */
+ arg_info = g_newa (MonoJitArgumentInfo, sig->param_count + 1);
+ stack_size = mono_arch_get_argument_info (sig, sig->param_count, arg_info);
+
+ if (stack_size)
+ arch_eh_info_size = sizeof (MonoArchEHJitInfo);
+ }
+
if (cfg->try_block_holes) {
for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) {
TryBlockHole *hole = tmp->data;
printf ("Number of try block holes %d\n", num_holes);
}
+ if (mono_method_has_declsec (cfg->method_to_register)) {
+ cas_size = sizeof (MonoMethodCasInfo);
+ }
+
if (COMPILE_LLVM (cfg))
num_clauses = cfg->llvm_ex_info_len;
else
if (cfg->method->dynamic) {
jinfo = g_malloc0 (MONO_SIZEOF_JIT_INFO + (num_clauses * sizeof (MonoJitExceptionInfo)) +
- generic_info_size + holes_size);
+ generic_info_size + holes_size + arch_eh_info_size + cas_size);
} else {
jinfo = mono_domain_alloc0 (cfg->domain, MONO_SIZEOF_JIT_INFO +
(num_clauses * sizeof (MonoJitExceptionInfo)) +
- generic_info_size + holes_size);
+ generic_info_size + holes_size + arch_eh_info_size + cas_size);
}
jinfo->method = cfg->method_to_register;
jinfo->code_size = cfg->code_len;
jinfo->used_regs = cfg->used_int_regs;
jinfo->domain_neutral = (cfg->opt & MONO_OPT_SHARED) != 0;
- jinfo->cas_inited = FALSE; /* initialization delayed at the first stalk walk using this method */
jinfo->num_clauses = num_clauses;
+
if (COMPILE_LLVM (cfg))
jinfo->from_llvm = TRUE;
if (cfg->generic_sharing_context) {
MonoInst *inst;
MonoGenericJitInfo *gi;
+ GSList *loclist = NULL;
jinfo->has_generic_jit_info = 1;
inst = cfg->rgctx_var;
if (!COMPILE_LLVM (cfg))
g_assert (inst->opcode == OP_REGOFFSET);
+ loclist = cfg->rgctx_loclist;
} else {
inst = cfg->args [0];
+ loclist = cfg->this_loclist;
+ }
+
+ if (loclist) {
+ /* Needed to handle async exceptions */
+ GSList *l;
+ int i;
+
+ gi->nlocs = g_slist_length (loclist);
+ if (cfg->method->dynamic)
+ gi->locations = g_malloc0 (gi->nlocs * sizeof (MonoDwarfLocListEntry));
+ else
+ gi->locations = mono_domain_alloc0 (cfg->domain, gi->nlocs * sizeof (MonoDwarfLocListEntry));
+ i = 0;
+ for (l = loclist; l; l = l->next) {
+ memcpy (&(gi->locations [i]), l->data, sizeof (MonoDwarfLocListEntry));
+ i ++;
+ }
}
if (COMPILE_LLVM (cfg)) {
g_assert (i == num_holes);
}
+ if (arch_eh_info_size) {
+ MonoArchEHJitInfo *info;
+
+ jinfo->has_arch_eh_info = 1;
+ info = mono_jit_info_get_arch_eh_info (jinfo);
+
+ info->stack_size = stack_size;
+ }
+
+ if (cas_size) {
+ jinfo->has_cas_info = 1;
+ }
+
if (COMPILE_LLVM (cfg)) {
if (num_clauses)
memcpy (&jinfo->clauses [0], &cfg->llvm_ex_info [0], num_clauses * sizeof (MonoJitExceptionInfo));
/* Temporarily disable this when running in the debugger until we have support
* for this in the debugger. */
- cfg->disable_omit_fp = TRUE;
+ /* This is no longer needed with sdb */
+ //cfg->disable_omit_fp = TRUE;
/* The debugger needs all locals to be on the stack or in a global register */
cfg->disable_vreg_to_lvreg = TRUE;
cfg->opt &= ~MONO_OPT_INLINE;
cfg->opt &= ~MONO_OPT_COPYPROP;
cfg->opt &= ~MONO_OPT_CONSPROP;
- cfg->opt &= ~MONO_OPT_GSHARED;
+ /* This is no longer needed with sdb */
+ //cfg->opt &= ~MONO_OPT_GSHARED;
/* This is needed for the soft debugger, which doesn't like code after the epilog */
cfg->disable_out_of_line_bblocks = TRUE;
return mono_get_addr_from_ftnptr ((gpointer)mono_icall_get_wrapper_full (mi, TRUE));
} else if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
- return mono_create_delegate_trampoline (method->klass);
+ return mono_create_delegate_trampoline (target_domain, method->klass);
#else
nm = mono_marshal_get_delegate_invoke (method, NULL);
return mono_get_addr_from_ftnptr (mono_compile_method (nm));
opt |= MONO_OPT_SHARED;
}
+ if (method->dynamic)
+ opt &= ~MONO_OPT_SHARED;
+
+ /* These methods can become invalid when a domain is unloaded */
+ if (method->klass->image != mono_get_corlib () || method->is_inflated)
+ opt &= ~MONO_OPT_SHARED;
+
if (opt & MONO_OPT_SHARED)
target_domain = mono_get_root_domain ();
else
target_domain = domain;
+ if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
+ WrapperInfo *info = mono_marshal_get_wrapper_info (method);
+
+ g_assert (info);
+ if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER)
+ method = info->d.synchronized_inner.method;
+ }
+
info = lookup_method (target_domain, method);
if (info) {
/* We can't use a domain specific method in another domain */
p = mono_create_ftnptr (target_domain, code);
if (callinfo) {
+ /*mono_register_jit_icall_wrapper takes the loader lock, so we take it on the outside. */
+ mono_loader_lock ();
mono_jit_lock ();
if (!callinfo->wrapper) {
callinfo->wrapper = p;
mono_debug_add_icall_wrapper (method, callinfo);
}
mono_jit_unlock ();
+ mono_loader_unlock ();
}
return p;
if (!ji)
return;
+ mono_debug_remove_method (method, domain);
+
mono_domain_lock (domain);
g_hash_table_remove (domain_jit_info (domain)->dynamic_code_hash, method);
mono_internal_hash_table_remove (&domain->jit_code_hash, method);
mono_handle_native_sigsegv (SIGSEGV, ctx);
}
- mono_arch_handle_exception (ctx, exc, FALSE);
+ mono_arch_handle_exception (ctx, exc);
}
void
exc = mono_get_exception_execution_engine ("SIGILL");
- mono_arch_handle_exception (ctx, exc, FALSE);
+ mono_arch_handle_exception (ctx, exc);
}
#if defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32)
SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler)
{
MonoJitInfo *ji;
- MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
gpointer fault_addr = NULL;
GET_CONTEXT;
mono_handle_native_sigsegv (SIGSEGV, ctx);
}
- mono_arch_handle_exception (ctx, NULL, FALSE);
+ mono_arch_handle_exception (ctx, NULL);
#endif
}
exc = mono_get_exception_execution_engine ("Interrupted (SIGINT).");
- mono_arch_handle_exception (ctx, exc, FALSE);
+ mono_arch_handle_exception (ctx, exc);
}
/* mono_jit_create_remoting_trampoline:
static gpointer
mini_create_ftnptr (MonoDomain *domain, gpointer addr)
{
-#ifdef __ia64__
- gpointer *desc;
+#if !defined(__ia64__) && !defined(__ppc64__) && !defined(__powerpc64__)
+ return addr;
+#else
+
+ gpointer* desc = NULL;
+ if ((desc = g_hash_table_lookup (domain->ftnptrs_hash, addr)))
+ return desc;
+# ifdef __ia64__
desc = mono_domain_code_reserve (domain, 2 * sizeof (gpointer));
desc [0] = addr;
desc [1] = NULL;
-
- return desc;
-#elif defined(__ppc64__) || defined(__powerpc64__)
+# elif defined(__ppc64__) || defined(__powerpc64__)
gpointer *desc;
desc = mono_domain_alloc0 (domain, 3 * sizeof (gpointer));
desc [0] = addr;
desc [1] = NULL;
desc [2] = NULL;
-
+# endif
+ g_hash_table_insert (domain->ftnptrs_hash, addr, desc);
return desc;
-#else
- return addr;
#endif
}
callbacks.get_addr_from_ftnptr = mini_get_addr_from_ftnptr;
callbacks.get_runtime_build_info = mono_get_runtime_build_info;
callbacks.set_cast_details = mono_set_cast_details;
+ callbacks.debug_log = mono_debugger_agent_debug_log;
+ callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled;
#ifdef MONO_ARCH_HAVE_IMT
if (mono_use_imt) {
if (!g_thread_supported ())
g_thread_init (NULL);
- mono_jit_tls_id = TlsAlloc ();
+ mono_native_tls_alloc (&mono_jit_tls_id, NULL);
setup_jit_tls_data ((gpointer)-1, mono_thread_abort);
if (default_opt & MONO_OPT_AOT)
if (mono_aot_only) {
/* This helps catch code allocation requests */
mono_code_manager_set_read_only (domain->code_mp);
+ mono_marshal_use_aot_wrappers (TRUE);
}
#ifdef MONO_ARCH_HAVE_IMT
mono_install_imt_thunk_builder (mono_arch_build_imt_thunk);
}
#endif
+ /*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/
+ mono_arch_finish_init ();
+
/* This must come after mono_init () in the aot-only case */
mono_exceptions_init ();
register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
register_icall (mono_get_lmf_addr, "mono_get_lmf_addr", "ptr", TRUE);
- register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "void", TRUE);
+ register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "ptr ptr", TRUE);
+ register_icall (mono_jit_set_domain, "mono_jit_set_domain", "void ptr", TRUE);
register_icall (mono_domain_get, "mono_domain_get", "ptr", TRUE);
register_icall (mono_get_throw_exception (), "mono_arch_throw_exception", "void object", TRUE);
register_icall (mono_object_castclass_with_cache, "mono_object_castclass_with_cache", "object object ptr ptr", FALSE);
register_icall (mono_object_isinst_with_cache, "mono_object_isinst_with_cache", "object object ptr ptr", FALSE);
+ register_icall (mono_debugger_agent_user_break, "mono_debugger_agent_user_break", "void", FALSE);
+
#endif
mono_generic_sharing_init ();
mono_runtime_cleanup (domain);
#endif
- free_jit_tls_data (TlsGetValue (mono_jit_tls_id));
+ free_jit_tls_data (mono_native_tls_get_value (mono_jit_tls_id));
mono_icall_cleanup ();
if (mono_inject_async_exc_method)
mono_method_desc_free (mono_inject_async_exc_method);
- TlsFree(mono_jit_tls_id);
+ mono_native_tls_free (mono_jit_tls_id);
DeleteCriticalSection (&jit_mutex);
default_opt &= ~opts;
}
-/*
+void
+mono_set_optimizations (guint32 opts)
+{
+ default_opt = opts;
+ default_opt_set = TRUE;
+}
+
+void
+mono_set_verbose_level (guint32 level)
+{
+ mini_verbose = level;
+}
+
+/**
* mono_get_runtime_build_info:
*
- * Return the runtime version + build date in string format.
- * The returned string is owned by the caller.
+ * Return the runtime version + build date in string format.
+ * The returned string is owned by the caller. The returned string
+ * format is "VERSION (FULL_VERSION BUILD_DATE)" and build date is optional.
*/
char*
mono_get_runtime_build_info (void)