1 /*
2  * Licensed to the .NET Foundation under one or more agreements.
3  * The .NET Foundation licenses this file to you under the MIT license.
4  * See the LICENSE file in the project root for more information.
5  */
6 
7 #ifndef __MONO_PROFILER_PRIVATE_H__
8 #define __MONO_PROFILER_PRIVATE_H__
9 
10 #include <mono/metadata/class-internals.h>
11 #define MONO_PROFILER_UNSTABLE_GC_ROOTS
12 #include <mono/metadata/profiler.h>
13 #include <mono/utils/mono-context.h>
14 #include <mono/utils/mono-os-mutex.h>
15 #include <mono/utils/mono-os-semaphore.h>
16 
17 struct _MonoProfilerDesc {
18 	MonoProfilerHandle next;
19 	MonoProfiler *prof;
20 	volatile gpointer cleanup_callback;
21 	volatile gpointer coverage_filter;
22 	volatile gpointer call_instrumentation_filter;
23 
24 #define _MONO_PROFILER_EVENT(name) \
25 	volatile gpointer name ## _cb;
26 #define MONO_PROFILER_EVENT_0(name, type) \
27 	_MONO_PROFILER_EVENT(name)
28 #define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
29 	_MONO_PROFILER_EVENT(name)
30 #define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
31 	_MONO_PROFILER_EVENT(name)
32 #define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
33 	_MONO_PROFILER_EVENT(name)
34 #define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
35 	_MONO_PROFILER_EVENT(name)
36 #include <mono/metadata/profiler-events.h>
37 #undef MONO_PROFILER_EVENT_0
38 #undef MONO_PROFILER_EVENT_1
39 #undef MONO_PROFILER_EVENT_2
40 #undef MONO_PROFILER_EVENT_3
41 #undef MONO_PROFILER_EVENT_4
42 #undef _MONO_PROFILER_EVENT
43 };
44 
45 typedef struct {
46 	gboolean startup_done;
47 
48 	MonoProfilerHandle profilers;
49 
50 	gboolean code_coverage;
51 	mono_mutex_t coverage_mutex;
52 	GHashTable *coverage_hash;
53 
54 	MonoProfilerHandle sampling_owner;
55 	MonoSemType sampling_semaphore;
56 	MonoProfilerSampleMode sample_mode;
57 	guint32 sample_freq;
58 
59 	gboolean allocations;
60 
61 	gboolean call_contexts;
62 	void (*context_enable) (void);
63 	gpointer (*context_get_this) (MonoProfilerCallContext *);
64 	gpointer (*context_get_argument) (MonoProfilerCallContext *, guint32);
65 	gpointer (*context_get_local) (MonoProfilerCallContext *, guint32);
66 	gpointer (*context_get_result) (MonoProfilerCallContext *);
67 	void (*context_free_buffer) (gpointer);
68 
69 #define _MONO_PROFILER_EVENT(name) \
70 	volatile gint32 name ## _count;
71 #define MONO_PROFILER_EVENT_0(name, type) \
72 	_MONO_PROFILER_EVENT(name)
73 #define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
74 	_MONO_PROFILER_EVENT(name)
75 #define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
76 	_MONO_PROFILER_EVENT(name)
77 #define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
78 	_MONO_PROFILER_EVENT(name)
79 #define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
80 	_MONO_PROFILER_EVENT(name)
81 #include <mono/metadata/profiler-events.h>
82 #undef MONO_PROFILER_EVENT_0
83 #undef MONO_PROFILER_EVENT_1
84 #undef MONO_PROFILER_EVENT_2
85 #undef MONO_PROFILER_EVENT_3
86 #undef MONO_PROFILER_EVENT_4
87 #undef _MONO_PROFILER_EVENT
88 } MonoProfilerState;
89 
90 extern MonoProfilerState mono_profiler_state;
91 
92 typedef struct {
93 	guint32 entries;
94 	struct {
95 		guchar *cil_code;
96 		guint32 count;
97 	} data [1];
98 } MonoProfilerCoverageInfo;
99 
100 void mono_profiler_started (void);
101 void mono_profiler_cleanup (void);
102 
103 static inline gboolean
mono_profiler_installed(void)104 mono_profiler_installed (void)
105 {
106 	return !!mono_profiler_state.profilers;
107 }
108 
109 MonoProfilerCoverageInfo *mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries);
110 
111 struct _MonoProfilerCallContext {
112 	/*
113 	 * Must be the first field (the JIT relies on it). Only filled out if this
114 	 * is a JIT frame; otherwise, zeroed.
115 	 */
116 	MonoContext context;
117 	/*
118 	 * A non-NULL MonoInterpFrameHandle if this is an interpreter frame.
119 	 */
120 	gpointer interp_frame;
121 	MonoMethod *method;
122 	/*
123 	 * Points to the return value for an epilogue context. For a prologue, this
124 	 * is set to NULL.
125 	 */
126 	gpointer return_value;
127 };
128 
129 MonoProfilerCallInstrumentationFlags mono_profiler_get_call_instrumentation_flags (MonoMethod *method);
130 
131 gboolean mono_profiler_sampling_enabled (void);
132 void mono_profiler_sampling_thread_post (void);
133 void mono_profiler_sampling_thread_wait (void);
134 
135 static inline gboolean
mono_profiler_allocations_enabled(void)136 mono_profiler_allocations_enabled (void)
137 {
138 	return mono_profiler_state.allocations;
139 }
140 
141 #define _MONO_PROFILER_EVENT(name, ...) \
142 	ICALL_DECL_EXPORT void mono_profiler_raise_ ## name (__VA_ARGS__);
143 #define MONO_PROFILER_EVENT_0(name, type) \
144 	_MONO_PROFILER_EVENT(name, void)
145 #define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
146 	_MONO_PROFILER_EVENT(name, arg1_type arg1_name)
147 #define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
148 	_MONO_PROFILER_EVENT(name, arg1_type arg1_name, arg2_type arg2_name)
149 #define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
150 	_MONO_PROFILER_EVENT(name, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name)
151 #define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
152 	_MONO_PROFILER_EVENT(name, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name, arg4_type arg4_name)
153 #include <mono/metadata/profiler-events.h>
154 #undef MONO_PROFILER_EVENT_0
155 #undef MONO_PROFILER_EVENT_1
156 #undef MONO_PROFILER_EVENT_2
157 #undef MONO_PROFILER_EVENT_3
158 #undef MONO_PROFILER_EVENT_4
159 #undef _MONO_PROFILER_EVENT
160 
161 /* These are the macros the rest of the runtime should use. */
162 
163 #define MONO_PROFILER_ENABLED(name) \
164 	G_UNLIKELY (mono_profiler_state.name ## _count)
165 
166 #define MONO_PROFILER_RAISE(name, args) \
167 	do { \
168 		if (MONO_PROFILER_ENABLED (name)) \
169 			mono_profiler_raise_ ## name args; \
170 	} while (0)
171 
172 #endif // __MONO_PROFILER_PRIVATE_H__
173