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())
|
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() {
|
fun generate() {
|
||||||
mv.visitCode()
|
mv.visitCode()
|
||||||
val startLabel = markNewLabel()
|
val startLabel = markNewLabel()
|
||||||
|
|||||||
-6
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
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.declarations.IrValueParameter
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||||
@@ -44,9 +42,5 @@ interface IrCallGenerator {
|
|||||||
codegen.gen(argumentExpression, parameterType, irValueParameter.type, blockInfo)
|
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
|
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.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
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.dump
|
||||||
import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
|
import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
@@ -72,32 +73,27 @@ class IrInlineCodegen(
|
|||||||
activeLambda = null
|
activeLambda = null
|
||||||
}
|
}
|
||||||
} else {
|
} 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) {
|
private fun putCapturedValueOnStack(argumentExpression: IrExpression, valueType: Type, capturedParamIndex: Int) {
|
||||||
val onStack = codegen.gen(argumentExpression, valueType, argumentExpression.type, BlockInfo())
|
val onStack = codegen.genOrGetLocal(argumentExpression, BlockInfo())
|
||||||
putArgumentOrCapturedToLocalVal(
|
val expectedType = JvmKotlinType(valueType, argumentExpression.type.toKotlinType())
|
||||||
JvmKotlinType(onStack.type, onStack.kotlinType), onStack, capturedParamIndex, capturedParamIndex, ValueKind.CAPTURED
|
putArgumentOrCapturedToLocalVal(expectedType, 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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun beforeValueParametersStart() {
|
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 {
|
public void testStackHeightBug() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/special/stackHeightBug.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/boxInline/stackOnReturn")
|
||||||
|
|||||||
Generated
+5
@@ -3412,6 +3412,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
public void testStackHeightBug() throws Exception {
|
public void testStackHeightBug() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/special/stackHeightBug.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/boxInline/stackOnReturn")
|
||||||
|
|||||||
+5
@@ -3412,6 +3412,11 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
|
|||||||
public void testStackHeightBug() throws Exception {
|
public void testStackHeightBug() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/special/stackHeightBug.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/boxInline/stackOnReturn")
|
||||||
|
|||||||
Generated
+5
@@ -3412,6 +3412,11 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
|
|||||||
public void testStackHeightBug() throws Exception {
|
public void testStackHeightBug() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/special/stackHeightBug.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/boxInline/stackOnReturn")
|
||||||
|
|||||||
Reference in New Issue
Block a user