Is the stack limit of 5287 in AS3 variable or predefined?

天涯浪子 提交于 2019-12-23 07:27:13

问题


I ran a test just now:

function overflow(stack:int = 0):void
{
    if(stack < 5290)
    {
        trace(stack);
        overflow(stack + 1);
    }
}

overflow();

This always throws a StackOverflow error after 5287 calls.

Error #1023: Stack overflow occurred.

Is this limit variable (depending on machine specs, environment, etc) or is that a flat value defined somewhere? If I change the if statement to less than 5287, I don't get the error.


回答1:


Obviously it's variable. Since all the calculations you really do are located in stack (disassembly report codes show pushbyte instructions and other stuff that's working with stack, as non-operand arithmetics), this value only reports how many function contexts can be put into the stack until it overflows.

I have decided to run some tests for recursion thresholds as based on this article that was referenced in baris's comment. The results were pretty embarrassing. Test environment: FlashDevelop 3.3.4 RTM, Flash player debugger 10.1.53.64, flash compile mode: release. "Debug" mode didn't change numbers cardinally, checked that too.

Locals number     Iterations (static int)       Iterations (Math.random())   
0                 5306                          
1                 4864                          4856
2                 4850                          4471
3                 4474                          4149
4                 4153                          3870
5                 3871                          3868
6                 3869                          3621
7                 3620                          3404
8                 3403                          3217
9                 3210                          3214
10                3214                          3042
11                3042                          3045
10 mixed          3042     1 value was assigned Math.random() and 9 - static int
10 advancedRandom 2890     1 value was assigned a custom random with 1 parameter

Note, all of these values vary within a margin of ten between subsequent executions. The "static int" and "Math.random()" are designations of what is assigned to locals wihin the recursively called function. This, however, leads me to assume the following:

  1. Including function calls into the recursive function adds to function context
  2. Memory for locals is assigned along with its type, in chunks of more than 8 bytes, because adding a local does not always decrease recursion limit
  3. Adding more than one call to a certain function does not add more memory to function context
  4. The "memory chunk" is most likely 16 bytes long, because this value is 2^N, an addition of one int or Number local does not always decrease recursion, and this is more than 8, as a raw value of a Number variable takes 8 bytes, being a double-precision floating-point.
  5. Assuming #4 is correct, the best value for function context size appeared to be 172 bytes, with total stack size being 912632 bytes. This largely confirms my initial assumption that the stack size is actually 1 megabyte in Flash 10. Flash 11 showed me a bit higher numbers when I have tried opening the test SWF in its debugger, but I didn't make extensive tests with it.



回答2:


Hm, this is interesting. I took a look at the link that Barış gave. It seems like it might be to be with 'method complexity' after all, but I am not sure how to further test it. I am using Flash CS5, publishing for Flash Player 10, Actionscript 3 (of course).

Original:

function overflow(stack:int = 0):void {
    if(stack < 5290){
        trace(stack);
        overflow(stack + 1);
    }
}
// gives 5287

Now adding a single Math.random() call to the overflow() method:

function overflow(stack:int = 0):void {
    Math.random();
    if(stack < 5290){
        trace(stack);
        overflow(stack + 1);
    }
}
// gives 4837

Adding multiple Math.random() calls make no difference, nor does storing it in a local variable or adding another parameter to the overflow() method to 'carry' that random generated value

function overflow(stack:int = 0):void {
    Math.random();
    Math.random();
    if(stack < 5290){
        trace(stack);
        overflow(stack + 1);
    }
}
// still gives 4837

At this point I tried different Math calls, such as:

// just the change to that 1 line:
Math.pow() // gives 4457
Math.random(), Math.sqrt(), Math.tan(), Math.log() // gives 4837

Interestingly, it doesn't seem to matter what you pass in to the Math class, but it remains constant:

Math.sqrt(5) vs Math.sqrt(Math.random()) // gives 4837
Math.tan(5) vs Math.tan(Math.random()) // gives 4837
Math.pow(5, 7) vs Math.pow(Math.random(), Math.random()) // 4457

Until I chained 3 of them:

Math.tan(Math.log(Math.random())); // gives 4457

It looks like two Math calls from that 'group' is "equal" to one Math.pow() call? =b Mixing Math.pow() and something else doesn't seem to decrease the value though:

Math.pow(Math.random(), Math.random()); // gives 4457

However, chaining two Math.pow()'s:

Math.pow(Math.pow(Math.random(), Math.random()), Math.random()); // 4133

I could go on and on, but I wonder if there is some pattern:

Results:   5287, 4837, 4457, 4133
Differences:  450   380   324



回答3:


Musst be variable! Just compiled your sample and i get to 5274 before stack overflow.

@baris thats for the mxmlc compiler

+1 for stack overflow question ^^



来源:https://stackoverflow.com/questions/15192839/is-the-stack-limit-of-5287-in-as3-variable-or-predefined

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!