JS Stack Overflow / Increase

Posted on
  • After I got over some memory inpasses - putting stuff in functions rather than execute on upload / level 0 - and setting to Save on send - write directly into the flash rather than RAM - I hit a next wall. Interpreter complains about:

    Execution Interrupted during event processing.
    Uncaught Error: Too much recursion - the stack is about to overflow

    I know that i'm not in an infinite recursion... Packing things in a timeout did not help to cut the calling hierarchy. Interestingly, it is on a return. The call is triggered by a watched button release.

    How can I increase the stack?

    Console output:

    Execution Interrupted during event processing.
    Uncaught Error: Too much recursion - the stack is about to overflow
     at line 1 col 15
    var b=c?a^7:a;return[b&&4?0:1];
                  ^
    in function called from line 1 col 50
    this.dsp.setColor.apply(this.dsp,this.clrs[0](a,b)),this;
                                                     ^
    in function "clr" called from line 1 col 72
    ...return b.fnt(a[0]).clr(a[1]).dsp.drawString(d,(e||0)+a[2],(f...
                                  ^
    in function "dl" called from line 1 col 401
    ...0],h,b[2],b[3],g],m[0],m[1]));
                                  ^
    in function "sliDu" called from line 1 col 142
    ...6],a[7],a[8],a[9],e,a[11],g);}
                                  ^
    in function "sliU" called from line 1 col 263
    ...a.sliU(a,b,b===a.ef?j:g,f,d));}
                                  ^
    in function "sli" called from line 1 col 33
    b&&(a.f|=b===c?256:8,a[b[1]](a,b));
                                    ^
    in function called from line 1 col 662
    ...b===c?256:8,a[b[1]](a,b));}),a.lf=a.af=0,a.dx=a.dy=-1;
                                  ^
    in function "evt" called from line 1 col 7
    a.evt(),(b=a.sx)>-1&&a._seu(a,(i=a.es)[b],i,b,-1),a.fl(),c[1...
          ^
    in function "g" called from line 1 col 45
    a[1]&&a[0]&&g(a,Math.round(b.time*1000)-a[1]);
                                                ^
    in function called from system
    > 
    
  • I'm afraid you can't increase the stack without rebuilding the firmware to decrease the amount of JsVars available. Which board are you running on?

    The interpreter is recursive-descent, so it does use up a bunch of stack for each function call. About 10 levels deep does sound about right. There are few ways around having so many stacked calls though:

    • use on/emit to send out events if you don't need a response
    • use Promises
    • add setTimeout(...,0) when to call a function - if you could do this halfway up your call stack you'd effectively split it in two

  • I use Pixle.js. I take a look what I can do without rebuilding firmware.

  • Ok, just changing the variables value will be enough: https://github.com/espruino/Espruino/blob/master/boards/PIXLJS.py#L25

    If you've got Linux (or Windows 10 with 'Linux on Windows' installed) then it should be pretty straightforward to rebuild - or @JumJum's firmware builder should work too

  • @Gordon, thanks for your detailed response. I eliminated some functions and added some ifs - to de-modularize increasing dependency and tighter coupling - to get temporarily over the issue - not the preferred SW best practice. Since it is in (the infrastructure) framework, it is manageable.

    When increasing application complexity without going more asynchronous, I expect it to happen again.

    Is there a way to ask the Interpreter how much stack space is left and a rough/average break down into number of nested function calls?

    Another question is how do fat arrow functions compare to standard functions? I know about some limitation but that may be different in the Espruino context with interpretation on the source / no byte/intermediate code.

    Regarding minification, which is not directly stack / nested calling related but share the memory restrictions: does the Esprima minification take this into consideration? Using google's closure compiler service for JavaScript has often a negative effect: this and undefined and some other constructs that are great w/ byte code but not with source interpretation, and the compiler is so smart that it requires some tricking to keep it from resolving and substituting. I'm aware of the some of the penalty by using a variable vs a constant, but memory is absolute, (execution) time can be stretched.

  • Is there a way to ask the Interpreter how much stack space is left

    I don't believe there is at the moment, no :(

    Another question is how do fat arrow functions compare to standard functions?

    They use slightly more storage sometimes because they store the value of this when they were executed. Otherwise there's not much in it.

    Regarding minification, which is not directly stack / nested calling related but share the memory restrictions: does the Esprima minification take this into consideration?

    I'm not sure I understand? It doesn't take anything Espruino-specific into account I'm afraid.

    You can also try E.setFlags({pretokenise:true}) which means Espruino does minification itself - and compresses reserved words down to a single character.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

JS Stack Overflow / Increase

Posted by Avatar for allObjects @allObjects

Actions