* Include interpreter methods in EventPipe session rundown events.
* Fix build error.
uintptr_t thread_ip;
uint32_t payload_data;
bool async_frame;
+ bool safe_point_frame;
} EventPipeSampleProfileData;
// Rundown flags.
if (root_domain) {
uint64_t domain_id = (uint64_t)root_domain;
- // Iterate all functions in use (both JIT and AOT).
+ // Iterate all functions in use (JIT, AOT and Interpreter).
EventPipeFireMethodEventsData events_data;
events_data.domain = root_domain;
events_data.buffer_size = 1024 * sizeof(uint32_t);
events_data.buffer = g_new (uint8_t, events_data.buffer_size);
events_data.method_events_func = method_events_func;
mono_jit_info_table_foreach_internal (eventpipe_fire_method_events_func, &events_data);
+ if (mono_get_runtime_callbacks ()->is_interpreter_enabled())
+ mono_get_runtime_callbacks ()->interp_jit_info_foreach (eventpipe_fire_method_events_func, &events_data);
g_free (events_data.buffer);
// Iterate all assemblies in domain.
EP_ASSERT (frame != NULL);
EP_ASSERT (data != NULL);
- gboolean result = false;
EventPipeSampleProfileData *sample_data = (EventPipeSampleProfileData *)data;
if (sample_data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR) {
- if (frame->type == FRAME_TYPE_MANAGED_TO_NATIVE)
+ switch (frame->type) {
+ case FRAME_TYPE_MANAGED:
+ sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
+ break;
+ case FRAME_TYPE_MANAGED_TO_NATIVE:
+ case FRAME_TYPE_TRAMPOLINE:
sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
- else
+ break;
+ case FRAME_TYPE_INTERP:
+ if (frame->managed)
+ sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
+ else
+ sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
+ break;
+ case FRAME_TYPE_INTERP_TO_MANAGED:
+ case FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX:
+ break;
+ default:
sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
+ }
}
- bool safe_point_frame = false;
- result = eventpipe_walk_managed_stack_for_thread (frame, ctx, &sample_data->stack_contents, &sample_data->async_frame, &safe_point_frame);
- if (sample_data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL && safe_point_frame)
- sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
- return result;
+ return eventpipe_walk_managed_stack_for_thread (frame, ctx, &sample_data->stack_contents, &sample_data->async_frame, &sample_data->safe_point_frame);
}
static
data->thread_ip = (uintptr_t)MONO_CONTEXT_GET_IP (&thread_state->ctx);
data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR;
data->async_frame = FALSE;
+ data->safe_point_frame = FALSE;
ep_stack_contents_reset (&data->stack_contents);
- mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_sample_profiler_walk_managed_stack_for_thread_func, thread_state, MONO_UNWIND_SIGNAL_SAFE, data);
+ mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_sample_profiler_walk_managed_stack_for_thread_func, thread_state, MONO_UNWIND_SIGNAL_SAFE, data);
+ if (data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL && data->safe_point_frame)
+ data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
+
sampled_thread_count++;
}
}
/* Safely access System.Delegate from native code */
TYPED_HANDLE_DECL (MonoDelegate);
+
+typedef void (*InterpJitInfoFunc) (MonoJitInfo *ji, gpointer user_data);
+
/*
* Callbacks supplied by the runtime and called by the modules in metadata/
* This interface is easier to extend than adding a new function type +
void (*get_exception_stats)(guint32 *exception_count);
// Same as compile_method, but returns a MonoFtnDesc in llvmonly mode
gpointer (*get_ftnptr)(MonoMethod *method, MonoError *error);
+ void (*interp_jit_info_foreach)(InterpJitInfoFunc func, gpointer user_data);
} MonoRuntimeCallbacks;
typedef gboolean (*MonoInternalStackWalk) (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data);
MONO_EE_CALLBACK (void, invalidate_transformed, (void)) \
MONO_EE_CALLBACK (void, cleanup, (void)) \
MONO_EE_CALLBACK (void, mark_stack, (gpointer thread_info, GcScanFunc func, gpointer gc_data, gboolean precise)) \
+ MONO_EE_CALLBACK (void, jit_info_foreach, (InterpJitInfoFunc func, gpointer user_data)) \
typedef struct _MonoEECallbacks {
{
}
+static void
+stub_jit_info_foreach (InterpJitInfoFunc func, gpointer user_data)
+{
+}
+
#undef MONO_EE_CALLBACK
#define MONO_EE_CALLBACK(ret, name, sig) stub_ ## name,
const int opcount_threshold = 100000;
static void
-interp_add_imethod (gpointer method)
+interp_add_imethod (gpointer method, gpointer user_data)
{
InterpMethod *imethod = (InterpMethod*) method;
if (imethod->opcounts > opcount_threshold)
jit_mm_lock (jit_mm);
imethods = (InterpMethod**) malloc (jit_mm->interp_code_hash.num_entries * sizeof (InterpMethod*));
- mono_internal_hash_table_apply (&jit_mm->interp_code_hash, interp_add_imethod);
+ mono_internal_hash_table_apply (&jit_mm->interp_code_hash, interp_add_imethod, NULL);
jit_mm_unlock (jit_mm);
qsort (imethods, num_methods, sizeof (InterpMethod*), imethod_opcount_comparer);
}
static void
-invalidate_transform (gpointer imethod_)
+invalidate_transform (gpointer imethod_, gpointer user_data)
{
InterpMethod *imethod = (InterpMethod *) imethod_;
imethod->transformed = FALSE;
MonoJitMemoryManager *jit_mm = get_default_jit_mm ();
jit_mm_lock (jit_mm);
- mono_internal_hash_table_apply (&jit_mm->interp_code_hash, invalidate_transform);
+ mono_internal_hash_table_apply (&jit_mm->interp_code_hash, invalidate_transform, NULL);
jit_mm_unlock (jit_mm);
if (need_stw_restart)
mono_restart_world (MONO_THREAD_INFO_FLAGS_NO_GC);
}
+typedef struct {
+ InterpJitInfoFunc func;
+ gpointer user_data;
+} InterpJitInfoFuncUserData;
+
+static void
+interp_call_jit_info_func (gpointer imethod, gpointer user_data)
+{
+ InterpJitInfoFuncUserData *data = (InterpJitInfoFuncUserData *)user_data;
+ data->func (((InterpMethod *)imethod)->jinfo, data->user_data);
+}
+
+static void
+interp_jit_info_foreach (InterpJitInfoFunc func, gpointer user_data)
+{
+ InterpJitInfoFuncUserData data = {func, user_data};
+
+ // FIXME: Enumerate all memory managers
+ MonoJitMemoryManager *jit_mm = get_default_jit_mm ();
+
+ jit_mm_lock (jit_mm);
+ mono_internal_hash_table_apply (&jit_mm->interp_code_hash, interp_call_jit_info_func, &data);
+ jit_mm_unlock (jit_mm);
+}
+
static void
interp_cleanup (void)
{
static void register_icalls (void);
static void runtime_cleanup (MonoDomain *domain, gpointer user_data);
static void mini_invalidate_transformed_interp_methods (MonoAssemblyLoadContext *alc, uint32_t generation);
+static void mini_interp_jit_info_foreach(InterpJitInfoFunc func, gpointer user_data);
gboolean
mono_running_on_valgrind (void)
callbacks.install_state_summarizer = mini_register_sigterm_handler;
#endif
callbacks.metadata_update_published = mini_invalidate_transformed_interp_methods;
+ callbacks.interp_jit_info_foreach = mini_interp_jit_info_foreach;
callbacks.init_mem_manager = init_jit_mem_manager;
callbacks.free_mem_manager = free_jit_mem_manager;
}
#endif /* HOST_WIN32 */
-void
+static void
mini_invalidate_transformed_interp_methods (MonoAssemblyLoadContext *alc G_GNUC_UNUSED, uint32_t generation G_GNUC_UNUSED)
{
mini_get_interp_callbacks ()->invalidate_transformed ();
}
+static void
+mini_interp_jit_info_foreach(InterpJitInfoFunc func, gpointer user_data)
+{
+ mini_get_interp_callbacks ()->jit_info_foreach (func, user_data);
+}
/*
* mini_get_default_mem_manager:
}
void
-mono_internal_hash_table_apply (MonoInternalHashTable *table, MonoInternalHashApplyFunc func)
+mono_internal_hash_table_apply (MonoInternalHashTable *table, MonoInternalHashApplyFunc func, gpointer user_data)
{
for (gint i = 0; i < table->size; i++) {
gpointer head = table->table [i];
while (head) {
- func (head);
+ func (head, user_data);
head = *(table->next_value (head));
}
}
typedef gpointer (*MonoInternalHashKeyExtractFunc) (gpointer value);
typedef gpointer* (*MonoInternalHashNextValueFunc) (gpointer value);
-typedef void (*MonoInternalHashApplyFunc) (gpointer value);
+typedef void (*MonoInternalHashApplyFunc) (gpointer value, gpointer user_data);
struct _MonoInternalHashTable
{
gpointer key, gpointer value);
void
-mono_internal_hash_table_apply (MonoInternalHashTable *table, MonoInternalHashApplyFunc func);
+mono_internal_hash_table_apply (MonoInternalHashTable *table, MonoInternalHashApplyFunc func, gpointer user_data);
gboolean
mono_internal_hash_table_remove (MonoInternalHashTable *table, gpointer key);