[tests] Reenable enum equals test on interpreter (#18673)
[mono-project.git] / mono / mini / tiered.c
blob3de15415966d7fcb115f31dee57312ef8e25f26e
1 #include <config.h>
2 #include <mono/utils/mono-compiler.h>
4 #include "mini.h"
5 #include "mini-runtime.h"
6 #include <mono/utils/mono-counters.h>
7 #include <mono/utils/mono-logger-internals.h>
9 #ifdef ENABLE_EXPERIMENT_TIERED
11 MiniTieredStats mini_tiered_stats;
13 static MonoCoopCond compilation_wait;
14 static MonoCoopMutex compilation_mutex;
16 #define NUM_TIERS 2
18 static GSList *compilation_queue [NUM_TIERS];
19 static CallsitePatcher patchers [NUM_TIERS] = { NULL };
21 static const char* const patch_kind_str[] = {
22 "INTERP",
23 "JIT",
26 static GHashTable *callsites_hash [TIERED_PATCH_KIND_NUM] = { NULL };
28 /* TODO: use scientific methods (TM) to determine values */
29 static const int threshold [NUM_TIERS] = {
30 1000, /* tier 0 */
31 3000, /* tier 1 */
34 static void
35 compiler_thread (void)
37 MonoInternalThread *internal = mono_thread_internal_current ();
38 internal->state |= ThreadState_Background;
39 internal->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
41 mono_native_thread_set_name (mono_native_thread_id_get (), "Tiered Compilation Thread");
43 while (TRUE) {
44 mono_coop_cond_wait (&compilation_wait, &compilation_mutex);
46 for (int tier_level = 0; tier_level < NUM_TIERS; tier_level++) {
47 GSList *ppcs = compilation_queue [tier_level];
48 compilation_queue [tier_level] = NULL;
50 for (GSList *ppc_= ppcs; ppc_ != NULL; ppc_ = ppc_->next) {
51 MiniTieredPatchPointContext *ppc = (MiniTieredPatchPointContext *) ppc_->data;
53 for (int patch_kind = 0; patch_kind < TIERED_PATCH_KIND_NUM; patch_kind++) {
54 if (!callsites_hash [patch_kind])
55 continue;
57 GSList *patchsites = g_hash_table_lookup (callsites_hash [patch_kind], ppc->target_method);
59 for (; patchsites != NULL; patchsites = patchsites->next) {
60 gpointer patchsite = (gpointer) patchsites->data;
62 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_TIERED, "tiered: patching %p with patch_kind=%s @ tier_level=%d", patchsite, patch_kind_str [patch_kind], tier_level);
63 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_TIERED, "\t-> caller=%s", mono_pmip (patchsite));
64 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_TIERED, "\t-> callee=%s", mono_method_full_name (ppc->target_method, TRUE));
66 gboolean success = patchers [patch_kind] (ppc, patchsite);
68 if (!success)
69 mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_TIERED, "tiered: couldn't patch %p with target %s, dropping it.", patchsite, mono_method_full_name (ppc->target_method, TRUE));
71 g_hash_table_remove (callsites_hash [patch_kind], ppc->target_method);
72 g_slist_free (patchsites);
74 g_free (ppc);
76 g_slist_free (ppcs);
78 mono_coop_mutex_unlock (&compilation_mutex);
82 void
83 mini_tiered_init (void)
85 ERROR_DECL (error);
87 mono_counters_init ();
88 mono_counters_register ("Methods promoted", MONO_COUNTER_TIERED | MONO_COUNTER_LONG, &mini_tiered_stats.methods_promoted);
90 mono_coop_cond_init (&compilation_wait);
91 mono_coop_mutex_init (&compilation_mutex);
93 mono_thread_create_internal (mono_domain_get (), compiler_thread, NULL, MONO_THREAD_CREATE_FLAGS_THREADPOOL, error);
94 mono_error_assert_ok (error);
97 void
98 mini_tiered_register_callsite_patcher (CallsitePatcher func, int level)
100 g_assert (level < NUM_TIERS);
102 patchers [level] = func;
105 void
106 mini_tiered_record_callsite (gpointer ip, MonoMethod *target_method, int patch_kind)
108 if (!callsites_hash [patch_kind])
109 callsites_hash [patch_kind] = g_hash_table_new (NULL, NULL);
111 GSList *patchsites = g_hash_table_lookup (callsites_hash [patch_kind], target_method);
112 patchsites = g_slist_prepend (patchsites, ip);
113 g_hash_table_insert (callsites_hash [patch_kind], target_method, patchsites);
116 void
117 mini_tiered_inc (MonoDomain *domain, MonoMethod *method, MiniTieredCounter *tcnt, int tier_level)
119 if (G_UNLIKELY (tcnt->hotness == threshold [tier_level] && !tcnt->promoted)) {
120 tcnt->promoted = TRUE;
121 mini_tiered_stats.methods_promoted++;
123 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_TIERED, "tiered: queued %s", mono_method_full_name (method, TRUE));
125 MiniTieredPatchPointContext *ppc = g_new0 (MiniTieredPatchPointContext, 1);
126 ppc->domain = domain;
127 ppc->target_method = method;
128 ppc->tier_level = tier_level;
130 mono_coop_mutex_lock (&compilation_mutex);
131 compilation_queue [tier_level] = g_slist_append (compilation_queue [tier_level], ppc);
132 mono_coop_mutex_unlock (&compilation_mutex);
133 mono_coop_cond_signal (&compilation_wait);
134 } else if (!tcnt->promoted) {
135 /* FIXME: inline that into caller */
136 tcnt->hotness++;
139 #else
140 MONO_EMPTY_SOURCE_FILE (tiered);
141 #endif