The bidirectional layout differs from the layouts used by many C++ implementations [Str87], though there are similarities. An object has a fixed memory layout, defined by its class. Figure 2 illustrates an object layout, which is divided in two parts (note that memory addresses increase downward within each box):
Figure 2: Bidirectional object layout
Dispatch vectors are shared by all objects of the particular class that owns them, but each object has its own copy of the dispatch header that points to them. Most objects have only a single dispatch vector, so only one word is consumed by the dispatch header. With the use of inheritance or subtyping, the dispatch header layout grows backward in memory, if it grows at all.
The bidirectional layout separates the fields and dispatch information of the object, whereas most C++ implementations intermingle them. One advantage of separating the dispatch information is that adjacent entries in the dispatch header can be merged into one entry by merging their corresponding dispatch vectors, using the rules described in Section 3.
To ensure that method code inherited from the superclass need not be recompiled, the bidirectional layout makes the layout of a class compatible with that of its superclass. Compatibility is achieved by nesting the superclass layout within that of the class, as shown in Figure 3. The dotted lines connect the layout of the superclass, Cs, to the corresponding portion of the layout of the class, C. The relationship of the two classes is indicated by the vertical arrow at the left of the figure. Because C contains a portion whose layout is compatible with Cs, inherited method code will work properly when passed a pointer to the Cs portion of the object.
Figure 3: Class/superclass compatibility
In general, a layout - whether of an object, a dispatch header, or just a dispatch vector - is compatible with the corresponding superclass layout if the superclass layout is embedded in the subclass layout.
Both abstract types and classes have dispatch header and dispatch vector layouts. Classes also provide dispatch header data that is copied into the beginning of objects of that class and contains pointers to the dispatch vectors shared by all objects of that class.
An object reference is implemented by a pointer into the dispatch header. The dispatch vector indirectly referenced by the pointer is called the current dispatch vector. Any object reference has some static, declared type, although the run-time type of the object may be any of that type's subtypes. Regardless of the actual run-time object type, the method indices of the current dispatch vector agree with the method indices of the last dispatch vector of the static type's layout. Note that one dispatch vector may contain methods for several types so long as the method indices do not conflict.
Andrew C. Myers. Bidirectional Object Layout for Separate Compilation.
Proceedings of OOPSLA '95, pp. 124-139.
Copyright © 1995 Association for Computing Machinery