ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Faster/Faster.pm
(Generate patch)

Comparing Faster/Faster.pm (file contents):
Revision 1.30 by root, Mon Mar 13 16:59:36 2006 UTC vs.
Revision 1.34 by root, Wed Mar 15 02:32:27 2006 UTC

8 8
9 perl -MFaster ... 9 perl -MFaster ...
10 10
11=head1 DESCRIPTION 11=head1 DESCRIPTION
12 12
13This module implements a very simple-minded JIT. It works by more or less 13This module implements a very simple-minded "JIT" (or actually AIT, ahead
14translating every function it sees into a C program, compiling it and then 14of time compiler). It works by more or less translating every function it
15replacing the function by the compiled code. 15sees into a C program, compiling it and then replacing the function by the
16compiled code.
16 17
17As a result, startup times are immense, as every function might lead to a 18As a result, startup times are immense, as every function might lead to a
18full-blown compilation. 19full-blown compilation.
19 20
20The speed improvements are also not great, you can expect 20% or so on 21The speed improvements are also not great, you can expect 20% or so on
21average, for code that runs very often. 22average, for code that runs very often. The reason for this is that data
23handling is mostly being done by the same old code, it just gets called
24a bit faster. Regexes and string operations won't get faster. Airhtmetic
25doresn't become any faster. Just the operands and other stuff is put on
26the stack faster, and the opcodes themselves have a bit less overhead.
22 27
23Faster is in the early stages of development. Due to its design its 28Faster is in the early stages of development. Due to its design its
24relatively safe to use (it will either work or simply slowdown the program 29relatively safe to use (it will either work or simply slowdown the program
25immensely, but rarely cause bugs). 30immensely, but rarely cause bugs).
26 31
32More intelligent algorithms (loop optimisation, type inference) could
33improve that easily, but requires a much more elaborate presentation and
34optimiser than what is in place. There are no plans to improve Faster in
35this way, yet, but it would provide a reasonably good place to start.
36
27Usage is very easy, just C<use Faster> and every function called from then 37Usage is very easy, just C<use Faster> and every function called from then
28on will be compiled. 38on will be compiled.
29 39
30Right now, Faster will leave lots of F<*.c>, F<*.o> and F<*.so> files in 40Right now, Faster can leave lots of F<*.c> and F<*.so> files in your
31your F<$FASTER_CACHEDIR> (by default F<$HOME/.perl-faster-cache>), and it 41F<$FASTER_CACHEDIR> (by default F<$HOME/.perl-faster-cache>), and it will
32will even create those temporary files in an insecure manner, so watch 42even create those temporary files in an insecure manner, so watch out.
33out.
34 43
35=over 4 44=over 4
36 45
37=cut 46=cut
38 47
63 File::Temp::tempdir (CLEANUP => 1) 72 File::Temp::tempdir (CLEANUP => 1)
64 }; 73 };
65 74
66my $COMPILE = "$Config{cc} -c -I$Config{archlibexp}/CORE $Config{optimize} $Config{ccflags} $Config{cccdlflags}"; 75my $COMPILE = "$Config{cc} -c -I$Config{archlibexp}/CORE $Config{optimize} $Config{ccflags} $Config{cccdlflags}";
67my $LINK = "$Config{ld} $Config{ldflags} $Config{lddlflags} $Config{ccdlflags}"; 76my $LINK = "$Config{ld} $Config{ldflags} $Config{lddlflags} $Config{ccdlflags}";
68my $LIBS = "$Config{libs}"; 77my $LIBS = "";
69my $_o = $Config{_o}; 78my $_o = $Config{_o};
70my $_so = ".so"; 79my $_so = ".so";
71 80
72# we don't need no steenking PIC on x86 81# we don't need no steenking PIC on x86
73$COMPILE =~ s/-f(?:PIC|pic)//g 82$COMPILE =~ s/-f(?:PIC|pic)//g
74 if $Config{archname} =~ /^(i[3456]86)-/; 83 if $Config{archname} =~ /^(i[3456]86)-/;
75 84
76my $opt_assert = $ENV{FASTER_DEBUG} > 1; 85my $opt_assert = $ENV{FASTER_DEBUG} & 2;
77my $verbose = $ENV{FASTER_VERBOSE}+0; 86my $verbose = $ENV{FASTER_VERBOSE}+0;
78 87
79warn "Faster: CACHEDIR is $CACHEDIR\n" if $verbose > 2; 88warn "Faster: CACHEDIR is $CACHEDIR\n" if $verbose > 2;
80 89
81our $source; 90our $source;
82 91
83our @ops; 92our @ops;
84our $insn; 93our $insn;
85our $op; 94our $op;
86our $op_name; 95our $op_name;
87our @op_loop;
88our %op_regcomp; 96our %op_regcomp;
89 97
90# ops that cause immediate return to the interpreter 98# ops that cause immediate return to the interpreter
91my %f_unsafe = map +($_ => undef), qw( 99my %f_unsafe = map +($_ => undef), qw(
92 leavesub leavesublv return 100 leavesub leavesublv return
154 padsv padav padhv padany 162 padsv padav padhv padany
155 aassign sassign orassign 163 aassign sassign orassign
156 rv2av rv2cv rv2gv rv2hv refgen 164 rv2av rv2cv rv2gv rv2hv refgen
157 gv gvsv 165 gv gvsv
158 add subtract multiply divide 166 add subtract multiply divide
159 complement cond_expr and or not bit_and bit_or bit_xor 167 complement cond_expr and or not
168 bit_and bit_or bit_xor
160 defined 169 defined
161 method method_named bless 170 method method_named bless
162 preinc postinc predec postdec 171 preinc postinc predec postdec
163 aelem aelemfast helem delete exists 172 aelem aelemfast helem delete exists
164 pushre subst list lslice join split concat 173 pushre subst list lslice join split concat
185sub out_callop { 194sub out_callop {
186 assert "nextop == (OP *)$$op"; 195 assert "nextop == (OP *)$$op";
187 $source .= " PL_op = nextop; nextop = " . (callop $op) . ";\n"; 196 $source .= " PL_op = nextop; nextop = " . (callop $op) . ";\n";
188} 197}
189 198
199sub out_jump {
200 assert "nextop == (OP *)${$_[0]}L";
201 $source .= " goto op_${$_[0]};\n";
202}
203
190sub out_cond_jump { 204sub out_cond_jump {
191 $source .= " if (nextop == (OP *)${$_[0]}L) goto op_${$_[0]};\n"; 205 $source .= " if (nextop == (OP *)${$_[0]}L) goto op_${$_[0]};\n";
192} 206}
193 207
194sub out_jump_next { 208sub out_jump_next {
485} 499}
486 500
487sub out_break_op { 501sub out_break_op {
488 my ($idx) = @_; 502 my ($idx) = @_;
489 503
504 if ($op->flags & B::OPf_SPECIAL && $insn->{loop}) {
505 # common case: no label, innermost loop only
506 my $next = $insn->{loop}{loop_targ}[$idx];
490 out_callop; 507 out_callop;
491 508 out_jump $next;
492 out_cond_jump $_->[$idx] 509 } elsif (my $loop = $insn->{loop}) {
493 for reverse @op_loop; 510 # less common case: maybe break to some outer loop
494
495 $source .= " return nextop;\n"; 511 $source .= " return nextop;\n";
512 # todo: walk stack up
513 } else {
514 $source .= " return nextop;\n";
515 }
496} 516}
497 517
498sub xop_next { 518sub op_next {
499 out_break_op 0; 519 out_break_op 0;
500} 520}
501 521
502sub op_last { 522sub op_last {
503 out_break_op 1; 523 out_break_op 1;
509 529
510sub cv2c { 530sub cv2c {
511 my ($cv) = @_; 531 my ($cv) = @_;
512 532
513 local @ops; 533 local @ops;
514 local @op_loop;
515 local %op_regcomp; 534 local %op_regcomp;
516 535
517 my %opsseen; 536 my $curloop;
518 my @todo = $cv->START; 537 my @todo = $cv->START;
519 my %op_target; 538 my %op_target;
520 my $numpushmark; 539 my $numpushmark;
540 my $scope;
521 541
542 my %op_seen;
522 while (my $op = shift @todo) { 543 while (my $op = shift @todo) {
544 my $next;
523 for (; $$op; $op = $op->next) { 545 for (; $$op; $op = $next) {
524 last if $opsseen{$$op}++; 546 last if $op_seen{$$op}++;
547
548 $next = $op->next;
525 549
526 my $name = $op->name; 550 my $name = $op->name;
527 my $class = B::class $op; 551 my $class = B::class $op;
528 552
529 my $insn = { op => $op }; 553 my $insn = { op => $op };
554
555 # end of loop reached?
556 $curloop = $curloop->{loop} if $curloop && $$op == ${$curloop->{loop_targ}[1]};
557
558 # remember enclosing loop
559 $insn->{loop} = $curloop if $curloop;
530 560
531 push @ops, $insn; 561 push @ops, $insn;
532 562
533 if (exists $extend{$name}) { 563 if (exists $extend{$name}) {
534 my $extend = $extend{$name}; 564 my $extend = $extend{$name};
535 $extend = $extend->($op) if ref $extend; 565 $extend = $extend->($op) if ref $extend;
536 $insn->{extend} = $extend if defined $extend; 566 $insn->{extend} = $extend if defined $extend;
537 } 567 }
538 568
539 push @todo, $op->next; 569 # TODO: mark scopes similar to loops, make them comparable
540 570 # static cxstack(?)
541 if ($class eq "LOGOP") { 571 if ($class eq "LOGOP") {
542 push @todo, $op->other; 572 push @todo, $op->other;
543 $op_target{${$op->other}}++; 573 $op_target{${$op->other}}++;
544 574
545 # regcomp/o patches ops at runtime, lets expect that 575 # regcomp/o patches ops at runtime, lets expect that
553 unshift @todo, $op->pmreplstart; 583 unshift @todo, $op->pmreplstart;
554 $op_target{${$op->pmreplstart}}++; 584 $op_target{${$op->pmreplstart}}++;
555 } 585 }
556 586
557 } elsif ($class eq "LOOP") { 587 } elsif ($class eq "LOOP") {
558 my @targ = ($op->nextop, $op->lastop->next, $op->redoop->next); 588 my @targ = ($op->nextop, $op->lastop->next, $op->redoop);
559 589
560 push @op_loop, \@targ; 590 unshift @todo, $next, $op->redoop, $op->nextop, $op->lastop;
561 push @todo, @targ; 591 $next = $op->redoop;
562 592
563 $op_target{$$_}++ for @targ; 593 $op_target{$$_}++ for @targ;
564 594
595 $insn->{loop_targ} = \@targ;
596 $curloop = $insn;
597
565 } elsif ($class eq "COP") { 598 } elsif ($class eq "COP") {
566 $insn->{bblock}++ if defined $op->label; 599 if (defined $op->label) {
600 $insn->{bblock}++;
601 $curloop->{contains_label}{$op->label}++ if $curloop; #TODO: should be within loop
602 }
567 603
568 } else { 604 } else {
569 if ($name eq "pushmark") { 605 if ($name eq "pushmark") {
570 $numpushmark++; 606 $numpushmark++;
571 } 607 }
719 $meta->{$f->{func}} = $f->{so} = $stem; 755 $meta->{$f->{func}} = $f->{so} = $stem;
720 } 756 }
721 757
722 close $fh; 758 close $fh;
723 system "$COMPILE -o $stem$_o $stem.c"; 759 system "$COMPILE -o $stem$_o $stem.c";
724 unlink "$stem.c" unless $ENV{FASTER_DEBUG} > 0; 760 unlink "$stem.c" unless $ENV{FASTER_DEBUG} & 1;
725 system "$LINK -o $stem$_so $stem$_o $LIBS"; 761 system "$LINK -o $stem$_so $stem$_o $LIBS";
726 unlink "$stem$_o"; 762 unlink "$stem$_o";
727 } 763 }
728 764
729 for my $f (@func) { 765 for my $f (@func) {
854These constructs will force the use of the interpreter for the currently 890These constructs will force the use of the interpreter for the currently
855executed function as soon as they are being encountered during execution. 891executed function as soon as they are being encountered during execution.
856 892
857 goto 893 goto
858 next, redo (but not well-behaved last's) 894 next, redo (but not well-behaved last's)
895 labels, if used
859 eval 896 eval
860 require 897 require
861 any use of formats 898 any use of formats
862 .., ... (flipflop operators) 899 .., ... (flipflop operators)
863 900

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines