1b1994897Sopenharmony_ci# Runtime class 2b1994897Sopenharmony_ci 3b1994897Sopenharmony_ciPanda runtime uses `panda::Class` to store all necessary language independent information about class. Virtual table and region for static fields are embedded to the `panda::Class` object so it has variable size. To get fast access to them `Class Word` field of the object header points to the instance of this class. `ClassLinker::GetClass` also return an instance of the `panda::Class`. 4b1994897Sopenharmony_ci 5b1994897Sopenharmony_ciPointer to the managed class object (instance of `panda.Class` or other in case of plugin-related code) can be obtained using `panda::Class::GetManagedObject` method: 6b1994897Sopenharmony_ci 7b1994897Sopenharmony_ci```cpp 8b1994897Sopenharmony_cipanda::Class *cls = obj->ClassAddr()->GetManagedObject(); 9b1994897Sopenharmony_ci``` 10b1994897Sopenharmony_ci 11b1994897Sopenharmony_ciWe store common runtime information separately from managed object to give more flexebility for its layout. Disadvantage of this approach is that we need additional dereference to get `panda::Class` from mirror class and vice versa. But we can use composition to reduce number of additional dereferencies. For example: 12b1994897Sopenharmony_ci 13b1994897Sopenharmony_ci```cpp 14b1994897Sopenharmony_cinamespace panda::coretypes { 15b1994897Sopenharmony_ciclass Class : public ObjectHeader { 16b1994897Sopenharmony_ci 17b1994897Sopenharmony_ci ... // Mirror fields 18b1994897Sopenharmony_ci 19b1994897Sopenharmony_ci panda::Class klass_; 20b1994897Sopenharmony_ci}; 21b1994897Sopenharmony_ci} // namespace panda::coretypes 22b1994897Sopenharmony_ci``` 23b1994897Sopenharmony_ci 24b1994897Sopenharmony_ciIn this case layout of the `coretypes::Class` will be following: 25b1994897Sopenharmony_ci 26b1994897Sopenharmony_ci 27b1994897Sopenharmony_ci mirror class (`coretypes::Class`) --------> +------------------+ <-+ 28b1994897Sopenharmony_ci | `Mark Word` | | 29b1994897Sopenharmony_ci | `Class Word` |-----+ 30b1994897Sopenharmony_ci +------------------+ | | 31b1994897Sopenharmony_ci | Mirror fields | | | 32b1994897Sopenharmony_ci panda class (`panda::Class`) ---------> +------------------+ <-|-+ 33b1994897Sopenharmony_ci | ... | | 34b1994897Sopenharmony_ci | `Managed Object` |---+ 35b1994897Sopenharmony_ci | ... | 36b1994897Sopenharmony_ci +------------------+ 37b1994897Sopenharmony_ci 38b1994897Sopenharmony_ciNote: as `panda::Class` object has variable size it must be last in the mirror class. 39b1994897Sopenharmony_ci 40b1994897Sopenharmony_ciSuch layout allows to get pointer to the `panda::Class` object from the `coretypes::Class` one and vice versa without dereferencies if we know language context and it's constant (some language specific code): 41b1994897Sopenharmony_ci 42b1994897Sopenharmony_ci```cpp 43b1994897Sopenharmony_ciauto *managed_class_obj = coretypes::Class::FromRuntimeClass(klass); 44b1994897Sopenharmony_ci... 45b1994897Sopenharmony_ciauto *runtime_class = managed_class_obj->GetRuntimeClass(); 46b1994897Sopenharmony_ci``` 47b1994897Sopenharmony_ci 48b1994897Sopenharmony_ciWhere `coretypes::Class::FromRuntimeClass` and `coretypes::Class::GetRuntimeClass` are implemented in the following way: 49b1994897Sopenharmony_ci 50b1994897Sopenharmony_ci 51b1994897Sopenharmony_ci```cpp 52b1994897Sopenharmony_cinamespace panda::coretypes { 53b1994897Sopenharmony_ciclass Class : public ObjectHeader { 54b1994897Sopenharmony_ci ... 55b1994897Sopenharmony_ci 56b1994897Sopenharmony_ci panda::Class *GetRuntimeClass() { 57b1994897Sopenharmony_ci return &klass_; 58b1994897Sopenharmony_ci } 59b1994897Sopenharmony_ci 60b1994897Sopenharmony_ci static constexpr size_t GetRuntimeClassOffset() { 61b1994897Sopenharmony_ci return MEMBER_OFFSET(Class, klass_); 62b1994897Sopenharmony_ci } 63b1994897Sopenharmony_ci 64b1994897Sopenharmony_ci static Class *FromRuntimeClass(panda::Class *klass) { 65b1994897Sopenharmony_ci return reinterpret_cast<Class *>(reinterpret_cast<uintptr_t>(klass) - GetRuntimeClassOffset()); 66b1994897Sopenharmony_ci } 67b1994897Sopenharmony_ci 68b1994897Sopenharmony_ci ... 69b1994897Sopenharmony_ci}; 70b1994897Sopenharmony_ci} // namespace panda::coretypes 71b1994897Sopenharmony_ci``` 72b1994897Sopenharmony_ci 73b1994897Sopenharmony_ciIn common places where language context can be different we can use `panda::Class::GetManagedObject`. For example: 74b1994897Sopenharmony_ci 75b1994897Sopenharmony_ci```cpp 76b1994897Sopenharmony_ciauto *managed_class_obj = klass->GetManagedObject(); 77b1994897Sopenharmony_ciObjectLock lock(managed_class_obj); 78b1994897Sopenharmony_ci``` 79b1994897Sopenharmony_ci 80b1994897Sopenharmony_ciInstead of 81b1994897Sopenharmony_ci 82b1994897Sopenharmony_ci```cpp 83b1994897Sopenharmony_ciObjectHeader *managed_class_obj; 84b1994897Sopenharmony_ciswitch (klass->GetSourceLang()) { 85b1994897Sopenharmony_ci case PANDA_ASSEMBLY: { 86b1994897Sopenharmony_ci managed_class_obj = coretypes::Class::FromRuntimeClass(klass); 87b1994897Sopenharmony_ci break; 88b1994897Sopenharmony_ci } 89b1994897Sopenharmony_ci case PLUGIN_SOURCE_LANG: { 90b1994897Sopenharmony_ci managed_class_obj = plugin::JClass::FromRuntimeClass(klass); 91b1994897Sopenharmony_ci break; 92b1994897Sopenharmony_ci } 93b1994897Sopenharmony_ci ... 94b1994897Sopenharmony_ci} 95b1994897Sopenharmony_ciObjectLock lock(managed_class_obj); 96b1994897Sopenharmony_ci``` 97