next up previous
Next: Self installation Up: Data Structures Used Previous: A garbage collector

Pointers to virtual method tables

Object oriented languages like C++ and Object Pascal support what are called virtual methods. Unlike plain vanilla methods, whose procedure addresses can be computed at compile time, the address of a virtual method may not be known until run time. Consider the case of an object class number that declares a virtual method show. The method show is assumed to print the number as floating point decimal. Suppose we now declare a class rational as a subclass of number with a show method that prints numbers out as a fraction.

Figure 3.13: The use of a virtual method table in object oriented programming

Given an instance x of the class number, the command must invoke a different method according to whether x is a plain old number, or is a rational number. The solution conventionally adopted to this problem is shown in figure 3.13. The objects themselves have a pointer, either full length, or datasegment-relative, to a table, the Virtual Method Table, that contains pointers to the actual methods used. There will be different Virtual Method Tables for plain numbers and for rationals, but in each of these tables, the entry that points to the show method will be at a position that is known at compile time.

If however these two classes are incorporated as libraries into different programs, it is likely that the addresses of the virtual method tables for the class rational in the datasegment will differ between the programs. Thus if a rational number is created in the persistent memory by one progam, but is subsequently used by a second program, the virtual method table pointer will be incorrect on the second occasion. Our implementation obviates this problem by a two step process:

  1. Each class that is used in a program must be registered with the persistent store before any instances are created or used. This is done by passing to a registration procedure.

    Figure 3.14: The heaps in segments 4098 and 4104 are show assigned to the class of rationals. On a segment fault, it is possible by inspecting the classes table to find which class `owns' a given segment.

    This procedure then creates a heap specially tailored to that class, and creates a class descriptor for the class if none exists in the persistent store at that time. The class descriptor has the form shown in figure 3.14.

    An entry is then made into the classes table at the index position of the persistent segment used for the heap, pointing to the class descriptor. If in the course of time, this heap is insufficient to hold all of the members of the class, additional ones are created. All the heaps owned by a class have their entries in the classes table set to point at the appropriate class descriptor.

    The system stores housekeeping tables in the ROOTBLOK file, whose structure is shown in figure 3.15.

    Figure 3.15: The type of the root block which provides housekeeping tables for the persistence manager.

    It has 4 components:

    This is the unique pointer from which all persistent data must eventually descend. The garbage collector uses it to determine which objects must persist. It will contain a pointer into a record in the persistent store.
    This is a table containing flags used to describe the attributes of all of the selectors. These flags indicate if the selector's segment is reserved for the persistent store, if it is currently holding persistent data, and if the data it contains is executable instructions.
    This is an array of heaps whose purpose wax described in more detail above.
    This is an array, indexed by persistent segment numbers, of pointers to class descriptors. These too, are described below.

  2. When an address fault occurs, the hardware passes the selector of the faulting segment to the interrupt handler. From this can be derived the segment number, allowing the classes table to be inspected. Should the entry in the classes table corresponding to the segment number be non-nil the descriptor of the class owning that segment is obtained.

    From the class descriptor, the value and offset within the instances, of the class's current virtual method table may be determined. This information can then be used to update all of the instances of the class, resident within the faulting heap segment, to point at the currently valid virtual method table.

    By the time the interrupt handler returns, the instance of the class whose pointer caused the fault has been loaded into memory, and its virtual method table made accessible.

next up previous
Next: Self installation Up: Data Structures Used Previous: A garbage collector

W Paul Cockshott
Fri Sep 6 10:29:18 BST 1996