fix stack overflow in inc/dec

This commit is contained in:
Folkert 2020-08-10 22:31:20 +02:00
parent ac6d72d077
commit 25e96fcade
2 changed files with 45 additions and 5 deletions

View File

@ -307,10 +307,16 @@ mod gen_list {
assert_concat_worked(2, 3);
assert_concat_worked(3, 3);
assert_concat_worked(4, 4);
// TODO TCE seems to be broken for large concats
// assert_concat_worked(150, 150);
// assert_concat_worked(129, 350);
// assert_concat_worked(350, 129);
}
#[test]
fn list_concat_large() {
// these values produce mono ASTs so large that
// it can cause a stack overflow. This has been solved
// for current code, but may become a problem again in the future.
assert_concat_worked(150, 150);
assert_concat_worked(129, 350);
assert_concat_worked(350, 129);
}
#[test]

View File

@ -568,9 +568,43 @@ impl<'a> Context<'a> {
}
// TODO should not be pub
pub fn visit_stmt(&self, stmt: &'a Stmt<'a>) -> (&'a Stmt<'a>, LiveVarSet) {
fn visit_stmt(&self, stmt: &'a Stmt<'a>) -> (&'a Stmt<'a>, LiveVarSet) {
use Stmt::*;
// let-chains can be very long, especially for large (list) literals
// in (rust) debug mode, this function can overflow the stack for such values
// so we have to write an explicit loop.
{
let mut cont = stmt;
let mut triples = Vec::new_in(self.arena);
while let Stmt::Let(symbol, expr, layout, new_cont) = cont {
triples.push((symbol, expr, layout));
cont = new_cont;
}
if !triples.is_empty() {
let mut ctx = self.clone();
for (symbol, expr, layout) in triples.iter() {
ctx = ctx.update_var_info(**symbol, layout, expr);
}
let (mut b, mut b_live_vars) = ctx.visit_stmt(cont);
for (symbol, expr, layout) in triples.into_iter().rev() {
let pair = ctx.visit_variable_declaration(
*symbol,
(*expr).clone(),
(*layout).clone(),
b,
&b_live_vars,
);
b = pair.0;
b_live_vars = pair.1;
}
return (b, b_live_vars);
}
}
match stmt {
Let(symbol, expr, layout, cont) => {
let ctx = self.update_var_info(*symbol, layout, expr);