# Copyright (C) 2001-2014, Parrot Foundation.

=pod

=head1 NAME

docs/pmc.pod - PMC (PMC Makers Compendium)

=head1 DESCRIPTION

This document covers some of the important internals of Parrot's PMCs.

=head1 PMC STRUCTURE ITEMS ACCESS

Ideally, there should be minimal direct access to a PMC's internals.  In order
to enforce encapsulation, most interaction with a PMC should be performed
through VTABLE function calls, which allow code to remain robust as PMC
internals are changed.

When it is not possible or practical to use VTABLE functions (for instance when
implementing PMC internals), ATTRs should be used.  ATTRs are declared after
the C<pmclass> line in a .pmc file.  For a given pmc ("Foo"), an ATTR ("bar")
can be accessed either directly: C<< PARROT_FOO(pmc)->bar >> or via a
SETATTR/GETATTR accessor macro: C<GETATTR_Foo_bar(INTERP, x)>.  Note that
inside a .pmc file, these can be shortened to C<GET_ATTR_bar(INTERP, x)>.

=head1 PMC STORAGE

PMCs can store data in two places.  8 bits can be stored in the PMC's flags.
These are accessed via PObj_private0_FLAG, PObj_private1_FLAG, etc, although
these flags should be #define'd on a per-PMC basis to have more meaningful
names.

If a PMC needs more than 8 bits of storage, it should declare ATTRs of
the appropriate type.  Storage for ATTRs hangs off of C<PMC_data()>.  See
F<src/pmc/exporter.pmc> for example code that does this.

The PMC UnionVal was removed from Parrot with 1.6.0.

=head2 ATTRs and C<PMC_data()>

If your PMC needs to store more data than will fit into the 8 bits of the PMC
flags, it should declare ATTRs of the appropriate type.  The pmc2c code will
generate a struct containing all ATTRs, including those inherited via
C<extends> declarations.  This struct will be named in the form
C<Parrot_x_attributes>, where C<x> is the name of your PMC, e.g.
C<Parrot_FixedIntegerArray_attributes>.

When creating a PMC that has one or more ATTRs, the C<Parrot_x_attributes>
struct must be allocated and assigned to C<PMC_data>, and freed on PMC
destruction. This can be done automatically by using the auto_attrs flag in
the PMC declaration, or manually by using the manual_attrs flag. You must set
one of those flags, a warning is emitted otherwise. In future releases
auto_attrs will be the default.

If C<manual_attrs> is specified or assumed the struct must be manually allocated
in the PMC's C<init()> and C<init_pmc()> VTABLE functions (if used)
and it must be destroyed in the C<destroy()> VTABLE function, the PMC must
also indicate that they need active destruction by calling
C<PObj_custom_destroy_SET()> or C<PObj_custom_mark_destroy_SETALL()>.

If your PMC only needs to store a single pointer, it can use C<PMC_data>
directly. Note that this may make maintaining your PMC difficult, should more
data ever need to be stored.

=head1 PMC FLAGS

Each PMC has 8 private flags named B<PObj_private0_FLAG> through
B<PObj_private7_FLAG>.  These may be used for storing 8 bits of PMC-specific
information.  See C<include/parrot/key.h> and C<src/pmc/key.pmc> for examples.

=head1 PMCs AND GC

The GC system doesn't make any assumptions about your PMC's layout. Whenever a
PMC is found in the root set, B<Parrot_gc_mark_PObj_alive()> is called with
that PMC. The PMC is responsible to mark all contained or referenced active
Parrot objects (Buffers, STRINGs or other PMCs) when its C<mark()> VTABLE
function is called.

C<pmc2c> can generate GC write barriers automatically for all methods
which change SELF and one of its pointers to other PMCs, but you can
also specify the method attribute C<:manual_wb> or C<:no_wb> to not add
write barriers automatically.

=head2 PMCs and Write Barriers

We mark needed or unneeded WBs ("write barriers") in each method for
SELF.  A PMC write barrier adds the PMC to the C<root_objects> list for
mandatory next collecting, so that dangling pointers to old PMCs are
recycled.

=head3 When To Write Barrier SELF in PMC VTABLE Methods

- If you change a PMC you didn't create, WB it.

- Any time you save a value to a new PMC in an old PMC, WB the old one.
  See F<src/vtable.tbl> for the C<:write> annotation.

=head3 How To Annotate Write Barriers for VTABLE Methods

Generally WBs are added automatically for C<:write> methods unless you
have more than one C<return> statement. But you can optimize that
manually.

- Mark a method as C<:manual_wb> if you added all WBs manually, if in the
body after all SELF changes were done, or in an inlined macro or in an
included function.  Or if the last method is a vtable method on SELF,
which does the WB then. We don't need to WB SELF twice per method
call.

- Mark a method as C<:no_wb> if no WB is needed. See above.
Only writers on SELF need a WB. Check F<src/vtable.tbl> for the
C<:write> annotation.

- If you leave out a C<:manual_wb> or C<:no_wb> attribute in a
C<:write> vtable method, C<pmc2c> will try to add the write barrier line
automatically before the return line or as last line of the
method. However this is not possible if the method has more than one
return. Then you need to add them manually switch to C<:manual_wb> or use
C<RETURN(decl variable)> statements instead, as with PCCMETHODs.

=head2 PMCs and System Resources

Whenever a PMC B<malloc()>s memory or opens a file or a database connection, it
has to take care of freeing or closing these resources.  This is done by
implementing the appropriate VTABLE functions (C<mark()> and C<destroy()>) and
setting the appropriate PObj flags.  The commonly used flags are described
below.

=head2 GC related flags

=over 4

=item PObj_custom_mark_FLAG

If your PMC contains any other B<PObj>s (STRINGs, PMCs, etc), your PMC must
implement the B<mark()> VTABLE function and set this flag.  The B<mark()>
VTABLE function must call B<Parrot_gc_mark_PObj_alive()> on all B<PObj>s which
your PMC contains.

=item PObj_custom_destroy_FLAG

If your PMC allocates any memory or opens any resources during its lifetime,
it must set B<PObj_custom_destroy> and implement the B<destroy()> VTABLE
function to free those resources.

=item PObj_needs_early_gc_FLAG (deprecated)

Set this flag if your PMC needs timely destruction, e.g. to close a file
handle at the end of a block scope if the PMC isn't alive any more. This is
only implemented with the C<MS> garbage collector. Use C<--gc=ms> at
Configure.pl to activate this.  Note that this feature does not work and is
deprecated since release 3.1.

=back

=head1 SEE ALSO

F<include/parrot/pobj.h>, F<src/gc/api.c>.

=cut
