From 98b88fef162f63335f145b660bfafabba075ee22 Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 15 Nov 2022 19:46:36 +0100 Subject: [PATCH] fix a weird merge conflict --- crates/compiler/alias_analysis/Cargo.toml | 2 +- crates/compiler/alias_analysis/src/lib.rs | 80 ++++++++++++++--------- 2 files changed, 51 insertions(+), 31 deletions(-) diff --git a/crates/compiler/alias_analysis/Cargo.toml b/crates/compiler/alias_analysis/Cargo.toml index 320e3e50f7..3b2abd0000 100644 --- a/crates/compiler/alias_analysis/Cargo.toml +++ b/crates/compiler/alias_analysis/Cargo.toml @@ -11,4 +11,4 @@ roc_collections = {path = "../collections"} roc_module = {path = "../module"} roc_mono = {path = "../mono"} roc_debug_flags = {path = "../debug_flags"} -bumpalo = { version = "3.11.0", features = ["collections"] } +bumpalo.workspace = true diff --git a/crates/compiler/alias_analysis/src/lib.rs b/crates/compiler/alias_analysis/src/lib.rs index 18a878a990..01d9287320 100644 --- a/crates/compiler/alias_analysis/src/lib.rs +++ b/crates/compiler/alias_analysis/src/lib.rs @@ -469,6 +469,34 @@ impl<'a> Env<'a> { } } +fn apply_refcount_operation<'a>( + builder: &mut FuncDefBuilder, + env: &mut Env<'a>, + block: BlockId, + modify_rc: &ModifyRc, +) -> Result<()> { + match modify_rc { + ModifyRc::Inc(symbol, _) => { + let argument = env.symbols[symbol]; + + // a recursive touch is never worse for optimizations than a normal touch + // and a bit more permissive in its type + builder.add_recursive_touch(block, argument)?; + } + + ModifyRc::Dec(symbol) => { + let argument = env.symbols[symbol]; + builder.add_recursive_touch(block, argument)?; + } + ModifyRc::DecRef(symbol) => { + let argument = env.symbols[symbol]; + builder.add_recursive_touch(block, argument)?; + } + } + + Ok(()) +} + fn stmt_spec<'a>( builder: &mut FuncDefBuilder, interner: &STLayoutInterner<'a>, @@ -486,12 +514,25 @@ fn stmt_spec<'a>( let mut queue = vec![symbol]; - while let Let(symbol, expr, expr_layout, c) = continuation { - let value_id = expr_spec(builder, interner, env, block, expr_layout, expr)?; - env.symbols.insert(*symbol, value_id); + loop { + match continuation { + Let(symbol, expr, expr_layout, c) => { + let value_id = expr_spec(builder, interner, env, block, expr_layout, expr)?; + env.symbols.insert(*symbol, value_id); - queue.push(symbol); - continuation = c; + queue.push(symbol); + continuation = c; + } + Refcounting(modify_rc, c) => { + // in practice it is common to see a chain of `Let`s interspersed with + // Inc/Dec. For e.g. the False interpreter, this caused stack overflows. + // so we handle RC operations here to limit recursion depth + apply_refcount_operation(builder, env, block, modify_rc)?; + + continuation = c; + } + _ => break, + } } let result = stmt_spec(builder, interner, env, block, layout, continuation)?; @@ -527,32 +568,11 @@ fn stmt_spec<'a>( Expect { remainder, .. } => stmt_spec(builder, interner, env, block, layout, remainder), ExpectFx { remainder, .. } => stmt_spec(builder, interner, env, block, layout, remainder), Ret(symbol) => Ok(env.symbols[symbol]), - Refcounting(modify_rc, continuation) => match modify_rc { - ModifyRc::Inc(symbol, _) => { - let argument = env.symbols[symbol]; + Refcounting(modify_rc, continuation) => { + apply_refcount_operation(builder, env, block, modify_rc)?; - // a recursive touch is never worse for optimizations than a normal touch - // and a bit more permissive in its type - builder.add_recursive_touch(block, argument)?; - - stmt_spec(builder, interner, env, block, layout, continuation) - } - - ModifyRc::Dec(symbol) => { - let argument = env.symbols[symbol]; - - builder.add_recursive_touch(block, argument)?; - - stmt_spec(builder, interner, env, block, layout, continuation) - } - ModifyRc::DecRef(symbol) => { - let argument = env.symbols[symbol]; - - builder.add_recursive_touch(block, argument)?; - - stmt_spec(builder, interner, env, block, layout, continuation) - } - }, + stmt_spec(builder, interner, env, block, layout, continuation) + } Join { id, parameters,