JVM_IR: do not generate redundant load+stores before inline calls

This commit is contained in:
pyos
2019-09-27 11:05:46 +02:00
committed by max-kammerer
parent 59408242db
commit cea69e0706
8 changed files with 57 additions and 28 deletions
@@ -166,6 +166,12 @@ class ExpressionCodegen(
return StackValue.onStack(type, irType.toKotlinType())
}
internal fun genOrGetLocal(expression: IrExpression, data: BlockInfo): StackValue =
if (expression is IrGetValue)
StackValue.local(findLocalIndex(expression.symbol), frameMap.typeOf(expression.symbol), expression.type.toKotlinType())
else
gen(expression, typeMapper.mapType(expression.type), expression.type, data)
fun generate() {
mv.visitCode()
val startLabel = markNewLabel()
@@ -16,8 +16,6 @@
package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.ValueKind
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
@@ -44,9 +42,5 @@ interface IrCallGenerator {
codegen.gen(argumentExpression, parameterType, irValueParameter.type, blockInfo)
}
fun putValueIfNeeded(parameterType: Type, value: StackValue, kind: ValueKind, parameterIndex: Int, codegen: ExpressionCodegen) {
value.put(parameterType, codegen.visitor)
}
object DefaultCallGenerator : IrCallGenerator
}
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
@@ -72,32 +73,27 @@ class IrInlineCodegen(
activeLambda = null
}
} else {
putValueOnStack(argumentExpression, parameterType, irValueParameter.index, blockInfo, irValueParameter.type)
val onStack = if (irValueParameter.index >= 0)
// Reuse an existing local if possible. NOTE: when stopping at a breakpoint placed
// in an inline function, arguments which reuse an existing local will not be visible
// in the debugger.
codegen.genOrGetLocal(argumentExpression, blockInfo)
else
// Do not reuse locals for receivers. While it's actually completely fine, the non-IR
// backend does not do it for internal reasons, and here we replicate the debugging
// experience.
codegen.gen(argumentExpression, parameterType, irValueParameter.type, blockInfo)
// TODO support default argument erasure: do nothing if the parameter is a default mask, the argument is a constant int,
// and processDefaultMaskOrMethodHandler(StackValue.constant(...), ValueKind.DEFAULT_MASK) is true.
val expectedType = JvmKotlinType(parameterType, irValueParameter.type.toKotlinType())
putArgumentOrCapturedToLocalVal(expectedType, onStack, -1, irValueParameter.index, ValueKind.CAPTURED)
}
}
override fun putValueIfNeeded(
parameterType: Type,
value: StackValue,
kind: ValueKind,
parameterIndex: Int,
codegen: ExpressionCodegen
) {
//TODO: support default argument erasure
//if (processDefaultMaskOrMethodHandler(value, kind)) return
putArgumentOrCapturedToLocalVal(JvmKotlinType(value.type, value.kotlinType), value, -1, parameterIndex, ValueKind.CAPTURED /*kind*/)
}
private fun putCapturedValueOnStack(argumentExpression: IrExpression, valueType: Type, capturedParamIndex: Int) {
val onStack = codegen.gen(argumentExpression, valueType, argumentExpression.type, BlockInfo())
putArgumentOrCapturedToLocalVal(
JvmKotlinType(onStack.type, onStack.kotlinType), onStack, capturedParamIndex, capturedParamIndex, ValueKind.CAPTURED
)
}
private fun putValueOnStack(argumentExpression: IrExpression, valueType: Type, paramIndex: Int, blockInfo: BlockInfo, irType: IrType) {
val onStack = codegen.gen(argumentExpression, valueType, irType, blockInfo)
putArgumentOrCapturedToLocalVal(JvmKotlinType(onStack.type, onStack.kotlinType), onStack, -1, paramIndex, ValueKind.CAPTURED)
val onStack = codegen.genOrGetLocal(argumentExpression, BlockInfo())
val expectedType = JvmKotlinType(valueType, argumentExpression.type.toKotlinType())
putArgumentOrCapturedToLocalVal(expectedType, onStack, capturedParamIndex, capturedParamIndex, ValueKind.CAPTURED)
}
override fun beforeValueParametersStart() {
@@ -0,0 +1,13 @@
// FILE: 1.kt
package test
inline fun f(g: () -> Int) {}
inline fun h(g: () -> Int) = run { f(g) }
// FILE: 2.kt
import test.*
fun box(): String {
h { 1 }
return "OK"
}
@@ -3412,6 +3412,11 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
public void testStackHeightBug() throws Exception {
runTest("compiler/testData/codegen/boxInline/special/stackHeightBug.kt");
}
@TestMetadata("unusedInlineLambda.kt")
public void testUnusedInlineLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/special/unusedInlineLambda.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/stackOnReturn")
@@ -3412,6 +3412,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
public void testStackHeightBug() throws Exception {
runTest("compiler/testData/codegen/boxInline/special/stackHeightBug.kt");
}
@TestMetadata("unusedInlineLambda.kt")
public void testUnusedInlineLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/special/unusedInlineLambda.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/stackOnReturn")
@@ -3412,6 +3412,11 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
public void testStackHeightBug() throws Exception {
runTest("compiler/testData/codegen/boxInline/special/stackHeightBug.kt");
}
@TestMetadata("unusedInlineLambda.kt")
public void testUnusedInlineLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/special/unusedInlineLambda.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/stackOnReturn")
@@ -3412,6 +3412,11 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
public void testStackHeightBug() throws Exception {
runTest("compiler/testData/codegen/boxInline/special/stackHeightBug.kt");
}
@TestMetadata("unusedInlineLambda.kt")
public void testUnusedInlineLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/special/unusedInlineLambda.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/stackOnReturn")