blob: 633ad630aa7f00a356c3ce7690ed52f613f7349f [file]
/*
* Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
#ifndef RUNTIME_OBJECT_TRAVERSAL_H
#define RUNTIME_OBJECT_TRAVERSAL_H
#include <type_traits>
#include "Memory.h"
#include "Natives.h"
#include "ReferenceOps.hpp"
#include "Types.h"
#include "ObjectOps.hpp"
namespace kotlin {
// TODO: Consider an iterator/ranges based approaches for traversals.
template <typename F>
PERFORMANCE_INLINE void traverseClassObjectFields(ObjHeader* object, F process) noexcept(noexcept(process(std::declval<mm::RefFieldAccessor>()))) {
const TypeInfo* typeInfo = object->type_info();
RuntimeAssert(typeInfo != theArrayTypeInfo, "Must not be an array of objects");
for (int index = 0; index < typeInfo->objOffsetsCount_; index++) {
auto fieldPtr = reinterpret_cast<ObjHeader**>(reinterpret_cast<uintptr_t>(object) + typeInfo->objOffsets_[index]);
process(mm::RefFieldAccessor(fieldPtr));
}
}
template <typename F>
PERFORMANCE_INLINE void traverseArrayOfObjectsElements(ArrayHeader* array, F process) noexcept(noexcept(process(std::declval<mm::RefFieldAccessor>()))) {
RuntimeAssert(array->type_info() == theArrayTypeInfo, "Must be an array of objects");
for (uint32_t index = 0; index < array->count_; index++) {
process(mm::RefFieldAccessor(ArrayAddressOfElementAt(array, index)));
}
}
template <typename F>
PERFORMANCE_INLINE void traverseObjectFields(ObjHeader* object, F process) noexcept(noexcept(process(std::declval<mm::RefFieldAccessor>()))) {
const TypeInfo* typeInfo = object->type_info();
// Only consider arrays of objects, not arrays of primitives.
if (typeInfo != theArrayTypeInfo) {
for (int index = 0; index < typeInfo->objOffsetsCount_; index++) {
auto fieldPtr = reinterpret_cast<ObjHeader**>(reinterpret_cast<uintptr_t>(object) + typeInfo->objOffsets_[index]);
process(mm::RefFieldAccessor(fieldPtr));
}
} else {
ArrayHeader* array = object->array();
for (uint32_t index = 0; index < array->count_; index++) {
process(mm::RefFieldAccessor(ArrayAddressOfElementAt(array, index)));
}
}
}
// FIXME explicitly mention no barriers
template <typename F>
PERFORMANCE_INLINE void traverseReferredObjects(ObjHeader* object, F process) noexcept(noexcept(process(std::declval<ObjHeader*>()))) {
traverseObjectFields(object, [&process](auto accessor) noexcept(noexcept(process(std::declval<ObjHeader*>()))) {
if (ObjHeader* ref = accessor.direct()) {
process(ref);
}
});
}
} // namespace kotlin
#endif // RUNTIME_OBJECT_TRAVERSAL_H