| 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]; |
| } |