Files
ark_runtime_core/docs/runtime-class.md
T
wanyanglan 14c9021696 add ark runtime_core
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I2564094cef9c6c41263e37faf9ffbbec14223dc7
2021-09-05 20:53:43 +08:00

3.4 KiB

Runtime class

Panda runtime uses panda::Class to store all necessary language independent information about classes. 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, the Class Word field of the object header points to the instance of this class. ClassLinker::GetClass also returns an instance of the panda::Class.

Pointer to the managed class object (instance of panda.Class or java.lang.Class in case of Java, for example) can be obtained using panda::Class::GetManagedObject method:

panda::Class *cls = obj->ClassAddr()->GetManagedObject();

Storing common runtime information separately from managed objects allows more flexibility for the layout but causes additional dereferences to get panda::Class from mirror classes and vice versa. However, we can use composition to reduce the number of additional dereferences.

namespace panda::coretypes {
class Class : public ObjectHeader {

    ... // Mirror fields

    panda::Class klass_;
};
}  // namespace panda::coretypes

The layout of the coretypes::Class is as follows:

mirror class (`coretypes::Class`) --------> +------------------+ <-+
                                            |    `Mark Word`   |   |
                                            |    `Class Word`  |-----+
                                            +------------------+   | |
                                            |   Mirror fields  |   | |
    panda class (`panda::Class`) ---------> +------------------+ <-|-+
                                            |      ...         |   |
                                            | `Managed Object` |---+
                                            |      ...         |
                                            +------------------+

Note: The panda::Class object must be the last in the mirror class because it has variable size.

Such 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):

auto *managed_class_obj = coretypes::Class::FromRuntimeClass(klass);
...
auto *runtime_class = managed_class_obj->GetRuntimeClass();

Where coretypes::Class::FromRuntimeClass and coretypes::Class::GetRuntimeClass are implemented in the following way:

namespace panda::coretypes {
class Class : public ObjectHeader {
    ...

    panda::Class *GetRuntimeClass() {
        return &klass_;
    }

    static constexpr size_t GetRuntimeClassOffset() {
        return MEMBER_OFFSET(Class, klass_);
    }

    static Class *FromRuntimeClass(panda::Class *klass) {
        return reinterpret_cast<Class *>(reinterpret_cast<uintptr_t>(klass) - GetRuntimeClassOffset());
    }

    ...
};
}  // namespace panda::coretypes

In common places where language context can be different we can use panda::Class::GetManagedObject. For example:

auto *managed_class_obj = klass->GetManagedObject();
ObjectLock lock(managed_class_obj);

Instead of

ObjectHeader *managed_class_obj;
switch (klass->GetSourceLang()) {
    case PANDA_ASSEMBLY: {
        managed_class_obj = coretypes::Class::FromRuntimeClass(klass);
        break;
    }
    case JAVA_8: {
        managed_class_obj = java::JClass::FromRuntimeClass(klass);
        break;
    }
    ...
}
ObjectLock lock(managed_class_obj);