This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Automate processing of op_private flags
authorDavid Mitchell <davem@iabyn.com>
Tue, 2 Sep 2014 16:11:42 +0000 (17:11 +0100)
committerDavid Mitchell <davem@iabyn.com>
Wed, 10 Sep 2014 13:25:05 +0000 (14:25 +0100)
commitf3574cc66412a684ced323c9c3183b20381c3f58
tree21a6ba05b8811dc488327cb841953e49971d1b1e
parent738ec38010d319318456d2882cb13e00547853de
Automate processing of op_private flags

Add a new config file, regen/op_private, which contains all the
information about the flags and descriptions for the OP op_private field.

Previously, the flags themselves were defined in op.h, accompanied by
textual descriptions (sometimes inaccurate or incomplete).

For display purposes, there were short labels for each flag found in
Concise.pm, and another set of labels for Perl_do_op_dump() in dump.c.
These two sets of labels differed from each other in spelling (e.g.
REFC verses REFCOUNT), and differed in completeness and accuracy.

With this commit, all the data to generate the defines and the labels is
derived from a single source, and are generated automatically by 'make
regen'. It also contains complete data on which bits are used for what by
each op. So any attempt to add a new flag for a particular op where that
bit is already in use, will raise an error in make regen.  This compares
to the previous practice of reading the descriptions in op.h and hoping
for the best.

It also makes use of data in regen/opcodes: for example, regen/op_private
specifies that all ops flagged as 'T' get the OPpTARGET_MY flag.

Since the set of labels used by Concise and Perl_do_op_dump() differed,
I've standardised on the Concise version. Thus this commit changes the
output produced by Concise only marginally, while Perl_do_op_dump() is
considerably different. As well as the change in labels (and missing
labels), Perl_do_op_dump() formerly had a bug whereby any unrecognised
bits would not be shown if there was at least one recognised bit.
So while Concise displayed (and still does) "LVINTRO,2", Perl_do_op_dump()
has changed:

    - PRIVATE = (INTRO)
    + PRIVATE = (LVINTRO,0x2)

Concise has mainly changed in that a few op/bit combinations weren't being
shown symbolically, and now are. I've avoiding fixing the ones that would
break tests; they'll be fixed up in the next few commits.

A few new OPp* flags have been added:

    OPpARG1_MASK
    OPpARG2_MASK
    OPpARG3_MASK
    OPpARG4_MASK
    OPpHINT_M_VMSISH_STATUS
    OPpHINT_M_VMSISH_TIME
    OPpHINT_STRICT_REFS

The last three are analogues for existing HINT_* flags. The former four
reflect that many ops some of the lower few bits of op_private to indicate
how many args the op expects. While (for now) this is still displayed as,
e.g. "LVINTRO,2", the definitions in regen/op_private now fully account
for which ops use which bits for the arg count.

There is a new module, B::Op_private, which allows this new data to be
accessed from Perl. For example,

    use B::Op_private;
    my $name  = $B::Op_private::bits{aelem}{7}; # OPpLVAL_INTRO
    my $value = $B::Op_private::defines{$name}; # 128
    my $label = $B::Op_private::labels{$name};  # LVINTRO

There are several new constant PL_* tables. PL_op_private_valid[]
specifies for each op number, which bits are valid for that op. In a
couple of commits' time, op_free() will use this on debugging builds to
assert that no ops gained any private flags which we don't know about.
In fact it was by using such a temporary assert repeatedly against the
test suite, that I tracked down most of the inconsistencies and errors in
the current flag data.

The other PL_op_private_* tables contain a compact representation of all
the ops/bits/labels in a format suitable for Perl_do_op_dump() to decode
Op_private. Overall, the perl binary is about 500 bytes smaller on my
system.
15 files changed:
MANIFEST
Porting/Maintainers.pl
dump.c
ext/B/B/Concise.pm
ext/B/Makefile.PL
ext/Devel-Peek/t/Peek.t
globvar.sym
lib/B/Op_private.pm [new file with mode: 0644]
op.h
opcode.h
pp.h
pp_sys.c
regen/op_private [new file with mode: 0644]
regen/opcode.pl
t/porting/regen.t