Skip to content

Commit

Permalink
[llvm] Fix LLVM JIT when used with multiple AppDomains.
Browse files Browse the repository at this point in the history
We currently reuse LLVM's command line parsing system to configure and
enable passes. When using the default code generator pass configuration,
the `ImplicitNullChecks` and `X86CallFrameOptimization` passes can only
be enabled or disabled via the command line argument parser: the
`cl::opt`s controlling these (and many other) passes are private to
their translation units, and `TargetPassConfig`/`X86PassConfig` read
from these `cl::opt`s with no other means to override these values.

Unfortunately, some LLVM command line options have restrictions on the
number of times they may be set, and running the LLVM command line
argument parser more than once can fail, because the 'number of
occurrences' counter is stored in each global `cl::opt`. This causes
several tests to fail--one such test is unhandled-exception-7.cs.

This change:
- removes the lazy LLVM JIT initialization logic and instead
  runs this initialization once during `mini_init`,

- moves some stray JIT-only code from mini-llvm.c to llvm-jit.cpp,

- wraps the declarations in domain-internals.h with a
  `G_BEGIN_DECLS`/`G_END_DECLS` pair, so that they avoid name
  mangling when included in C++ source, and

- removes `exception_cb` and `emitted_cb`: neither were actually used
  by live code.
  • Loading branch information
imhameed committed Feb 14, 2020
1 parent 860fe5c commit 16d40c0
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 154 deletions.
4 changes: 4 additions & 0 deletions src/mono/mono/metadata/domain-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#define MONO_APPDOMAIN_SETUP_CLASS_NAME "MonoDomainSetup"
#endif

G_BEGIN_DECLS

/*
* If this is set, the memory belonging to appdomains is not freed when a domain is
* unloaded, and assemblies loaded by the appdomain are not unloaded either. This
Expand Down Expand Up @@ -702,4 +704,6 @@ mono_domain_ambient_alc (MonoDomain *domain)
return mono_domain_default_alc (domain);
}

G_END_DECLS

#endif /* __MONO_METADATA_DOMAIN_INTERNALS_H__ */
60 changes: 42 additions & 18 deletions src/mono/mono/mini/llvm-jit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,22 @@ void bzero (void *to, size_t count) { memset (to, 0, count); }

#endif

static AllocCodeMemoryCb *alloc_code_mem_cb;
static MonoNativeTlsKey current_cfg_tls_id;

static unsigned char*
alloc_code (LLVMValueRef function, int size)
{
MonoCompile *cfg;

cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);

if (cfg) {
// FIXME: dynamic
return (unsigned char*)mono_domain_code_reserve (cfg->domain, size);
} else {
return (unsigned char*)mono_domain_code_reserve (mono_domain_get (), size);
}
}

class MonoJitMemoryManager : public RTDyldMemoryManager
{
Expand Down Expand Up @@ -118,7 +133,7 @@ MonoJitMemoryManager::allocateCodeSection(uintptr_t Size,
unsigned SectionID,
StringRef SectionName)
{
uint8_t *mem = alloc_code_mem_cb (NULL, Size);
uint8_t *mem = alloc_code (NULL, Size);
PendingCodeMem.push_back (sys::MemoryBlock ((void *)mem, Size));
return mem;
}
Expand Down Expand Up @@ -254,11 +269,6 @@ struct MonoLLVMJIT {
}
};

static void
init_mono_llvm_jit ()
{
}

static MonoLLVMJIT *
make_mono_llvm_jit (TargetMachine *target_machine)
{
Expand Down Expand Up @@ -420,26 +430,23 @@ class MonoLLVMJIT {

static MonoJitMemoryManager *mono_mm;

static void
init_mono_llvm_jit ()
{
mono_mm = new MonoJitMemoryManager ();
}

static MonoLLVMJIT *
make_mono_llvm_jit (TargetMachine *target_machine)
{
mono_mm = new MonoJitMemoryManager ();
return new MonoLLVMJIT(target_machine, mono_mm);
}

#endif

static MonoLLVMJIT *jit;

MonoEERef
mono_llvm_create_ee (AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, LLVMExecutionEngineRef *ee)
void
mono_llvm_jit_init ()
{
alloc_code_mem_cb = alloc_cb;
if (jit != nullptr) return;

mono_native_tls_alloc (&current_cfg_tls_id, NULL);

InitializeNativeTarget ();
InitializeNativeTargetAsmPrinter();
Expand All @@ -464,9 +471,17 @@ mono_llvm_create_ee (AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb,
auto TM = EB.selectTarget ();
assert (TM);

init_mono_llvm_jit ();
jit = make_mono_llvm_jit (TM);
}

void
mono_llvm_jit_set_tls_cfg (MonoCompile *cfg) {
mono_native_tls_set_value (current_cfg_tls_id, cfg);
}

MonoEERef
mono_llvm_create_ee (LLVMExecutionEngineRef *ee)
{
return NULL;
}

Expand Down Expand Up @@ -494,8 +509,17 @@ mono_llvm_set_unhandled_exception_handler (void)
{
}

void
mono_llvm_jit_init ()
{
}

void
mono_llvm_jit_set_tls_cfg (MonoCompile *cfg) {
}

MonoEERef
mono_llvm_create_ee (AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, LLVMExecutionEngineRef *ee)
mono_llvm_create_ee (LLVMExecutionEngineRef *ee)
{
g_error ("LLVM JIT not supported on this platform.");
return NULL;
Expand Down
12 changes: 7 additions & 5 deletions src/mono/mono/mini/llvm-jit.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@

G_BEGIN_DECLS

typedef unsigned char * (AllocCodeMemoryCb) (LLVMValueRef function, int size);
typedef void (FunctionEmittedCb) (LLVMValueRef function, void *start, void *end);
typedef void (ExceptionTableCb) (void *data);

typedef void* MonoEERef;

void
mono_llvm_jit_init (void);

void
mono_llvm_jit_set_tls_cfg (MonoCompile *cfg);

MonoEERef
mono_llvm_create_ee (AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, LLVMExecutionEngineRef *ee);
mono_llvm_create_ee (LLVMExecutionEngineRef *ee);

void
mono_llvm_dispose_ee (MonoEERef *mono_ee);
Expand Down
6 changes: 3 additions & 3 deletions src/mono/mono/mini/mini-llvm-loaded.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#ifdef MONO_LLVM_LOADED

typedef struct {
void (*init)(void);
void (*init)(gboolean);
void (*cleanup)(void);
void (*emit_method)(MonoCompile *cfg);
void (*emit_call)(MonoCompile *cfg, MonoCallInst *call);
Expand All @@ -28,9 +28,9 @@ typedef struct {
static LoadedBackend backend;

void
mono_llvm_init (void)
mono_llvm_init (gboolean enable_jit)
{
backend.init ();
backend.init (enable_jit);
}

void
Expand Down
133 changes: 8 additions & 125 deletions src/mono/mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,6 @@ typedef enum {
INTRINS_NUM
} IntrinsicId;

static MonoNativeTlsKey current_cfg_tls_id;

static MonoLLVMModule aot_module;

static GHashTable *intrins_id_to_name;
Expand Down Expand Up @@ -8380,7 +8378,7 @@ mono_llvm_emit_method (MonoCompile *cfg)
mono_loader_lock ();

/* Used to communicate with the callbacks */
mono_native_tls_set_value (current_cfg_tls_id, cfg);
mono_llvm_jit_set_tls_cfg (cfg);

ctx = g_new0 (EmitContext, 1);
ctx->cfg = cfg;
Expand Down Expand Up @@ -8481,7 +8479,7 @@ mono_llvm_emit_method (MonoCompile *cfg)

free_ctx (ctx);

mono_native_tls_set_value (current_cfg_tls_id, NULL);
mono_llvm_jit_set_tls_cfg (NULL);

mono_loader_unlock ();
}
Expand Down Expand Up @@ -9946,13 +9944,11 @@ add_types (MonoLLVMModule *module)
}

void
mono_llvm_init (void)
mono_llvm_init (gboolean enable_jit)
{
GHashTable *h;
int i;

mono_native_tls_alloc (&current_cfg_tls_id, NULL);

h = g_hash_table_new (NULL, NULL);
for (i = 0; i < INTRINS_NUM; ++i)
g_hash_table_insert (h, GINT_TO_POINTER (intrinsics [i].id), (gpointer)intrinsics [i].name);
Expand All @@ -9962,6 +9958,9 @@ mono_llvm_init (void)
for (i = 0; i < INTRINS_NUM; ++i)
g_hash_table_insert (h, (gpointer)intrinsics [i].name, GINT_TO_POINTER (intrinsics [i].id + 1));
intrins_name_to_id = h;

if (enable_jit)
mono_llvm_jit_init ();
}

void
Expand Down Expand Up @@ -11026,7 +11025,7 @@ mono_llvm_free_domain_info (MonoDomain *domain)
}

void
mono_llvm_init (void)
mono_llvm_init (gboolean enable_jit)
{
}

Expand All @@ -11036,122 +11035,6 @@ mono_llvm_init (void)

/* LLVM JIT support */

static unsigned char*
alloc_cb (LLVMValueRef function, int size)
{
MonoCompile *cfg;

cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);

if (cfg) {
// FIXME: dynamic
return (unsigned char*)mono_domain_code_reserve (cfg->domain, size);
} else {
return (unsigned char*)mono_domain_code_reserve (mono_domain_get (), size);
}
}

static void
emitted_cb (LLVMValueRef function, void *start, void *end)
{
MonoCompile *cfg;

cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
g_assert (cfg);
cfg->code_len = (guint8*)end - (guint8*)start;
}

static void
exception_cb (void *data)
{
MonoCompile *cfg;
MonoJitExceptionInfo *ei;
guint32 ei_len, i, j, nested_len, nindex;
gpointer *type_info;
int this_reg, this_offset;

cfg = (MonoCompile*)mono_native_tls_get_value (current_cfg_tls_id);
g_assert (cfg);

/*
* data points to a DWARF FDE structure, convert it to our unwind format and
* save it.
* An alternative would be to save it directly, and modify our unwinder to work
* with it.
*/
cfg->encoded_unwind_ops = mono_unwind_decode_fde ((guint8*)data, &cfg->encoded_unwind_ops_len, NULL, &ei, &ei_len, &type_info, &this_reg, &this_offset);
if (cfg->verbose_level > 1)
mono_print_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);

/* Count nested clauses */
nested_len = 0;
for (i = 0; i < ei_len; ++i) {
gint32 cindex1 = *(gint32*)type_info [i];
MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];

for (j = 0; j < cfg->header->num_clauses; ++j) {
int cindex2 = j;
MonoExceptionClause *clause2 = &cfg->header->clauses [cindex2];

if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
nested_len ++;
}
}
}

cfg->llvm_ex_info = (MonoJitExceptionInfo*)mono_mempool_alloc0 (cfg->mempool, (ei_len + nested_len) * sizeof (MonoJitExceptionInfo));
cfg->llvm_ex_info_len = ei_len + nested_len;
memcpy (cfg->llvm_ex_info, ei, ei_len * sizeof (MonoJitExceptionInfo));
/* Fill the rest of the information from the type info */
for (i = 0; i < ei_len; ++i) {
gint32 clause_index = *(gint32*)type_info [i];
MonoExceptionClause *clause = &cfg->header->clauses [clause_index];

cfg->llvm_ex_info [i].flags = clause->flags;
cfg->llvm_ex_info [i].data.catch_class = clause->data.catch_class;
cfg->llvm_ex_info [i].clause_index = clause_index;
}

/*
* For nested clauses, the LLVM produced exception info associates the try interval with
* the innermost handler, while mono expects it to be associated with all nesting clauses.
* So add new clauses which use the IL info (catch class etc.) from the nesting clause,
* and everything else from the nested clause.
*/
nindex = ei_len;
for (i = 0; i < ei_len; ++i) {
gint32 cindex1 = *(gint32*)type_info [i];
MonoExceptionClause *clause1 = &cfg->header->clauses [cindex1];

for (j = 0; j < cfg->header->num_clauses; ++j) {
int cindex2 = j;
MonoExceptionClause *clause2 = &cfg->header->clauses [cindex2];
MonoJitExceptionInfo *nesting_ei, *nested_ei;

if (cindex1 != cindex2 && clause1->try_offset >= clause2->try_offset && clause1->handler_offset <= clause2->handler_offset) {
/* clause1 is the nested clause */
nested_ei = &cfg->llvm_ex_info [i];
nesting_ei = &cfg->llvm_ex_info [nindex];
nindex ++;

memcpy (nesting_ei, nested_ei, sizeof (MonoJitExceptionInfo));

nesting_ei->flags = clause2->flags;
nesting_ei->data.catch_class = clause2->data.catch_class;
nesting_ei->clause_index = cindex2;
}
}
}
g_assert (nindex == ei_len + nested_len);
cfg->llvm_this_reg = this_reg;
cfg->llvm_this_offset = this_offset;

/* type_info [i] is cfg mempool allocated, no need to free it */

g_free (ei);
g_free (type_info);
}

/*
* decode_llvm_eh_info:
*
Expand Down Expand Up @@ -11265,7 +11148,7 @@ init_jit_module (MonoDomain *domain)
module->context = LLVMGetGlobalContext ();
module->intrins_by_id = g_new0 (LLVMValueRef, INTRINS_NUM);

module->mono_ee = (MonoEERef*)mono_llvm_create_ee (alloc_cb, emitted_cb, exception_cb, &module->ee);
module->mono_ee = (MonoEERef*)mono_llvm_create_ee (&module->ee);

add_intrinsics (module->lmodule);
add_types (module);
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/mini/mini-llvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ typedef enum {
} LLVMModuleFlags;

/* KEEP THIS IN SYNCH WITH mini-llvm-loaded.c */
MONO_LLVM_INTERNAL void mono_llvm_init (void);
MONO_LLVM_INTERNAL void mono_llvm_init (gboolean enable_jit);
MONO_LLVM_INTERNAL void mono_llvm_cleanup (void);
MONO_LLVM_INTERNAL void mono_llvm_emit_method (MonoCompile *cfg);
MONO_LLVM_INTERNAL void mono_llvm_emit_call (MonoCompile *cfg, MonoCallInst *call);
Expand Down
4 changes: 2 additions & 2 deletions src/mono/mono/mini/mini-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -4015,7 +4015,7 @@ llvm_init_inner (void)
if (!mono_llvm_load (NULL))
return FALSE;

mono_llvm_init ();
mono_llvm_init (!mono_compile_aot);
return TRUE;
}
#endif
Expand Down Expand Up @@ -4270,7 +4270,7 @@ mini_init (const char *filename, const char *runtime_version)
}
}
if (mono_use_llvm)
mono_llvm_init ();
mono_llvm_init (!mono_compile_aot);
#endif

mono_trampolines_init ();
Expand Down

0 comments on commit 16d40c0

Please sign in to comment.