blob: af3bf625c86d6e01ec9ce190b22916f9d4140d8c [file] [log] [blame]
Object layout for Java objects
------------------------------
Each Java object will have the following basic layout:
struct llvm_java_object_base {
struct llvm_java_object_header header;
struct llvm_java_object_vtable* vtable;
};
Additional fields go to the end of the struct.
The 'llvm_java_object_header' is not defined yet.
struct llvm_java_object_header {
// gc info, hash info, locking
};
The vtable holds a nested struct of a 'llvm_java_object_typeinfo'
object. All methods are added after the nested struct and calls to
them are made by fetching the correct function pointer from the vtable
at runtime.
struct llvm_java_object_vtable {
struct java_object_typeinfo typeinfo;
};
For each class we keep track of its depth and an array of vtables to
all its superclasses. The depth of a class is the number of
superclasses it has. So java.lang.Object has depth 0, class A (extends
java.lang.Object) has depth 1 and so on. We also keep an array of
pointers to interface vtables. Each interface (vtable) gets a unique
number and it is indexed to this array. This mostly empty array is
filled up to the last interface implemented (the interface with the
largest index in this array). Since interfaces cannot implement other
interfaces (they can only extend) the lastIface and interfaces are
used to differentiate between class typeinfo's and interface
typeinfo's. More specifically if interfaces == -1 then this typeinfo
is for an interface and the lastIface field is the unique number of
this interface in the objects interfaces array. The field lastIface is
the max index of all implemented interfaces. For a class that doesn't
implement any it is -1.
struct llvm_java_object_typeinfo {
unsigned depth;
struct llvm_java_object_vtable** vtables;
int lastIface;
union {
struct llvm_java_object_vtable** interfaces;
int interfaceFlag;
};
};
The structure of llvm_java_object_typeinfo allows constant time
dynamic type checks:
int isInstanceOf(struct llvm_java_object_base* obj,
struct llvm_java_object_vtable* clazz) {
struct llvm_java_object_vtable* objClazz = obj->vtable;
if (objClazz == clazz)
return 1;
// we are checking against a class' typeinfo
if (clazz->typeinfo.interfaceFlag != -1)
return objClazz->typeinfo.depth > clazz->typeinfo.depth &&
objClazz->typeinfo.vtables[clazz->typeinfo.depth] == clazz;
// otherwise we are checking against an interface's typeinfo
else
return objClazz->typeinfo.lastIface >= clazz->typeinfo.lastIface &&
objClazz->typeinfo.interfaces[clazz->typeinfo.lastIface];
}