NTK Stack Overflow During Compilation

One of the Newton 2.x OS Q&As
Copyright © 1997 Newton, Inc. All Rights Reserved. Newton, Newton Technology, Newton Works, the Newton, Inc. logo, the Newton Technology logo, the Light Bulb logo and MessagePad are trademarks of Newton, Inc. and may be registered in the U.S.A. and other countries. Windows is a registered trademark of Microsoft Corp. All other trademarks and company names are the intellectual property of their respective owners.


For the most recent version of the Q&As on the World Wide Web, check the URL: http://www.newton-inc.com/dev/techinfo/qa/qa.htm
If you've copied this file locally,click here to go to the main Newton Q&A page.
This document was exported on 7/23/97.


NTK Stack Overflow During Compilation (11/24/95)

Q: When I build my project that has very deeply nested statements, NTK runs out of memory and quits. What's going wrong?

A: The deep nesting in your project is causing the compiler to overflow the stack space available in NTK. NTK 1.6 is more likely than than NTK 1.5 to suffer this problem due to new compiler code which nests deeper while parsing if-then-else statements, causing the stack to overflow into the application heap.

If you see an inadvertent crash in NTK during a save operation or a package build:

1) If you are familiar with MacsBug, examine the stack. This particular case will show up in the stack as several calls to the same function before the actual crash.
2) Otherwise, temporarily reduce the number of "else" branches and rebuild the package. If the problem disappears, stack overflow is the prime suspect.

There are at least three ways to avoid this problem and possibly improve performance at the same time:
1) Re-arrange the 'else' statements to resemble a balanced tree
2) Instead of If-then-else statements use:
An array of functions (with integers as selectors)
A frame of functions (with symbols as selectors)
3) Finally, as a temporary work around, you can increase the stack size using the ResEdit application.

Re-arrange the 'else' statements to resemble a balanced tree

This solution is the simplest to implement if you need to change existing code. It accommodates non-contiguous integer selectors, and in most cases is faster.

For example, the following code:
   if x = 1 then        dosomething    else        if x = 2 then            doSomethingElse        else            if x = 3 then                doYetAnotherThing            else                if x = 4 then                    doOneMoreThing                else                    if x = 5 then                        doSomethingSimple                    else                        if x = 6 then                            doThatThing                        else                            if x = 7 then                                doThisThing                            else // x = 8                                doTheOtherThing

...can be rewritten like this:

   if x <= 4 then        if x <= 2 then            if x = 1 then                doSomething            else // x = 2                doSomethingElse        else            if x = 3 then                doYetAnotherThing            else // x = 4                doOneMoreThing    else        if x <= 6 then            if x = 5 then                doSomethingSimple            else // x = 6                doThatThing        else           if x = 7 then                doThisThing           else // x = 8                doTheOtherThing;

Note that the if/then/else statement nesting is "unusual" to illustrate the nesting that the compiler must make each statement is nested as the compiler would process it.


Use an array of functions with integer selectors

Replace a long if-then-else statement with an array of functions. The code is more compact and readable. For a large set of alternatives, the faster direct lookup should compensate for the extra function call. This approach is most useful for a contiguous range of selector values (e.g., 11 to 65). It can accommodate a few "holes" (for example, 11 to 32, 34 to 56, 58 to 65). It is not practical for non-contiguous selectors (e.g., 31, 77, 256, 1038...)

For example, the following code:

    if x = 1 then        dosuchandsuch;    else        if x = 2 then            dosomethingelse;        else            if x = 3 then                andsoon;

...can be rewritten like this:

        cmdArray := [func() dosuchandsuch,        func() dosomethingelse,            func() andsoon];        call cmdArray[x] with ();


Use a frame of functions with symbols for selectors

This alternative provides the flexibility of using symbols for selecting the outcome.

For example, the following code:

    if x = 'foo then        dosuchandsuch;    else        if x = 'bar then            dosomethingelse;        else            if x = 'baz then                andsoon;


...can be rewritten like this:
    cmdFrame := {foo: func() dosuchandsuch,                    bar: func() dosomethingelse,                    baz: func() andsoon};      call cmdFrame.(x) with ();

Increase NTK's stack size using the ResEdit application

Open the Newton Toolkit application with ResEdit.

Double-click on the "mem!" resource icon

Double-click on resource ID 1000 named "Additional NTK Memory Requirements"

Change the fifth (and last) value. This is an hexadecimal number. In NTK 1.6, you should see "0001 8000" which is 98304 bytes (or 96k) to add to the total stack size. For example, to increase this value to 128k = 131072 bytes change the hexadecimal value to "0002 0000".