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