unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* CPS Update
@ 2013-02-16  0:53 Noah Lavine
  2013-02-16  7:39 ` Stefan Israelsson Tampe
  2013-03-08 22:57 ` Noah Lavine
  0 siblings, 2 replies; 16+ messages in thread
From: Noah Lavine @ 2013-02-16  0:53 UTC (permalink / raw)
  To: guile-devel

[-- Attachment #1: Type: text/plain, Size: 1076 bytes --]

Hello,

The wip-rtl-cps branch has been rebased again (on top of wip-rtl). It now
includes support for toplevel references and sets, thanks mostly to Andy's
work on supporting them in RTL. (Although you shouldn't kick that part of
it too hard just yet; I think I know where it will break.) Other highlights
include using the top-level variable support to evaluate "(+ 3 4)"
correctly.

Overall, I think it's coming along well. The parts of Tree-IL that are left
to implement are local mutable variables (should be easy after toplevel
ones), module references and sets (very similar to top-level ones),
closures, and the dynamic environment stuff. Local mutable variables are my
next project, and then I think closures.

One question I've had is, can we assume that the variables in the (guile)
module are immutable? I think the current compiler does this. Otherwise
there's no correct way to inline primitive procedures like + unless we have
a way to invalidate our compiled code and recompile it (which I would like
to have anyway, but that's a different story).

Best,
Noah

[-- Attachment #2: Type: text/html, Size: 1318 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-02-16  0:53 CPS Update Noah Lavine
@ 2013-02-16  7:39 ` Stefan Israelsson Tampe
  2013-02-16 16:29   ` Noah Lavine
  2013-03-08 22:57 ` Noah Lavine
  1 sibling, 1 reply; 16+ messages in thread
From: Stefan Israelsson Tampe @ 2013-02-16  7:39 UTC (permalink / raw)
  To: Noah Lavine; +Cc: guile-devel

Hey Noha,

Great work indeed.

Isn't the primitiveness decided by tree-il? you wil get a (<primcall>
...) tree il element and then should know how to emit a
corresponding primitive instruction(s). Anyway I think that your
conclusion is right, it would not make sense to support overwriting
these primitives dynamically, but

scheme@(guile-user)> (set! + (lambda x (apply * x)))
scheme@(guile-user)> (+ 2 3)
$1 = 6
scheme@(guile-user)> (define (f x y) (+ x y))
scheme@(guile-user)> ,x f
Disassembly of #<procedure f (x y)>:

   0    (assert-nargs-ee/locals 2)      ;; 2 args, 0 locals
   2    (local-ref 0)                   ;; `x'
   4    (local-ref 1)                   ;; `y'
   6    (add)
   7    (return)

So things are not consistent!

BTW
If you like I could work on getting define* and lambda* to work, I
have that code in my branch and should be able
to make it work on your branch as well. WDYT?

/Stefan

On Sat, Feb 16, 2013 at 1:53 AM, Noah Lavine <noah.b.lavine@gmail.com> wrote:
> Hello,
>
> The wip-rtl-cps branch has been rebased again (on top of wip-rtl). It now
> includes support for toplevel references and sets, thanks mostly to Andy's
> work on supporting them in RTL. (Although you shouldn't kick that part of it
> too hard just yet; I think I know where it will break.) Other highlights
> include using the top-level variable support to evaluate "(+ 3 4)"
> correctly.
>
> Overall, I think it's coming along well. The parts of Tree-IL that are left
> to implement are local mutable variables (should be easy after toplevel
> ones), module references and sets (very similar to top-level ones),
> closures, and the dynamic environment stuff. Local mutable variables are my
> next project, and then I think closures.
>
> One question I've had is, can we assume that the variables in the (guile)
> module are immutable? I think the current compiler does this. Otherwise
> there's no correct way to inline primitive procedures like + unless we have
> a way to invalidate our compiled code and recompile it (which I would like
> to have anyway, but that's a different story).
>
> Best,
> Noah
>



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-02-16  7:39 ` Stefan Israelsson Tampe
@ 2013-02-16 16:29   ` Noah Lavine
  2013-02-16 19:14     ` Mark H Weaver
  2013-02-19 17:29     ` Stefan Israelsson Tampe
  0 siblings, 2 replies; 16+ messages in thread
From: Noah Lavine @ 2013-02-16 16:29 UTC (permalink / raw)
  To: Stefan Israelsson Tampe; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 3191 bytes --]

Hello,


On Sat, Feb 16, 2013 at 2:39 AM, Stefan Israelsson Tampe <
stefan.itampe@gmail.com> wrote:
>
> Isn't the primitiveness decided by tree-il? you wil get a (<primcall>
> ...) tree il element and then should know how to emit a
> corresponding primitive instruction(s).


Oh, you're right. I was thinking about that because I don't run the Tree-IL
optimizers when I test it, so I don't get any Tree-IL primitives.
Eventually maybe the primitive generation should happen in CPS, but I don't
think it has to happen all at once.


> Anyway I think that your
> conclusion is right, it would not make sense to support overwriting
> these primitives dynamically, but
>
> scheme@(guile-user)> (set! + (lambda x (apply * x)))
> scheme@(guile-user)> (+ 2 3)
> $1 = 6
> scheme@(guile-user)> (define (f x y) (+ x y))
> scheme@(guile-user)> ,x f
> Disassembly of #<procedure f (x y)>:
>
>    0    (assert-nargs-ee/locals 2)      ;; 2 args, 0 locals
>    2    (local-ref 0)                   ;; `x'
>    4    (local-ref 1)                   ;; `y'
>    6    (add)
>    7    (return)
>
> So things are not consistent!
>

Good example! This looks like a bug to me. I think I read that loading
GOOPS turns things like '+ into generic operations - that might be a case
where this matters a lot.

I have thought a bit about how to fix this. The module system already
allows us to be notified whenever a variable changes, so it would be easy
to watch all of the variables in (guile) and recompile procedures when they
change. I might take a look at this soon.


> BTW
> If you like I could work on getting define* and lambda* to work, I
> have that code in my branch and should be able
> to make it work on your branch as well. WDYT?


Thanks, but I haven't even gotten far enough to think about this. I'm still
working on getting all of the basic features going. After that I would
definitely like define* and lambda*.

Noah


>
> /Stefan
>
> On Sat, Feb 16, 2013 at 1:53 AM, Noah Lavine <noah.b.lavine@gmail.com>
> wrote:
> > Hello,
> >
> > The wip-rtl-cps branch has been rebased again (on top of wip-rtl). It now
> > includes support for toplevel references and sets, thanks mostly to
> Andy's
> > work on supporting them in RTL. (Although you shouldn't kick that part
> of it
> > too hard just yet; I think I know where it will break.) Other highlights
> > include using the top-level variable support to evaluate "(+ 3 4)"
> > correctly.
> >
> > Overall, I think it's coming along well. The parts of Tree-IL that are
> left
> > to implement are local mutable variables (should be easy after toplevel
> > ones), module references and sets (very similar to top-level ones),
> > closures, and the dynamic environment stuff. Local mutable variables are
> my
> > next project, and then I think closures.
> >
> > One question I've had is, can we assume that the variables in the (guile)
> > module are immutable? I think the current compiler does this. Otherwise
> > there's no correct way to inline primitive procedures like + unless we
> have
> > a way to invalidate our compiled code and recompile it (which I would
> like
> > to have anyway, but that's a different story).
> >
> > Best,
> > Noah
> >
>

[-- Attachment #2: Type: text/html, Size: 4494 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-02-16 16:29   ` Noah Lavine
@ 2013-02-16 19:14     ` Mark H Weaver
  2013-02-16 19:36       ` Noah Lavine
  2013-02-19 17:29     ` Stefan Israelsson Tampe
  1 sibling, 1 reply; 16+ messages in thread
From: Mark H Weaver @ 2013-02-16 19:14 UTC (permalink / raw)
  To: Noah Lavine; +Cc: guile-devel

Noah Lavine <noah.b.lavine@gmail.com> writes:
> Oh, you're right. I was thinking about that because I don't run the
> Tree-IL optimizers when I test it, so I don't get any Tree-IL
> primitives.

I think you should be running the existing tree-il passes before you
convert to CPS.  As I pointed out earlier, many optimizers will not be
able to work well after conversion to CPS, fundamentally because CPS
loses information about where order of evaluation is unspecified.

Furthermore, some of the existing passes make important simplifications
to the resulting tree-il.  For example, the code in fix-letrec.scm
eliminates all <letrec> nodes, so that's one less thing for you to have
to implement.  Primitives.scm marks primitives explicitly using
<primcall> tree-il nodes, so that later code doesn't have to make thorny
assumptions about what variables should be considered primitives.

> I think I read that loading GOOPS turns things like '+ into generic
> operations - that might be a case where this matters a lot.

No, because GOOPS has a special mechanism for cases like '+': they are
called "primitive generics".  When numerical operations are unable to
handle the argument types provided, they calls 'scm_wta_dispatch_*'.
Therefore, adding new methods to numerical operations does not involve
changing their bindings.  This is good because it means that you can
extend numerical operations without slowing them down at all for
built-in numbers.

> I have thought a bit about how to fix this. The module system already
> allows us to be notified whenever a variable changes, so it would be
> easy to watch all of the variables in (guile) and recompile procedures
> when they change. I might take a look at this soon.

This would be nice too, of course, but I warn you that it's a can of
worms.  In the general case, it involves on-stack replacement, because
you might need to recompile a procedure that's currently in the middle
of being run, and thus currently has activation records on the stack(s).

Thanks for you work on this, Noah!

      Mark



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-02-16 19:14     ` Mark H Weaver
@ 2013-02-16 19:36       ` Noah Lavine
  2013-02-16 21:18         ` Mark H Weaver
  0 siblings, 1 reply; 16+ messages in thread
From: Noah Lavine @ 2013-02-16 19:36 UTC (permalink / raw)
  To: Mark H Weaver; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 2990 bytes --]

Hello,

On Sat, Feb 16, 2013 at 2:14 PM, Mark H Weaver <mhw@netris.org> wrote:

> Noah Lavine <noah.b.lavine@gmail.com> writes:
> > Oh, you're right. I was thinking about that because I don't run the
> > Tree-IL optimizers when I test it, so I don't get any Tree-IL
> > primitives.
>
> I think you should be running the existing tree-il passes before you
> convert to CPS.  As I pointed out earlier, many optimizers will not be
> able to work well after conversion to CPS, fundamentally because CPS
> loses information about where order of evaluation is unspecified.
>
> Furthermore, some of the existing passes make important simplifications
> to the resulting tree-il.  For example, the code in fix-letrec.scm
> eliminates all <letrec> nodes, so that's one less thing for you to have
> to implement.  Primitives.scm marks primitives explicitly using
> <primcall> tree-il nodes, so that later code doesn't have to make thorny
> assumptions about what variables should be considered primitives.


Interesting points. I think you're right that Tree-IL should be optimized
first. For the specific issue of order of evaluation, I'm hoping to add
something (either a special function or a special node type) to CPS to
represent continuations that can be evaluated in any order. It seems like
evaluation order is a decision that should be made in either the code
generator or the register allocator, and those operate on CPS. I also
dislike losing information.


> > I think I read that loading GOOPS turns things like '+ into generic
> > operations - that might be a case where this matters a lot.
>
> No, because GOOPS has a special mechanism for cases like '+': they are
> called "primitive generics".  When numerical operations are unable to
> handle the argument types provided, they calls 'scm_wta_dispatch_*'.
> Therefore, adding new methods to numerical operations does not involve
> changing their bindings.  This is good because it means that you can
> extend numerical operations without slowing them down at all for
> built-in numbers.
>

I see. That's very cool.


>
> > I have thought a bit about how to fix this. The module system already
> > allows us to be notified whenever a variable changes, so it would be
> > easy to watch all of the variables in (guile) and recompile procedures
> > when they change. I might take a look at this soon.
>
> This would be nice too, of course, but I warn you that it's a can of
> worms.  In the general case, it involves on-stack replacement, because
> you might need to recompile a procedure that's currently in the middle
> of being run, and thus currently has activation records on the stack(s).
>

You mean if a function modifies another function that called it. Yes, that
seems complicated. It's not very important to me to fix it in general,
because I don't know of a case where it's useful. I think fixing it without
the on-stack replacement would be a reasonable compromise.


> Thanks for you work on this, Noah!
>

Thank you!

Noah

[-- Attachment #2: Type: text/html, Size: 4157 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-02-16 19:36       ` Noah Lavine
@ 2013-02-16 21:18         ` Mark H Weaver
  2013-02-19 15:51           ` Noah Lavine
  0 siblings, 1 reply; 16+ messages in thread
From: Mark H Weaver @ 2013-02-16 21:18 UTC (permalink / raw)
  To: Noah Lavine; +Cc: guile-devel

Hi Noah,

> On Sat, Feb 16, 2013 at 2:14 PM, Mark H Weaver <mhw@netris.org> wrote:
[...]
>     Noah Lavine <noah.b.lavine@gmail.com> writes:
[...]
>     > I have thought a bit about how to fix this. The module system already
>     > allows us to be notified whenever a variable changes, so it would be
>     > easy to watch all of the variables in (guile) and recompile procedures
>     > when they change. I might take a look at this soon.
>     
>     
>     This would be nice too, of course, but I warn you that it's a can of
>     worms.  In the general case, it involves on-stack replacement, because
>     you might need to recompile a procedure that's currently in the middle
>     of being run, and thus currently has activation records on the
>     stack(s).
>     
>
> You mean if a function modifies another function that called it.

There are many other cases.  Think multiple threads, coroutines, logic
programming systems, etc.  That's why I wrote "stack(s)".  Actually, I
should have written "(partial) continuation(s)".  There are any number
of ways that an activation record for some procedure you modify could
still be alive somewhere in the heap.  The issue can arise even with
simple lazy data structures.  I don't think it's something we should
punt on.  IMO anyway.

What do you think?

    Mark



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-02-16 21:18         ` Mark H Weaver
@ 2013-02-19 15:51           ` Noah Lavine
  2013-02-19 16:21             ` Mark H Weaver
  0 siblings, 1 reply; 16+ messages in thread
From: Noah Lavine @ 2013-02-19 15:51 UTC (permalink / raw)
  To: Mark H Weaver; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 1899 bytes --]

Hello,

On Sat, Feb 16, 2013 at 4:18 PM, Mark H Weaver <mhw@netris.org> wrote:

> Hi Noah,
>
> > On Sat, Feb 16, 2013 at 2:14 PM, Mark H Weaver <mhw@netris.org> wrote:
> [...]
> >     Noah Lavine <noah.b.lavine@gmail.com> writes:
> >
> > You mean if a function modifies another function that called it.
>
> There are many other cases.  Think multiple threads, coroutines, logic
> programming systems, etc.  That's why I wrote "stack(s)".  Actually, I
> should have written "(partial) continuation(s)".  There are any number
> of ways that an activation record for some procedure you modify could
> still be alive somewhere in the heap.  The issue can arise even with
> simple lazy data structures.  I don't think it's something we should
> punt on.  IMO anyway.
>
> What do you think?
>

Yes, you're right. I hadn't thought about those cases. This is a tricky
question.

But before we continue, are you sure that the right semantics is to modify
all of the continuations? In particular, let's say you have a function like
this:

(define (func x)
  (+ x 2 (my-special-function x)))

And my-special-function captures its continuation, k. Later on, you modify
func to be this:

(define (func x)
  (+ x 2))

Now what is the continuation k supposed to do? That continuation doesn't
exist in the latest version of func. I think in this case you have to treat
it like a closure that is still holding on to the continuation that it was
passed (conceptually, at least) when it was called. So it would return to
the old version of func.

On the other hand, take the same example, but this time redefine "+"
instead of "func". Now, does the continuation k call the new definition of
+, or the old one?

These really are questions for me. I don't know what the correct behavior
here is, but I think that if we can answer both of these questions, then we
know more or less what the correct thing to do is.

Noah

[-- Attachment #2: Type: text/html, Size: 2811 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-02-19 15:51           ` Noah Lavine
@ 2013-02-19 16:21             ` Mark H Weaver
  2013-02-22  8:25               ` William ML Leslie
  0 siblings, 1 reply; 16+ messages in thread
From: Mark H Weaver @ 2013-02-19 16:21 UTC (permalink / raw)
  To: Noah Lavine; +Cc: guile-devel

Noah Lavine <noah.b.lavine@gmail.com> writes:
> But before we continue, are you sure that the right semantics is to
> modify all of the continuations? In particular, let's say you have a
> function like this:
>
> (define (func x)
>   (+ x 2 (my-special-function x)))
>
> And my-special-function captures its continuation, k. Later on, you
> modify func to be this:
>
> (define (func x)
>   (+ x 2))
>
> Now what is the continuation k supposed to do? That continuation
> doesn't exist in the latest version of func. I think in this case you
> have to treat it like a closure that is still holding on to the
> continuation that it was passed (conceptually, at least) when it was
> called. So it would return to the old version of func.

Yes.  If you redefine 'func', that only affects future calls to func,
not existing calls.

> On the other hand, take the same example, but this time redefine "+"
> instead of "func". Now, does the continuation k call the new
> definition of +, or the old one?

In your example above, it's unspecified, because the operator and
operands of a procedure call are evaluated in unspecified order.
Therefore, an implementation is allowed to evaluate '+' either before or
after it evaluates (my-special-function x).

However, consider this slightly different example:

(define (func x)
  (let ((r (my-special-function x)))
    (+ x 2 r)))

Here, (my-special-function x) must be evaluated before evaluating '+'.
Evaluating '+' means to fetch the value stored in the location denoted
by '+'.  Therefore, if '+' is rebound during the call to
'my-special-function', then the new binding for '+' must be used.

This is a case where on-stack-replacement is needed to implement the
correct semantics.

To summarize, when you rebind a function 'foo', it is not the existing
activation records for 'foo' that you need to worry about.  Instead, you
need to worry about existing activation records for all compiled
procedures 'bar' that incorporated assumptions about 'foo'.

Thanks for working on this,

     Mark



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-02-16 16:29   ` Noah Lavine
  2013-02-16 19:14     ` Mark H Weaver
@ 2013-02-19 17:29     ` Stefan Israelsson Tampe
  1 sibling, 0 replies; 16+ messages in thread
From: Stefan Israelsson Tampe @ 2013-02-19 17:29 UTC (permalink / raw)
  To: Noah Lavine; +Cc: guile-devel

Hi,

1. Does any other system recompile stuff that set! a + operation
2. Isn't the least we should do to warn when a user set! + as I did in
the last email
3. Wouldn't it be a good idea to allow a user to specify which basic
vm op's would be translated
   to a macine instruction or not. So say that I would like to count
the number of scheme + guile uses at
   startup, then I could specify in a configuration that + should not
be comiled to a vm-op and then recompile guile and then use set!

On Sat, Feb 16, 2013 at 5:29 PM, Noah Lavine <noah.b.lavine@gmail.com> wrote:
> Hello,
>
>
> On Sat, Feb 16, 2013 at 2:39 AM, Stefan Israelsson Tampe
> <stefan.itampe@gmail.com> wrote:
>>
>> Isn't the primitiveness decided by tree-il? you wil get a (<primcall>
>> ...) tree il element and then should know how to emit a
>> corresponding primitive instruction(s).
>
>
> Oh, you're right. I was thinking about that because I don't run the Tree-IL
> optimizers when I test it, so I don't get any Tree-IL primitives. Eventually
> maybe the primitive generation should happen in CPS, but I don't think it
> has to happen all at once.
>
>>
>> Anyway I think that your
>> conclusion is right, it would not make sense to support overwriting
>> these primitives dynamically, but
>>
>> scheme@(guile-user)> (set! + (lambda x (apply * x)))
>> scheme@(guile-user)> (+ 2 3)
>> $1 = 6
>> scheme@(guile-user)> (define (f x y) (+ x y))
>> scheme@(guile-user)> ,x f
>> Disassembly of #<procedure f (x y)>:
>>
>>    0    (assert-nargs-ee/locals 2)      ;; 2 args, 0 locals
>>    2    (local-ref 0)                   ;; `x'
>>    4    (local-ref 1)                   ;; `y'
>>    6    (add)
>>    7    (return)
>>
>> So things are not consistent!
>
>
> Good example! This looks like a bug to me. I think I read that loading GOOPS
> turns things like '+ into generic operations - that might be a case where
> this matters a lot.
>
> I have thought a bit about how to fix this. The module system already allows
> us to be notified whenever a variable changes, so it would be easy to watch
> all of the variables in (guile) and recompile procedures when they change. I
> might take a look at this soon.
>
>>
>> BTW
>> If you like I could work on getting define* and lambda* to work, I
>> have that code in my branch and should be able
>> to make it work on your branch as well. WDYT?
>
>
> Thanks, but I haven't even gotten far enough to think about this. I'm still
> working on getting all of the basic features going. After that I would
> definitely like define* and lambda*.
>
> Noah
>
>>
>>
>> /Stefan
>>
>> On Sat, Feb 16, 2013 at 1:53 AM, Noah Lavine <noah.b.lavine@gmail.com>
>> wrote:
>> > Hello,
>> >
>> > The wip-rtl-cps branch has been rebased again (on top of wip-rtl). It
>> > now
>> > includes support for toplevel references and sets, thanks mostly to
>> > Andy's
>> > work on supporting them in RTL. (Although you shouldn't kick that part
>> > of it
>> > too hard just yet; I think I know where it will break.) Other highlights
>> > include using the top-level variable support to evaluate "(+ 3 4)"
>> > correctly.
>> >
>> > Overall, I think it's coming along well. The parts of Tree-IL that are
>> > left
>> > to implement are local mutable variables (should be easy after toplevel
>> > ones), module references and sets (very similar to top-level ones),
>> > closures, and the dynamic environment stuff. Local mutable variables are
>> > my
>> > next project, and then I think closures.
>> >
>> > One question I've had is, can we assume that the variables in the
>> > (guile)
>> > module are immutable? I think the current compiler does this. Otherwise
>> > there's no correct way to inline primitive procedures like + unless we
>> > have
>> > a way to invalidate our compiled code and recompile it (which I would
>> > like
>> > to have anyway, but that's a different story).
>> >
>> > Best,
>> > Noah
>> >
>
>



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-02-19 16:21             ` Mark H Weaver
@ 2013-02-22  8:25               ` William ML Leslie
  2013-02-23  7:49                 ` Mark H Weaver
  0 siblings, 1 reply; 16+ messages in thread
From: William ML Leslie @ 2013-02-22  8:25 UTC (permalink / raw)
  To: guile-devel

On 20 February 2013 03:21, Mark H Weaver <mhw@netris.org> wrote:
> (define (func x)
>   (let ((r (my-special-function x)))
>     (+ x 2 r)))
>
> Here, (my-special-function x) must be evaluated before evaluating '+'.
> Evaluating '+' means to fetch the value stored in the location denoted
> by '+'.  Therefore, if '+' is rebound during the call to
> 'my-special-function', then the new binding for '+' must be used.
>
> This is a case where on-stack-replacement is needed to implement the
> correct semantics.
>
> To summarize, when you rebind a function 'foo', it is not the existing
> activation records for 'foo' that you need to worry about.  Instead, you
> need to worry about existing activation records for all compiled
> procedures 'bar' that incorporated assumptions about 'foo'.

Recompiling every procedure that uses + when somebody binds it means
compiling a lot of code that probably isn't going to be used.  More
likely, if + has been inlined here, the compiler will have to emit a
guard that checks inlining assumptions as the start of the let body.
This is how those sort of semantics are preserved where OSR is not
implemented.

Regarding rebinding (+): A few people have expressed opinions about
scheme becoming less fluid, and I think most would probably agree that
even if certain bindings are assumed constant or types are declared in
module APIs and specialised code generated, the most-general code
still wants to be available, and ideally from within the .so .

-- 
William Leslie



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-02-22  8:25               ` William ML Leslie
@ 2013-02-23  7:49                 ` Mark H Weaver
  2013-02-25  4:54                   ` William ML Leslie
  0 siblings, 1 reply; 16+ messages in thread
From: Mark H Weaver @ 2013-02-23  7:49 UTC (permalink / raw)
  To: William ML Leslie; +Cc: guile-devel

William ML Leslie <william.leslie.ttg@gmail.com> writes:

> On 20 February 2013 03:21, Mark H Weaver <mhw@netris.org> wrote:
>> (define (func x)
>>   (let ((r (my-special-function x)))
>>     (+ x 2 r)))
>>
>> Here, (my-special-function x) must be evaluated before evaluating '+'.
>> Evaluating '+' means to fetch the value stored in the location denoted
>> by '+'.  Therefore, if '+' is rebound during the call to
>> 'my-special-function', then the new binding for '+' must be used.
>>
>> This is a case where on-stack-replacement is needed to implement the
>> correct semantics.
>>
>> To summarize, when you rebind a function 'foo', it is not the existing
>> activation records for 'foo' that you need to worry about.  Instead, you
>> need to worry about existing activation records for all compiled
>> procedures 'bar' that incorporated assumptions about 'foo'.
>
> Recompiling every procedure that uses + when somebody binds it means
> compiling a lot of code that probably isn't going to be used.  More
> likely, if + has been inlined here, the compiler will have to emit a
> guard that checks inlining assumptions as the start of the let body.

I'm afraid this isn't good enough.  Even if one ignores the possibility
of multiple threads, checks would have to be added not just at the start
of each let body, but also upon return from every procedure that might
rebind '+' or capture its continuation.  This includes all procedures
accessed through toplevel/module bindings.

Therefore, I repeat my initial assertion that this is a can of worms.
I'd like to see it implemented in Guile some day, but it's a big job.

     Regards,
       Mark



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-02-23  7:49                 ` Mark H Weaver
@ 2013-02-25  4:54                   ` William ML Leslie
  2013-02-26 10:24                     ` Mark H Weaver
  0 siblings, 1 reply; 16+ messages in thread
From: William ML Leslie @ 2013-02-25  4:54 UTC (permalink / raw)
  To: guile-devel

On 23 February 2013 18:49, Mark H Weaver <mhw@netris.org> wrote:
> William ML Leslie <william.leslie.ttg@gmail.com> writes:
>> Recompiling every procedure that uses + when somebody binds it means
>> compiling a lot of code that probably isn't going to be used.  More
>> likely, if + has been inlined here, the compiler will have to emit a
>> guard that checks inlining assumptions as the start of the let body.
>
> I'm afraid this isn't good enough.  Even if one ignores the possibility
> of multiple threads, checks would have to be added not just at the start
> of each let body, but also upon return from every procedure that might
> rebind '+' or capture its continuation.  This includes all procedures
> accessed through toplevel/module bindings.

Not each let body, the let body in the example code.  Specifically, a
guard needs to be placed whenever code with undetermined effect
happens-before a 'call' to an inlined function.  That we are talking
about happens-before means the possibility of runtime invalidation of
code is limited not only by calls to functions of unknown effect, but
also by usages of the variable.

> Therefore, I repeat my initial assertion that this is a can of worms.

Except that most dynamic compilers for imperative languages already do
this (because it's a pretty common thing to need to do).

--
William Leslie



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-02-25  4:54                   ` William ML Leslie
@ 2013-02-26 10:24                     ` Mark H Weaver
  0 siblings, 0 replies; 16+ messages in thread
From: Mark H Weaver @ 2013-02-26 10:24 UTC (permalink / raw)
  To: William ML Leslie; +Cc: guile-devel

Hi William,

William ML Leslie <william.leslie.ttg@gmail.com> writes:
> On 23 February 2013 18:49, Mark H Weaver <mhw@netris.org> wrote:
>> William ML Leslie <william.leslie.ttg@gmail.com> writes:
>>> Recompiling every procedure that uses + when somebody binds it means
>>> compiling a lot of code that probably isn't going to be used.  More
>>> likely, if + has been inlined here, the compiler will have to emit a
>>> guard that checks inlining assumptions as the start of the let body.
>>
>> I'm afraid this isn't good enough.  Even if one ignores the possibility
>> of multiple threads, checks would have to be added not just at the start
>> of each let body, but also upon return from every procedure that might
>> rebind '+' or capture its continuation.  This includes all procedures
>> accessed through toplevel/module bindings.
>
> Not each let body, the let body in the example code.

Ah, sorry, I misunderstood you.

> Specifically, a guard needs to be placed whenever code with
> undetermined effect happens-before a 'call' to an inlined function.

Yes.  Thank you for expressing it much more clearly than I had.  I would
further refine it to "a guard needs to be placed whenever code that
might mutate an inlined variable happens-before the inlined variable
would have been referenced."

> That we are talking about happens-before means the possibility of
> runtime invalidation of code is limited not only by calls to functions
> of unknown effect, but also by usages of the variable.

You bring up an important point: that a happens-before relation can be
composed of an arbitrarily long chain of other relations.  This requires
more careful study.

>> Therefore, I repeat my initial assertion that this is a can of worms.
>
> Except that most dynamic compilers for imperative languages already do
> this (because it's a pretty common thing to need to do).

I didn't realize that this technique was so commonly implemented.
Nonetheless, I worry that this technique may not perform as well for
Scheme as for other languages.  The reason is that in Scheme, calls to
procedures of unknown effect are vastly more common than in other
languages, at least for Schemes that allow arbitrary variables such as
'+' to be mutated.

Thanks for your insights.

     Regards,
       Mark



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-02-16  0:53 CPS Update Noah Lavine
  2013-02-16  7:39 ` Stefan Israelsson Tampe
@ 2013-03-08 22:57 ` Noah Lavine
  2013-03-09  8:31   ` Andy Wingo
  1 sibling, 1 reply; 16+ messages in thread
From: Noah Lavine @ 2013-03-08 22:57 UTC (permalink / raw)
  To: guile-devel

[-- Attachment #1: Type: text/plain, Size: 2578 bytes --]

Hello,

Another quick update on CPS. I just pushed patches that implement closure
conversion and use it to compile closures correctly. I think this is a big
step forward for the CPS compiler. Since the last email, I've also
implemented local mutable variables, and sequences (as part of that).

Somewhat shockingly, I think that's almost every language feature. The
other things (dynamic environment, prompts) can actually be done by making
closures and calling the functions that implement them - it's just faster
to use the RTL instructions. However, I think the primitive procedure
generation is robust enough to handle those without too much trouble.

The bigger task now is a combination of finding and eliminating bugs and
slowly removing the ugly hacks I put in there. I don't think there are too
many, but the way the closure conversion handles letrecs and the big case
statement in the  primitive instruction generator are notable examples.
There are also some arbitrary limitations in the code - things like only
allowing one argument to a procedure, or one procedure in a letrec. I put
those in because I knew I could remove them without fundamentally changing
things, and I wanted to sketch out the whole compiler first to get the
organization right. Now I need to go through and fix all of that.

But overall, I think the CPS compiler is going well.

Best,
Noah



On Fri, Feb 15, 2013 at 7:53 PM, Noah Lavine <noah.b.lavine@gmail.com>wrote:

> Hello,
>
> The wip-rtl-cps branch has been rebased again (on top of wip-rtl). It now
> includes support for toplevel references and sets, thanks mostly to Andy's
> work on supporting them in RTL. (Although you shouldn't kick that part of
> it too hard just yet; I think I know where it will break.) Other highlights
> include using the top-level variable support to evaluate "(+ 3 4)"
> correctly.
>
> Overall, I think it's coming along well. The parts of Tree-IL that are
> left to implement are local mutable variables (should be easy after
> toplevel ones), module references and sets (very similar to top-level
> ones), closures, and the dynamic environment stuff. Local mutable variables
> are my next project, and then I think closures.
>
> One question I've had is, can we assume that the variables in the (guile)
> module are immutable? I think the current compiler does this. Otherwise
> there's no correct way to inline primitive procedures like + unless we have
> a way to invalidate our compiled code and recompile it (which I would like
> to have anyway, but that's a different story).
>
> Best,
> Noah
>
>

[-- Attachment #2: Type: text/html, Size: 3161 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-03-08 22:57 ` Noah Lavine
@ 2013-03-09  8:31   ` Andy Wingo
  2013-04-03 20:50     ` Noah Lavine
  0 siblings, 1 reply; 16+ messages in thread
From: Andy Wingo @ 2013-03-09  8:31 UTC (permalink / raw)
  To: Noah Lavine; +Cc: guile-devel

On Fri 08 Mar 2013 23:57, Noah Lavine <noah.b.lavine@gmail.com> writes:

> Somewhat shockingly, I think that's almost every language feature.

Wow, nice work :-))

Sounds like great stuff.  I hope to join you in this work once 2.0.8 is
out.  It's really great that you're working on this!

Cheers,

Andy
-- 
http://wingolog.org/



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CPS Update
  2013-03-09  8:31   ` Andy Wingo
@ 2013-04-03 20:50     ` Noah Lavine
  0 siblings, 0 replies; 16+ messages in thread
From: Noah Lavine @ 2013-04-03 20:50 UTC (permalink / raw)
  To: Andy Wingo; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 525 bytes --]

On Sat, Mar 9, 2013 at 3:31 AM, Andy Wingo <wingo@pobox.com> wrote:

> On Fri 08 Mar 2013 23:57, Noah Lavine <noah.b.lavine@gmail.com> writes:
>
> > Somewhat shockingly, I think that's almost every language feature.
>
> Wow, nice work :-))
>
> Sounds like great stuff.  I hope to join you in this work once 2.0.8 is
> out.  It's really great that you're working on this!
>

Thanks a lot. I am not an expert by any means, and it would be great to
have someone like you who really knows what they're doing hacking at it.

Noah

[-- Attachment #2: Type: text/html, Size: 1009 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2013-04-03 20:50 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-02-16  0:53 CPS Update Noah Lavine
2013-02-16  7:39 ` Stefan Israelsson Tampe
2013-02-16 16:29   ` Noah Lavine
2013-02-16 19:14     ` Mark H Weaver
2013-02-16 19:36       ` Noah Lavine
2013-02-16 21:18         ` Mark H Weaver
2013-02-19 15:51           ` Noah Lavine
2013-02-19 16:21             ` Mark H Weaver
2013-02-22  8:25               ` William ML Leslie
2013-02-23  7:49                 ` Mark H Weaver
2013-02-25  4:54                   ` William ML Leslie
2013-02-26 10:24                     ` Mark H Weaver
2013-02-19 17:29     ` Stefan Israelsson Tampe
2013-03-08 22:57 ` Noah Lavine
2013-03-09  8:31   ` Andy Wingo
2013-04-03 20:50     ` Noah Lavine

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).