[K/N] Support of collectReferenceFieldValues function

This commit is contained in:
Pavel Kunyavskiy
2022-06-30 12:05:32 +02:00
committed by Space
parent 3f1e06b32e
commit c7131a68ce
4 changed files with 164 additions and 0 deletions
@@ -16,6 +16,9 @@
#include "KAssert.h"
#include "TypeInfo.h"
#include "Memory.h"
#include "Types.h"
#include "KString.h"
extern "C" {
@@ -39,4 +42,14 @@ InterfaceTableRecord const* LookupInterfaceTableRecord(InterfaceTableRecord cons
return interfaceTable + l;
}
RUNTIME_NOTHROW int Kotlin_internal_reflect_getObjectReferenceFieldsCount(ObjHeader* object) {
auto *info = object->type_info();
if (info->IsArray()) return 0;
return info->objOffsetsCount_;
}
RUNTIME_NOTHROW OBJ_GETTER(Kotlin_internal_reflect_getObjectReferenceFieldByIndex, ObjHeader* object, int index) {
RETURN_OBJ(*reinterpret_cast<ObjHeader**>(reinterpret_cast<uintptr_t>(object) + object->type_info()->objOffsets_[index]));
}
}
@@ -19,3 +19,36 @@ internal fun debugDescription(kClass: KClass<*>, identity: Int): String {
val identityStr = unsignedIdentity.toString(16)
return "$className@$identityStr"
}
@GCUnsafeCall("Kotlin_internal_reflect_getObjectReferenceFieldsCount")
private external fun getObjectReferenceFieldsCount(o: Any): Int
@GCUnsafeCall("Kotlin_internal_reflect_getObjectReferenceFieldByIndex")
private external fun getObjectReferenceFieldByIndex(o: Any, index: Int): Any?
/**
* Returns [List] of non-null reference fields of the object.
*
* This function is intended to be used for testing and debugging purposes.
* - It heavily relies on internal ABI details. No compatibility guarantees on exact list contents are provided.
* - Order and representation of object's fields are subject to change.
* - Performance characteristics of the implementation
*
* Limitations:
* - Primitives (unboxed [Int], [Double], [Float], etc.) are not included in the result.
* - Non-boxed value classes over primitives are not included in the result.
* - Non-boxed value classes over references are included in the result as the underlying reference type.
* - Synthetic fields (e.g. special fields for delegation) are included in the result.
* - There is no way to find which reference in the result corresponds to which field.
*
* For `Array<T>` list of all its non-null elements is returned.
* For primitive arrays ([IntArray], [DoubleArray], [FloatArray], etc.) empty list is returned.
*/
@InternalForKotlinNative
public fun Any.collectReferenceFieldValues() : List<Any> {
return when {
this is Array<*> -> this.filterNotNull()
else -> (0 until getObjectReferenceFieldsCount(this@collectReferenceFieldValues)).mapNotNull {
getObjectReferenceFieldByIndex(this@collectReferenceFieldValues, it)
}
}
}