Binding x.f to slots

The goal is to find the address and static type for the value designated by x.f. This could be a built-in value, a method or object reference. The compiler knows the static type of x, while f is assumed here to be a constant. The following treatment can be easily generalized to handle the cases where f is an expression.

The class of x can be found based upon the static type of x. For instance, x may be a dynamically typed data item in which case the data tag implies the class. Alternatively, it could be a reference to a vtable for an object or for a view of an object defined by an interface.

There is more than one way to approach this problem. This offers the compiler the opportunity to select between them according to the relative costs in any context. The costs involve compile-time costs and run-time costs and further break down into time and space costs.

Not all cases apply in all contexts. If x.f is bound, the value it is bound to shouldn't vary according to which case is used. This involves a small overhead for the specific classes and properties where this ambiguity might otherwise arise.

Case 0: The class of x is known at compile-time.

The slot address and type can be computed trivially from x and the class definition.

Case 1: Property name f occurs in only one class.

Generate code to get the class of x and see if it is the class that contains f. If not generate an exception. A generalization of this handles the case where f only occurs in one class or its subclasses.

Case 2: Property name f is a property of this class

Generate code to get the class of x and compare it with the class of this. If not fall back to more general cases. Note that this case applies whether f is a public, package protected, protected or private property of this class.

Case 3: Many different classes define property name f

Each class is required to define a generic method for mapping property names to slots. A pointer to this method is placed at a fixed offset in the vtable for the class. The compiler generates code to get the class of x and to call the lookup method via this offset. The method provides further checks for inappropriate access to private or protected or package protected fields. But see case 6 for an alternative approach for package protected properties.

Case 4: Property name f occurs in only a few classes

This is a generalization of case 1. The compiler generates a method for each such f that maps x to the desired slot based upon the class of x as determined at run-time.

Case 5: Property name f occurs in an interface definition

The call to get the class of x behaves in the same way as for normal objects. This makes it practical to use the same lookup mechanism as in case 3. The difference is that the interface's lookup method needs to defererence the property to the slot used in the class the interface applies to. In this case x references a vtable for the view onto the object specified by the interface.

Case 6: x is an object exported from another package

If a class has package private properties, then the compiler generates an interface definition for the view of that class from other packages. This reduces the problem to case 5. If the class doesn't have package private properties it is treated in the same way as a class in the current package. Note that this allows classes to export multiple views of themselves. A package version selects a set of such views.

Case 7: f is a property of a super class of x

This is treated by a generalization of case 2. An exception is generated if f is a private property of the superclass. This says either that x doesn't have property f or that an attempt has been made to access a private field of a superclass, according to the compiler settings. If the class of x is known at compile-time the error can be detected during compilation.

Case 8: x is known to be a given class C or subclass of C

This can be handled by interpreting x as if it were class C. In other words by finding the offset for property f in class C and applying this offset to x. If x is a subclass of C and the subclass and C differ in the way f is defined (e.g. f is private to C) this approach can yield different results to applying case 3 (dynamic lookup). The difference can be avoided by an additional check if needed depending on f. A similar problem occurs if f is defined by the subclass but not by C. When this happens case 8 fails and case 3 can be tried.