From 873b84491dbd672e13690f8d2ce49d803673a94f Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Wed, 26 Oct 2022 12:06:36 +0300 Subject: [PATCH] [K/N][codegen] Fixed bug with huge arrays during escape analysis Escape analysis tried to allocate some very big arrays on the stack because an overflow happened during size computation --- .../konan/optimizations/EscapeAnalysis.kt | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt index e9debdaf4f3..a8baf55563c 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt @@ -656,8 +656,8 @@ internal object EscapeAnalysis { else -> null } - private fun arraySize(itemSize: Int, length: Int) = - pointerSize /* typeinfo */ + 4 /* size */ + itemSize * length + private fun arraySize(itemSize: Int, length: Int): Long = + pointerSize /* typeinfo */ + 4 /* size */ + itemSize * length.toLong() private fun analyze(callGraph: CallGraph, pointsToGraph: PointsToGraph, function: DataFlowIR.FunctionSymbol.Declared) { context.log {"Before calls analysis" } @@ -1573,6 +1573,8 @@ internal object EscapeAnalysis { escapeOrigins.forEach { propagateEscapeOrigin(it) } + // TODO: To a setting? + val allowedToAlloc = 65536 val stackArrayCandidates = mutableListOf() for ((node, ptgNode) in nodes) { if (node.ir == null) continue @@ -1592,9 +1594,9 @@ internal object EscapeAnalysis { if (itemSize != null) { val sizeArgument = node.arguments.first().node val arrayLength = arrayLengthOf(sizeArgument) - if (arrayLength != null) { - stackArrayCandidates += - ArrayStaticAllocation(ptgNode, irClass, arraySize(itemSize, arrayLength)) + val arraySize = arraySize(itemSize, arrayLength ?: Int.MAX_VALUE) + if (arraySize <= allowedToAlloc) { + stackArrayCandidates += ArrayStaticAllocation(ptgNode, irClass, arraySize.toInt()) } else { // Can be placed into the local arena. // TODO. Support Lifetime.LOCAL @@ -1616,14 +1618,13 @@ internal object EscapeAnalysis { } stackArrayCandidates.sortBy { it.size } - // TODO: To a setting? - var allowedToAlloc = 65536 + var remainedToAlloc = allowedToAlloc for ((ptgNode, irClass, size) in stackArrayCandidates) { if (lifetimeOf(ptgNode) != Lifetime.STACK) continue - if (size <= allowedToAlloc) - allowedToAlloc -= size + if (size <= remainedToAlloc) + remainedToAlloc -= size else { - allowedToAlloc = 0 + remainedToAlloc = 0 // Do not exile primitive arrays - they ain't reference no object. if (irClass.symbol == symbols.array && propagateExiledToHeapObjects) { context.log { "Forcing node ${nodeToString(ptgNode.node!!)} to escape" }