Fix garbage cycle collection for kotlin.Array
This commit is contained in:
committed by
SvyatoslavScherbina
parent
b31590f545
commit
2934588bbe
+7
-1
@@ -165,6 +165,12 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
val objOffsetsPtr = staticData.placeGlobalConstArray("krefs:$className", int32Type,
|
||||
objOffsets.map { Int32(it.toInt()) })
|
||||
|
||||
val objOffsetsCount = if (classDesc.descriptor == context.builtIns.array) {
|
||||
1 // To mark it as non-leaf.
|
||||
} else {
|
||||
objOffsets.size
|
||||
}
|
||||
|
||||
val fields = llvmDeclarations.fields.mapIndexed { index, field ->
|
||||
// Note: using FQ name because a class may have multiple fields with the same name due to property overriding
|
||||
val nameSignature = field.fqNameSafe.localHash // FIXME: add signature
|
||||
@@ -191,7 +197,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
name,
|
||||
size,
|
||||
superType,
|
||||
objOffsetsPtr, objOffsets.size,
|
||||
objOffsetsPtr, objOffsetsCount,
|
||||
interfacesPtr, interfaces.size,
|
||||
methodsPtr, methods.size,
|
||||
fieldsPtr, if (classDesc.isInterface) -1 else fields.size,
|
||||
|
||||
@@ -2117,6 +2117,10 @@ task memory_cycles0(type: RunKonanTest) {
|
||||
source = "runtime/memory/cycles0.kt"
|
||||
}
|
||||
|
||||
task memory_cycles1(type: RunKonanTest) {
|
||||
source = "runtime/memory/cycles1.kt"
|
||||
}
|
||||
|
||||
task memory_basic0(type: RunKonanTest) {
|
||||
source = "runtime/memory/basic0.kt"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package runtime.memory.cycles1
|
||||
|
||||
import kotlin.test.*
|
||||
import konan.ref.*
|
||||
|
||||
@Test fun runTest() {
|
||||
val weakRefToTrashCycle = createLoop()
|
||||
konan.internal.GC.collect()
|
||||
assertNull(weakRefToTrashCycle.get())
|
||||
}
|
||||
|
||||
private fun createLoop(): WeakReference<Any> {
|
||||
val loop = Array<Any?>(1, { null })
|
||||
loop[0] = loop
|
||||
|
||||
return WeakReference(loop)
|
||||
}
|
||||
@@ -442,12 +442,13 @@ inline void traverseContainerObjectFields(ContainerHeader* container, func proce
|
||||
ObjHeader* obj = reinterpret_cast<ObjHeader*>(container + 1);
|
||||
for (int object = 0; object < container->objectCount(); object++) {
|
||||
const TypeInfo* typeInfo = obj->type_info();
|
||||
for (int index = 0; index < typeInfo->objOffsetsCount_; index++) {
|
||||
ObjHeader** location = reinterpret_cast<ObjHeader**>(
|
||||
reinterpret_cast<uintptr_t>(obj + 1) + typeInfo->objOffsets_[index]);
|
||||
process(location);
|
||||
}
|
||||
if (typeInfo == theArrayTypeInfo) {
|
||||
if (typeInfo != theArrayTypeInfo) {
|
||||
for (int index = 0; index < typeInfo->objOffsetsCount_; index++) {
|
||||
ObjHeader** location = reinterpret_cast<ObjHeader**>(
|
||||
reinterpret_cast<uintptr_t>(obj + 1) + typeInfo->objOffsets_[index]);
|
||||
process(location);
|
||||
}
|
||||
} else {
|
||||
ArrayHeader* array = obj->array();
|
||||
for (int index = 0; index < array->count_; index++) {
|
||||
process(ArrayAddressOfElementAt(array, index));
|
||||
|
||||
@@ -81,8 +81,10 @@ struct TypeInfo {
|
||||
int32_t instanceSize_;
|
||||
// Must be pointer to Any for array classes, and null for Any.
|
||||
const TypeInfo* superType_;
|
||||
// All object references inside this object.
|
||||
// All object reference fields inside this object.
|
||||
const int32_t* objOffsets_;
|
||||
// Count of object reference fields inside this object.
|
||||
// 1 for kotlin.Array to mark it as non-leaf.
|
||||
int32_t objOffsetsCount_;
|
||||
const TypeInfo* const* implementedInterfaces_;
|
||||
int32_t implementedInterfacesCount_;
|
||||
|
||||
Reference in New Issue
Block a user