[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
This commit is contained in:
Igor Chevdar
2022-10-26 12:06:36 +03:00
parent d4cfb002d0
commit 873b84491d
@@ -656,8 +656,8 @@ internal object EscapeAnalysis {
else -> null else -> null
} }
private fun arraySize(itemSize: Int, length: Int) = private fun arraySize(itemSize: Int, length: Int): Long =
pointerSize /* typeinfo */ + 4 /* size */ + itemSize * length pointerSize /* typeinfo */ + 4 /* size */ + itemSize * length.toLong()
private fun analyze(callGraph: CallGraph, pointsToGraph: PointsToGraph, function: DataFlowIR.FunctionSymbol.Declared) { private fun analyze(callGraph: CallGraph, pointsToGraph: PointsToGraph, function: DataFlowIR.FunctionSymbol.Declared) {
context.log {"Before calls analysis" } context.log {"Before calls analysis" }
@@ -1573,6 +1573,8 @@ internal object EscapeAnalysis {
escapeOrigins.forEach { propagateEscapeOrigin(it) } escapeOrigins.forEach { propagateEscapeOrigin(it) }
// TODO: To a setting?
val allowedToAlloc = 65536
val stackArrayCandidates = mutableListOf<ArrayStaticAllocation>() val stackArrayCandidates = mutableListOf<ArrayStaticAllocation>()
for ((node, ptgNode) in nodes) { for ((node, ptgNode) in nodes) {
if (node.ir == null) continue if (node.ir == null) continue
@@ -1592,9 +1594,9 @@ internal object EscapeAnalysis {
if (itemSize != null) { if (itemSize != null) {
val sizeArgument = node.arguments.first().node val sizeArgument = node.arguments.first().node
val arrayLength = arrayLengthOf(sizeArgument) val arrayLength = arrayLengthOf(sizeArgument)
if (arrayLength != null) { val arraySize = arraySize(itemSize, arrayLength ?: Int.MAX_VALUE)
stackArrayCandidates += if (arraySize <= allowedToAlloc) {
ArrayStaticAllocation(ptgNode, irClass, arraySize(itemSize, arrayLength)) stackArrayCandidates += ArrayStaticAllocation(ptgNode, irClass, arraySize.toInt())
} else { } else {
// Can be placed into the local arena. // Can be placed into the local arena.
// TODO. Support Lifetime.LOCAL // TODO. Support Lifetime.LOCAL
@@ -1616,14 +1618,13 @@ internal object EscapeAnalysis {
} }
stackArrayCandidates.sortBy { it.size } stackArrayCandidates.sortBy { it.size }
// TODO: To a setting? var remainedToAlloc = allowedToAlloc
var allowedToAlloc = 65536
for ((ptgNode, irClass, size) in stackArrayCandidates) { for ((ptgNode, irClass, size) in stackArrayCandidates) {
if (lifetimeOf(ptgNode) != Lifetime.STACK) continue if (lifetimeOf(ptgNode) != Lifetime.STACK) continue
if (size <= allowedToAlloc) if (size <= remainedToAlloc)
allowedToAlloc -= size remainedToAlloc -= size
else { else {
allowedToAlloc = 0 remainedToAlloc = 0
// Do not exile primitive arrays - they ain't reference no object. // Do not exile primitive arrays - they ain't reference no object.
if (irClass.symbol == symbols.array && propagateExiledToHeapObjects) { if (irClass.symbol == symbols.array && propagateExiledToHeapObjects) {
context.log { "Forcing node ${nodeToString(ptgNode.node!!)} to escape" } context.log { "Forcing node ${nodeToString(ptgNode.node!!)} to escape" }