guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Better generator and iterator support in guile w.r.t. speed


From: Stefan Israelsson Tampe
Subject: Re: Better generator and iterator support in guile w.r.t. speed
Date: Wed, 06 Mar 2013 19:44:37 +0100
User-agent: KMail/4.9.4 (Linux/3.5.0-25-generic; KDE/4.9.4; x86_64; ; )

Hi all, 

In my previous mail I did some discussions about what structure to use
in order to allow efficient implementatin og generators and one main
observation is that the curretn rtl strategy can be used.

Now Have you all thought about the stack beeing a must to execute
funcitons. Well we have threads but we can get lightweight in process
threads quite naturally in the rtl version of guile. We could call it
a coroutine and let it be an object

co = (code,stack,ip,outer-stack)

The idea here is that the code will have a fixed sized stack that is
just enough room to store all locals and intermediate variables
e.g. all the registers needed to execute the function. Any call would
then need to hook onto the outer stack. The stack is typically of the
form
stack =
 
[IP
 OUTER-FP
 LOCALS
 ...]

At the creation, IP points to the starting code position and then
after each exit the next ip is stored in IP and so on.

To support this we need a few new operations
* MULTIMOVE,       from the local stack to outer stack
* MULTIMOVE,       to the local stack from the outer stack
* OUTER-TAIL-CALL  This re-uses the outer call frame used to call this
                   coroutine and resets the IP to the initial value
* OUTER-CALL       This will setup a new call frame on the outer stack
                   execute the function there
* RESET-IP         RESET the IP value to the initial start value
* STORE-IP         Store an local ip adress in IP using a label.
* OUTER-RETURN     Simply return using the OUTER-FP and make sure 

* CALL-CO          This will call a CO routine by setting up the 
* TAIL-CALL-CO     call frame or reusing the current one (in tail 
context)
                   then set the OUTER-FP and jump to the IP value if a
                   number else throw an error. And then setting IP to
                   #f and start executing
  


This will probably work quite ok. But the question is how well it play
with call/cc and classic prompts as well as usage of the same object
many times. 

1. This object can only be located one time in the stack because when
in use IP = #f and another application of the object down the stack
would throw an error at the application

2. call/cc prompt code dynwinds and fluids inside co needs to have
special versions

3. When one store the stack space one need to make sure that the co
routines also get copied.

To note is that these objects should be able to live immersed in the
stack space for quick allocation when we inline them inside functions.

----------------------------------
Anyway I will explore this concept semewhat more and see if all scheme
features can be made to interop in a good way with it.
----------------------------------

I would also come back to the question if we should have a special
tree-il concept that can be used to model this behavior. I'm now
inclined to concider something like.

(lexical-prompts
    ((g #:exits     (a ...) 
        #:body      (th thunk)
        #:exit-case (((a) (lambda (k kind arg ...) code2)) ...))
     ...)
  code ...)
    
The default expansion of this woule then be something like
(letrec  ((g . l)   (let* ((tag (make-tag))
                         (th  thunk))
                         (call-with-prompts tag
                         (apply th l)
                         (lambda (k kind arg ...)
                                 (case kind ((a) code2 ...) ...)))))
          ...)
   code ...)

So if we can prove:
1. The only references of g ... inside th is through e.g. (a g arg ...)
   where we mean ( g arg ...) = (abort-to-prompt tag 'a g arg ...).

2. these (a ...) forms is not included in any lambda definitions or
   entering any funciton via it's argumnets.

3. g is never feeded as an argument to a function or located inside a
   closure definition anywhere in the form.

4. in ((code2 ...) ...) ... any applications of g ... is located in
   tail position.

5.th is always setted to either k or the initial thunk or never setted
  in any of the ((a) ...) forms.

with these things satisfied we should be able to inline the co routine
or generator inside of the function with quite good
characteristic. This is interesting this should be a logically step up
in generality from CL's tagbody.

Of cause there is a lot of substructure and combination of the general 
construct.

>From the rtl code we would manage just ok with the old instructions
just fine except for the need to be be able to store a label value and
goto to a stored label value aka named goto.

WDYT?

/Stefan

                            
                          
    





reply via email to

[Prev in Thread] Current Thread [Next in Thread]