* [mono] Set the 'dynamic' flag on method builders on creation so a MonoDynamicMethod is allocated instead of a MonoMethodWrapper.
* [mono][interp] Fix memory leaks for interpreted dynamic methods.
* Add a mempool to MonoDynamicMethod.
* Modify the intepreter code to allocate from this mempool when
interpreting dynamic methods.
struct _MonoDynamicMethod {
MonoMethodWrapper method;
MonoAssembly *assembly;
+ MonoMemPool *mp;
};
struct _MonoMethodPInvoke {
}
static void
-mb_set_dynamic_ilgen (MonoMethodBuilder *mb)
-{
- mb->dynamic = 1;
-}
-
-static void
emit_synchronized_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *method, MonoGenericContext *ctx, MonoGenericContainer *container, MonoMethod *enter_method, MonoMethod *exit_method, MonoMethod *gettypefromhandle_method)
{
int i, pos, pos2, this_local, taken_local, ret_local = 0;
cb.emit_return = emit_return_ilgen;
cb.emit_vtfixup_ftnptr = emit_vtfixup_ftnptr_ilgen;
cb.mb_skip_visibility = mb_skip_visibility_ilgen;
- cb.mb_set_dynamic = mb_set_dynamic_ilgen;
cb.mb_emit_exception = mb_emit_exception_ilgen;
cb.mb_emit_exception_for_error = mb_emit_exception_for_error_ilgen;
cb.mb_emit_byte = mb_emit_byte_ilgen;
sig = mono_method_signature_internal (method);
- mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
+ if (target_handle)
+ mb = mono_mb_new_dynamic (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
+ else
+ mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
/*the target gchandle must be the first entry after size and the wrapper itself.*/
mono_mb_add_data (mb, target_handle);
mb, csig, sig->param_count + 16,
info, NULL);
} else {
- get_marshal_cb ()->mb_set_dynamic (mb);
res = mono_mb_create (mb, csig, sig->param_count + 16, NULL);
}
}
mspecs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
mono_method_get_marshal_info (method, mspecs);
- mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
+ mb = mono_mb_new_dynamic (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
csig = mono_metadata_signature_dup_full (image, sig);
csig->hasthis = 0;
csig->pinvoke = 1;
mono_marshal_emit_managed_wrapper (mb, sig, mspecs, &m, method, 0, error);
mono_error_assert_ok (error);
- get_marshal_cb ()->mb_set_dynamic (mb);
method = mono_mb_create (mb, csig, sig->param_count + 16, NULL);
mono_mb_free (mb);
}
sig = mono_method_signature_internal (method);
- mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_MANAGED);
+ mb = mono_mb_new_dynamic (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_MANAGED);
param_count = sig->param_count + sig->hasthis;
get_marshal_cb ()->emit_vtfixup_ftnptr (mb, method, param_count, type);
- get_marshal_cb ()->mb_set_dynamic (mb);
method = mono_mb_create (mb, sig, param_count, NULL);
mono_mb_free (mb);
void (*emit_return) (MonoMethodBuilder *mb);
void (*emit_vtfixup_ftnptr) (MonoMethodBuilder *mb, MonoMethod *method, int param_count, guint16 type);
void (*mb_skip_visibility) (MonoMethodBuilder *mb);
- void (*mb_set_dynamic) (MonoMethodBuilder *mb);
void (*mb_emit_exception) (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg);
void (*mb_emit_exception_for_error) (MonoMethodBuilder *mb, const MonoError *emitted_error);
void (*mb_emit_byte) (MonoMethodBuilder *mb, guint8 op);
#undef OPDEF
static MonoMethodBuilder *
-new_base_ilgen (MonoClass *klass, MonoWrapperType type)
+new_base_ilgen (MonoClass *klass, MonoWrapperType type, gboolean dynamic)
{
MonoMethodBuilder *mb;
MonoMethod *m;
mb = g_new0 (MonoMethodBuilder, 1);
- mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
+ if (dynamic)
+ mb->method = m = (MonoMethod *)g_new0 (MonoDynamicMethod, 1);
+ else
+ mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
m->klass = klass;
m->inline_info = 1;
mb->code_size = 40;
mb->code = (unsigned char *)g_malloc (mb->code_size);
mb->init_locals = TRUE;
+ mb->dynamic = dynamic;
/* placeholder for the wrapper always at index 1 */
mono_mb_add_data (mb, NULL);
image = m_class_get_image (mb->method->klass);
if (mb->dynamic) {
- /* Allocated in reflection_methodbuilder_to_mono_method () */
+ /* Allocated in reflection_methodbuilder_to_mono_method ()/mb_new () */
method = mb->method;
} else {
method = (MonoMethod *)mb_alloc0 (mb, sizeof (MonoMethodWrapper));
MonoMethodBuilder *
mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType type)
{
- MonoMethodBuilder *mb = get_mb_cb ()->new_base (klass, type);
+ MonoMethodBuilder *mb = get_mb_cb ()->new_base (klass, type, FALSE);
mb->name = (char*)name;
mb->no_dup_name = TRUE;
return mb;
MonoMethodBuilder *
mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
{
- MonoMethodBuilder *mb = get_mb_cb ()->new_base (klass, type);
+ MonoMethodBuilder *mb = get_mb_cb ()->new_base (klass, type, FALSE);
+ mb->name = g_strdup (name);
+ return mb;
+}
+
+MonoMethodBuilder *
+mono_mb_new_dynamic (MonoClass *klass, const char *name, MonoWrapperType type)
+{
+ MonoMethodBuilder *mb = get_mb_cb ()->new_base (klass, type, TRUE);
mb->name = g_strdup (name);
return mb;
}
typedef struct {
int version;
- MonoMethodBuilder* (*new_base) (MonoClass *klass, MonoWrapperType type);
+ MonoMethodBuilder* (*new_base) (MonoClass *klass, MonoWrapperType type, gboolean dynamic);
void (*free) (MonoMethodBuilder *mb);
MonoMethod* (*create_method) (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack);
} MonoMethodBuilderCallbacks;
MONO_COMPONENT_API MonoMethodBuilder *
mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type);
+MONO_COMPONENT_API MonoMethodBuilder *
+mono_mb_new_dynamic (MonoClass *klass, const char *name, MonoWrapperType type);
+
MonoMethodBuilder *
mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType type);
sig = mono_method_signature_internal (method);
- imethod = (InterpMethod*)m_method_alloc0 (method, sizeof (InterpMethod));
+ MonoMemPool *dyn_mp = NULL;
+ if (method->dynamic)
+ // FIXME: Use this in more places
+ dyn_mp = mono_mempool_new_size (sizeof (InterpMethod));
+
+ if (dyn_mp)
+ imethod = (InterpMethod*)mono_mempool_alloc0 (dyn_mp, sizeof (InterpMethod));
+ else
+ imethod = (InterpMethod*)m_method_alloc0 (method, sizeof (InterpMethod));
imethod->method = method;
imethod->param_count = sig->param_count;
imethod->hasthis = sig->hasthis;
imethod->rtype = m_class_get_byval_arg (mono_defaults.string_class);
else
imethod->rtype = mini_get_underlying_type (sig->ret);
- imethod->param_types = (MonoType**)m_method_alloc0 (method, sizeof (MonoType*) * sig->param_count);
+ if (dyn_mp)
+ imethod->param_types = (MonoType**)mono_mempool_alloc0 (dyn_mp, sizeof (MonoType*) * sig->param_count);
+ else
+ imethod->param_types = (MonoType**)m_method_alloc0 (method, sizeof (MonoType*) * sig->param_count);
for (i = 0; i < sig->param_count; ++i)
imethod->param_types [i] = mini_get_underlying_type (sig->params [i]);
jit_mm_lock (jit_mm);
InterpMethod *old_imethod;
- if (!((old_imethod = mono_internal_hash_table_lookup (&jit_mm->interp_code_hash, method))))
+ if (!((old_imethod = mono_internal_hash_table_lookup (&jit_mm->interp_code_hash, method)))) {
mono_internal_hash_table_insert (&jit_mm->interp_code_hash, method, imethod);
- else {
+ if (method->dynamic)
+ ((MonoDynamicMethod*)method)->mp = dyn_mp;
+ } else {
+ if (dyn_mp)
+ mono_mempool_destroy (dyn_mp);
imethod = old_imethod; /* leak the newly allocated InterpMethod to the mempool */
}
jit_mm_unlock (jit_mm);
return offset;
}
+static gpointer
+imethod_alloc0 (InterpMethod *imethod, size_t size)
+{
+ if (imethod->method->dynamic)
+ return mono_mempool_alloc0 (((MonoDynamicMethod*)imethod->method)->mp, (guint)size);
+ else
+ return m_method_alloc0 (imethod->method, (guint)size);
+}
+
static guint32*
initialize_arg_offsets (InterpMethod *imethod, MonoMethodSignature *csig)
{
if (!sig)
sig = mono_method_signature_internal (imethod->method);
int arg_count = sig->hasthis + sig->param_count;
- guint32 *arg_offsets = (guint32*) g_malloc ((arg_count + 1) * sizeof (int));
+ guint32 *arg_offsets = (guint32*)imethod_alloc0 (imethod, (arg_count + 1) * sizeof (int));
int index = 0, offset = 0;
if (sig->hasthis) {
arg_offsets [index] = ALIGN_TO (offset, MINT_STACK_SLOT_SIZE);
mono_memory_write_barrier ();
- if (mono_atomic_cas_ptr ((gpointer*)&imethod->arg_offsets, arg_offsets, NULL) != NULL)
- g_free (arg_offsets);
+ /* If this fails, the new one is leaked in the mem manager */
+ mono_atomic_cas_ptr ((gpointer*)&imethod->arg_offsets, arg_offsets, NULL);
return imethod->arg_offsets;
}
addr = mini_llvmonly_create_ftndesc (method, entry_wrapper, entry_ftndesc);
- // FIXME:
- MonoJitMemoryManager *jit_mm = get_default_jit_mm ();
+ MonoJitMemoryManager *jit_mm = jit_mm_for_method (method);
jit_mm_lock (jit_mm);
if (!jit_mm->interp_method_pointer_hash)
jit_mm->interp_method_pointer_hash = g_hash_table_new (NULL, NULL);
interp_free_method (MonoMethod *method)
{
MonoJitMemoryManager *jit_mm = jit_mm_for_method (method);
+ InterpMethod *imethod;
+ MonoDynamicMethod *dmethod = (MonoDynamicMethod*)method;
jit_mm_lock (jit_mm);
- /* InterpMethod is allocated in the domain mempool. We might haven't
- * allocated an InterpMethod for this instance yet */
+ imethod = (InterpMethod*)mono_internal_hash_table_lookup (&jit_mm->interp_code_hash, method);
mono_internal_hash_table_remove (&jit_mm->interp_code_hash, method);
+ if (imethod && jit_mm->interp_method_pointer_hash) {
+ if (imethod->jit_entry)
+ g_hash_table_remove (jit_mm->interp_method_pointer_hash, imethod->jit_entry);
+ if (imethod->llvmonly_unbox_entry)
+ g_hash_table_remove (jit_mm->interp_method_pointer_hash, imethod->llvmonly_unbox_entry);
+ }
jit_mm_unlock (jit_mm);
+
+ if (dmethod->mp) {
+ mono_mempool_destroy (dmethod->mp);
+ dmethod->mp = NULL;
+ }
}
#if COUNT_OPS
imethod = mono_interp_get_imethod (il_state->method);
if (!imethod->transformed) {
// In case method is in process of being tiered up, make sure it is compiled
- mono_interp_transform_method (imethod, context, error);
+ mono_interp_transform_method (imethod, context, error);
mono_error_assert_ok (error);
}
static MintICallSig
interp_get_icall_sig (MonoMethodSignature *sig);
+static gpointer
+imethod_alloc0 (TransformData *td, size_t size)
+{
+ if (td->rtm->method->dynamic)
+ return mono_mempool_alloc0 (((MonoDynamicMethod*)td->rtm->method)->mp, (guint)size);
+ else
+ return mono_mem_manager_alloc0 (td->mem_manager, (guint)size);
+}
+
static void
interp_generate_icall_throw (TransformData *td, MonoJitICallInfo *icall_info, gpointer arg1, gpointer arg2)
{
push_simple_type (td, STACK_TYPE_I);
interp_ins_set_dreg (td->last_ins, td->sp [-1].local);
/* This is a memory slot used by the wrapper */
- gpointer addr = mono_mem_manager_alloc0 (td->mem_manager, sizeof (gpointer));
+ gpointer addr = imethod_alloc0 (td, sizeof (gpointer));
td->last_ins->data [0] = get_data_item_index (td, addr);
break;
}
size = compute_native_offset_estimates (td);
// Generate the compacted stream of instructions
- td->new_code = ip = (guint16*)mono_mem_manager_alloc0 (td->mem_manager, size * sizeof (guint16));
+ td->new_code = ip = (guint16*)imethod_alloc0 (td, size * sizeof (guint16));
if (td->patchpoint_data_n) {
g_assert (mono_interp_tiering_enabled ());
- td->patchpoint_data = (int*)mono_mem_manager_alloc0 (td->mem_manager, (td->patchpoint_data_n * 2 + 1) * sizeof (int));
+ td->patchpoint_data = (int*)imethod_alloc0 (td, (td->patchpoint_data_n * 2 + 1) * sizeof (int));
td->patchpoint_data [td->patchpoint_data_n * 2] = G_MAXINT32;
}
#if HOST_BROWSER
if (backward_branch_offsets_count > 0) {
- rtm->backward_branch_offsets = mono_mem_manager_alloc(td->mem_manager, backward_branch_offsets_count * sizeof(guint16));
+ rtm->backward_branch_offsets = imethod_alloc0 (td, backward_branch_offsets_count * sizeof(guint16));
rtm->backward_branch_offsets_count = backward_branch_offsets_count;
memcpy(rtm->backward_branch_offsets, backward_branch_offsets, backward_branch_offsets_count * sizeof(guint16));
}
static void
interp_mark_reachable_bblocks (TransformData *td)
{
- InterpBasicBlock **queue = mono_mem_manager_alloc0 (td->mem_manager, td->bb_count * sizeof (InterpBasicBlock*));
+ InterpBasicBlock **queue = mono_mempool_alloc0 (td->mempool, td->bb_count * sizeof (InterpBasicBlock*));
InterpBasicBlock *current;
int cur_index = 0;
int next_position = 0;
code_len_u8 = GPTRDIFF_TO_UINT32 ((guint8 *) td->new_code_end - (guint8 *) td->new_code);
code_len_u16 = GPTRDIFF_TO_UINT32 (td->new_code_end - td->new_code);
- rtm->clauses = (MonoExceptionClause*)mono_mem_manager_alloc0 (td->mem_manager, header->num_clauses * sizeof (MonoExceptionClause));
+ rtm->clauses = (MonoExceptionClause*)imethod_alloc0 (td, header->num_clauses * sizeof (MonoExceptionClause));
memcpy (rtm->clauses, header->clauses, header->num_clauses * sizeof(MonoExceptionClause));
rtm->code = (gushort*)td->new_code;
rtm->init_locals = header->init_locals;
rtm->alloca_size = td->total_locals_size + td->max_stack_size;
g_assert ((rtm->alloca_size % MINT_STACK_ALIGNMENT) == 0);
rtm->locals_size = td->param_area_offset;
+ // FIXME: Can't allocate this using imethod_alloc0 as its registered with mono_interp_register_imethod_data_items ()
+ //rtm->data_items = (gpointer*)imethod_alloc0 (td, td->n_data_items * sizeof (td->data_items [0]));
rtm->data_items = (gpointer*)mono_mem_manager_alloc0 (td->mem_manager, td->n_data_items * sizeof (td->data_items [0]));
memcpy (rtm->data_items, td->data_items, td->n_data_items * sizeof (td->data_items [0]));
int jinfo_len;
jinfo_len = mono_jit_info_size ((MonoJitInfoFlags)0, header->num_clauses, 0);
MonoJitInfo *jinfo;
- jinfo = (MonoJitInfo *)mono_mem_manager_alloc0 (td->mem_manager, jinfo_len);
+ jinfo = (MonoJitInfo *)imethod_alloc0 (td, jinfo_len);
jinfo->is_interp = 1;
rtm->jinfo = jinfo;
mono_jit_info_init (jinfo, method, (guint8*)rtm->code, code_len_u8, (MonoJitInfoFlags)0, header->num_clauses, 0);
MonoFtnDesc*
mini_llvmonly_create_ftndesc (MonoMethod *m, gpointer addr, gpointer arg)
{
- MonoFtnDesc *ftndesc = (MonoFtnDesc*)m_method_alloc0 (m, sizeof (MonoFtnDesc));
+ MonoFtnDesc *ftndesc;
+
+ if (m->dynamic && ((MonoDynamicMethod*)m)->mp)
+ ftndesc = mono_mempool_alloc0 (((MonoDynamicMethod*)m)->mp, sizeof (MonoFtnDesc));
+ else
+ ftndesc = (MonoFtnDesc*)m_method_alloc0 (m, sizeof (MonoFtnDesc));
ftndesc->addr = addr;
ftndesc->arg = arg;
ftndesc->method = m;
if (slot_index < 0) {
/* Initialize the IMT trampoline to a 'trampoline' so the generated code doesn't have to initialize it */
// FIXME: Memory management
- gpointer *ftndesc = g_malloc (2 * sizeof (gpointer));
- IMTTrampInfo *info = g_new0 (IMTTrampInfo, 1);
+ gpointer *ftndesc = m_class_alloc0 (vt->klass, 2 * sizeof (gpointer));
+ IMTTrampInfo *info = m_class_alloc0 (vt->klass, sizeof (IMTTrampInfo));
info->vtable = vt;
info->slot = index;
ftndesc [0] = (gpointer)mini_llvmonly_initial_imt_tramp;