[aot] Fix the name of the mono_gc_wbarrier_range_copy icall. FullAOT with direct calls requires it.
if ((cfg->method == method) && cfg->coverage_info) {
guint32 cil_offset = ip - header->code;
+ gpointer counter = &cfg->coverage_info->data [cil_offset].count;
cfg->coverage_info->data [cil_offset].cil_code = ip;
- /* TODO: Use an increment here */
-#if defined(TARGET_X86)
- MONO_INST_NEW (cfg, ins, OP_STORE_MEM_IMM);
- ins->inst_p0 = &(cfg->coverage_info->data [cil_offset].count);
- ins->inst_imm = 1;
- MONO_ADD_INS (cfg->cbb, ins);
-#else
- EMIT_NEW_PCONST (cfg, ins, &(cfg->coverage_info->data [cil_offset].count));
- MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, ins->dreg, 0, 1);
-#endif
+ if (mono_arch_opcode_supported (OP_ATOMIC_ADD_I4)) {
+ MonoInst *one_ins, *load_ins;
+
+ EMIT_NEW_PCONST (cfg, load_ins, counter);
+ EMIT_NEW_ICONST (cfg, one_ins, 1);
+ MONO_INST_NEW (cfg, ins, OP_ATOMIC_ADD_I4);
+ ins->dreg = mono_alloc_ireg (cfg);
+ ins->inst_basereg = load_ins->dreg;
+ ins->inst_offset = 0;
+ ins->sreg2 = one_ins->dreg;
+ ins->type = STACK_I4;
+ MONO_ADD_INS (cfg->cbb, ins);
+ } else {
+ EMIT_NEW_PCONST (cfg, ins, counter);
+ MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, ins->dreg, 0, 1);
+ }
}
if (cfg->verbose_level > 3)
static int i8_align;
static gpointer single_step_tramp, breakpoint_tramp;
-static gpointer get_tls_tramp;
/*
* The code generated for sequence points reads from this location, which is
return code;
}
+static guint8*
+emit_ldr_imm (guint8 *code, int dreg, int sreg, int imm)
+{
+ if (!arm_is_imm12 (imm)) {
+ g_assert (dreg != sreg);
+ code = emit_big_add (code, dreg, sreg, imm);
+ ARM_LDR_IMM (code, dreg, dreg, 0);
+ } else {
+ ARM_LDR_IMM (code, dreg, sreg, imm);
+ }
+ return code;
+}
+
/* If dreg == sreg, this clobbers IP */
static guint8*
emit_sub_imm (guint8 *code, int dreg, int sreg, int imm)
void
mono_arch_init (void)
{
- const char *cpu_arch;
+ char *cpu_arch;
#ifdef TARGET_WATCHOS
mini_get_debug_options ()->soft_breakpoints = TRUE;
* works. Most ARM devices have VFP units these days, so
* normally soft float code would not be exercised much.
*/
- const char *soft = g_getenv ("MONO_ARM_FORCE_SOFT_FLOAT");
+ char *soft = g_getenv ("MONO_ARM_FORCE_SOFT_FLOAT");
if (soft && !strncmp (soft, "1", 1))
arm_fpu = MONO_ARM_FPU_NONE;
if (cfg->compile_aot) {
g_assert (info_var);
g_assert (info_var->opcode == OP_REGOFFSET);
- g_assert (arm_is_imm12 (info_var->inst_offset));
}
if (!cfg->soft_breakpoints && !cfg->compile_aot) {
var = ss_method_var;
g_assert (var);
g_assert (var->opcode == OP_REGOFFSET);
- g_assert (arm_is_imm12 (var->inst_offset));
- ARM_LDR_IMM (code, dreg, var->inst_basereg, var->inst_offset);
-
+ code = emit_ldr_imm (code, dreg, var->inst_basereg, var->inst_offset);
/* Read the value and check whether it is non-zero. */
ARM_LDR_IMM (code, dreg, dreg, 0);
ARM_CMP_REG_IMM (code, dreg, 0, 0);
var = ss_trigger_page_var;
g_assert (var);
g_assert (var->opcode == OP_REGOFFSET);
- g_assert (arm_is_imm12 (var->inst_offset));
- ARM_LDR_IMM (code, dreg, var->inst_basereg, var->inst_offset);
+ code = emit_ldr_imm (code, dreg, var->inst_basereg, var->inst_offset);
} else {
ARM_LDR_IMM (code, dreg, ARMREG_PC, 0);
ARM_B (code, 0);
guint32 offset = code - cfg->native_code;
guint32 val;
- ARM_LDR_IMM (code, dreg, info_var->inst_basereg, info_var->inst_offset);
+ var = info_var;
+ code = emit_ldr_imm (code, dreg, var->inst_basereg, var->inst_offset);
/* Add the offset */
val = ((offset / 4) * sizeof (guint8*)) + MONO_STRUCT_OFFSET (SeqPointInfo, bp_addrs);
/* Load the info->bp_addrs [offset], which is either 0 or the address of a trigger page */
if (info_var) {
g_assert (info_var->opcode == OP_REGOFFSET);
- g_assert (arm_is_imm12 (info_var->inst_offset));
- ARM_LDR_IMM (code, dreg, info_var->inst_basereg, info_var->inst_offset);
+ code = emit_ldr_imm (code, dreg, info_var->inst_basereg, info_var->inst_offset);
/* Load the trigger page addr */
ARM_LDR_IMM (code, dreg, dreg, MONO_STRUCT_OFFSET (SeqPointInfo, ss_trigger_page));
ARM_STR_IMM (code, dreg, ss_trigger_page_var->inst_basereg, ss_trigger_page_var->inst_offset);
*
* type metadata format:
* type: TYPE_METADATA
- * exinfo: one of: TYPE_END_LOAD, TYPE_END_UNLOAD (optional for TYPE_THREAD and TYPE_DOMAIN)
+ * exinfo: one of: TYPE_END_LOAD, TYPE_END_UNLOAD (optional for TYPE_THREAD and TYPE_DOMAIN,
+ * doesn't occur for TYPE_CLASS)
* [mtype: byte] metadata type, one of: TYPE_CLASS, TYPE_IMAGE, TYPE_ASSEMBLY, TYPE_DOMAIN,
* TYPE_THREAD, TYPE_CONTEXT
* [pointer: sleb128] pointer of the metadata type depending on mtype
* exclusive lock, and we need those to arrive with a reasonably
* consistent frequency so that readers don't have to queue up too many
* events between sync points.
+ *
+ * The lock does not support recursion.
*/
static volatile gint32 buffer_lock_state;
static volatile gint32 buffer_lock_exclusive_intent;
-// Can be used recursively.
static void
buffer_lock (void)
{
InterlockedDecrement (&buffer_lock_state);
}
-// Cannot be used recursively.
static void
buffer_lock_excl (void)
{
g_assert (logbuffer->cursor <= logbuffer->buf_end && "Why are we writing past the buffer end?");
}
+// The reader lock must be held.
static void
register_method_local (MonoMethod *method, MonoJitInfo *ji)
{
info->ji = ji;
info->time = current_time ();
- buffer_lock ();
-
GPtrArray *arr = thread->methods ? thread->methods : (thread->methods = g_ptr_array_new ());
g_ptr_array_add (arr, info);
-
- buffer_unlock ();
}
}
g_free (name);
}
-static void
-class_unloaded (MonoProfiler *prof, MonoClass *klass)
-{
- char *name;
-
- if (InterlockedRead (&runtime_inited))
- name = mono_type_get_name (mono_class_get_type (klass));
- else
- name = type_name (klass);
-
- int nlen = strlen (name) + 1;
- MonoImage *image = mono_class_get_image (klass);
-
- ENTER_LOG (&class_unloads_ctr, logbuffer,
- EVENT_SIZE /* event */ +
- BYTE_SIZE /* type */ +
- LEB128_SIZE /* klass */ +
- LEB128_SIZE /* image */ +
- nlen /* name */
- );
-
- emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
- emit_byte (logbuffer, TYPE_CLASS);
- emit_ptr (logbuffer, klass);
- emit_ptr (logbuffer, image);
- memcpy (logbuffer->cursor, name, nlen);
- logbuffer->cursor += nlen;
-
- EXIT_LOG;
-
- if (runtime_inited)
- mono_free (name);
- else
- g_free (name);
-}
-
static void process_method_enter_coverage (MonoProfiler *prof, MonoMethod *method);
static void
if (result != MONO_PROFILE_OK)
return;
+ buffer_lock ();
+
register_method_local (method, ji);
+
+ buffer_unlock ();
}
static void
if (config.effective_mask & PROFLOG_CLASS_EVENTS) {
events |= MONO_PROFILE_CLASS_EVENTS;
- mono_profiler_install_class (NULL, class_loaded, class_unloaded, NULL);
+ mono_profiler_install_class (NULL, class_loaded, NULL, NULL);
}
if (config.effective_mask & PROFLOG_JIT_COMPILATION_EVENTS) {
changed address field in TYPE_SAMPLE_UBIN to be based on ptr_base
added an image pointer field to assembly load events
added an exception object field to TYPE_CLAUSE
+ class unload events no longer exist (they were never emitted)
*/
enum {
decode_uleb128 (p, &p); /* flags */
if (debug)
fprintf (outfile, "%s class %p (%s in %p) at %llu\n", load_str, (void*)(ptr_base + ptrdiff), p, (void*)(ptr_base + imptrdiff), (unsigned long long) time_base);
- if (subtype == TYPE_END_LOAD)
- add_class (ptr_base + ptrdiff, (char*)p);
+ add_class (ptr_base + ptrdiff, (char*)p);
while (*p) p++;
p++;
} else if (mtype == TYPE_IMAGE) {