Parrot Virtual Machine/PMC System

PMCs

edit

We've discussed PMCs already -- in the Parrot Virtual Machine/Polymorphic Containers (PMCs) chapter -- including how to define new PMC types using the PMC compiler, and how to use them in PIR programs. This chapter is going to go into more detail about how PMCs are actually used in Parrot, including memory management of PMCs, morphing PMCs, and interfacing with PMCs.

PMC System Overview

edit

The PMC data structure is deceptively simple, and is designed to be extensible enough for general purpose data and functionality use. Here is the definition of the PMC structure and the associated PMC_EXT structure:

struct PMC {
    Parrot_UInt     flags;
    VTABLE         *vtable;
    DPOINTER       *data;
    struct PMC_EXT *pmc_ext;
};

typedef struct PMC_EXT {
    DPOINTER *data;
    PMC *_metadata;
    struct _Sync *_synchronize;
    PMC *_next_for_GC;
} PMC_EXT;

As we can see in these definitions, the PMC is actually very small. Much of the information about a PMC, including all it's various methods and VTABLE interfaces is stored in the ->vtable pointer. The VTABLE structure is a very large structure that contains function pointers for all the various VTABLE interfaces.

PMC Data

edit

Every PMC type also contains a pointer for a data structure that's specific to that PMC. These data structures are defined based upon the inheritance hierarchy of the PMC and the various attributes that it has been defined with. For instance, this PMC definition:

pmclass MyPmc {
    ATTR INTVAL a;
    ATTR FLOATVAL b;
    ATTR STRING *c;
    ATTR PMC *d;

    ...
}

will turn into this C data structure definition:

typedef struct Parrot_MyPmc_attributes {
    INTVAL a;
    FLOATVAL b;
    STRING *c;
    PMC *d;
} Parrot_MyPmc_attributes;

This structure is supposed to be contained in the ->data pointer, which should always be accessed using the PMC_data macro. This way if the PMC structure definition changes eventually, all code that uses the macros properly will be automatically updated because the macro will be updated. Here is an example of an initialization VTABLE that uses these attributes:

VTABLE void init () {
    Parrot_MyPmc_attributes *p = mem_allocate_typed(Parrot_MyPmc_attributes);
    p->a = 0;
    p->b = 0.0
    p->c = NULL;
    p->d = PMCNULL;
    PMC_data(SELF) = p;
}

There is another macro which uses the word PARROT and the name of the PMC in all capital letters to retrieve the data structure again and properly cast it (so your compiler doesn't give warnings about using pointers without a cast):

Parrot_MyPmc_attributes *attr = PARROT_MYPMC(SELF);



PObjects

edit

C isn't a class-based (or "object oriented") language, but many lessons from OO programming methodologies have been adapted for use in Parrot's code base. PMCs, STRINGs, and a few other data types are based off the definition of a "PObj", also known as a "Buffer":

typedef struct Buffer {
    Parrot_UInt flags;
} Buffer;

Notice how the first two entries in the Buffer are the same as in the PMC? All objects that start off with these two data items are said to be "PObject isomorphic". For short, we say that all pobject isomorphic are simply "PObjects", and there are many types of PObjects. The memory management system, for example, can test the flags of all pobjects to determine what type of PObject a memory object is.

A PMC may optionally contain a PMC_EXT structure, which adds additional functionality. PMC_EXT allows a PMC to be shared between multiple threads, or multiple Parrot interpreters without introducing data contention. PMC_EXT also allows a PMC to contain a hash of metadata (attribute value pairs), which are typically added as attributes in PIR.

PObject Flags

edit

PMC Management

edit

PMCs are allocated from two special pools, a PMC pool and a constant PMC pool. Constant PMCs are considered to be immutable and everlasting, and so are never modified nor collected by the garbage collector. STRINGS are allocated in either a string pool or a constant string pool. The same relationship applies, constant strings are never modified and never collected. PMC_EXT structures are not currently managed by the memory management subsystem. However, since PMC_EXTs are assigned to PMCs in a one-to-one relationship, we always know we can free it when it's PMC is freed.

In terms of garbage collection, PMCs are one of the only aggregate data types in Parrot. STRINGS do not contain pointers to other data items of interest to the garbage collector. Stack chunks, which are used internally in some structures are PObjs and are also aggregates, but are marked separately by the collector and are not treated as aggregates directly.

VTables

edit

VTables represent a standard interface to PMCs of all types. For every single PMC, there are a series of standard operations that you can perform (or attempt). Not all PMCs support all Vtable operations

VTable Types

edit

VTables are complicated data items that contain, in addition to a large series of function pointers, a number of data items to support PMCs. One of the data items is a class PMC, a PMC that represents a particular PMC class. Another item is an enum that differentiates between all PMC classes.

Class PMCs

edit

Resources

edit


Previous Parrot Virtual Machine Next
Run Core Memory and Garbage Collection