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".