Skip to content

Latest commit

 

History

History
161 lines (115 loc) · 6.35 KB

pmc.pod

File metadata and controls

161 lines (115 loc) · 6.35 KB

NAME

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

DESCRIPTION

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

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 pmclass line in a .pmc file. For a given pmc ("Foo"), an ATTR ("bar") can be accessed either directly: PARROT_FOO(pmc)->bar or via a SETATTR/GETATTR accessor macro: GETATTR_Foo_bar(INTERP, x). Note that inside a .pmc file, these can be shortened to GET_ATTR_bar(INTERP, x).

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 PMC_data(). See src/pmc/exporter.pmc for example code that does this.

The PMC UnionVal was removed from Parrot with 1.6.0.

ATTRs and 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 extends declarations. This struct will be named in the form Parrot_x_attributes, where x is the name of your PMC, e.g. Parrot_FixedIntegerArray_attributes.

When creating a PMC that has one or more ATTRs, the Parrot_x_attributes struct must be allocated and assigned to 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 manual_attrs is specified or assumed the struct must be manually allocated in the PMC's init() and init_pmc() VTABLE functions (if used) and it must be destroyed in the destroy() VTABLE function, the PMC must also indicate that they need active destruction by calling PObj_custom_destroy_SET() or PObj_custom_mark_destroy_SETALL().

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

PMC FLAGS

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

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, 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 mark() VTABLE function is called.

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 :manual_wb or :no_wb to not add write barriers automatically.

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 root_objects list for mandatory next collecting, so that dangling pointers to old PMCs are recycled.

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 src/vtable.tbl for the :write annotation.

How To Annotate Write Barriers for VTABLE Methods

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

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

- If you leave out a :manual_wb or :no_wb attribute in a :write vtable method, 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 :manual_wb or use RETURN(decl variable) statements instead, as with PCCMETHODs.

PMCs and System Resources

Whenever a PMC 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 (mark() and destroy()) and setting the appropriate PObj flags. The commonly used flags are described below.

PObj_custom_mark_FLAG

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

PObj_custom_destroy_FLAG

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

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 MS garbage collector. Use --gc=ms at Configure.pl to activate this. Note that this feature does not work and is deprecated since release 3.1.

SEE ALSO

include/parrot/pobj.h, src/gc/api.c.