Skip to content

Commit

Permalink
2009-09-20 Zoltan Varga <vargaz@gmail.com>
Browse files Browse the repository at this point in the history
	* mini.c (mini_create_jit_domain_info): Register a destructor function
	for the runtime_invoke_hash.

	* mini-amd64.c (mono_arch_get_dyn_call_args): Rename this to
	'mono_arch_dyn_call_start'. Pass the pointer to the return value buffer to
	this function.
	(mono_arch_get_dyn_call_ret): Rename this to 'mono_arch_dyn_call_finish'.
	(dyn_call_supported): Simplify this by using get_call_info ().
	(mono_arch_dyn_call_free): New destructor function.

svn path=/trunk/mono/; revision=142284
  • Loading branch information
vargaz committed Sep 20, 2009
1 parent bd0b05d commit f243417
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 108 deletions.
10 changes: 10 additions & 0 deletions mono/mini/ChangeLog
@@ -1,5 +1,15 @@
2009-09-20 Zoltan Varga <vargaz@gmail.com>

* mini.c (mini_create_jit_domain_info): Register a destructor function
for the runtime_invoke_hash.

* mini-amd64.c (mono_arch_get_dyn_call_args): Rename this to
'mono_arch_dyn_call_start'. Pass the pointer to the return value buffer to
this function.
(mono_arch_get_dyn_call_ret): Rename this to 'mono_arch_dyn_call_finish'.
(dyn_call_supported): Simplify this by using get_call_info ().
(mono_arch_dyn_call_free): New destructor function.

* generics.cs: Remove a printf.

* method-to-ir.c (mono_method_to_ir): Allocate some param area for DYN_CALL.
Expand Down
169 changes: 67 additions & 102 deletions mono/mini/mini-amd64.c
Expand Up @@ -255,6 +255,7 @@ typedef struct {
guint32 reg_usage;
guint32 freg_usage;
gboolean need_stack_align;
gboolean vtype_retaddr;
ArgInfo ret;
ArgInfo sig_cookie;
ArgInfo args [1];
Expand Down Expand Up @@ -618,6 +619,8 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
else
cinfo = g_malloc0 (sizeof (CallInfo) + (sizeof (ArgInfo) * n));

cinfo->nargs = n;

gr = 0;
fr = 0;

Expand Down Expand Up @@ -669,9 +672,11 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
guint32 tmp_gr = 0, tmp_fr = 0, tmp_stacksize = 0;

add_valuetype (gsctx, sig, &cinfo->ret, sig->ret, TRUE, &tmp_gr, &tmp_fr, &tmp_stacksize);
if (cinfo->ret.storage == ArgOnStack)
if (cinfo->ret.storage == ArgOnStack) {
cinfo->vtype_retaddr = TRUE;
/* The caller passes the address where the value is stored */
add_general (&gr, &stack_size, &cinfo->ret);
}
break;
}
case MONO_TYPE_TYPEDBYREF:
Expand Down Expand Up @@ -2126,161 +2131,120 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
x86_branch32 (code, cond, 0, sign); \
}

typedef struct {
MonoMethodSignature *sig;
CallInfo *cinfo;
} ArchDynCallInfo;

typedef struct {
mgreg_t regs [PARAM_REGS];
mgreg_t res;
guint8 *ret;
} DynCallArgs;

static gboolean
dyn_call_supported (MonoMethodSignature *sig)
dyn_call_supported (MonoMethodSignature *sig, CallInfo *cinfo)
{
int i;

#ifdef PLATFORM_WIN32
return FALSE;
#endif

if (sig->hasthis + sig->param_count > PARAM_REGS)
if (cinfo->nargs > PARAM_REGS)
return FALSE;

switch (sig->ret->type) {
case MONO_TYPE_VOID:
case MONO_TYPE_I1:
case MONO_TYPE_U1:
case MONO_TYPE_I2:
case MONO_TYPE_U2:
case MONO_TYPE_I4:
case MONO_TYPE_U4:
case MONO_TYPE_I:
case MONO_TYPE_U:
case MONO_TYPE_I8:
case MONO_TYPE_U8:
case MONO_TYPE_BOOLEAN:
case MONO_TYPE_CHAR:
case MONO_TYPE_STRING:
case MONO_TYPE_CLASS:
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_OBJECT:
case MONO_TYPE_PTR:
break;
case MONO_TYPE_GENERICINST:
if (!MONO_TYPE_IS_REFERENCE (sig->ret))
return FALSE;
break;
case MONO_TYPE_VALUETYPE:
if (!sig->ret->data.klass->enumtype)
switch (cinfo->ret.storage) {
case ArgNone:
case ArgInIReg:
if (cinfo->vtype_retaddr)
/* FIXME: Add an Arg<...> constant for this */
return FALSE;
break;
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
/* assume gshared */
break;
default:
return FALSE;
}
for (i = 0; i < sig->param_count; ++i) {
MonoType *t = sig->params [i];

if (t->byref)
continue;

handle_enum:
switch (t->type) {
case MONO_TYPE_R4:
case MONO_TYPE_R8:
case MONO_TYPE_TYPEDBYREF:
return FALSE;
case MONO_TYPE_VALUETYPE:
if (t->data.klass->enumtype) {
t = mono_class_enum_basetype (t->data.klass);
goto handle_enum;
}
return FALSE;
case MONO_TYPE_GENERICINST:
if (!MONO_TYPE_IS_REFERENCE (t))
return FALSE;
break;
case MONO_TYPE_STRING:
case MONO_TYPE_CLASS:
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_OBJECT:
case MONO_TYPE_PTR:
case MONO_TYPE_BOOLEAN:
case MONO_TYPE_CHAR:
case MONO_TYPE_I1:
case MONO_TYPE_U1:
case MONO_TYPE_I2:
case MONO_TYPE_U2:
case MONO_TYPE_I4:
case MONO_TYPE_U4:
case MONO_TYPE_I:
case MONO_TYPE_U:
case MONO_TYPE_I8:
case MONO_TYPE_U8:
break;
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
/* assume gshared */
for (i = 0; i < cinfo->nargs; ++i) {
switch (cinfo->args [i].storage) {
case ArgInIReg:
break;
default:
return FALSE;
break;
}
}

return TRUE;
}

typedef struct {
MonoMethodSignature *sig;
} DynCallInfo;

typedef struct {
mgreg_t regs [PARAM_REGS];
mgreg_t res;
} DynCallArgs;

/*
* mono_arch_dyn_call_prepare:
*
* Return a pointer to an arch-specific structure in malloc-ed memory which
* contains information needed by mono_arch_get_dyn_call_args (). Return NULL
* if OP_DYN_CALL is not supported for SIG.
* Return a pointer to an arch-specific structure which contains information
* needed by mono_arch_get_dyn_call_args (). Return NULL if OP_DYN_CALL is not
* supported for SIG.
* This function is equivalent to ffi_prep_cif in libffi.
*/
MonoDynCallInfo*
mono_arch_dyn_call_prepare (MonoMethodSignature *sig)
{
DynCallInfo *info;
ArchDynCallInfo *info;
CallInfo *cinfo;

if (!dyn_call_supported (sig))
cinfo = get_call_info (NULL, NULL, sig, FALSE);

if (!dyn_call_supported (sig, cinfo)) {
g_free (cinfo);
return NULL;
}

info = g_new0 (DynCallInfo, 1);
info = g_new0 (ArchDynCallInfo, 1);
// FIXME: Preprocess the info to speed up get_dyn_call_args ().
info->sig = sig;
info->cinfo = cinfo;

return (MonoDynCallInfo*)info;
}

/*
* mono_arch_get_dyn_call_args:
* mono_arch_dyn_call_free:
*
* Free a MonoDynCallInfo structure.
*/
void
mono_arch_dyn_call_free (MonoDynCallInfo *info)
{
ArchDynCallInfo *ainfo = (ArchDynCallInfo*)info;

g_free (ainfo->cinfo);
g_free (ainfo);
}

/*
* mono_arch_get_start_dyn_call:
*
* Convert the arguments ARGS to a format which can be passed to OP_DYN_CALL, and
* store the result into BUF.
* ARGS should be an array of pointers pointing to the arguments.
* RET should point to a memory buffer large enought to hold the result of the
* call.
* This function should be as fast as possible, any work which does not depend
* on the actual values of the arguments should be done in
* mono_arch_dyn_call_prepare ().
* get_dyn_call_args + OP_DYN_CALL + get_dyn_call_ret is equivalent to ffi_call in
* start_dyn_call + OP_DYN_CALL + finish_dyn_call is equivalent to ffi_call in
* libffi.
*/
void
mono_arch_get_dyn_call_args (MonoDynCallInfo *info, gpointer **args, guint8 *buf, int buf_len)
mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret, guint8 *buf, int buf_len)
{
DynCallArgs *p = (DynCallArgs*)buf;
int arg_index, greg, i;
MonoMethodSignature *sig = ((DynCallInfo*)info)->sig;
MonoMethodSignature *sig = ((ArchDynCallInfo*)info)->sig;

g_assert (buf_len >= sizeof (DynCallArgs));

p->res = 0;
p->ret = ret;

arg_index = 0;
greg = 0;
Expand Down Expand Up @@ -2342,18 +2306,19 @@ mono_arch_get_dyn_call_args (MonoDynCallInfo *info, gpointer **args, guint8 *buf
}

/*
* mono_arch_get_dyn_call_ret:
* mono_arch_finish_dyn_call:
*
* Store the result of a dyn call into a buffer pointed to by RET. BUF should
* point to the buffer returned by get_dyn_call_args ().
* Store the result of a dyn call into the return value buffer passed to
* start_dyn_call ().
* This function should be as fast as possible, any work which does not depend
* on the actual values of the arguments should be done in
* mono_arch_dyn_call_prepare ().
*/
void
mono_arch_get_dyn_call_ret (MonoDynCallInfo *info, guint8 *buf, guint8 *ret)
mono_arch_finish_dyn_call (MonoDynCallInfo *info, guint8 *buf)
{
MonoMethodSignature *sig = ((DynCallInfo*)info)->sig;
MonoMethodSignature *sig = ((ArchDynCallInfo*)info)->sig;
guint8 *ret = ((DynCallArgs*)buf)->ret;

switch (mono_type_get_underlying_type (sig->ret)->type) {
case MONO_TYPE_VOID:
Expand Down
22 changes: 18 additions & 4 deletions mono/mini/mini.c
Expand Up @@ -4576,7 +4576,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
dyn_runtime_invoke = mono_jit_compile_method (invoke);
}

/* Convert the arguments to the format expected by get_dyn_call_args */
/* Convert the arguments to the format expected by start_dyn_call () */
args = g_alloca ((sig->param_count + sig->hasthis) * sizeof (gpointer));
pindex = 0;
if (sig->hasthis)
Expand All @@ -4595,11 +4595,11 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec

//printf ("M: %s\n", mono_method_full_name (method, TRUE));

mono_arch_get_dyn_call_args (info->dyn_call_info, (gpointer**)args, buf, sizeof (buf));
mono_arch_start_dyn_call (info->dyn_call_info, (gpointer**)args, retval, buf, sizeof (buf));

dyn_runtime_invoke (buf, exc, info->compiled_method);

mono_arch_get_dyn_call_ret (info->dyn_call_info, buf, retval);
mono_arch_finish_dyn_call (info->dyn_call_info, buf);

if (info->ret_box_class)
return mono_value_box (domain, info->ret_box_class, retval);
Expand Down Expand Up @@ -4853,6 +4853,8 @@ mini_get_addr_from_ftnptr (gpointer descr)
return descr;
#endif
}

static void runtime_invoke_info_free (gpointer value);

static void
mini_create_jit_domain_info (MonoDomain *domain)
Expand All @@ -4865,7 +4867,7 @@ mini_create_jit_domain_info (MonoDomain *domain)
info->delegate_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
info->static_rgctx_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
info->llvm_vcall_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
info->runtime_invoke_hash = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, g_free);
info->runtime_invoke_hash = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);

domain->runtime_info = info;
}
Expand All @@ -4884,6 +4886,18 @@ dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
g_free (di);
}

static void
runtime_invoke_info_free (gpointer value)
{
RuntimeInvokeInfo *info = (RuntimeInvokeInfo*)value;

#ifdef MONO_ARCH_DYN_CALL_SUPPORTED
if (info->dyn_call_info)
mono_arch_dyn_call_free (info->dyn_call_info);
#endif
g_free (info);
}

static void
mini_free_jit_domain_info (MonoDomain *domain)
{
Expand Down
5 changes: 3 additions & 2 deletions mono/mini/mini.h
Expand Up @@ -1591,8 +1591,9 @@ void mono_arch_emit_call (MonoCompile *cfg, MonoCallInst
void mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) MONO_INTERNAL;
void mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val) MONO_INTERNAL;
MonoDynCallInfo *mono_arch_dyn_call_prepare (MonoMethodSignature *sig) MONO_INTERNAL;
void mono_arch_get_dyn_call_args (MonoDynCallInfo *info, gpointer **args, guint8 *buf, int buf_len) MONO_INTERNAL;
void mono_arch_get_dyn_call_ret (MonoDynCallInfo *info, guint8 *buf, guint8 *ret) MONO_INTERNAL;
void mono_arch_dyn_call_free (MonoDynCallInfo *info) MONO_INTERNAL;
void mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret, guint8 *buf, int buf_len) MONO_INTERNAL;
void mono_arch_finish_dyn_call (MonoDynCallInfo *info, guint8 *buf) MONO_INTERNAL;
MonoInst *mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) MONO_INTERNAL;
void mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins) MONO_INTERNAL;
void mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *ins) MONO_INTERNAL;
Expand Down

0 comments on commit f243417

Please sign in to comment.