Skip to content

Commit b09c0d2

Browse files
committed
[mono][interp] Reduce max memory usage during interp compilation
Create a new mempool for optimization iteration. For complex methods we typically do multiple optimization iterations. For each iteration we were allocating memory from the global method mempool, which was freed at the end of method compilation. We now allocate most of the memory inside a separate mempool which is freed at the end of each iteration. Allocate some of the temporary data with malloc so we can free it earlier. As an exception we allocate also var_values with malloc. We don't allocate it to the global mempool since this table is very big and it is wasteful. We don't allocate it to the optimization mempool since it is used for better code gen outside of optimization passes, in the var offset allocator.
1 parent 7ec65fa commit b09c0d2

File tree

3 files changed

+37
-15
lines changed

3 files changed

+37
-15
lines changed

src/mono/mono/mini/interp/transform-opt.c

+30-15
Original file line numberDiff line numberDiff line change
@@ -532,8 +532,8 @@ dfs_visit (TransformData *td)
532532
{
533533
int dfs_index = 0;
534534
int next_stack_index = 0;
535-
td->bblocks = (InterpBasicBlock**)mono_mempool_alloc0 (td->mempool, sizeof (InterpBasicBlock*) * td->bb_count);
536-
InterpBasicBlock **stack = (InterpBasicBlock**)mono_mempool_alloc0 (td->mempool, sizeof (InterpBasicBlock*) * td->bb_count);
535+
td->bblocks = (InterpBasicBlock**)mono_mempool_alloc0 (td->opt_mempool, sizeof (InterpBasicBlock*) * td->bb_count);
536+
InterpBasicBlock **stack = (InterpBasicBlock**)g_malloc0 (sizeof (InterpBasicBlock*) * td->bb_count);
537537

538538
g_assert (!td->entry_bb->in_count);
539539
stack [next_stack_index++] = td->entry_bb;
@@ -558,6 +558,7 @@ dfs_visit (TransformData *td)
558558
}
559559
}
560560

561+
g_free (stack);
561562
return dfs_index;
562563
}
563564

@@ -622,7 +623,7 @@ is_bblock_ssa_cfg (TransformData *td, InterpBasicBlock *bb)
622623
static void
623624
interp_compute_dominators (TransformData *td)
624625
{
625-
InterpBasicBlock **idoms = (InterpBasicBlock**)mono_mempool_alloc0 (td->mempool, sizeof (InterpBasicBlock*) * td->bblocks_count);
626+
InterpBasicBlock **idoms = (InterpBasicBlock**)mono_mempool_alloc0 (td->opt_mempool, sizeof (InterpBasicBlock*) * td->bblocks_count);
626627

627628
idoms [0] = td->entry_bb;
628629
gboolean changed = TRUE;
@@ -698,7 +699,7 @@ static void
698699
interp_compute_dominance_frontier (TransformData *td)
699700
{
700701
int bitsize = mono_bitset_alloc_size (td->bblocks_count, 0);
701-
char *mem = (char *)mono_mempool_alloc0 (td->mempool, bitsize * td->bblocks_count);
702+
char *mem = (char *)mono_mempool_alloc0 (td->opt_mempool, bitsize * td->bblocks_count);
702703

703704
for (int i = 0; i < td->bblocks_count; i++) {
704705
td->bblocks [i]->dfrontier = mono_bitset_mem_new (mem, td->bblocks_count, 0);
@@ -975,7 +976,7 @@ static void
975976
compute_gen_kill_sets (TransformData *td)
976977
{
977978
int bitsize = mono_bitset_alloc_size (td->renamable_vars_size, 0);
978-
char *mem = (char *)mono_mempool_alloc0 (td->mempool, bitsize * td->bblocks_count * 4);
979+
char *mem = (char *)mono_mempool_alloc0 (td->opt_mempool, bitsize * td->bblocks_count * 4);
979980

980981
for (int i = 0; i < td->bblocks_count; i++) {
981982
InterpBasicBlock *bb = td->bblocks [i];
@@ -1094,7 +1095,7 @@ bb_insert_phi (TransformData *td, InterpBasicBlock *bb, int var)
10941095
g_print ("BB%d NEW_PHI %d\n", bb->index, var);
10951096

10961097
phi->dreg = var;
1097-
phi->info.args = (int*)mono_mempool_alloc (td->mempool, (bb->in_count + 1) * sizeof (int));
1098+
phi->info.args = (int*)mono_mempool_alloc (td->opt_mempool, (bb->in_count + 1) * sizeof (int));
10981099
int i;
10991100
for (i = 0; i < bb->in_count; i++)
11001101
phi->info.args [i] = var;
@@ -1109,7 +1110,7 @@ bb_insert_dead_phi (TransformData *td, InterpBasicBlock *bb, int var)
11091110
bitset = bb->first_ins->info.dead_phi_vars;
11101111
} else {
11111112
InterpInst *phi = interp_insert_ins_bb (td, bb, NULL, MINT_DEAD_PHI);
1112-
gpointer mem = mono_mempool_alloc0 (td->mempool, mono_bitset_alloc_size (td->renamable_vars_size, 0));
1113+
gpointer mem = mono_mempool_alloc0 (td->opt_mempool, mono_bitset_alloc_size (td->renamable_vars_size, 0));
11131114
phi->info.dead_phi_vars = bitset = mono_bitset_mem_new (mem, td->renamable_vars_size, 0);
11141115
}
11151116
int ext_index = td->vars [var].ext_index;
@@ -1322,7 +1323,7 @@ rename_vars_in_bb_start (TransformData *td, InterpBasicBlock *bb)
13221323
if (renamed_var != -1) {
13231324
g_assert (td->vars [renamed_var].renamed_ssa_fixed);
13241325
int renamed_var_ext = td->vars [renamed_var].ext_index;
1325-
InterpLivenessPosition *liveness_ptr = (InterpLivenessPosition*)mono_mempool_alloc (td->mempool, sizeof (InterpLivenessPosition));
1326+
InterpLivenessPosition *liveness_ptr = (InterpLivenessPosition*)mono_mempool_alloc (td->opt_mempool, sizeof (InterpLivenessPosition));
13261327
*liveness_ptr = current_liveness;
13271328
td->renamed_fixed_vars [renamed_var_ext].live_limit_bblocks = g_slist_prepend (td->renamed_fixed_vars [renamed_var_ext].live_limit_bblocks, liveness_ptr);
13281329
}
@@ -1347,7 +1348,7 @@ rename_vars_in_bb_end (TransformData *td, InterpBasicBlock *bb)
13471348
g_assert (td->vars [renamed_var].renamed_ssa_fixed);
13481349
int renamed_var_ext = td->vars [renamed_var].ext_index;
13491350
if (!td->renamed_fixed_vars [renamed_var_ext].live_out_bblocks) {
1350-
gpointer mem = mono_mempool_alloc0 (td->mempool, mono_bitset_alloc_size (td->bblocks_count, 0));
1351+
gpointer mem = mono_mempool_alloc0 (td->opt_mempool, mono_bitset_alloc_size (td->bblocks_count, 0));
13511352
td->renamed_fixed_vars [renamed_var_ext].live_out_bblocks = mono_bitset_mem_new (mem, td->bblocks_count, 0);
13521353
}
13531354

@@ -1386,8 +1387,8 @@ static void
13861387
rename_vars (TransformData *td)
13871388
{
13881389
int next_stack_index = 0;
1389-
InterpBasicBlock **stack = (InterpBasicBlock**)mono_mempool_alloc0 (td->mempool, sizeof (InterpBasicBlock*) * td->bblocks_count);
1390-
gboolean *bb_status = (gboolean*)mono_mempool_alloc0 (td->mempool, sizeof (InterpBasicBlock*) * td->bblocks_count);
1390+
InterpBasicBlock **stack = (InterpBasicBlock**)g_malloc0 (sizeof (InterpBasicBlock*) * td->bblocks_count);
1391+
gboolean *bb_status = (gboolean*)g_malloc0 (sizeof (InterpBasicBlock*) * td->bblocks_count);
13911392

13921393
stack [next_stack_index++] = td->entry_bb;
13931394

@@ -1414,6 +1415,9 @@ rename_vars (TransformData *td)
14141415
}
14151416
}
14161417

1418+
g_free (stack);
1419+
g_free (bb_status);
1420+
14171421
if (td->verbose_level) {
14181422
g_print ("\nFIXED SSA VARS LIVENESS LIMIT:\n");
14191423
for (unsigned int i = 0; i < td->renamed_fixed_vars_size; i++) {
@@ -1718,7 +1722,7 @@ interp_link_bblocks (TransformData *td, InterpBasicBlock *from, InterpBasicBlock
17181722
static void
17191723
interp_mark_reachable_bblocks (TransformData *td)
17201724
{
1721-
InterpBasicBlock **queue = mono_mempool_alloc0 (td->mempool, td->bb_count * sizeof (InterpBasicBlock*));
1725+
InterpBasicBlock **queue = g_malloc0 (td->bb_count * sizeof (InterpBasicBlock*));
17221726
InterpBasicBlock *current;
17231727
int cur_index = 0;
17241728
int next_position = 0;
@@ -1761,6 +1765,8 @@ interp_mark_reachable_bblocks (TransformData *td)
17611765
if (needs_retry)
17621766
goto retry;
17631767
}
1768+
1769+
g_free (queue);
17641770
}
17651771

17661772
/**
@@ -2714,7 +2720,7 @@ interp_cprop (TransformData *td)
27142720
// FIXME
27152721
// There is no need to zero, if we pay attention to phi args vars. They
27162722
// can be used before the definition.
2717-
td->var_values = (InterpVarValue*) mono_mempool_alloc0 (td->mempool, td->vars_size * sizeof (InterpVarValue));
2723+
td->var_values = (InterpVarValue*) g_malloc0 (td->vars_size * sizeof (InterpVarValue));
27182724

27192725
// Traverse in dfs order. This guarantees that we always reach the definition first before the
27202726
// use of the var. Exception is only for phi nodes, where we don't care about the definition
@@ -3790,8 +3796,7 @@ interp_prepare_no_ssa_opt (TransformData *td)
37903796
td->vars [i].has_indirects = (td->vars [i].indirects > 0) ? TRUE : FALSE;
37913797
}
37923798

3793-
if (!td->bblocks)
3794-
td->bblocks = (InterpBasicBlock**)mono_mempool_alloc0 (td->mempool, sizeof (InterpBasicBlock*) * td->bb_count);
3799+
td->bblocks = (InterpBasicBlock**)mono_mempool_alloc0 (td->opt_mempool, sizeof (InterpBasicBlock*) * td->bb_count);
37953800

37963801
int i = 0;
37973802
for (InterpBasicBlock *bb = td->entry_bb; bb != NULL; bb = bb->next_bb) {
@@ -3861,6 +3866,14 @@ interp_optimize_code (TransformData *td)
38613866
g_print ("Huge method. SSA disabled for first iteration\n");
38623867
}
38633868
optimization_retry:
3869+
if (td->opt_mempool != NULL)
3870+
mono_mempool_destroy (td->opt_mempool);
3871+
if (td->var_values != NULL) {
3872+
g_free (td->var_values);
3873+
td->var_values = NULL;
3874+
}
3875+
td->opt_mempool = mono_mempool_new ();
3876+
38643877
td->need_optimization_retry = FALSE;
38653878

38663879
if (td->disable_ssa)
@@ -3897,6 +3910,8 @@ interp_optimize_code (TransformData *td)
38973910
goto optimization_retry;
38983911
}
38993912

3913+
mono_mempool_destroy (td->opt_mempool);
3914+
39003915
if (td->verbose_level) {
39013916
g_print ("\nOptimized IR:\n");
39023917
mono_interp_print_td_code (td);

src/mono/mono/mini/interp/transform.c

+6
Original file line numberDiff line numberDiff line change
@@ -8875,6 +8875,12 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, MonoG
88758875
if (td->optimized) {
88768876
MONO_TIME_TRACK (mono_interp_stats.optimize_time, interp_optimize_code (td));
88778877
interp_alloc_offsets (td);
8878+
// Offset allocator uses computed ref counts from var values. We have to free this
8879+
// table later here.
8880+
if (td->var_values != NULL) {
8881+
g_free (td->var_values);
8882+
td->var_values = NULL;
8883+
}
88788884
#if HOST_BROWSER
88798885
if (mono_interp_opt & INTERP_OPT_JITERPRETER)
88808886
jiterp_insert_entry_points (rtm, td);

src/mono/mono/mini/interp/transform.h

+1
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ typedef struct
324324
InterpBasicBlock **idoms; // immediate dominator for each bblock, index from reverse postorder dfs
325325
int bb_count;
326326
MonoMemPool *mempool;
327+
MonoMemPool *opt_mempool;
327328
MonoMemoryManager *mem_manager;
328329
GList *basic_blocks;
329330
GPtrArray *relocs;

0 commit comments

Comments
 (0)