#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-tls.h>
#include <mono/utils/mono-hwcap-x86.h>
+#include <mono/utils/mono-threads.h>
#include "trace.h"
#include "ir-emit.h"
#define IS_REX(inst) (((inst) >= 0x40) && ((inst) <= 0x4f))
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
/* Under windows, the calling convention is never stdcall */
#define CALLCONV_IS_STDCALL(call_conv) (FALSE)
#else
/* The size of the single step instruction causing the actual fault */
static int single_step_fault_size;
+/* The single step trampoline */
+static gpointer ss_trampoline;
+
/* Offset between fp and the first argument in the callee */
#define ARGS_OFFSET 16
#define GP_SCRATCH_REG AMD64_R11
#define DEBUG(a) if (cfg->verbose_level > 1) a
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
static AMD64_Reg_No param_regs [] = { AMD64_RCX, AMD64_RDX, AMD64_R8, AMD64_R9 };
static AMD64_Reg_No return_regs [] = { AMD64_RAX, AMD64_RDX };
}
}
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
#define FLOAT_PARAM_REGS 4
#else
#define FLOAT_PARAM_REGS 8
ptype = mini_type_get_underlying_type (gsctx, type);
switch (ptype->type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_CHAR:
case MONO_TYPE_I1:
case MONO_TYPE_U1:
case MONO_TYPE_I2:
break;
case MONO_TYPE_R4:
case MONO_TYPE_R8:
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
class2 = ARG_CLASS_INTEGER;
#else
class2 = ARG_CLASS_SSE;
klass = mono_class_from_mono_type (type);
size = mini_type_stack_size_full (gsctx, &klass->byval_arg, NULL, sig->pinvoke);
-#ifndef HOST_WIN32
+#ifndef TARGET_WIN32
if (!sig->pinvoke && ((is_return && (size == 8)) || (!is_return && (size <= 16)))) {
/* We pass and return vtypes of size 8 in a register */
} else if (!sig->pinvoke || (size == 0) || (size > 16)) {
g_assert (info);
g_assert (fields);
-#ifndef HOST_WIN32
+#ifndef TARGET_WIN32
if (info->native_size > 16) {
ainfo->offset = *stack_size;
*stack_size += ALIGN_TO (info->native_size, 8);
gr = 0;
fr = 0;
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
/* Reserve space where the callee can save the argument registers */
stack_size = 4 * sizeof (mgreg_t);
#endif
/* return value */
- {
- ret_type = mini_type_get_underlying_type (gsctx, sig->ret);
- switch (ret_type->type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- case MONO_TYPE_PTR:
- case MONO_TYPE_FNPTR:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_STRING:
- cinfo->ret.storage = ArgInIReg;
- cinfo->ret.reg = AMD64_RAX;
- break;
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
+ ret_type = mini_type_get_underlying_type (gsctx, sig->ret);
+ switch (ret_type->type) {
+ 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_PTR:
+ case MONO_TYPE_FNPTR:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_STRING:
+ cinfo->ret.storage = ArgInIReg;
+ cinfo->ret.reg = AMD64_RAX;
+ break;
+ case MONO_TYPE_U8:
+ case MONO_TYPE_I8:
+ cinfo->ret.storage = ArgInIReg;
+ cinfo->ret.reg = AMD64_RAX;
+ break;
+ case MONO_TYPE_R4:
+ cinfo->ret.storage = ArgInFloatSSEReg;
+ cinfo->ret.reg = AMD64_XMM0;
+ break;
+ case MONO_TYPE_R8:
+ cinfo->ret.storage = ArgInDoubleSSEReg;
+ cinfo->ret.reg = AMD64_XMM0;
+ break;
+ case MONO_TYPE_GENERICINST:
+ if (!mono_type_generic_inst_is_valuetype (ret_type)) {
cinfo->ret.storage = ArgInIReg;
cinfo->ret.reg = AMD64_RAX;
break;
- case MONO_TYPE_R4:
- cinfo->ret.storage = ArgInFloatSSEReg;
- cinfo->ret.reg = AMD64_XMM0;
- break;
- case MONO_TYPE_R8:
- cinfo->ret.storage = ArgInDoubleSSEReg;
- cinfo->ret.reg = AMD64_XMM0;
- break;
- case MONO_TYPE_GENERICINST:
- if (!mono_type_generic_inst_is_valuetype (ret_type)) {
- cinfo->ret.storage = ArgInIReg;
- cinfo->ret.reg = AMD64_RAX;
- break;
- }
- /* fall through */
+ }
+ /* fall through */
#if defined( __native_client_codegen__ )
- case MONO_TYPE_TYPEDBYREF:
+ case MONO_TYPE_TYPEDBYREF:
#endif
- case MONO_TYPE_VALUETYPE: {
- guint32 tmp_gr = 0, tmp_fr = 0, tmp_stacksize = 0;
+ case MONO_TYPE_VALUETYPE: {
+ guint32 tmp_gr = 0, tmp_fr = 0, tmp_stacksize = 0;
- add_valuetype (gsctx, sig, &cinfo->ret, ret_type, TRUE, &tmp_gr, &tmp_fr, &tmp_stacksize);
- if (cinfo->ret.storage == ArgOnStack) {
- cinfo->vtype_retaddr = TRUE;
- /* The caller passes the address where the value is stored */
- }
- break;
+ add_valuetype (gsctx, sig, &cinfo->ret, ret_type, TRUE, &tmp_gr, &tmp_fr, &tmp_stacksize);
+ if (cinfo->ret.storage == ArgOnStack) {
+ cinfo->vtype_retaddr = TRUE;
+ /* The caller passes the address where the value is stored */
}
+ break;
+ }
#if !defined( __native_client_codegen__ )
- case MONO_TYPE_TYPEDBYREF:
- /* Same as a valuetype with size 24 */
- cinfo->vtype_retaddr = TRUE;
- break;
+ case MONO_TYPE_TYPEDBYREF:
+ /* Same as a valuetype with size 24 */
+ cinfo->vtype_retaddr = TRUE;
+ break;
#endif
- case MONO_TYPE_VOID:
- break;
- default:
- g_error ("Can't handle as return value 0x%x", ret_type->type);
- }
+ case MONO_TYPE_VOID:
+ break;
+ default:
+ g_error ("Can't handle as return value 0x%x", ret_type->type);
}
pstart = 0;
ArgInfo *ainfo = &cinfo->args [sig->hasthis + i];
MonoType *ptype;
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
/* The float param registers and other param registers must be the same index on Windows x64.*/
if (gr > fr)
fr = gr;
ptype = mini_type_get_underlying_type (gsctx, sig->params [i]);
switch (ptype->type) {
- case MONO_TYPE_BOOLEAN:
case MONO_TYPE_I1:
case MONO_TYPE_U1:
add_general (&gr, &stack_size, ainfo);
break;
case MONO_TYPE_I2:
case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
add_general (&gr, &stack_size, ainfo);
break;
case MONO_TYPE_I4:
#ifndef __native_client_codegen__
regs = g_list_prepend (regs, (gpointer)AMD64_R15);
#endif
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
regs = g_list_prepend (regs, (gpointer)AMD64_RDI);
regs = g_list_prepend (regs, (gpointer)AMD64_RSI);
#endif
}
}
- if (cfg->gen_seq_points_debug_data) {
+ if (cfg->gen_sdb_seq_points) {
MonoInst *ins;
if (cfg->compile_aot) {
MonoInst *ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
ins->flags |= MONO_INST_VOLATILE;
cfg->arch.seq_point_info_var = ins;
+
+ ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+ ins->flags |= MONO_INST_VOLATILE;
+ cfg->arch.ss_tramp_var = ins;
}
ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
if (cfg->method->save_lmf) {
cfg->lmf_ir = TRUE;
-#if !defined(HOST_WIN32)
+#if !defined(TARGET_WIN32)
if (mono_get_lmf_tls_offset () != -1 && !optimize_for_xen)
cfg->lmf_ir_mono_lmf = TRUE;
#endif
p->regs [greg ++] = PTR_TO_GREG(ret);
for (i = pindex; i < sig->param_count; i++) {
- MonoType *t = mono_type_get_underlying_type (sig->params [i]);
+ MonoType *t = mini_type_get_underlying_type (NULL, sig->params [i]);
gpointer *arg = args [arg_index ++];
if (t->byref) {
p->regs [greg ++] = *(guint64*)(arg);
break;
#endif
- case MONO_TYPE_BOOLEAN:
case MONO_TYPE_U1:
p->regs [greg ++] = *(guint8*)(arg);
break;
p->regs [greg ++] = *(gint16*)(arg);
break;
case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
p->regs [greg ++] = *(guint16*)(arg);
break;
case MONO_TYPE_I4:
MonoMethodSignature *sig = dinfo->sig;
guint8 *ret = ((DynCallArgs*)buf)->ret;
mgreg_t res = ((DynCallArgs*)buf)->res;
- MonoType *sig_ret = mono_type_get_underlying_type (sig->ret);
+ MonoType *sig_ret = mini_type_get_underlying_type (NULL, sig->ret);
switch (sig_ret->type) {
case MONO_TYPE_VOID:
*(gint8*)ret = res;
break;
case MONO_TYPE_U1:
- case MONO_TYPE_BOOLEAN:
*(guint8*)ret = res;
break;
case MONO_TYPE_I2:
*(gint16*)ret = res;
break;
case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
*(guint16*)ret = res;
break;
case MONO_TYPE_I4:
static inline guint8*
emit_call (MonoCompile *cfg, guint8 *code, guint32 patch_type, gconstpointer data, gboolean win64_adjust_stack)
{
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
if (win64_adjust_stack)
amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 32);
#endif
code = emit_call_body (cfg, code, patch_type, data);
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
if (win64_adjust_stack)
amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 32);
#endif
int sreg = tree->sreg1;
int need_touch = FALSE;
-#if defined(HOST_WIN32)
+#if defined(TARGET_WIN32)
need_touch = TRUE;
#elif defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK)
if (!tree->flags & MONO_INST_INIT)
guint8*
mono_amd64_emit_tls_get (guint8* code, int dreg, int tls_offset)
{
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
if (tls_offset < 64) {
x86_prefix (code, X86_GS_PREFIX);
amd64_mov_reg_mem (code, dreg, (tls_offset * 8) + 0x1480, 8);
static guint8*
amd64_emit_tls_set (guint8 *code, int sreg, int tls_offset)
{
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
g_assert_not_reached ();
#elif defined(__APPLE__)
x86_prefix (code, X86_GS_PREFIX);
amd64_emit_tls_set_reg (guint8 *code, int sreg, int offset_reg)
{
/* offset_reg contains a value translated by mono_arch_translate_tls_offset () */
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
g_assert_not_reached ();
#elif defined(__APPLE__)
x86_prefix (code, X86_GS_PREFIX);
case OP_SEQ_POINT: {
int i;
- /*
- * Read from the single stepping trigger page. This will cause a
- * SIGSEGV when single stepping is enabled.
- * We do this _before_ the breakpoint, so single stepping after
- * a breakpoint is hit will step to the next IL offset.
- */
if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
- MonoInst *var = cfg->arch.ss_trigger_page_var;
+ if (cfg->compile_aot) {
+ MonoInst *var = cfg->arch.ss_tramp_var;
+ guint8 *label;
+
+ /* Load ss_tramp_var */
+ amd64_mov_reg_membase (code, AMD64_R11, var->inst_basereg, var->inst_offset, 8);
+ /* Load the trampoline address */
+ amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, 8);
+ /* Call it if it is non-null */
+ amd64_test_reg_reg (code, AMD64_R11, AMD64_R11);
+ label = code;
+ amd64_branch8 (code, X86_CC_Z, 0, FALSE);
+ amd64_call_reg (code, AMD64_R11);
+ amd64_patch (label, code);
+ } else {
+ /*
+ * Read from the single stepping trigger page. This will cause a
+ * SIGSEGV when single stepping is enabled.
+ * We do this _before_ the breakpoint, so single stepping after
+ * a breakpoint is hit will step to the next IL offset.
+ */
+ MonoInst *var = cfg->arch.ss_trigger_page_var;
- amd64_mov_reg_membase (code, AMD64_R11, var->inst_basereg, var->inst_offset, 8);
- amd64_alu_membase_imm_size (code, X86_CMP, AMD64_R11, 0, 0, 4);
+ amd64_mov_reg_membase (code, AMD64_R11, var->inst_basereg, var->inst_offset, 8);
+ amd64_alu_membase_imm_size (code, X86_CMP, AMD64_R11, 0, 0, 4);
+ }
}
/*
guint32 offset = code - cfg->native_code;
guint32 val;
MonoInst *info_var = cfg->arch.seq_point_info_var;
+ guint8 *label;
/* Load info var */
amd64_mov_reg_membase (code, AMD64_R11, info_var->inst_basereg, info_var->inst_offset, 8);
val = ((offset) * sizeof (guint8*)) + MONO_STRUCT_OFFSET (SeqPointInfo, bp_addrs);
- /* Load the info->bp_addrs [offset], which is either a valid address or the address of a trigger page */
+ /* Load the info->bp_addrs [offset], which is either NULL or the address of the breakpoint trampoline */
amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, val, 8);
- amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, 8);
+ amd64_test_reg_reg (code, AMD64_R11, AMD64_R11);
+ label = code;
+ amd64_branch8 (code, X86_CC_Z, 0, FALSE);
+ /* Call the trampoline */
+ amd64_call_reg (code, AMD64_R11);
+ amd64_patch (label, code);
} else {
/*
* A placeholder for a possible breakpoint inserted by
amd64_shift_reg (code, X86_SAR, ins->dreg);
break;
case OP_SHR_IMM:
- g_assert (amd64_is_imm32 (ins->inst_imm));
- amd64_shift_reg_imm_size (code, X86_SAR, ins->dreg, ins->inst_imm, 4);
- break;
case OP_LSHR_IMM:
g_assert (amd64_is_imm32 (ins->inst_imm));
amd64_shift_reg_imm (code, X86_SAR, ins->dreg, ins->inst_imm);
amd64_shift_reg (code, X86_SHR, ins->dreg);
break;
case OP_SHL_IMM:
- g_assert (amd64_is_imm32 (ins->inst_imm));
- amd64_shift_reg_imm_size (code, X86_SHL, ins->dreg, ins->inst_imm, 4);
- break;
case OP_LSHL_IMM:
g_assert (amd64_is_imm32 (ins->inst_imm));
amd64_shift_reg_imm (code, X86_SHL, ins->dreg, ins->inst_imm);
amd64_ret (code);
break;
}
-
+ case OP_GET_EX_OBJ:
+ if (ins->dreg != AMD64_RAX)
+ amd64_mov_reg_reg (code, ins->dreg, AMD64_RAX, sizeof (gpointer));
+ break;
case OP_LABEL:
ins->inst_c0 = code - cfg->native_code;
break;
MONO_VARINFO (cfg, ins->inst_c0)->live_range_end = code - cfg->native_code;
break;
}
- case OP_NACL_GC_SAFE_POINT: {
-#if defined(__native_client_codegen__) && defined(__native_client_gc__)
- if (cfg->compile_aot)
- code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, (gpointer)mono_nacl_gc, TRUE);
- else {
- guint8 *br [1];
+ case OP_GC_SAFE_POINT: {
+ gpointer polling_func = NULL;
+ int compare_val = 0;
+ guint8 *br [1];
- amd64_mov_reg_imm_size (code, AMD64_R11, (gpointer)&__nacl_thread_suspension_needed, 4);
- amd64_test_membase_imm_size (code, AMD64_R11, 0, 0xFFFFFFFF, 4);
- br[0] = code; x86_branch8 (code, X86_CC_EQ, 0, FALSE);
- code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, (gpointer)mono_nacl_gc, TRUE);
- amd64_patch (br[0], code);
- }
+#if defined (USE_COOP_GC)
+ polling_func = (gpointer)mono_threads_state_poll;
+ compare_val = 1;
+#elif defined(__native_client_codegen__) && defined(__native_client_gc__)
+ polling_func = (gpointer)mono_nacl_gc;
+ compare_val = 0xFFFFFFFF;
#endif
+ if (!polling_func)
+ break;
+
+ amd64_test_membase_imm_size (code, ins->sreg1, 0, compare_val, 4);
+ br[0] = code; x86_branch8 (code, X86_CC_EQ, 0, FALSE);
+ code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, polling_func, TRUE);
+ amd64_patch (br[0], code);
break;
}
+
case OP_GC_LIVENESS_DEF:
case OP_GC_LIVENESS_USE:
case OP_GC_PARAM_SLOT_LIVENESS_DEF:
mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
mono_emit_unwind_op_offset (cfg, code, AMD64_RBP, - cfa_offset);
async_exc_point (code);
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
mono_arch_unwindinfo_add_push_nonvol (&cfg->arch.unwindinfo, cfg->native_code, code, AMD64_RBP);
#endif
/* These are handled automatically by the stack marking code */
amd64_mov_reg_reg (code, AMD64_RBP, AMD64_RSP, sizeof(mgreg_t));
mono_emit_unwind_op_def_cfa_reg (cfg, code, AMD64_RBP);
async_exc_point (code);
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
mono_arch_unwindinfo_add_set_fpreg (&cfg->arch.unwindinfo, cfg->native_code, code, AMD64_RBP);
#endif
}
/* Allocate stack frame */
if (alloc_size) {
/* See mono_emit_stack_alloc */
-#if defined(HOST_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK)
+#if defined(TARGET_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK)
guint32 remaining_size = alloc_size;
/*FIXME handle unbounded code expansion, we should use a loop in case of more than X interactions*/
guint32 required_code_size = ((remaining_size / 0x1000) + 1) * 10; /*10 is the max size of amd64_alu_reg_imm + amd64_test_membase_reg*/
mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
}
async_exc_point (code);
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
if (cfg->arch.omit_fp)
mono_arch_unwindinfo_add_alloc_stack (&cfg->arch.unwindinfo, cfg->native_code, code, 0x1000);
#endif
mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
async_exc_point (code);
}
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
if (cfg->arch.omit_fp)
mono_arch_unwindinfo_add_alloc_stack (&cfg->arch.unwindinfo, cfg->native_code, code, remaining_size);
#endif
}
}
- if (cfg->gen_seq_points_debug_data) {
+ if (cfg->gen_sdb_seq_points) {
MonoInst *info_var = cfg->arch.seq_point_info_var;
/* Initialize seq_point_info_var */
amd64_mov_membase_reg (code, info_var->inst_basereg, info_var->inst_offset, AMD64_R11, 8);
}
- /* Initialize ss_trigger_page_var */
- ins = cfg->arch.ss_trigger_page_var;
-
- g_assert (ins->opcode == OP_REGOFFSET);
-
if (cfg->compile_aot) {
+ /* Initialize ss_tramp_var */
+ ins = cfg->arch.ss_tramp_var;
+ g_assert (ins->opcode == OP_REGOFFSET);
+
amd64_mov_reg_membase (code, AMD64_R11, info_var->inst_basereg, info_var->inst_offset, 8);
- amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, MONO_STRUCT_OFFSET (SeqPointInfo, ss_trigger_page), 8);
+ amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, MONO_STRUCT_OFFSET (SeqPointInfo, ss_tramp_addr), 8);
+ amd64_mov_membase_reg (code, ins->inst_basereg, ins->inst_offset, AMD64_R11, 8);
} else {
+ /* Initialize ss_trigger_page_var */
+ ins = cfg->arch.ss_trigger_page_var;
+
+ g_assert (ins->opcode == OP_REGOFFSET);
+
amd64_mov_reg_imm (code, AMD64_R11, (guint64)ss_trigger_page);
+ amd64_mov_membase_reg (code, ins->inst_basereg, ins->inst_offset, AMD64_R11, 8);
}
- amd64_mov_membase_reg (code, ins->inst_basereg, ins->inst_offset, AMD64_R11, 8);
}
cfg->code_len = code - cfg->native_code;
/* We have to shift the arguments left */
amd64_mov_reg_reg (code, AMD64_RAX, AMD64_ARG_REG1, 8);
for (i = 0; i < param_count; ++i) {
-#ifdef HOST_WIN32
+#ifdef TARGET_WIN32
if (i < 3)
amd64_mov_reg_reg (code, param_regs [i], param_regs [i + 1], 8);
else
}
nacl_global_codeman_validate (&start, 64, &code);
+ mono_arch_flush_icache (start, code - start);
if (code_len)
*code_len = code - start;
SeqPointInfo *info = mono_arch_get_seq_point_info (mono_domain_get (), ji->code_start);
g_assert (info->bp_addrs [native_offset] == 0);
- info->bp_addrs [native_offset] = bp_trigger_page;
+ info->bp_addrs [native_offset] = mini_get_breakpoint_trampoline ();
} else {
/*
* In production, we will use int3 (has to fix the size in the md
guint32 native_offset = ip - (guint8*)ji->code_start;
SeqPointInfo *info = mono_arch_get_seq_point_info (mono_domain_get (), ji->code_start);
- g_assert (info->bp_addrs [native_offset] == 0);
- info->bp_addrs [native_offset] = info;
+ info->bp_addrs [native_offset] = NULL;
} else {
for (i = 0; i < breakpoint_size; ++i)
x86_nop (code);
mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
{
if (ji->from_aot) {
- /* amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, 8) */
- MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + 3);
+ /* The breakpoint instruction is a call */
} else {
MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + breakpoint_fault_size);
}
mono_arch_start_single_stepping (void)
{
mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
+ ss_trampoline = mini_get_single_step_trampoline ();
}
/*
mono_arch_stop_single_stepping (void)
{
mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
+ ss_trampoline = NULL;
}
/*
{
SeqPointInfo *info;
MonoJitInfo *ji;
- int i;
// FIXME: Add a free function
// FIXME: Optimize the size
info = g_malloc0 (sizeof (SeqPointInfo) + (ji->code_size * sizeof (gpointer)));
- info->ss_trigger_page = ss_trigger_page;
- info->bp_trigger_page = bp_trigger_page;
- /* Initialize to a valid address */
- for (i = 0; i < ji->code_size; ++i)
- info->bp_addrs [i] = info;
+ info->ss_tramp_addr = &ss_trampoline;
mono_domain_lock (domain);
g_hash_table_insert (domain_jit_info (domain)->arch_seq_points,