Blog Closed

This blog has moved to Github. This page will not be updated and is not open for comments. Please go to the new site for updated content.

Tuesday, May 12, 2009

Contexts into PMCs: The plan

Turning Parrot_Context structures into PMCs is not going to be a trivial process. There are a number of reasons for this:
  1. Contexts are very complicated structures
  2. Contexts are very central to the operation of Parrot, so any conversion will affect the majority of the codebase
  3. The VTABLE interface is designed for data items that serve a singular purpose, while Contexts serve several purposes in Parrot. There isn't going to be a good fit between what needs to be done with Contexts to the VTABLE interface.
Since VTABLEs are relatively limited, any Context PMC is likely to require a number of direct accesses to the various internal data fields using the {GET|SET}_ATTR_* macros. If we tried to use a STRING-based property lookup to access internal members, it would be a major performance bottleneck for Parrot. A STRING-based property lookup could also be available to allow introspection from the PIR level, but that's separate issue entirely (although a nice perk to think about!)

Here are some ideas for what the VTABLE interface might be able to be used for:
  • init: This will throw an exception (at least at first) because we don't want Contexts being created from PIR initially. However, eventually we are probably going to want to be able, not only to access Contexts directly from PIR, but actually to subclass and extend them. I'll post more information about this idea tomorrow.
  • {get|set}_*_keyed_int: These will provide accesses to the various register sets. So "VTABLE_set_string_keyed_int" will set the Nth S register to the given value, "VTABLE_get_pmc_keyed_int" will get the Nth P register value.
  • {push|pop}_*: These will provide ways to pass positional arguments and return values, and then retrieve them again.
  • {get|set}_*_keyed_string: The hash interface, used to set/retrieve named parameters and returns. Note that this could also be used to supplant LexPad/LexInfo PMCs as the way to handle lexical variables. Imagine for a second that named parameters to a subroutine could be a direct subset of named lexical variables, and accessed in the exact same way. I won't get too much into speculation today, but I will in my post tomorrow.
  • invoke: Not entirely sure about this one yet. Since we are intending to unify Contexts and RetContinuations, maybe an invoke on the Context will perform the return. I don't know if we want to do anything else with this too.
  • {get|set}_pmc: There are a number of PMC values pointed to by the Context: The current Sub, the current Invocant object, the associated LexPad, the current namespace, the returns signature, and the lexically-scoped list of handlers. Which one would we access through get_pmc, if any? I have no idea. In reality, we will probably not use get_pmc, and instead use the ATTR accessor macros to deal with all of these values.
  • add_parent: There are two different Contexts that could be considered the "parent": The previous Context in the call chain, and the outer Context in the case of a closure. Either could be the "parent" in this case.
So that's a brief overview about what the VTABLE interface to the Context PMC will look like. Obviously we will also implement basics, like destroy, init_pmc, visit, mark, freeze, thaw, etc. These will all do the kinds of operations we expect of any PMC.

Here are some of the initial steps that I think we can take to replace struct Parrot_Context with Context PMCs. I think that if we can follow these steps we should be able to keep Parrot stable throughout the conversion process without allowing anything to be broken for too long:
  1. Encapsulate all the existing fields into a new PMC with no vtables and no methods
  2. Modify the PMC to remove fields used for ref-counting, and replace pointers to other contexts with pointers to Context PMCs.
  3. Modify the Context allocation/initialization routines in src/gc/register.c to allocate a new Context PMC instead
  4. Modify the CONTEXT(interp) macro to be ((Parrot_Context_attributes)PMC_data((interp)->ctx)) instead of ((interp)->ctx.state). At this point, the switch over to the new Context PMC should be complete, and Parrot should be using the PMC directly (although with very little respect for encapsulation) for all it's context-related needs.
  5. Implement various VTABLE methods to handle some common operations, and replace direct ATTR accesses with VTABLE calls instead.
  6. Optimize like a crazed elephant
  7. Profit!

What's really interesting in all this, which is something I've alluded to earlier, is that we open the possibility for Contexts to be manipulated in PIR code and introspected from there as well, things that are not currently possible. What kinds of cool control structures and situations will people develop once we have this?

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.