#define JUMP_SIZE 6
#define ENABLE_WRONG_METHOD_CHECK 0
+#define mono_mini_arch_lock() EnterCriticalSection (&mini_arch_mutex)
+#define mono_mini_arch_unlock() LeaveCriticalSection (&mini_arch_mutex)
+
/*========================= End of Defines =========================*/
/*------------------------------------------------------------------*/
static inline void add_general (guint *, size_data *, ArgInfo *);
static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
static inline void add_float (guint *, size_data *, ArgInfo *);
-static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *, gboolean);
+static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
static void catch_SIGILL(int, siginfo_t *, void *);
breakpoint_t breakpointCode;
+/*
+ * This mutex protects architecture specific caches
+ */
+static CRITICAL_SECTION mini_arch_mutex;
+
/*====================== End of Global Variables ===================*/
/*------------------------------------------------------------------*/
/*------------------------------------------------------------------*/
int
-mono_arch_get_argument_info (MonoMethodSignature *csig,
+mono_arch_get_argument_info (MonoGenericSharingContext *gsctx, MonoMethodSignature *csig,
int param_count,
MonoJitArgumentInfo *arg_info)
{
sig = mono_method_signature (method);
- cinfo = get_call_info (NULL, NULL, sig, sig->pinvoke);
+ cinfo = get_call_info (NULL, NULL, sig);
if (cinfo->struct_ret) {
printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
switch(method->klass->this_arg.type) {
case MONO_TYPE_VALUETYPE:
if (obj) {
- guint64 *value = ((void *)this + sizeof(MonoObject));
+ guint64 *value = (guint64 *) ((uintptr_t)this + sizeof(MonoObject));
printf("this:[value:%p:%016lx], ", this, *value);
} else
printf ("this:[NULL], ");
/*------------------------------------------------------------------*/
/* */
-/* Name - mono_arch_cpu_optimizazions */
+/* Name - mono_arch_cpu_optimizations */
/* */
/* Function - Returns the optimizations supported on this CPU */
/* */
/*------------------------------------------------------------------*/
guint32
-mono_arch_cpu_optimizazions (guint32 *exclude_mask)
+mono_arch_cpu_optimizations (guint32 *exclude_mask)
{
guint32 opts = 0;
/*========================= End of Function ========================*/
+/*------------------------------------------------------------------*/
+/* */
+/* Name - mono_arch_cpu_enumerate_simd_versions */
+/* */
+/* Function - Returns the SIMD instruction sets on this CPU */
+/* */
+/*------------------------------------------------------------------*/
+guint32
+mono_arch_cpu_enumerate_simd_versions (void)
+{
+ /* SIMD is currently unimplemented */
+ return 0;
+}
+/*========================= End of Function ========================*/
+
/*------------------------------------------------------------------*/
/* */
/* Name - */
/*------------------------------------------------------------------*/
static CallInfo *
-get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig, gboolean is_pinvoke)
+get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
{
guint i, fr, gr, size, pstart;
int nParm = sig->hasthis + sig->param_count;
MonoType *ret_type;
- guint32 simpletype, align;
+ guint32 simpleType, align;
+ gboolean is_pinvoke = sig->pinvoke;
CallInfo *cinfo;
size_data *sz;
MonoGenericSharingContext *gsctx = cfg ? cfg->generic_sharing_context : NULL;
/* area that the callee will use. */
/*----------------------------------------------------------*/
- ret_type = mono_type_get_underlying_type (sig->ret);
+ ret_type = mini_type_get_underlying_type (gsctx, sig->ret);
ret_type = mini_get_basic_type_from_generic (gsctx, ret_type);
- simpletype = ret_type->type;
+ simpleType = ret_type->type;
enum_retvalue:
- switch (simpletype) {
+ switch (simpleType) {
case MONO_TYPE_BOOLEAN:
case MONO_TYPE_I1:
case MONO_TYPE_U1:
case MONO_TYPE_VALUETYPE: {
MonoClass *klass = mono_class_from_mono_type (sig->ret);
if (klass->enumtype) {
- simpletype = mono_class_enum_basetype (klass)->type;
+ simpleType = mono_class_enum_basetype (klass)->type;
goto enum_retvalue;
}
- if (sig->pinvoke)
- size = mono_class_native_size (klass, &align);
- else
- size = mono_class_value_size (klass, &align);
+ size = mini_type_stack_size_full (gsctx, &klass->byval_arg, NULL, sig->pinvoke);
cinfo->struct_ret = 1;
cinfo->ret.size = size;
continue;
}
- ptype = mono_type_get_underlying_type (sig->params [i]);
- ptype = mini_get_basic_type_from_generic (gsctx, ptype);
- simpletype = ptype->type;
- cinfo->args[nParm].type = simpletype;
- switch (simpletype) {
+ ptype = mini_type_get_underlying_type (gsctx, sig->params [i]);
+ simpleType = ptype->type;
+ cinfo->args[nParm].type = simpleType;
+ switch (simpleType) {
case MONO_TYPE_BOOLEAN:
case MONO_TYPE_I1:
case MONO_TYPE_U1:
nParm++;
break;
case MONO_TYPE_GENERICINST:
- if (!mono_type_generic_inst_is_valuetype (sig->params [i])) {
+ if (!mono_type_generic_inst_is_valuetype (ptype)) {
cinfo->args[nParm].size = sizeof(gpointer);
add_general (&gr, sz, cinfo->args+nParm);
nParm++;
/* Fall through */
case MONO_TYPE_VALUETYPE: {
MonoMarshalType *info;
- MonoClass *klass = mono_class_from_mono_type (sig->params [i]);
- if (sig->pinvoke)
- size = mono_class_native_size (klass, &align);
- else
- size = mono_class_value_size (klass, &align);
-
- info = mono_marshal_load_type_info (klass);
+ MonoClass *klass = mono_class_from_mono_type (ptype);
- if ((info->native_size == sizeof(float)) &&
- (info->num_fields == 1) &&
- (info->fields[0].field->type->type == MONO_TYPE_R4)) {
- cinfo->args[nParm].size = sizeof(float);
- add_float(&fr, sz, cinfo->args+nParm);
- nParm ++;
- break;
- }
+ size = mini_type_stack_size_full(gsctx, &klass->byval_arg, NULL, sig->pinvoke);
+ if (simpleType != MONO_TYPE_GENERICINST) {
+ info = mono_marshal_load_type_info(klass);
- if ((info->native_size == sizeof(double)) &&
- (info->num_fields == 1) &&
- (info->fields[0].field->type->type == MONO_TYPE_R8)) {
- cinfo->args[nParm].size = sizeof(double);
- add_float(&fr, sz, cinfo->args+nParm);
- nParm ++;
- break;
+ if ((info->native_size == sizeof(float)) &&
+ (info->num_fields == 1) &&
+ (info->fields[0].field->type->type == MONO_TYPE_R4)) {
+ cinfo->args[nParm].size = sizeof(float);
+ add_float(&fr, sz, cinfo->args+nParm);
+ nParm ++;
+ break;
+ }
+
+ if ((info->native_size == sizeof(double)) &&
+ (info->num_fields == 1) &&
+ (info->fields[0].field->type->type == MONO_TYPE_R8)) {
+ cinfo->args[nParm].size = sizeof(double);
+ add_float(&fr, sz, cinfo->args+nParm);
+ nParm ++;
+ break;
+ }
}
cinfo->args[nParm].vtsize = 0;
}
break;
default:
- g_error ("Can't trampoline 0x%x", sig->params [i]->type);
+ g_error ("Can't trampoline 0x%x", ptype);
}
}
sig = mono_method_signature (cfg->method);
- cinfo = get_call_info (cfg, cfg->mempool, sig, sig->pinvoke);
+ cinfo = get_call_info (cfg, cfg->mempool, sig);
if (!cinfo->struct_ret) {
switch (mono_type_get_underlying_type (sig->ret)->type) {
curinst++;
}
+ cfg->locals_min_stack_offset = offset;
+
curinst = cfg->locals_start;
for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
inst = cfg->varinfo [iVar];
iVar, inst->inst_offset, size));
}
+ cfg->locals_max_stack_offset = offset;
+
/*------------------------------------------------------*/
/* Allow space for the trace method stack area if needed*/
/*------------------------------------------------------*/
- if (mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method))
+ if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method))
+ || (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
offset += S390_TRACE_STACK_SIZE;
/*------------------------------------------------------*/
sig = mono_method_signature (cfg->method);
- cinfo = get_call_info (cfg, cfg->mempool, sig, sig->pinvoke);
+ cinfo = get_call_info (cfg, cfg->mempool, sig);
if (cinfo->struct_ret) {
cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
n = sig->param_count + sig->hasthis;
DEBUG (g_print ("Call requires: %d parameters\n",n));
- cinfo = get_call_info (cfg, cfg->mempool, sig, sig->pinvoke);
+ cinfo = get_call_info (cfg, cfg->mempool, sig);
stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
cinfo->sz.parm_size + cinfo->sz.offset;
frmReg, ainfo->offparm);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
ainfo->reg, ainfo->offset, treg);
+
+ if (cfg->compute_gc_maps) {
+ MonoInst *def;
+
+ EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
+ }
}
break;
}
MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
src->dreg, 0, size);
+
+ if (cfg->compute_gc_maps) {
+ MonoInst *def;
+
+ EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
+ }
}
}
{
guchar *code = p;
int save_mode = SAVE_NONE,
- saveOffset;
+ saveOffset,
+ offset;
MonoMethod *method = cfg->method;
int rtype = mono_type_get_underlying_type (mono_method_signature (method)->ret)->type;
+ offset = code - cfg->native_code;
+ /*-----------------------------------------*/
+ /* We need about 128 bytes of instructions */
+ /*-----------------------------------------*/
+ if (offset > (cfg->code_size - 128)) {
+ cfg->code_size *= 2;
+ cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
+ code = cfg->native_code + offset;
+ }
+
saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
if (method->save_lmf)
saveOffset -= sizeof(MonoLMF);
/* ensure ins->sreg1 is not NULL */
s390_lg (code, s390_r0, 0, ins->sreg1, 0);
s390_ltgr (code, s390_r0, s390_r0);
+ EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
}
break;
case OP_ARGLIST: {
/* floating point opcodes */
case OP_R8CONST: {
- if (*((float *) ins->inst_p0) == 0) {
+ if (*((double *) ins->inst_p0) == 0) {
s390_lzdr (code, ins->dreg);
} else {
s390_basr (code, s390_r13, 0);
case OP_MEMORY_BARRIER: {
}
break;
+ case OP_GC_LIVENESS_DEF:
+ case OP_GC_LIVENESS_USE:
+ case OP_GC_PARAM_SLOT_LIVENESS_DEF:
+ ins->backend.pc_offset = code - cfg->native_code;
+ break;
+ case OP_GC_SPILL_SLOT_LIVENESS_DEF:
+ ins->backend.pc_offset = code - cfg->native_code;
+ bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
+ break;
default:
g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
g_assert_not_reached ();
case MONO_PATCH_INFO_EXC:
case MONO_PATCH_INFO_ABS:
case MONO_PATCH_INFO_METHOD:
+ case MONO_PATCH_INFO_RGCTX_FETCH:
case MONO_PATCH_INFO_INTERNAL_METHOD:
case MONO_PATCH_INFO_CLASS_INIT:
+ case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+ case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
s390_patch_addr (ip, (guint64) target);
continue;
case MONO_PATCH_INFO_SWITCH:
int pos = 0, i;
CallInfo *cinfo;
- cinfo = get_call_info (NULL, NULL, sig, sig->pinvoke);
+ cinfo = get_call_info (NULL, NULL, sig);
if (cinfo->struct_ret) {
ArgInfo *ainfo = &cinfo->ret;
if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
tracing = 1;
cfg->code_size += 256;
- }
+ } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
+ cfg->code_size += 256;
if (method->save_lmf)
cfg->code_size += 200;
mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
+ /* store runtime generic context */
+ if (cfg->rgctx_var) {
+ g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
+
+ s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
+ cfg->rgctx_var->inst_basereg,
+ cfg->rgctx_var->inst_offset);
+ }
+
/* compute max_offset in order to use short forward jumps
* we always do it on s390 because the immediate displacement
* for jumps is too small
sig = mono_method_signature (method);
pos = 0;
- cinfo = get_call_info (cfg, cfg->mempool, sig, sig->pinvoke);
+ cinfo = get_call_info (cfg, cfg->mempool, sig);
if (cinfo->struct_ret) {
ArgInfo *ainfo = &cinfo->ret;
pos++;
}
- if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
- if (cfg->compile_aot)
- /* AOT code is only used in the root domain */
- s390_lghi (code, s390_r2, 0);
- else {
- s390_basr(code, s390_r14, 0);
- s390_j (code, 6);
- s390_llong(code, cfg->domain);
- s390_lg (code, s390_r2, 0, s390_r14, 4);
- }
-
- s390_basr(code, s390_r14, 0);
- s390_j (code, 6);
- mono_add_patch_info (cfg, code - cfg->native_code,
- MONO_PATCH_INFO_INTERNAL_METHOD,
- (gpointer)"mono_jit_thread_attach");
- s390_llong(code, 0);
- s390_lg (code, s390_r1, 0, s390_r14, 4);
- s390_basr (code, s390_r14, s390_r1);
- }
-
if (method->save_lmf) {
/*---------------------------------------------------------------*/
/* build the MonoLMF structure on the stack - see mini-s390x.h */
/*---------------------------------------------------------------*/
/* On return from this call r2 have the address of the &lmf */
/*---------------------------------------------------------------*/
- s390_basr(code, s390_r14, 0);
- s390_j (code, 6);
- mono_add_patch_info (cfg, code - cfg->native_code,
- MONO_PATCH_INFO_INTERNAL_METHOD,
- (gpointer)"mono_get_lmf_addr");
- s390_llong(code, 0);
- s390_lg (code, s390_r1, 0, s390_r14, 4);
- s390_basr (code, s390_r14, s390_r1);
+ if (lmf_addr_tls_offset == -1) {
+ s390_basr(code, s390_r14, 0);
+ s390_j (code, 6);
+ mono_add_patch_info (cfg, code - cfg->native_code,
+ MONO_PATCH_INFO_INTERNAL_METHOD,
+ (gpointer)"mono_get_lmf_addr");
+ s390_llong(code, 0);
+ s390_lg (code, s390_r1, 0, s390_r14, 4);
+ s390_basr (code, s390_r14, s390_r1);
+ } else {
+ /*-------------------------------------------------------*/
+ /* Get LMF by getting value from thread level storage */
+ /*-------------------------------------------------------*/
+ s390_ear (code, s390_r1, 0);
+ s390_sllg(code, s390_r1, s390_r1, 0, 32);
+ s390_ear (code, s390_r1, 1);
+ s390_lg (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset);
+ }
/*---------------------------------------------------------------*/
/* Set lmf.lmf_addr = jit_tls->lmf */
if (mono_jit_trace_calls != NULL)
max_epilog_size += 128;
-
- if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
+ else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
max_epilog_size += 128;
while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
-// if (cfg->frame_reg != STK_BASE)
-// s390_lgr (code, STK_BASE, cfg->frame_reg);
s390_lg (code, STK_BASE, 0, STK_BASE, 0);
} else
code = backUpStackPtr(cfg, code);
mono_arch_finish_init (void)
{
appdomain_tls_offset = mono_domain_get_tls_offset();
- lmf_tls_offset = mono_get_jit_tls_offset();
- lmf_addr_tls_offset = mono_get_jit_tls_offset();
+ lmf_tls_offset = mono_get_lmf_tls_offset();
+ lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset();
}
/*========================= End of Function ========================*/
/*========================= End of Function ========================*/
+/*------------------------------------------------------------------*/
+/* */
+/* Name - mono_arch_find_static_call_vtable */
+/* */
+/* Function - Find the static call vtable. */
+/* */
+/*------------------------------------------------------------------*/
+
+MonoVTable*
+mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
+{
+ mgreg_t *r = (mgreg_t*)regs;
+
+ return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/* */
+/* Name - mono_arch_get_cie_program */
+/* */
+/* Function - Find the static call vtable. */
+/* */
+/*------------------------------------------------------------------*/
+
+GSList*
+mono_arch_get_cie_program (void)
+{
+ GSList *l = NULL;
+
+ mono_add_unwind_op_def_cfa (l, NULL, NULL, STK_BASE, 0);
+
+ return(l);
+}
+
+/*========================= End of Function ========================*/
+
#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
/*------------------------------------------------------------------*/