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:
+7
-1
@@ -60,9 +60,15 @@ class OptimizationMethodVisitor(
|
|||||||
RedundantNopsCleanupMethodTransformer()
|
RedundantNopsCleanupMethodTransformer()
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun canBeOptimized(node: MethodNode): Boolean {
|
fun canBeOptimized(node: MethodNode): Boolean {
|
||||||
val totalFramesSizeMb = node.instructions.size() * (node.maxLocals + node.maxStack) / (1024 * 1024)
|
val totalFramesSizeMb = node.instructions.size() * (node.maxLocals + node.maxStack) / (1024 * 1024)
|
||||||
return totalFramesSizeMb < MEMORY_LIMIT_BY_METHOD_MB
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.optimization.boxing
|
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.isLoadOperation
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
||||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||||
@@ -31,6 +32,7 @@ import java.util.*
|
|||||||
|
|
||||||
class PopBackwardPropagationTransformer : MethodTransformer() {
|
class PopBackwardPropagationTransformer : MethodTransformer() {
|
||||||
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||||
|
if (!OptimizationMethodVisitor.canBeOptimizedUsingSourceInterpreter(methodNode)) return
|
||||||
Transformer(methodNode).transform()
|
Transformer(methodNode).transform()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +65,7 @@ class PopBackwardPropagationTransformer : MethodTransformer() {
|
|||||||
private val frames by lazy { analyzeMethodBody() }
|
private val frames by lazy { analyzeMethodBody() }
|
||||||
|
|
||||||
fun transform() {
|
fun transform() {
|
||||||
if (!insns.any { it.isPurePush() }) return
|
if (insns.none { it.isPop() || it.isPurePush() }) return
|
||||||
|
|
||||||
computeTransformations()
|
computeTransformations()
|
||||||
for ((insn, transformation) in transformations.entries) {
|
for ((insn, transformation) in transformations.entries) {
|
||||||
@@ -257,6 +259,9 @@ fun AbstractInsnNode.isPurePush() =
|
|||||||
opcode in Opcodes.ACONST_NULL .. Opcodes.LDC + 2 ||
|
opcode in Opcodes.ACONST_NULL .. Opcodes.LDC + 2 ||
|
||||||
isUnitInstance()
|
isUnitInstance()
|
||||||
|
|
||||||
|
fun AbstractInsnNode.isPop() =
|
||||||
|
opcode == Opcodes.POP || opcode == Opcodes.POP2
|
||||||
|
|
||||||
fun AbstractInsnNode.isUnitInstance() =
|
fun AbstractInsnNode.isUnitInstance() =
|
||||||
opcode == Opcodes.GETSTATIC &&
|
opcode == Opcodes.GETSTATIC &&
|
||||||
this is FieldInsnNode && owner == "kotlin/Unit" && name == "INSTANCE"
|
this is FieldInsnNode && owner == "kotlin/Unit" && name == "INSTANCE"
|
||||||
|
|||||||
Reference in New Issue
Block a user