Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Mono] Include loaded interpreter methods as EventPipe session rundown method events. #54953

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions src/mono/mono/eventpipe/ep-rt-mono.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ typedef struct _EventPipeSampleProfileData {
uintptr_t thread_ip;
uint32_t payload_data;
bool async_frame;
bool safe_point_frame;
} EventPipeSampleProfileData;

// Rundown flags.
Expand Down Expand Up @@ -898,13 +899,15 @@ eventpipe_execute_rundown (
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.
Expand Down Expand Up @@ -997,21 +1000,32 @@ eventpipe_sample_profiler_walk_managed_stack_for_thread_func (
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
Expand Down Expand Up @@ -1515,8 +1529,12 @@ ep_rt_mono_sample_profiler_write_sampling_event_for_threads (
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++;
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/mono/mono/metadata/object-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,9 @@ typedef struct {
/* 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 +
Expand Down Expand Up @@ -643,6 +646,7 @@ typedef struct {
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);
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/ee.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ typedef gpointer MonoInterpFrameHandle;
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 {

Expand Down
5 changes: 5 additions & 0 deletions src/mono/mono/mini/interp-stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,11 @@ stub_mark_stack (gpointer thread_data, GcScanFunc func, gpointer gc_data, gboole
{
}

static void
stub_jit_info_foreach (InterpJitInfoFunc func, gpointer user_data)
{
}

#undef MONO_EE_CALLBACK
#define MONO_EE_CALLBACK(ret, name, sig) stub_ ## name,

Expand Down
33 changes: 29 additions & 4 deletions src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -7325,7 +7325,7 @@ static int num_methods;
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)
Expand All @@ -7351,7 +7351,7 @@ interp_print_method_counts (void)

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);
Expand All @@ -7372,7 +7372,7 @@ interp_set_optimizations (guint32 opts)
}

static void
invalidate_transform (gpointer imethod_)
invalidate_transform (gpointer imethod_, gpointer user_data)
{
InterpMethod *imethod = (InterpMethod *) imethod_;
imethod->transformed = FALSE;
Expand Down Expand Up @@ -7451,13 +7451,38 @@ interp_invalidate_transformed (void)
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)
{
Expand Down
9 changes: 8 additions & 1 deletion src/mono/mono/mini/mini-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ GSList *mono_interp_only_classes;
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)
Expand Down Expand Up @@ -4357,6 +4358,7 @@ mini_init (const char *filename, const char *runtime_version)
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;

Expand Down Expand Up @@ -5139,12 +5141,17 @@ mono_runtime_install_custom_handlers_usage (void)
}
#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:
Expand Down
4 changes: 2 additions & 2 deletions src/mono/mono/utils/mono-internal-hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,12 @@ mono_internal_hash_table_insert (MonoInternalHashTable *table,
}

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));
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/mono/mono/utils/mono-internal-hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ typedef struct _MonoInternalHashTable MonoInternalHashTable;

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
{
Expand Down Expand Up @@ -73,7 +73,7 @@ mono_internal_hash_table_insert (MonoInternalHashTable *table,
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);
Expand Down