JVM_IR minor cleanup in inliner

This commit is contained in:
Dmitry Petrov
2021-08-05 14:53:08 +03:00
committed by TeamCityServer
parent d88a665fa8
commit ec90649854
2 changed files with 62 additions and 43 deletions
@@ -461,9 +461,9 @@ class ExpressionCodegen(
require(callee.parent is IrClass) { "Unhandled intrinsic in ExpressionCodegen: ${callee.render()}" } require(callee.parent is IrClass) { "Unhandled intrinsic in ExpressionCodegen: ${callee.render()}" }
val callable = methodSignatureMapper.mapToCallableMethod(expression, irFunction) val callable = methodSignatureMapper.mapToCallableMethod(expression, irFunction)
val callGenerator = getOrCreateCallGenerator(expression, data, callable.signature) val callGenerator = getOrCreateCallGenerator(expression, data, callable.signature)
val isSuspensionPoint = expression.isSuspensionPoint()
if (isSuspensionPoint != SuspensionPointKind.NEVER) { val suspensionPointKind = expression.getSuspensionPointKind()
if (suspensionPointKind != SuspensionPointKind.NEVER) {
addInlineMarker(mv, isStartNotEnd = true) addInlineMarker(mv, isStartNotEnd = true)
} }
@@ -490,16 +490,16 @@ class ExpressionCodegen(
expression.markLineNumber(true) expression.markLineNumber(true)
if (isSuspensionPoint != SuspensionPointKind.NEVER) { if (suspensionPointKind != SuspensionPointKind.NEVER) {
addSuspendMarker(mv, isStartNotEnd = true, isSuspensionPoint == SuspensionPointKind.NOT_INLINE) addSuspendMarker(mv, isStartNotEnd = true, suspensionPointKind == SuspensionPointKind.NOT_INLINE)
} }
callGenerator.genCall(callable, this, expression, isInsideCondition) callGenerator.genCall(callable, this, expression, isInsideCondition)
val unboxedInlineClassIrType = callee.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass() val unboxedInlineClassIrType = callee.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()
if (isSuspensionPoint != SuspensionPointKind.NEVER) { if (suspensionPointKind != SuspensionPointKind.NEVER) {
addSuspendMarker(mv, isStartNotEnd = false, isSuspensionPoint == SuspensionPointKind.NOT_INLINE) addSuspendMarker(mv, isStartNotEnd = false, suspensionPointKind == SuspensionPointKind.NOT_INLINE)
if (unboxedInlineClassIrType != null) { if (unboxedInlineClassIrType != null) {
generateResumePathUnboxing(mv, unboxedInlineClassIrType, typeMapper) generateResumePathUnboxing(mv, unboxedInlineClassIrType, typeMapper)
} }
@@ -541,17 +541,24 @@ class ExpressionCodegen(
} }
} }
private fun IrFunctionAccessExpression.isSuspensionPoint(): SuspensionPointKind = when { private fun IrFunctionAccessExpression.getSuspensionPointKind(): SuspensionPointKind =
!symbol.owner.isSuspend || !irFunction.shouldContainSuspendMarkers() -> SuspensionPointKind.NEVER when {
// Copy-pasted bytecode blocks are not suspension points. !symbol.owner.isSuspend || !irFunction.shouldContainSuspendMarkers() ->
symbol.owner.isInline -> SuspensionPointKind.NEVER
if (symbol.owner.name.asString() == "suspendCoroutineUninterceptedOrReturn" && // Copy-pasted bytecode blocks are not suspension points.
symbol.owner.getPackageFragment()?.fqName == FqName("kotlin.coroutines.intrinsics") symbol.owner.isInline ->
) SuspensionPointKind.ALWAYS else SuspensionPointKind.NEVER if (symbol.owner.name.asString() == "suspendCoroutineUninterceptedOrReturn" &&
// This includes inline lambdas, but only in functions intended for the inliner; in others, they stay as `f.invoke()`. symbol.owner.getPackageFragment()?.fqName == FqName("kotlin.coroutines.intrinsics")
dispatchReceiver.isReadOfInlineLambda() -> SuspensionPointKind.NOT_INLINE )
else -> SuspensionPointKind.ALWAYS SuspensionPointKind.ALWAYS
} else
SuspensionPointKind.NEVER
// This includes inline lambdas, but only in functions intended for the inliner; in others, they stay as `f.invoke()`.
dispatchReceiver.isReadOfInlineLambda() ->
SuspensionPointKind.NOT_INLINE
else ->
SuspensionPointKind.ALWAYS
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: BlockInfo): PromisedValue { override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: BlockInfo): PromisedValue {
val callee = expression.symbol.owner val callee = expression.symbol.owner
@@ -645,7 +652,8 @@ class ExpressionCodegen(
internal fun genOrGetLocal(expression: IrExpression, type: Type, parameterType: IrType, data: BlockInfo): StackValue = internal fun genOrGetLocal(expression: IrExpression, type: Type, parameterType: IrType, data: BlockInfo): StackValue =
if (expression is IrGetValue) if (expression is IrGetValue)
StackValue.local( StackValue.local(
findLocalIndex(expression.symbol), frameMap.typeOf(expression.symbol), findLocalIndex(expression.symbol),
frameMap.typeOf(expression.symbol),
expression.symbol.owner.realType.toIrBasedKotlinType() expression.symbol.owner.realType.toIrBasedKotlinType()
) )
else else
@@ -1403,7 +1411,9 @@ class ExpressionCodegen(
} }
private fun getOrCreateCallGenerator( private fun getOrCreateCallGenerator(
element: IrFunctionAccessExpression, data: BlockInfo, signature: JvmMethodSignature element: IrFunctionAccessExpression,
data: BlockInfo,
signature: JvmMethodSignature
): IrCallGenerator { ): IrCallGenerator {
if (!element.symbol.owner.isInlineFunctionCall(context) || if (!element.symbol.owner.isInlineFunctionCall(context) ||
classCodegen.irClass.fileParent.fileEntry is MultifileFacadeFileEntry || classCodegen.irClass.fileParent.fileEntry is MultifileFacadeFileEntry ||
@@ -55,7 +55,7 @@ class IrInlineCodegen(
) { ) {
val isInlineParameter = irValueParameter.isInlineParameter() val isInlineParameter = irValueParameter.isInlineParameter()
if (isInlineParameter && argumentExpression.isInlineIrExpression()) { if (isInlineParameter && argumentExpression.isInlineIrExpression()) {
val irReference = (argumentExpression as IrBlock).statements.filterIsInstance<IrFunctionReference>().single() val irReference = (argumentExpression as IrBlock).statements.last() as IrFunctionReference
val lambdaInfo = IrExpressionLambdaImpl(codegen, irReference) val lambdaInfo = IrExpressionLambdaImpl(codegen, irReference)
rememberClosure(parameterType, irValueParameter.index, lambdaInfo) rememberClosure(parameterType, irValueParameter.index, lambdaInfo)
lambdaInfo.generateLambdaBody(sourceCompiler) lambdaInfo.generateLambdaBody(sourceCompiler)
@@ -65,30 +65,39 @@ class IrInlineCodegen(
putCapturedToLocalVal(onStack, param, ir.type.toIrBasedKotlinType()) putCapturedToLocalVal(onStack, param, ir.type.toIrBasedKotlinType())
} }
} else { } else {
val kind = when (irValueParameter.origin) { val kind = when {
IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION -> ValueKind.DEFAULT_MASK irValueParameter.origin == IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION ->
IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION -> ValueKind.METHOD_HANDLE_IN_DEFAULT ValueKind.DEFAULT_MASK
else -> when { irValueParameter.origin == IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION ->
argumentExpression is IrContainerExpression && argumentExpression.origin == IrStatementOrigin.DEFAULT_VALUE -> ValueKind.METHOD_HANDLE_IN_DEFAULT
if (isInlineParameter) ValueKind.DEFAULT_INLINE_PARAMETER else ValueKind.DEFAULT_PARAMETER argumentExpression is IrContainerExpression && argumentExpression.origin == IrStatementOrigin.DEFAULT_VALUE ->
// TODO ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND? if (isInlineParameter)
isInlineParameter && irValueParameter.type.isSuspendFunctionTypeOrSubtype() -> ValueKind.DEFAULT_INLINE_PARAMETER
ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER else
else -> ValueKind.GENERAL ValueKind.DEFAULT_PARAMETER
} // TODO ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_PARAMETER_CALLED_IN_SUSPEND?
isInlineParameter && irValueParameter.type.isSuspendFunctionTypeOrSubtype() ->
ValueKind.NON_INLINEABLE_ARGUMENT_FOR_INLINE_SUSPEND_PARAMETER
else ->
ValueKind.GENERAL
} }
val onStack = when (kind) { val onStack = when (kind) {
ValueKind.METHOD_HANDLE_IN_DEFAULT -> StackValue.constant(null, AsmTypes.OBJECT_TYPE) ValueKind.METHOD_HANDLE_IN_DEFAULT ->
ValueKind.DEFAULT_MASK -> StackValue.constant((argumentExpression as IrConst<*>).value, Type.INT_TYPE) StackValue.constant(null, AsmTypes.OBJECT_TYPE)
ValueKind.DEFAULT_PARAMETER, ValueKind.DEFAULT_INLINE_PARAMETER -> StackValue.createDefaultValue(parameterType) ValueKind.DEFAULT_MASK ->
// Here we replicate the old backend: reusing the locals for everything except extension receivers. StackValue.constant((argumentExpression as IrConst<*>).value, Type.INT_TYPE)
// TODO when stopping at a breakpoint placed in an inline function, arguments which reuse an existing ValueKind.DEFAULT_PARAMETER, ValueKind.DEFAULT_INLINE_PARAMETER ->
// local will not be visible in the debugger, so this needs to be reconsidered. StackValue.createDefaultValue(parameterType)
else -> if (irValueParameter.index >= 0) else -> {
codegen.genOrGetLocal(argumentExpression, parameterType, irValueParameter.type, blockInfo) // Here we replicate the old backend: reusing the locals for everything except extension receivers.
else // TODO when stopping at a breakpoint placed in an inline function, arguments which reuse an existing
codegen.gen(argumentExpression, parameterType, irValueParameter.type, blockInfo) // local will not be visible in the debugger, so this needs to be reconsidered.
if (irValueParameter.index >= 0)
codegen.genOrGetLocal(argumentExpression, parameterType, irValueParameter.type, blockInfo)
else
codegen.gen(argumentExpression, parameterType, irValueParameter.type, blockInfo)
}
} }
val expectedType = JvmKotlinType(parameterType, irValueParameter.type.toIrBasedKotlinType()) val expectedType = JvmKotlinType(parameterType, irValueParameter.type.toIrBasedKotlinType())
@@ -166,8 +175,8 @@ fun IrExpression.isInlineIrExpression() =
when (this) { when (this) {
is IrBlock -> origin.isInlineIrExpression() is IrBlock -> origin.isInlineIrExpression()
is IrCallableReference<*> -> true.also { is IrCallableReference<*> -> true.also {
assert((0 until valueArgumentsCount).count { getValueArgument(it) != null } == 0) { assert((0 until valueArgumentsCount).none { getValueArgument(it) != null }) {
"Expecting 0 value arguments for bounded callable reference: ${dump()}" "Expecting 0 value arguments for bound callable reference: ${dump()}"
} }
} }
else -> false else -> false