| Re: local buffers and tail-call optimization |
|
 |
|
 |
|
 |
|
 |
Group: comp.lang.forth · Group Profile
Author: Anton ErtlAnton Ertl Date: Aug 30, 2008 01:02
>>If a Forth system supports local buffers (or another locals extension
>>that produces addresses of local memory, e.g., Gforth's
>>variable-flavoured locals), then it has to define the lifetime of the
>>memory the address points to. Typically the lifetime will be until
>>the end of the definition that the buffer was defined in.
>>
>>This inhibits tail-call optimization; consider:
>>
>>: bar ( addr -- )
>> ... ;
>>
>>: foo { | [ 1 ] x } x bar ;
>>
>>in the syntax proposed by Stephen Pelc or
>>
>>: foo 1 lbuffer bar ;
>
>In practice this not very important, as (especially with
>buffers as opposed to values) bar will manipulate the buffer
>from which a result will be extracted.
>
>: foo { | [ /struct ] x }
> x bar x manipulate x .bField @
>;
Another practical use would be to put something in the buffer that is
then read by the callee, e.g.:
: emit ( c -- )
1 lbuffer tuck c!
1 type ;
Here the call to TYPE looks like a tail-call, but it isn't.
>Given the ingenuity of programmers, and widespread recognition
>that return addresses are on the return stack (despite what
>any standard may say), determining the routines that are safe
>for tail optimisation is a non-trivial exercise, as any return
>stack manipulation propagates in the call tree.
It's non-trivial, but doable to analyse it if you want to go for that.
The other option is to make it the programmers' responsibility to turn
off tail-call optimization and inliners if they do return-address
manipulation stuff.
> Practical use
>trumps any standard IMHO.
Sure, but I don't think that return-address manipulation is used
widely enough to justify any more effort than to provide a switch for
turning off optimizations that don't agree with them.
- anton
|