JVM_IR: do not generate redundant load+stores before inline calls
This commit is contained in:
+6
@@ -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()
|
||||
|
||||
-6
@@ -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
|
||||
}
|
||||
|
||||
+18
-22
@@ -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"
|
||||
}
|
||||
+5
@@ -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")
|
||||
|
||||
Generated
+5
@@ -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")
|
||||
|
||||
+5
@@ -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")
|
||||
|
||||
Generated
+5
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user