Re: Next Apocalypse

2003-09-16 Thread Robin Berjon
My, is this a conspiracy to drag -internals onto -language to make it look alive? :)

You guys almost made me drop my coffee mug...

--
Robin Berjon <[EMAIL PROTECTED]>
Research Scientist, Expway  http://expway.com/
7FC0 6F5F D864 EFB8 08CE  8E74 58E6 D5DB 4889 2488


Re: This week's summary

2003-09-16 Thread Leopold Toetsch
Piers Cawley <[EMAIL PROTECTED]> wrote:
> ... spending the morning of your 36th birthday

Happy birthday to you and us.
l - "A full year has passed, hasn't it?" - eo


Re: Next Apocalypse

2003-09-16 Thread Dan Sugalski
On Tue, 16 Sep 2003, Ph. Marek wrote:

> > You can, of course, stop even potential optimization once the first "I can
> > change the rules" operation is found, but since even assignment can change
> > the rules that's where we are right now. We'd like to get better by
> > optimizing based on what we can see at compile time, but that's a very,
> > very difficult thing to do.

> How about retaining some "debug" info, (line number come to mind), but only at 
> expression level??

This is insufficient, since many (potentially most) optimizations result 
in reordered, refactored, moved, and/or mangled code that doesn't have a 
line-for-line, or expression-for-expression, correspondence to the 
original. If it did, this would all be much easier.

The alternative, of course, is to not apply those transforms, but then 
you're left with pretty much no optimizations.

Dan



Re: Next Apocalypse

2003-09-16 Thread David Storrs
On Mon, Sep 15, 2003 at 11:49:52AM -0400, Gordon Henriksen wrote:
> Austin Hastings wrote:
> 
> > Given that threads are present, and given the continuation based
> > nature of the interpreter, I assume that code blocks can be closured.
> > So why not allocate JITed methods on the heap and manage them as first
> > class closures, so that the stackref will hold them until the stack
> > exits?
> 
> 
> Austin,
> 
> That's a fine and dandy way to do some things, like progressive
> optimization ala HotSpot. (e.g., "Oh! I've been called 10,000 times.
> Maybe you should bother to run a peephole analyzer over me?") But when
> an assumption made by the already-executing routine is actually
> violated, it causes incorrect behavior. Here's an example:
> 
> class My::PluginBase;
> 
> method say_hi() {
> # Default implementation.
> print "Hello, world.\n";
> }
> 
> 
> package main;
> 
> load_plugin($filepath) { ... }
> 
> my $plugin is My::PluginBase;
> $plugin = load_plugin($ARGV[0]);
> $plugin.SayHi();
> 
> Now, while it would obviously seem a bad idea to you, it would be
> reasonable for perl to initially optimize the method call
> $plugin.say_hi() to the function call My::PluginBase::say_hi($plugin).
> But when load_plugin loads a subclass of My::PluginBase from the file
> specified in $ARGV[0], then that assumption is violated. Now, the
> optimization has to be backed out, or the program will never call the
> subclass's say_hi. Letting the GC clean up the old version of main when
> the notification is received isn't enough--the existing stack frame must
> actually be rewritten to use the newly-compiled version.


This discussion seems to contain two separate problems, and I'm not
always sure which one is being addressed.  The components I see are:

1) Detecting when the assumptions have been violated and the code has
   to be changed; and,

2) Actually making the change after we know that we need to.


I have at least a vague idea of why #1 would be difficult.  As to
#2...assuming that the original source is available (or can be
recovered), then regenerating the expression does not seem difficult.
Or am I missing something?


--Dks


RE: Next Apocalypse

2003-09-16 Thread Gordon Henriksen
David Storrs wrote:

> This discussion seems to contain two separate problems, and I'm not
> always sure which one is being addressed.  The components I see are:
> 
> 1) Detecting when the assumptions have been violated and the code has
>to be changed; and,
> 
> 2) Actually making the change after we know that we need to.
> 
> 
> I have at least a vague idea of why #1 would be difficult.  As to
> #2...assuming that the original source is available (or can be
> recovered), then regenerating the expression does not seem difficult.
> Or am I missing something?

David,

Recompiling isn't hard (assuming that compiling is already implemented).
Nor is notification of changes truly very difficult.

What you're missing is what I was trying to demonstrate with my plugin
example, and what Dan also pointed out with his mutating a subroutine
that returns a constant (and was presumably inlined). If the routine is
RUNNING at the time an assumption made by the optimizer becomes invalid,
then the stack frame needs to be munged from the old, optimized version
compilation to the new, pessimized version. THAT is the hard
problem--one of register & variable remapping and PC mutation--and it is
impossible to solve after code motion optimizations, for the same reason
that C++ debuggers get horribly confused when running over -O3 code.

--
 
Gordon Henriksen
IT Manager
ICLUBcentral Inc.
[EMAIL PROTECTED]




RE: Next Apocalypse

2003-09-16 Thread Austin Hastings

--- Gordon Henriksen <[EMAIL PROTECTED]> wrote:
> David Storrs wrote:
> 
> > This discussion seems to contain two separate problems, and I'm not
> > always sure which one is being addressed.  The components I see
> are:
> > 
> > 1) Detecting when the assumptions have been violated and the code
> has
> >to be changed; and,
> > 
> > 2) Actually making the change after we know that we need to.
> > 
> > 
> > I have at least a vague idea of why #1 would be difficult.  As to
> > #2...assuming that the original source is available (or can be
> > recovered), then regenerating the expression does not seem
> difficult.
> > Or am I missing something?
> 
> David,
> 
> Recompiling isn't hard (assuming that compiling is already
> implemented).
> Nor is notification of changes truly very difficult.
> 

Let's try again:

 1: sub othersub {...}
 2:
 3: sub foo {
 4:   my $a = 13;
 5:   my $b = 12;
 6: 
 7:othersub;
 8:my $c = $a + $b;
 9: 
10:print $c;
11: }
12:
13: eval "sub othersub { &::infix+ := &::infix-; }";
14: foo;

In theory, we should get Object(1) as a result.

So let's compile that:

4: temp_a = 13;
5: temp_b = 12;
7: call othersub
8: push temp_b
8: push temp_a
8: call ::infix+
9: call print

Now let's optimize it:

; temp_a, temp_b are MY, so suppress them.
7:  call othersub
 ; We do CSE at compile time
 ; We don't use C after the print, so drop it
9:  push 25
9:  call print

So when we execute othersub, and notice that the world has shifted
beneath our feet, what do we do?

We don't even have the right registers laying about. There are no "a"
and "b" values to pass to the operator+ routine. (An advantage,
actually: losing an intermediate value would be a worse scenario.)

Two possibilities:

1- Some classes of optimization could be forced to occupy a certain
minimum size. The act of breaking the optimization assumptions could
replace the optimization (e.g., CSE) with a thunk.

  Example:
cse: push 25
 call print

  Becomes:
cse: push 25
 branch $+3
 nop
 nop
 call print

  So that we could replace it with:
cse: call undo_cse
 call print

  Where presumably undo_cse performed the operations in source code
order. (What's more, it would make perl binaries *very* compressible
:-)

2- In the "living dangerously" category, go with my original
suggestion: GC the compiled code blocks, and just keep executing what
you've got until you leave the block. Arguably, sequence points could
be used here to partition the blocks into smaller elements.

This tends to make event loops act really stupid, but ...

=Austin



Re: This week's summary

2003-09-16 Thread Piers Cawley
Leopold Toetsch <[EMAIL PROTECTED]> writes:

> Piers Cawley <[EMAIL PROTECTED]> wrote:
>> ... spending the morning of your 36th birthday
>
> Happy birthday to you and us.

Thanks.