There are two distinct stacks to deal with in the emscripten world: the native call stack and the linear memory stack.
The linear memory stack is maintained by convention within the WebAssembly code, with the stack pointer in a global variable which points at a region of linear memory, and is just used for stack-allocating data that needs to have its address taken or otherwise cannot fit in locals. A function that doesn't allocate stack data might make recursive calls without ever moving the linear memory stack pointer, or a single function might allocate huge amounts of data dynamically. But you can access that stack pointer and see how close you are to the edge. Meanwhile the native call stack is where the "real" stack frames for native, JS, and WebAssembly functions live, and from WebAssembly or JS you have _very_ few means to introspect it. In particular note that JS/Wasm engines will prevent too-deep recursion safely -- but using vendor-specific limits with no consistency or standards. The good news is that too-deep recursion has reasonably predictable behavior _after the fact_ -- a trap/exception is thrown on a too-deep call for the native call stack, which will unwind all the Wasm functions on the stack up to the nearest JS catch block. The bad news is that there's no checking _ahead of time_ for the native call stack. You either have to try to maintain a depth counter yourself along with external knowledge of how deep various browser implementations allow the stack to get, or you let them run until they die and then clean up. This requires carefully keeping track of what happens when an exception gets thrown, and proper cleanup may require adding explicit exception-handling try/catch blocks to intermediate functions, which means call-outs between Wasm and JS. -- brion On Mon, Nov 4, 2019 at 12:11 PM Hostile Fork <[email protected]> wrote: > I'm asking from the perspective of writing a language interpreter...where > each user function call increases the stack depth of the underlying C > interpreter by some amount. (Similar to a CPython implementation.) > > I know there is a tactic of rethinking your language to use a bytecode--in > which recursions in code the user writes don't increase the stack depth of > the C interpreter. This means you expand your user's stack with something > like a malloc()...hence "stack overflow" isn't a > standards-breaking-semantic-failure-of-C, it's just conventional "memory > exhaustion" and you can catch it. (Similar to a PyPy implementation.) > > But--here's my thinking: running in a browser isn't exactly "bare metal". > You've got a whole JavaScript engine and an instrumentable WASM backend > that can pull off things like Asyncify. Should you *really* have to throw > in another layer of bytecode, *just* to get enough awareness to gracefully > prevent stack overflow crashes? Isn't there some kind of way to say "I'm > going to call this WASM function, and the compiler knows it would take up N > amount of stack, so tell me if I have that much before I call it"? And if > it is recursive, couldn't it have some relation in it to give it the self > awareness to say how much just *one* call would make, along with a promise > to check before it decides to make another? > > Just wondering if anyone out there is thinking along these lines. But if > not, then... > > ...is there any chance at being able to get some measure on a thread of > about how much space is left on the stack, enough to make a bit of informed > guesswork in recursive routines of whether they want to recurse further? > I'm not supper happy with the CPython method of telling users "guess an > integer recursion limit, if you crash irrecoverably then lower it, if you > think you can raise it without crashing then give it a shot". > > Thanks, > --Brian > http://hostilefork.com > > -- > You received this message because you are subscribed to the Google Groups > "emscripten-discuss" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/emscripten-discuss/5b3b2f19-96b9-46fd-b131-5af8abb86d6a%40googlegroups.com > <https://groups.google.com/d/msgid/emscripten-discuss/5b3b2f19-96b9-46fd-b131-5af8abb86d6a%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "emscripten-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/emscripten-discuss/CAFnWYT%3DYNJbKcWZB0mGNsKKqNynW9BXY1Wsucsi%2B%2Bz5wGpd8Kw%40mail.gmail.com.
