-
-
Notifications
You must be signed in to change notification settings - Fork 421
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
boa_tester
stack overflows in debug mode
#4089
Comments
Yeah I think we're going to have to fix this properly, if you run the benchmarks in debug mode (just the first one or second one) it also stack overflows. I think we're gonna have to find the smallest test case that causes this and try to fix it, it's happening at the parser level. |
The problem is here (function(){
(function(){
... repeated 32 times in total ...
})()
})() Rust generator let mut js = String::new();
let n = 32;
(0..n).for_each(|_| js += "(function(){ ");
(0..n).for_each(|_| js += " })()"); First of all, in the case there will be about 20 nested I tried to reduce stack size for this case, and even made it about 3 times shorter(mostly by boxing & in one place you can remove about 7 nested calls per *And you can say: "hmm 35 is more than 32 so we are done!" But unfortunately this results are for the next code: #[test]
fn tmp_test() {
let mut js = String::new();
let n = 36;
(0..n).for_each(|_| js += "(function(){ \n");
(0..n).for_each(|_| js += " })()");
let interner = &mut Interner::default();
crate::Parser::new(crate::Source::from_bytes(&js))
.parse_script(&boa_ast::scope::Scope::new_global(), interner)
.expect("failed to parse");
} And when you run A little visual comparison:
So, as you can see, stack allocation with And I don't know how to optimize the stack size further. I move many things into So I have some questions:
|
Just found out that some stack-size optimizations affect only |
Hey @Nikita-str thanks for taking such a detailed look at this problem. I really appreciated the small reproducible test case you made. It looks like we need to refactor how the parsing works to not keep hitting these stack overflows long term by the looks of it. There was some similar discussion about this on another issue here #162, what are your thoughts? It would be good long term to be able to run Boa in dev mode and not have stack overflows so we can debug issues like this, which makes me think adjusting the opt-level is a sticking plaster for now.
I don’t understand this, could you explain more? |
I tried to reduce the stack size while debugging with Example of such splitting:fn parse(...) -> Output {
... many code here # 1 ...
OftenRecExpression::parse(...);
... many code here # 2 ...
} into fn parse(...) -> Output {
parse_prefix(...);
OftenRecExpression::parse(...);
parse_tail(...)
}
fn parse_prefix(...) -> AnyOutput {
... many code here # 1 ...
}
fn parse_tail(...) -> Output {
... many code here # 2 ...
} Now about #162. With the current approach you can only shift the numbers on which this happens. To make stack overflow impossible in general case you should rewrite parser fully, except for dead-end call branches. And, I'm making very intuitive first-sight assumption based on how I would try to solve the issue, probably you should have some stack structure that will return through all N calls when recursion happens and save all context(local variables), and if it happens to work(lol) there will be no more nested calls than longest non-repeating chain of statement (in other words, no more than amount of existing |
Running the
boa_tester
in debug in the main branch aborts with a stack overflow.In release mode everything seems fine, but we should still investigate.
The text was updated successfully, but these errors were encountered: