June 2011 Archives

How perl compiles subs and methods

This was just added to perloptree.pod in B::C

Call a subroutine

subname(args...) =>

pushmark
    args ...
gv => *subname
entersub

Call a method

Here we have several combinations to define the package and the method name, either compile-time (static as constant string), or dynamic as GV (for the method name) or PADSV (package name).

method_named holds the method name as sv if known at compile time. If not gv (of the name) and method is used. The package name is at the top of the stack. A call stack is added with pushmark.

Static compile time package and method

Class->subname(args...) =>

pushmark
const => PV "Class"
    args ...
method_named => PV "subname"
entersub

Run-time package and compile-time method

$obj->subname(args...) =>

pushmark
padsv => GV *packagename
    args ...
method_named => PV "subname"
entersub

Run-time package and run-time method

$obj->$meth(args...) =>

pushmark
padsv => GV *packagename
    args ...
gvsv => GV *meth
method
entersub

Compile-time package and run-time method

Class->$meth(args...) =>

pushmark
const => PV "Class"
    args ...
gvsv => GV *meth
method
entersub

Possible Optimizations

Optimization of static methods, e.g. Class->new

The purely static case is of course lame and can be massively optimized. See http://www.perl.com/pub/2000/06/dougpatch.html for the discussion of the old patch

The case

Class->subname(args...) =>

pushmark
const PV => "Class"
    args ...
method_named => PV "subname"
entersub

can be optimized if &Class::subname is defined. Otherwise we'd need to ensure a complle-time const @ISA with some sort of new package attribute. :locked for subs and packages is free. Only a package attribute make sense here really.

The optimization would get rid of the run-time stash lookup for the string "Class", use the string as first arg to entersub, and the method_named op can be replaced by gv => &Class::subname.

pushmark
const PV => "Class"
    args ...
gv => *Class::subname
entersub

Voila, static method calls almost as fast as function calls, and no ops have to be added.

Benchmark

method calls get +3.95 % faster, and only 6.21% slower than sub calls. Without this optimization method calls are 10.87% slower than subs.

Optimization of methods with typed objects

A similar optimization can be done for typed objects if the object class contains that method, or the found method or defined package is locked. A Class declaration binds the package to $obj, and can therefore be optimized.

my Class $obj;
$obj->method(); # and `&Class::method` is defined, 
       # or `package Child :locked; `
       # or sub `Child::method :locked {}` and `@Class::ISA` is Readonly

Easy enough.

Locked classes

Moose came up with immutable classes. If CORE needs to optimize such semantics, either we would need to come up with such a type hint, best for packages.

package NAME :locked # or 
package NAME :immutable #or
package NAME :const #or
package NAME :readonly #or
package NAME :final

would make sense.

Or Readonly %{NAME::}; Readonly @NAME::ISA; for all packages in the inheritance list until the method is found.

Or Moose could just implement those fixes in a CHECK block via B::Generate or XS. This would be much faster than inlining methods or caching for most methods.

Call CV's directly

In case of XSUB's or in any case when the CV slot of the subname glob is known not to be changed since compile-time (type-hints: sub :locked :const or :immutable), it would make sense to create a faster entersub perl op, which calls the CV directly and does not do the glob run-time lookup.

gv => *Class::subname
entersub

=>

entersubcv  => &Class::subname

or maybe

cv => &Class::subname
entersubcv

entersubxs for the XSUB counterpart.

XSUB's should be seperated from normal CV's for Safe to work correctly. perl subs are generally safe, xsubs generally unsafe.

MacOSX German Emacs keys

I've tried now up to 4 different Emacs on my german MacBook Air, and finally it looks like I can manage. Aquamacs is the best so far.

  1. xemacs my first choice as I use it everywhere else. looks awful, intolerable

  2. emacs-23.3 from ports +x11 in various flavors. Tried for 3 months. Together with TextMate, Padre, and even Eclipse. Eclipse was best and fastest, but I want an emacs as everywhere else.

  3. emacs-23.3 +cocoa patch Tried for one month.

  4. Emacs.App from ports Native cocoa patch, but german keys do not work. At all. /Applications/MacPorts/Emacs.app/Contents/MacOS/Emacs

  5. Aquamacs This is it! Like my XEmacs on Windows and emacs on unices. See also http://www.emacswiki.org/emacs/AquamacsFAQ#toc5 And with the following key settings I can finally type my programs.

.emacs

(when (eq system-type 'darwin) 
    (global-set-key (kbd "M-7") "|")
    (global-set-key (kbd "M-8") "{")
    (global-set-key (kbd "M-9") "}")
    (global-set-key (kbd "M-ΓΌ") "[")
    (global-set-key (kbd "M-+") "]")
    (global-set-key (kbd "C--") "\\")

/Applications/Aquamacs.app/Contents/MacOS/Aquamacs

~/bin/edit

#!/bin/sh
#if test -n "$(pgrep Emacs)"; then
#  /Applications/MacPorts/Emacs.app/Contents/MacOS/bin/emacsclient $*
#else
#  /Applications/MacPorts/Emacs.app/Contents/MacOS/Emacs $*
#fi
if test -n "$(pgrep Aquamacs)"; then
  /Applications/Aquamacs.app/Contents/MacOS/bin/emacsclient $*
else
  /Applications/Aquamacs.app/Contents/MacOS/Aquamacs $*
fi

The Problem

On the german keyboard there are no easy accessible {} | \ [] keys.

With native Cocoa apps you can use KeyRemap4MacBook and select some settings from "For German" to reach these keys.

Emacs, even Cocoa apps such the last three, bypasses the hooks. But with the .emacs workarounds and Aquamacs I can now live with it.

About Reini Urban

user-pic Working at cPanel on B::C (the perl-compiler), p2, types, parrot, B::Generate, cygwin perl and more guts (LLVM, jit, optimizations).