Fatal: Optimize out calls to fill_protos

When we just need a leak guard for an already compiled CORE sub, there
is no reason to call fill_protos.  The leak guard itself has
sufficient information to obtain the prototype in case of a leak
(optimization for the non-leaking case).

Signed-off-by: Niels Thykier <niels@thykier.net>
Fatal: special case "@" prototypes in fill_protos

A clean "@" prototype can use @_ directly without any unpacking at
all.  That is, we generate

   $sub(@_)

instead of

   $sub(@_[0..$#_])

It does not appear to have a performance impact (of any kind), but the
generated sub looks a bit less awkward.

Signed-off-by: Niels Thykier <niels@thykier.net>
Fatal: Refactor the use of set_prototype

It turns out that set_prototype can be convinced to accept a subref
stored in a scalar varable via:

   set_prototype(\&$subref, $proto);

So use this to simplify the leak guard creation code.

Signed-off-by: Niels Thykier <niels@thykier.net>
Fatal: Merge the two parts of the leak guard

By merging the two parts of the leak guard, we avoid the overhead of
the goto between the two.  As an added bonus, we no longer need to
meddle with @_, since the leak guard can now "close over" the values
it needs.

Signed-off-by: Niels Thykier <niels@thykier.net>
Fatal: Rewrite leak_guard to get rid of $leaked variable

Signed-off-by: Niels Thykier <niels@thykier.net>
Fatal: Fix a bug in _make_core_trampoline with ";" prototypes

Correctly handle prototypes that start directly with ";" (e.g. close),
where the first "call" will be "empty".

Signed-off-by: Niels Thykier <niels@thykier.net>
Fatal: Reuse a variable rather than re-computing

Signed-off-by: Niels Thykier <niels@thykier.net>
Fatal: Rewrite _expand_tag to improve its efficiency

Have _expand_tag recurse rather than inline expand tags.  This have
the side-effect of ensuring that each tag is computed at most once
rather than each time they are referred to from another tag.

Furthermore, have _expand_tag handle "tag aliases" more efficiently by
letting them share the reference to their actual contents.  This means
that the memory usage for an alias is O(1) rather than O(n).

Finally, filter out duplicate entries from the final list.  This
should dratically reduce the memory requirement of ":all", which would
previously contain everything multiple times.  Note that the ":all"
tag is still fair expensive to compute (at least compared to other
tags) since every tag is still expanded (and most of them filtered out
again).

Signed-off-by: Niels Thykier <niels@thykier.net>
Fatal: Introduce helper method for {,un}import

Introduce a helper method to expand tags in arguments for import and
unimport, so a destructive iteration is no longer needed.  The helper
preserves the order of input arguments with tags expanded inplace and
filtering out duplicates.

Signed-off-by: Niels Thykier <niels@thykier.net>
Merge pull request #25 from nthykier/optimizations-for-2.19

Optimizations and a bugfix for 2.20

Courtesy of nthykier, who is a hero of the free people of the internet.