Permalink
Browse files

distinguish FINAL phase from CHECK phase

CHECK phase is always after the parsing of the current compilation
unit.  FINAL phase is after the main application's CHECK phase,
when the application as a whole commits to optimization policies.
In other words, a FINAL block defined in a module is not run when the
module is compiled (that would be a CHECK instead), but rather when the
application using the module is completing its compilation and linking.
  • Loading branch information...
1 parent 14e9ce6 commit a7444d895a3641df8ee44311f3613c1612c4de33 @TimToady TimToady committed May 15, 2013
Showing with 31 additions and 23 deletions.
  1. +4 −3 S02-bits.pod
  2. +11 −4 S04-control.pod
  3. +8 −8 S06-routines.pod
  4. +2 −2 S10-packages.pod
  5. +4 −4 S12-objects.pod
  6. +2 −2 S19-commandline.pod
View
@@ -13,8 +13,8 @@ Synopsis 2: Bits and Pieces
Created: 10 Aug 2004
- Last Modified: 13 May 2013
- Version: 273
+ Last Modified: 15 May 2013
+ Version: 274
This document summarizes Apocalypse 2, which covers small-scale
lexical items and typological issues. (These Synopses also contain
@@ -4175,7 +4175,8 @@ such a declaration will occur by the end of the current compilation unit:
foo $x:; # not a provisional call; it's a method call on $x
foo $x: $y; # not a provisional call; it's a method call on $x
-If a postdeclaration is not seen, the compile fails at C<CHECK> time.
+If a postdeclaration is not seen, the compile fails at C<CHECK> time,
+that is, at the end of compilation for this compilation unit.
(You are still free to predeclare subroutines explicitly, of course.)
The postdeclaration may be in any lexical or package scope that
could have made the declaration visible to the provisional call had the
View
@@ -13,7 +13,7 @@ Synopsis 4: Blocks and Statements
Created: 19 Aug 2004
Last Modified: 15 May 2013
- Version: 122
+ Version: 123
This document summarizes Apocalypse 4, which covers the block and
statement syntax of Perl.
@@ -1349,6 +1349,7 @@ them respond to various control exceptions and exit values:
BEGIN {...}* at compile time, ASAP, only ever runs once
CHECK {...}* at compile time, ALAP, only ever runs once
+ FINAL {...}* at link time, ALAP, only ever runs once
INIT {...}* at run time, ASAP, only ever runs once
END {...} at run time, ALAP, only ever runs once
@@ -1369,6 +1370,8 @@ them respond to various control exceptions and exit values:
CATCH {...} catch exceptions, before LEAVE
CONTROL {...} catch control exceptions, before LEAVE
+ COMPOSE {...} when a role is composed into a class
+
Those marked with a C<*> can also be used within an expression:
my $compiletime = BEGIN { now };
@@ -1417,6 +1420,9 @@ Code that is generated at run time can still fire off C<CHECK>
and C<INIT> phasers, though of course those phasers can't do things that
would require travel back in time. You need a wormhole for that.
+The compiler is free to ignore C<FINAL> phasers compiled at run time
+since they're too late for the application-wide linking decisions.
+
Some of these phasers also have corresponding traits that can be set on variables.
These have the advantage of passing the variable in question into
the closure as its topic:
@@ -1433,7 +1439,8 @@ a list of phasers rather than a single phaser. In general, initializing
phasers execute in order declared, while finalizing phasers execute in
the opposite order. When phasers are in different modules, the
C<INIT> and C<END> phasers are treated as if declared at C<use> time in
-the using module.
+the using module. (It is erroneous to depend on this order if the
+module is used more than once, however.)
The semantics of C<INIT> and C<START> are not equivalent to each
other in the case of cloned closures. An C<INIT> only runs once for
@@ -1506,7 +1513,7 @@ any C<CATCH> and C<CONTROL> phasers. This includes
the C<LEAVE> variants, C<KEEP> and C<UNDO>. C<POST> phasers are evaluated after
everything else, to guarantee that even C<LEAVE> phasers can't violate postconditions.
Likewise C<PRE> phasers fire off before any C<ENTER> or C<FIRST> (though not
-before C<BEGIN>, C<CHECK>, or C<INIT>, since those are done at compile or
+before C<BEGIN>, C<CHECK>, C<FINAL>, or C<INIT>, since those are done at compile or
process initialization time).
The C<POST> block can be defined in one of two ways. Either the
@@ -1823,7 +1830,7 @@ that can carry the info lazily. Neither approach is pretty.]
Some closures produce C<Block> objects at compile time that cannot be
cloned, because they're not attached to any runtime code that can
-actually clone them. C<BEGIN>, C<CHECK>, C<INIT>, and C<END> blocks
+actually clone them. C<BEGIN>, C<CHECK>, C<FINAL>, C<INIT>, and C<END> blocks
fall into this category. Therefore you can't reliably refer to
run-time variables from these closures even if they appear to be in the
scope. (The compile-time closure may, in fact, see some kind of permanent
View
@@ -16,8 +16,8 @@ Synopsis 6: Subroutines
Created: 21 Mar 2003
- Last Modified: 23 Feb 2013
- Version: 157
+ Last Modified: 15 May 2013
+ Version: 158
This document summarizes Apocalypse 6, which covers subroutines and the
new type system.
@@ -2955,7 +2955,7 @@ to be able to handle various unforeseen conditions (perhaps).
Note that all routines are (by default) considered to be candidates
for inlining and constant folding. The optimizer is allowed to start
-making these optimizations after the main program's C<CHECK> time,
+making these optimizations after the main program's C<FINAL> time,
@jnthn

jnthn May 15, 2013

Owner

This really needs to be reconsidered and talk about compilation units, not whole programs. Otherwise we can not really do any kind of inlining in the compiler, using what a Perl 6 compiler knows about the things in its lexical scope (which is more than most runtimes ever can). We would have to keep all code in AST form to retain that ability and follow this bit of spec, so precompilation would really have to mean mean serializing an AST, nothing more. Goodbye to mapping bytecode into memory, etc. We should be making different mistakes to Perl 5.

And saying we should defer all inling until runtime and let VM level stuff do it is also a fail. Sure, if we only want Perl 6 to perform well on some magical custom VM we may manage it, but that is also 5-think.

For things like method inlining, I agree it can't happen until application close time. But for lexical routines, we should allow inlining per compilation unit, after its CHECK time. All of our operators are lexical multi-dispatches; our ability to have them inlned at the point of code gen - which we expect to be able to do per compilation unit - is not only important for speed, but also for generating efficient code. We should not be leaving an addition of two native integers being cheap hanging on a VM untangling Perl 6 multi-dispatch (yeah, right) and realizing it can inline what that calls. It just won't happen, in general.

but not before. After any routine is "hard" inlined or constant
folded, it is explicitly retyped as immutable; any attempt to
wrap an immutable routine will result in failure of the wrap call.
@@ -2964,14 +2964,14 @@ a subclass of C<Routine>.
On the other hand, it is also possible to explicitly mark a routine
as mutable, and then the ability to wrap it must be preserved even
-after C<CHECK> time. This is done by recasting to C<SoftRoutine>.
+after C<FINAL> time. This is done by recasting to C<SoftRoutine>.
Explicitly marking a routine as either mutable or immutable should
be considered permanent. It is still possible to inline soft
routines, but only if the possibility of indirection is detected
inline as well, and provision made (either inline or via external
rewriting) for dealing with any wrappers.
-Hence, any routine marked as soft before C<CHECK> time is exempt
+Hence, any routine marked as soft before C<FINAL> time is exempt
from hard inlining or folding. There are several methods of
marking a routine as soft, however no method is provided for marking
routines as hard, since that is the job of the optimizer.
@@ -3005,7 +3005,7 @@ your optimizer into more of a "pessimizer".
For any normal standalone application, any C<use soft> pragma applies
to the entire program in which it participates, provided it is
-performed before C<CHECK> time. The optimizer may then harden
+performed before C<FINAL> time. The optimizer may then harden
anything that was not requested to remain soft.
A plug-in system, such as for a web server, may choose either to allow
@@ -3014,9 +3014,9 @@ optimizer harden individual plug-ins independently, or treat all
plug-ins as a part of the same program by softening all plug-ins.
(Similar considerations apply to optimizing classes to closed/final.)
-Note that installing a wrapper before C<CHECK> time is specifically
+Note that installing a wrapper before C<FINAL> time is specifically
I<not> one of the ways to mark a routine as soft. Such a routine
-may still be hardened at C<CHECK> time despite being wrapped during
+may still be hardened at C<FINAL> time despite being wrapped during
compile time.
=head2 The C<&?ROUTINE> object
View
@@ -107,8 +107,8 @@ to run at all if the result of some previous compilation's run has
been cached.)
If it is desired to have code that varies in meaning from run to run,
-then you should put such code into an INIT block. (Likewise, you
-could put code into a CHECK block that has inconsistent semantics
+then you should put such code into an C<INIT> block. (Likewise, you
+could put code into a C<CHECK> block that has inconsistent semantics
from compilation to compilation, but that's probably a bad idea.)
In any case, it is erroneous for any external module to depend
View
@@ -13,8 +13,8 @@ Synopsis 12: Objects
Created: 27 Oct 2004
- Last Modified: 8 Mar 2013
- Version: 128
+ Last Modified: 15 May 2013
+ Version: 129
=head1 Overview
@@ -2191,7 +2191,7 @@ the command line or from a mouse click.
These pragmatics (whether explicit or assumed) merely change the application's
default to closed and final,
-which means that at the end of the main compilation (C<CHECK> time)
+which means that at the end of the main compilation (C<FINAL> time)
the optimizer is allowed to look for candidate classes to close or
finalize. But anyone (including the main application) can request
that any class stay open or nonfinal, and the class closer/finalizer
@@ -2238,7 +2238,7 @@ must specifically pessimize the class:
class Mammal is repr(*) {...}
An C<augment> is allowed to do this as long as it is before the
-main C<CHECK> time, at which point the compiler commits to its
+main C<FINAL> time, at which point the compiler commits to its
optimization strategies. Compilers are not required to support
run-time pessimizations (though they may). Compilers may also generate
both optimal and pessimal code paths and choose which to run based
View
@@ -404,12 +404,12 @@ argument list.
=item --check-syntax, -c
-Check syntax, then exit. Desugars to C<-e 'CHECK{ compiles_ok(); exit; }'>.
+Check syntax, then exit. Desugars to C<-e 'CHECK { compiles_ok(); exit; }'>.
=item --doc
Lookup Perl documentation in Pod format. Desugars to
-C<-e 'CHECK{ compiles_ok(); dump_perldoc(); }'>. C<$*ARGS> contains the
+C<-e 'CHECK { compiles_ok(); dump_perldoc(); }'>. C<$*ARGS> contains the
arguments passed to C<perl6>, and is available at C<CHECK> time, so
C<dump_perldoc()> can respond to command-line options.

0 comments on commit a7444d8

Please sign in to comment.