Re: Next Apocalypse
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
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
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
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
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
--- 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
Leopold Toetsch <[EMAIL PROTECTED]> writes: > Piers Cawley <[EMAIL PROTECTED]> wrote: >> ... spending the morning of your 36th birthday > > Happy birthday to you and us. Thanks.