Skip PopBackwardPropagation for methods with large frames or no POPs

TODO get rid of SourceInterpreter here, it's quite expensive.
This commit is contained in:
Dmitry Petrov
2017-06-19 16:06:39 +03:00
parent 0a622e4440
commit 9356c1e0ef
2 changed files with 13 additions and 2 deletions
@@ -60,9 +60,15 @@ class OptimizationMethodVisitor(
RedundantNopsCleanupMethodTransformer()
)
private fun canBeOptimized(node: MethodNode): Boolean {
fun canBeOptimized(node: MethodNode): Boolean {
val totalFramesSizeMb = node.instructions.size() * (node.maxLocals + node.maxStack) / (1024 * 1024)
return totalFramesSizeMb < MEMORY_LIMIT_BY_METHOD_MB
}
fun canBeOptimizedUsingSourceInterpreter(node: MethodNode): Boolean {
val frameSize = node.maxLocals + node.maxStack
val totalFramesSizeMb = node.instructions.size().toLong() * frameSize * frameSize / (1024 * 1024)
return totalFramesSizeMb < MEMORY_LIMIT_BY_METHOD_MB
}
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.codegen.optimization.boxing
import org.jetbrains.kotlin.codegen.optimization.OptimizationMethodVisitor
import org.jetbrains.kotlin.codegen.optimization.common.isLoadOperation
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
@@ -31,6 +32,7 @@ import java.util.*
class PopBackwardPropagationTransformer : MethodTransformer() {
override fun transform(internalClassName: String, methodNode: MethodNode) {
if (!OptimizationMethodVisitor.canBeOptimizedUsingSourceInterpreter(methodNode)) return
Transformer(methodNode).transform()
}
@@ -63,7 +65,7 @@ class PopBackwardPropagationTransformer : MethodTransformer() {
private val frames by lazy { analyzeMethodBody() }
fun transform() {
if (!insns.any { it.isPurePush() }) return
if (insns.none { it.isPop() || it.isPurePush() }) return
computeTransformations()
for ((insn, transformation) in transformations.entries) {
@@ -257,6 +259,9 @@ fun AbstractInsnNode.isPurePush() =
opcode in Opcodes.ACONST_NULL .. Opcodes.LDC + 2 ||
isUnitInstance()
fun AbstractInsnNode.isPop() =
opcode == Opcodes.POP || opcode == Opcodes.POP2
fun AbstractInsnNode.isUnitInstance() =
opcode == Opcodes.GETSTATIC &&
this is FieldInsnNode && owner == "kotlin/Unit" && name == "INSTANCE"