Extending Rotor with Structural Reflection to support Dynamic Languages

The complexity of the SSCLI implementation prevented us from directly implementing the operations inside the runtime environment. We followed several steps were defined to gradually incorporate structural reflection in Rotor. Modifying different parts of the system one by one (from BCL to the binary code generated at runtime) has allowed us to refine the model using the experience gained. We are currently developing the forth step.

  1. Stage 1. BCL-level implementation. In this step we implemented all the new BCL reflective primitives described in the API section. For this step we simply develop the primitives in C#, making use of .Net introspective capabilities. The runtime environment was not modified in this step. The programmer should use all the reflective features explicitly by means of the BCL.

    The phase 1 implementation uses a central data structure that uses four C# hash-tables to store relationships between added members and their owners (either classes or instances). When accessing members, these hash-tables are consulted first and, if the member has not been reflectively added, the rest of the process continues searching in the class hierarchy using introspection. If the top of the hierarchy is reached without finding the appropriate member, a MissingMemberException is thrown. This implementation is much easier than developing the code inside the runtime environment but its execution performance is significantly slower.

  2. Stage 2. This phase was the virtual machine level implementation. In this second step we moved the implementation of the BCL primitives developed in the previous step to an equivalent C implementation inside the execution environment. The BCL interface was not modified, but the implementation was included inside the virtual machine getting significantly better runtime performance. We used Rotor internal structures, data types and routines to our advantage.

    The most important decision was to find the suitable place to put the data structure that stored the reflective information. Since direct object structure manipulation turns to be much more difficult than we expected, due to its fixed-size object design, we decided to use the Syncblock of each to store reflective data. Thus, we assigned each object (and class) a specific structure to store its reflective information.

  3. Stage 3. In this case we added the JIT-level implementation. We modified the Rotor JIT code generation mechanism, extending the semantics of some IL instruction (see the API section). The code generated by the JIT was changed in order to support structural reflection of existing .Net applications. Runtime performance of this phase implied a considerably improvement of previous phases.

  4. Stage 4. The last implementation phase in our project is to enable the support of additional primitives offered by dynamic languages. These primitives make use of the reflective services developed in previous phases. We are currently working in the dynamic inheritance facility that Python (but not Ruby) implement. The setSuper primitive allows the programmer to change the class of any object; it also permits inheritance hierarchy adaptation. This phase is currently under development.