[profiler] log profiler: limit method instrumentation to selected methods (#5517)
[mono.git] / mono / mini / mini.h
index e86b807375f7a0605c056cec4f41e56d24a59388..42a0356ef839cfc17c5bf341d1b088f247898055 100644 (file)
 #include "mono/metadata/marshal.h"
 #include "mono/metadata/security-manager.h"
 #include "mono/metadata/exception.h"
-
-#ifdef __native_client_codegen__
-#include <nacl/nacl_dyncode.h>
-#endif
-
+#include "mono/metadata/callspec.h"
 
 /*
  * The mini code should not have any compile time dependencies on the GC being used, so the same object file from mini/
 #endif
 
 /* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION 140
+#define MONO_AOT_FILE_VERSION 141
 
 //TODO: This is x86/amd64 specific.
 #define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6))
 
 /* Remap printf to g_print (we use a mix of these in the mini code) */
-#ifdef PLATFORM_ANDROID
+#ifdef HOST_ANDROID
 #define printf g_print
 #endif
 
@@ -542,9 +538,8 @@ typedef struct MonoMethodVar MonoMethodVar;
 typedef struct MonoBasicBlock MonoBasicBlock;
 typedef struct MonoLMF MonoLMF;
 typedef struct MonoSpillInfo MonoSpillInfo;
-typedef struct MonoTraceSpec MonoTraceSpec;
 
-extern MonoTraceSpec *mono_jit_trace_calls;
+extern MonoCallSpec *mono_jit_trace_calls;
 extern gboolean mono_break_on_exc;
 extern int mono_exc_esp_offset;
 extern gboolean mono_compile_aot;
@@ -557,7 +552,7 @@ extern MonoMethodDesc *mono_break_at_bb_method;
 extern int mono_break_at_bb_bb_num;
 extern gboolean mono_verify_all;
 extern gboolean mono_do_x86_stack_align;
-extern const char *mono_build_date;
+extern MONO_API const char *mono_build_date;
 extern gboolean mono_do_signal_chaining;
 extern gboolean mono_do_crash_chaining;
 extern MONO_API gboolean mono_use_llvm;
@@ -595,6 +590,20 @@ extern const gint8 ins_sreg_counts [];
 
 #define mono_bb_first_ins(bb) (bb)->code
 
+/*
+ * Iterate through all used registers in the instruction.
+ * Relies on the existing order of the MONO_INST enum: MONO_INST_{DREG,SREG1,SREG2,SREG3,LEN}
+ * INS is the instruction, IDX is the register index, REG is the pointer to a register.
+ */
+#define MONO_INS_FOR_EACH_REG(ins, idx, reg) for ((idx) = INS_INFO ((ins)->opcode)[MONO_INST_DEST] != ' ' ? MONO_INST_DEST : \
+                                                         (mono_inst_get_num_src_registers (ins) ? MONO_INST_SRC1 : MONO_INST_LEN); \
+                                                 (reg) = (idx) == MONO_INST_DEST ? &(ins)->dreg : \
+                                                         ((idx) == MONO_INST_SRC1 ? &(ins)->sreg1 : \
+                                                          ((idx) == MONO_INST_SRC2 ? &(ins)->sreg2 : \
+                                                           ((idx) == MONO_INST_SRC3 ? &(ins)->sreg3 : NULL))), \
+                                                         idx < MONO_INST_LEN; \
+                                                 (idx) = (idx) > mono_inst_get_num_src_registers (ins) + (INS_INFO ((ins)->opcode)[MONO_INST_DEST] != ' ') ? MONO_INST_LEN : (idx) + 1)
+
 struct MonoSpillInfo {
        int offset;
 };
@@ -746,6 +755,9 @@ struct MonoBasicBlock {
        /* List of call sites in this bblock sorted by pc_offset */
        GSList *gc_callsites;
 
+       /* If this is not null, the basic block is a try hole for this clause */
+       MonoExceptionClause *clause_hole;
+
        /*
         * The region encodes whether the basic block is inside
         * a finally, catch, filter or none of these.
@@ -1158,10 +1170,6 @@ typedef struct {
        MonoContext     ex_ctx;
        ResumeState resume_state;
 
-       /*Variabled use to implement handler blocks (finally/catch/etc) guards during interruption*/
-       /* handler block return address */
-       gpointer handler_block_return_address;
-
        /* handler block been guarded. It's safe to store this even for dynamic methods since there
        is an activation on stack making sure it will remain alive.*/
        MonoJitExceptionInfo *handler_block;
@@ -1203,11 +1211,16 @@ typedef struct {
         */
        gpointer abort_exc_stack_threshold;
 
-
        /*
         * List of methods being JIT'd in the current thread.
         */
        int active_jit_methods;
+
+       gpointer interp_context;
+
+#if defined(TARGET_WIN32)
+       MonoContext stack_restore_ctx;
+#endif
 } MonoJitTlsData;
 
 /*
@@ -1476,7 +1489,6 @@ typedef enum {
        MONO_TRAMPOLINE_RESTORE_STACK_PROT,
        MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING,
        MONO_TRAMPOLINE_VCALL,
-       MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD,
        MONO_TRAMPOLINE_NUM
 } MonoTrampolineType;
 
@@ -1487,7 +1499,7 @@ typedef enum {
 
 /* These trampolines receive an argument directly in a register */
 #define MONO_TRAMPOLINE_TYPE_HAS_ARG(t)                \
-       ((t) == MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD)
+       (FALSE)
 
 /* optimization flags */
 #define OPTFLAG(id,shift,name,descr) MONO_OPT_ ## id = 1 << shift,
@@ -1625,10 +1637,18 @@ typedef struct {
 
        /* A hashtable of region ID-> SP var mappings */
        /* An SP var is a place to store the stack pointer (used by handlers)*/
+       /*
+        * FIXME We can potentially get rid of this, since it was mainly used
+        * for hijacking return address for handler.
+        */
        GHashTable      *spvars;
 
-       /* A hashtable of region ID -> EX var mappings */
-       /* An EX var stores the exception object passed to catch/filter blocks */
+       /*
+        * A hashtable of region ID -> EX var mappings
+        * An EX var stores the exception object passed to catch/filter blocks
+        * For finally blocks, it is set to TRUE if we should throw an abort
+        * once the execution of the finally block is over.
+        */
        GHashTable      *exvars;
 
        GList           *ldstr_list; /* used by AOT */
@@ -1664,11 +1684,6 @@ typedef struct {
        MonoInst *stack_inbalance_var;
 
        unsigned char   *cil_start;
-#ifdef __native_client_codegen__
-       /* this alloc is not aligned, native_code */
-       /* is the 32-byte aligned version of this */
-       unsigned char   *native_code_alloc;
-#endif
        unsigned char   *native_code;
        guint            code_size;
        guint            code_len;
@@ -1677,7 +1692,6 @@ typedef struct {
        guint            epilog_end;
        regmask_t        used_int_regs;
        guint32          opt;
-       guint32          prof_options;
        guint32          flags;
        guint32          comp_done;
        guint32          verbose_level;
@@ -1756,7 +1770,7 @@ typedef struct {
        gpointer         debug_info;
        guint32          lmf_offset;
     guint16          *intvars;
-       MonoProfileCoverageInfo *coverage_info;
+       MonoProfilerCoverageInfo *coverage_info;
        GHashTable       *token_info_hash;
        MonoCompileArch  arch;
        guint32          inline_depth;
@@ -1906,8 +1920,16 @@ typedef struct {
        int stat_inlineable_methods;
        int stat_inlined_methods;
        int stat_code_reallocs;
+
+       MonoProfilerCallInstrumentationFlags prof_flags;
 } MonoCompile;
 
+#define MONO_CFG_PROFILE(cfg, flag) \
+       G_UNLIKELY ((cfg)->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_ ## flag)
+
+#define MONO_CFG_PROFILE_CALL_CONTEXT(cfg) \
+       (MONO_CFG_PROFILE (cfg, ENTER_CONTEXT) || MONO_CFG_PROFILE (cfg, LEAVE_CONTEXT))
+
 typedef enum {
        MONO_CFG_HAS_ALLOCA = 1 << 0,
        MONO_CFG_HAS_CALLS  = 1 << 1,
@@ -1945,49 +1967,49 @@ typedef struct {
        gint32 loads_eliminated;
        gint32 stores_eliminated;
        gint32 optimized_divisions;
-       int methods_with_llvm;
-       int methods_without_llvm;
+       gint32 methods_with_llvm;
+       gint32 methods_without_llvm;
        char *max_ratio_method;
        char *biggest_method;
-       double jit_method_to_ir;
-       double jit_liveness_handle_exception_clauses;
-       double jit_handle_out_of_line_bblock;
-       double jit_decompose_long_opts;
-       double jit_decompose_typechecks;
-       double jit_local_cprop;
-       double jit_local_emulate_ops;
-       double jit_optimize_branches;
-       double jit_handle_global_vregs;
-       double jit_local_deadce;
-       double jit_local_alias_analysis;
-       double jit_if_conversion;
-       double jit_bb_ordering;
-       double jit_compile_dominator_info;
-       double jit_compute_natural_loops;
-       double jit_insert_safepoints;
-       double jit_ssa_compute;
-       double jit_ssa_cprop;
-       double jit_ssa_deadce;
-       double jit_perform_abc_removal;
-       double jit_ssa_remove;
-       double jit_local_cprop2;
-       double jit_handle_global_vregs2;
-       double jit_local_deadce2;
-       double jit_optimize_branches2;
-       double jit_decompose_vtype_opts;
-       double jit_decompose_array_access_opts;
-       double jit_liveness_handle_exception_clauses2;
-       double jit_analyze_liveness;
-       double jit_linear_scan;
-       double jit_arch_allocate_vars;
-       double jit_spill_global_vars;
-       double jit_local_cprop3;
-       double jit_local_deadce3;
-       double jit_codegen;
-       double jit_create_jit_info;
-       double jit_gc_create_gc_map;
-       double jit_save_seq_point_info;
-       double jit_time;
+       gdouble jit_method_to_ir;
+       gdouble jit_liveness_handle_exception_clauses;
+       gdouble jit_handle_out_of_line_bblock;
+       gdouble jit_decompose_long_opts;
+       gdouble jit_decompose_typechecks;
+       gdouble jit_local_cprop;
+       gdouble jit_local_emulate_ops;
+       gdouble jit_optimize_branches;
+       gdouble jit_handle_global_vregs;
+       gdouble jit_local_deadce;
+       gdouble jit_local_alias_analysis;
+       gdouble jit_if_conversion;
+       gdouble jit_bb_ordering;
+       gdouble jit_compile_dominator_info;
+       gdouble jit_compute_natural_loops;
+       gdouble jit_insert_safepoints;
+       gdouble jit_ssa_compute;
+       gdouble jit_ssa_cprop;
+       gdouble jit_ssa_deadce;
+       gdouble jit_perform_abc_removal;
+       gdouble jit_ssa_remove;
+       gdouble jit_local_cprop2;
+       gdouble jit_handle_global_vregs2;
+       gdouble jit_local_deadce2;
+       gdouble jit_optimize_branches2;
+       gdouble jit_decompose_vtype_opts;
+       gdouble jit_decompose_array_access_opts;
+       gdouble jit_liveness_handle_exception_clauses2;
+       gdouble jit_analyze_liveness;
+       gdouble jit_linear_scan;
+       gdouble jit_arch_allocate_vars;
+       gdouble jit_spill_global_vars;
+       gdouble jit_local_cprop3;
+       gdouble jit_local_deadce3;
+       gdouble jit_codegen;
+       gdouble jit_create_jit_info;
+       gdouble jit_gc_create_gc_map;
+       gdouble jit_save_seq_point_info;
+       gdouble jit_time;
        gboolean enabled;
 } MonoJitStats;
 
@@ -2342,7 +2364,18 @@ MonoDomain* mini_init                      (const char *filename, const char *ru
 void        mini_cleanup                   (MonoDomain *domain);
 MONO_API MonoDebugOptions *mini_get_debug_options   (void);
 MONO_API gboolean    mini_parse_debug_option (const char *option);
-void        mini_profiler_enable_with_options (const char *profile_options);
+
+/* profiler support */
+void        mini_add_profiler_argument (const char *desc);
+void        mini_profiler_emit_enter (MonoCompile *cfg);
+void        mini_profiler_emit_leave (MonoCompile *cfg, MonoInst *ret);
+void        mini_profiler_emit_tail_call (MonoCompile *cfg, MonoMethod *target);
+void        mini_profiler_context_enable (void);
+gpointer    mini_profiler_context_get_this (MonoProfilerCallContext *ctx);
+gpointer    mini_profiler_context_get_argument (MonoProfilerCallContext *ctx, guint32 pos);
+gpointer    mini_profiler_context_get_local (MonoProfilerCallContext *ctx, guint32 pos);
+gpointer    mini_profiler_context_get_result (MonoProfilerCallContext *ctx);
+void        mini_profiler_context_free_buffer (gpointer buffer);
 
 /* graph dumping */
 void mono_cfg_dump_create_context (MonoCompile *cfg);
@@ -2467,6 +2500,7 @@ MonoInst* mono_emit_jit_icall_by_info (MonoCompile *cfg, int il_offset, MonoJitI
 MonoInst* mono_emit_method_call (MonoCompile *cfg, MonoMethod *method, MonoInst **args, MonoInst *this_ins);
 void      mono_create_helper_signatures (void);
 MonoInst* mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature *sig, MonoInst **args);
+gboolean  mini_should_insert_breakpoint (MonoMethod *method);
 
 gboolean  mini_class_is_system_array (MonoClass *klass);
 MonoMethodSignature *mono_get_element_address_signature (int arity);
@@ -2484,12 +2518,6 @@ void      mono_liveness_handle_exception_clauses (MonoCompile *cfg);
 /* Native Client functions */
 gpointer mono_realloc_native_code(MonoCompile *cfg);
 
-#if defined(__native_client__) || defined(__native_client_codegen__)
-extern volatile int __nacl_thread_suspension_needed;
-void __nacl_suspend_thread_if_needed(void);
-void mono_nacl_gc(void);
-#endif
-
 extern MonoDebugOptions debug_options;
 
 static inline MonoMethod*
@@ -2638,11 +2666,11 @@ MonoInst*         mini_emit_get_gsharedvt_info_klass (MonoCompile *cfg, MonoClas
 MonoInst*         mini_emit_calli (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args, MonoInst *addr, MonoInst *imt_arg, MonoInst *rgctx_arg);
 MonoInst*         mini_emit_memory_barrier (MonoCompile *cfg, int kind);
 void              mini_emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value);
-gboolean          mini_emit_wb_aware_memcpy (MonoCompile *cfg, MonoClass *klass, MonoInst *iargs[4], int size, int align);
 MonoInst*         mini_emit_memory_load (MonoCompile *cfg, MonoType *type, MonoInst *src, int offset, int ins_flag);
 void              mini_emit_memory_store (MonoCompile *cfg, MonoType *type, MonoInst *dest, MonoInst *value, int ins_flag);
 void              mini_emit_memory_copy_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoInst *size, int ins_flag);
 void              mini_emit_memory_init_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *value, MonoInst *size, int ins_flag);
+void              mini_emit_memory_copy (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native, int ins_flag);
 
 MonoMethod*       mini_get_memcpy_method (void);
 MonoMethod*       mini_get_memset_method (void);
@@ -2750,13 +2778,13 @@ void      mono_arch_free_jit_tls_data           (MonoJitTlsData *tls);
 void      mono_arch_fill_argument_info          (MonoCompile *cfg);
 void      mono_arch_allocate_vars               (MonoCompile *m);
 int       mono_arch_get_argument_info           (MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info);
-gboolean  mono_arch_print_tree                         (MonoInst *tree, int arity);
 void      mono_arch_emit_call                   (MonoCompile *cfg, MonoCallInst *call);
 void      mono_arch_emit_outarg_vt              (MonoCompile *cfg, MonoInst *ins, MonoInst *src);
 void      mono_arch_emit_setret                 (MonoCompile *cfg, MonoMethod *method, MonoInst *val);
 MonoDynCallInfo *mono_arch_dyn_call_prepare     (MonoMethodSignature *sig);
 void      mono_arch_dyn_call_free               (MonoDynCallInfo *info);
-void      mono_arch_start_dyn_call              (MonoDynCallInfo *info, gpointer **args, guint8 *ret, guint8 *buf, int buf_len);
+int       mono_arch_dyn_call_get_buf_size       (MonoDynCallInfo *info);
+void      mono_arch_start_dyn_call              (MonoDynCallInfo *info, gpointer **args, guint8 *ret, guint8 *buf);
 void      mono_arch_finish_dyn_call             (MonoDynCallInfo *info, guint8 *buf);
 MonoInst *mono_arch_emit_inst_for_method        (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args);
 void      mono_arch_decompose_opts              (MonoCompile *cfg, MonoInst *ins);
@@ -2798,6 +2826,9 @@ gboolean  mono_arch_is_breakpoint_event         (void *info, void *sigctx);
 void     mono_arch_skip_breakpoint              (MonoContext *ctx, MonoJitInfo *ji);
 void     mono_arch_skip_single_step             (MonoContext *ctx);
 gpointer mono_arch_get_seq_point_info           (MonoDomain *domain, guint8 *code);
+#endif
+
+#ifdef MONO_ARCH_HAVE_INIT_LMF_EXT
 void     mono_arch_init_lmf_ext                 (MonoLMFExt *ext, gpointer prev_lmf);
 #endif
 
@@ -2851,12 +2882,6 @@ guint32 mono_arch_get_plt_info_offset           (guint8 *plt_entry, mgreg_t *reg
 GSList *mono_arch_get_trampolines               (gboolean aot);
 gpointer mono_arch_get_enter_icall_trampoline   (MonoTrampInfo **info);
 
-/* Handle block guard */
-gpointer mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause, MonoContext *ctx, gpointer new_value);
-gpointer mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot);
-gpointer mono_create_handler_block_trampoline (void);
-gboolean mono_install_handler_block_guard (MonoThreadUnwindState *ctx);
-
 /*New interruption machinery */
 void
 mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data);
@@ -2906,6 +2931,7 @@ void     mono_llvm_clear_exception              (void);
 MonoObject *mono_llvm_load_exception            (void);
 void     mono_llvm_reset_exception              (void);
 void     mono_llvm_raise_exception              (MonoException *e);
+void     mono_llvm_reraise_exception            (MonoException *e);
 gint32 mono_llvm_match_exception                (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end, gpointer rgctx, MonoObject *this_obj);
 
 gboolean
@@ -2966,8 +2992,7 @@ MONO_API void      mono_debugger_run_finally             (MonoContext *start_ctx
 MONO_API gboolean mono_breakpoint_clean_code (guint8 *method_start, guint8 *code, int offset, guint8 *buf, int size);
 
 /* Tracing */
-MonoTraceSpec *mono_trace_parse_options         (const char *options);
-void           mono_trace_set_assembly          (MonoAssembly *assembly);
+MonoCallSpec *mono_trace_set_options           (const char *options);
 gboolean       mono_trace_eval                  (MonoMethod *method);
 
 extern void
@@ -3107,7 +3132,7 @@ void mono_cfg_set_exception_invalid_program (MonoCompile *cfg, char *msg);
        }
 
 GTimer *mono_time_track_start (void);
-void mono_time_track_end (double *time, GTimer *timer);
+void mono_time_track_end (gdouble *time, GTimer *timer);
 
 void mono_update_jit_stats (MonoCompile *cfg);
 
@@ -3182,6 +3207,8 @@ MonoInst*   mono_emit_simd_field_load (MonoCompile *cfg, MonoClassField *field,
 guint32     mono_arch_cpu_enumerate_simd_versions (void);
 void        mono_simd_intrinsics_init (void);
 
+gboolean    mono_class_is_magic_int (MonoClass *klass);
+gboolean    mono_class_is_magic_float (MonoClass *klass);
 MonoInst*   mono_emit_native_types_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args);
 MonoType*   mini_native_type_replace_type (MonoType *type) MONO_LLVM_INTERNAL;
 
@@ -3243,4 +3270,31 @@ gboolean MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal);
  */
 void mono_interruption_checkpoint_from_trampoline (void);
 
+
+#if defined (HOST_WASM)
+
+#define MONO_RETURN_ADDRESS_N(N) NULL
+#define MONO_RETURN_ADDRESS() MONO_RETURN_ADDRESS_N(0)
+
+
+#elif defined (__GNUC__)
+
+#define MONO_RETURN_ADDRESS_N(N) (__builtin_extract_return_addr (__builtin_return_address (N)))
+#define MONO_RETURN_ADDRESS() MONO_RETURN_ADDRESS_N(0)
+
+#elif defined(_MSC_VER)
+
+#include <intrin.h>
+#pragma intrinsic(_ReturnAddress)
+
+#define MONO_RETURN_ADDRESS() _ReturnAddress()
+#define MONO_RETURN_ADDRESS_N(N) NULL
+
+#else
+
+#error "Missing return address intrinsics implementation"
+
+#endif
+
+
 #endif /* __MONO_MINI_H__ */