For the rtl generation I've seen that I can optimize <let-values> much more by introducing local tail-call environment. e.g. let-values will introduce an implicit call frame for local tail-calls. with this
we could argue that the call-with-values primcall could be coded as
And then try to optimize this. To try optimize this you will hit a problem with the rtl code. We will
hit the barrier because we would like to skip producing a list x and skip using apply but in stead deduce that we can do a call-with-values trick and call the function directly by overlaying the function slot in the consumer call. Darn you will need call-with-values still because of not knowing the number of
arguments beforehand and therefore we cannot deduce the registers needed to calculate the consumer without making the list and do a apply as usual.
(Hint in call-with-values the consumer is evaluated before the producer is evaluated and trying to do the same
in let-values is probably going to confuse people.)
But in most cases we do now beforehand the number of arguments e.g. (let-values (((x y) producer)) (consumer x y))
And with the work I plan to do this will be as efficient or better then using call-with-values. Actually I'm not pleased with this interface
at this low level and going around in a circle one realizes that we can design another interface
(call-frame-chain producer case-lambda) This s very similar to call-with-values but I use another form because this will calculate the producer and evaluate it before the cons
and hence in the first example it will calculate the list x and do the apply as an apply. Today I cannot decide if we could merge the two notions but for now the new name has a decriptive feature of what's happening e.g. we create a local call frame and make use of that.
Also the producer and case-lambda need not be functions the producer can be ordinary code that uses values to return e.g. very much like <let-values> and the consumer lambda may be any case-lambda that can introduce code as is done for loops to make them more efficient.
HOW WILL I CHAIN THIS
This will probably lead to some really hard work but in end it will mean that letting the flow go through 'let-values' will be as efficient or more efficient as coding the same algorithm using
tail-call and continuation closures and will be ideal when we have many state variables that's being copied to the same slot and sometimes being updated. It also will make it possible for peval to optimize this kind of functional programming style.
A little how I think.
1. In each step of the calculation we have a context i) tail ii) push iii) skip
N.B. I skiped the values context and let mem below be any list like (x y) or even (x . y)
2. In case of push we have a memory(ies)location to push the result to that flows with the context In the case of tail, the context memory will be the location of the tail call frame.
3. make sure we have tail-call-forms that can manage a location parameter of the frame
A call to call-frame-chain will setup the metadata for a call at the stack position basically and then issue the producer by setting it in a tail call context with the memory position of the beginning of the call frame as the context mem slot with this local tail call's
will reuse the the local frame and continue. There is one optimization to take note of tough, if we find that the form's context is in tail context with a mem slot we will reuse that memory slot e.g. if we are in the ordinary tail context we will just use the usual call frame.
The consumer will be called or expanded in a consumer context and the result of that will have the context of the surounding environment.
Something along these line is what I plan to introduce. Does it make sense?
[Prev in Thread]
[Next in Thread]
rtl let-values call-with-values,
Stefan Israelsson Tampe<=