|Compile to C difficulties email@example.com (Charlie) (2006-09-08)|
|Re: Compile to C difficulties firstname.lastname@example.org (Michael Tiomkin) (2006-09-08)|
|Re: Compile to C difficulties email@example.com (Pascal Bourguignon) (2006-09-08)|
|Re: Compile to C difficulties firstname.lastname@example.org (George Neuner) (2006-09-09)|
|Re: Compile to C difficulties email@example.com (Charlie) (2006-09-11)|
|Re: Compile to C difficulties firstname.lastname@example.org (George Neuner) (2006-09-12)|
|Re: Compile to C difficulties email@example.com (Charlie) (2006-09-16)|
|Re: Compile to C difficulties firstname.lastname@example.org (russell kym horsell) (2006-09-18)|
|From:||George Neuner <email@example.com>|
|Date:||9 Sep 2006 15:41:09 -0400|
|Posted-Date:||09 Sep 2006 15:41:09 EDT|
On 8 Sep 2006 16:56:43 -0400, "Charlie" <firstname.lastname@example.org>
>Jenny/Jenagin is implimented with a version of Gentle, which
>compiles to C in a simplistic fashion. Since many of the rules
>are recursive, the C procedure stack can overflow ...
>Currently I am working on improved translation to C.
Stack limits on most systems are pretty liberal (see below) so if the
stack is routinely overflowing, I would work seriously on eliminating
recursion in the generated code.
>I can use my own stack from heap memory but this slows the
>execution. So I can run normally with the C stack, then switch over
>to the heap stack.
>Is there a reasonable way to obtain a good limit?
The default stack allocation for many compilers is 1..4 megabytes.
From there the stack grows automatically up to some maximum. Windows
allows the stack to grow up to 1GB (assuming address space isn't
otherwise exhausted). Maximum stack size on Unix/Linux is usually a
linker option but note that the stack+heap can't exceed the user
process memory limit which defaults to 256MB on most systems (see
>If the C stack competes with the Heap space or grows into virtual
>memory, is this even a good idea?
Not really. The stack and the heap compete for address space, so
overflowing the stack into the heap typically does not accomplish
anything except increasing complexity and reducing performance.
Your options are limited if you insist on compiling to C. The best
solution is to generate code that does not overflow the stack in the
first place. If you can't guarantee that, you can
1) Create an "infinite" stack by swapping it to disk. This is not
generally portable as it depends on the system's VMM functions. To
do this you split the stack into 2 or more segments with no-access
guard pages at the ends. You then catch access faults on the guard
pages, switching segments and spilling/filling them using the disk as
the stack expands and contracts.
The good part of this solution is that the stack can grow to use all
available disk space while having a constant footprint in memory. The
bad part is that there are severe performance penalties if you
spill/fill stack segments too often. You can reduce the impact by
using many smallish segments (that can be copied quickly) rather than
a few large ones.
2) Find (or write) a C compiler or interpreter that aggressively
optimizes tail calls and mutual recursion. I don't know of any such
beast off hand ... in my experience most C compilers are rather bad at
these particular optimizations.
This won't solve the problem of too many recursive functions calls but
might delay having to rewrite the code generator.
>As the heap stack grows and contracts, it leaves pointers to unneeded
>"garbage". It seems wasteful to zero the heap stack contents as it
>contracts. But leaving the pointers would prevent a garbage collector
>recycling the garbage. Ideally I would like to zero the left over
>stack immediately before a garbage collector starts, but the most
>popular Boehm GC does not seem to have hooks for this purpose.
The real stack has the same problem ... C just doesn't know about or
support GC and few (if any) C compilers bother to reset pointer
variables after their last use. On the real stack the effect is
limited because there are not likely to be many unused pointers at any
particular time and because a GC library won't scan beyond the top of
the stack. In your case, the GC just sees a block on the heap and
scans the entire block.
WRT Boehm, I don't know exactly what you are doing, but from your
comments I am guessing that you are allocating an array on the heap
and manipulating the CPU stack pointer to switch to/from it. One
thing you can try is starting your application with GC disabled,
allocating your stack array in an uncollected heap, then enabling GC
and using GC_add_roots()/GC_remove_roots() to control what parts of
the stack array are scanned.
Hope this helps.
Return to the
Search the comp.compilers archives again.