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()}" }
val callable = methodSignatureMapper.mapToCallableMethod(expression, irFunction)
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)
}
@@ -490,16 +490,16 @@ class ExpressionCodegen(
expression.markLineNumber(true)
if (isSuspensionPoint != SuspensionPointKind.NEVER) {
addSuspendMarker(mv, isStartNotEnd = true, isSuspensionPoint == SuspensionPointKind.NOT_INLINE)
if (suspensionPointKind != SuspensionPointKind.NEVER) {
addSuspendMarker(mv, isStartNotEnd = true, suspensionPointKind == SuspensionPointKind.NOT_INLINE)
}
callGenerator.genCall(callable, this, expression, isInsideCondition)
val unboxedInlineClassIrType = callee.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()
if (isSuspensionPoint != SuspensionPointKind.NEVER) {
addSuspendMarker(mv, isStartNotEnd = false, isSuspensionPoint == SuspensionPointKind.NOT_INLINE)
if (suspensionPointKind != SuspensionPointKind.NEVER) {
addSuspendMarker(mv, isStartNotEnd = false, suspensionPointKind == SuspensionPointKind.NOT_INLINE)
if (unboxedInlineClassIrType != null) {
generateResumePathUnboxing(mv, unboxedInlineClassIrType, typeMapper)
}
@@ -541,17 +541,24 @@ class ExpressionCodegen(
}
}
private fun IrFunctionAccessExpression.isSuspensionPoint(): SuspensionPointKind = when {
!symbol.owner.isSuspend || !irFunction.shouldContainSuspendMarkers() -> SuspensionPointKind.NEVER
// Copy-pasted bytecode blocks are not suspension points.
symbol.owner.isInline ->
if (symbol.owner.name.asString() == "suspendCoroutineUninterceptedOrReturn" &&
symbol.owner.getPackageFragment()?.fqName == FqName("kotlin.coroutines.intrinsics")
) 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
}
private fun IrFunctionAccessExpression.getSuspensionPointKind(): SuspensionPointKind =
when {
!symbol.owner.isSuspend || !irFunction.shouldContainSuspendMarkers() ->
SuspensionPointKind.NEVER
// Copy-pasted bytecode blocks are not suspension points.
symbol.owner.isInline ->
if (symbol.owner.name.asString() == "suspendCoroutineUninterceptedOrReturn" &&
symbol.owner.getPackageFragment()?.fqName == FqName("kotlin.coroutines.intrinsics")
)
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 {
val callee = expression.symbol.owner
@@ -645,7 +652,8 @@ class ExpressionCodegen(
internal fun genOrGetLocal(expression: IrExpression, type: Type, parameterType: IrType, data: BlockInfo): StackValue =
if (expression is IrGetValue)
StackValue.local(
findLocalIndex(expression.symbol), frameMap.typeOf(expression.symbol),
findLocalIndex(expression.symbol),
frameMap.typeOf(expression.symbol),
expression.symbol.owner.realType.toIrBasedKotlinType()
)
else
@@ -1403,7 +1411,9 @@ class ExpressionCodegen(
}
private fun getOrCreateCallGenerator(
element: IrFunctionAccessExpression, data: BlockInfo, signature: JvmMethodSignature
element: IrFunctionAccessExpression,
data: BlockInfo,
signature: JvmMethodSignature
): IrCallGenerator {
if (!element.symbol.owner.isInlineFunctionCall(context) ||
classCodegen.irClass.fileParent.fileEntry is MultifileFacadeFileEntry ||
@@ -55,7 +55,7 @@ class IrInlineCodegen(
) {
val isInlineParameter = irValueParameter.isInlineParameter()
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)
rememberClosure(parameterType, irValueParameter.index, lambdaInfo)
lambdaInfo.generateLambdaBody(sourceCompiler)
@@ -65,30 +65,39 @@ class IrInlineCodegen(
putCapturedToLocalVal(onStack, param, ir.type.toIrBasedKotlinType())
}
} else {
val kind = when (irValueParameter.origin) {
IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION -> ValueKind.DEFAULT_MASK
IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION -> ValueKind.METHOD_HANDLE_IN_DEFAULT
else -> when {
argumentExpression is IrContainerExpression && argumentExpression.origin == IrStatementOrigin.DEFAULT_VALUE ->
if (isInlineParameter) ValueKind.DEFAULT_INLINE_PARAMETER else 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 kind = when {
irValueParameter.origin == IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION ->
ValueKind.DEFAULT_MASK
irValueParameter.origin == IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION ->
ValueKind.METHOD_HANDLE_IN_DEFAULT
argumentExpression is IrContainerExpression && argumentExpression.origin == IrStatementOrigin.DEFAULT_VALUE ->
if (isInlineParameter)
ValueKind.DEFAULT_INLINE_PARAMETER
else
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) {
ValueKind.METHOD_HANDLE_IN_DEFAULT -> StackValue.constant(null, AsmTypes.OBJECT_TYPE)
ValueKind.DEFAULT_MASK -> StackValue.constant((argumentExpression as IrConst<*>).value, Type.INT_TYPE)
ValueKind.DEFAULT_PARAMETER, ValueKind.DEFAULT_INLINE_PARAMETER -> StackValue.createDefaultValue(parameterType)
// Here we replicate the old backend: reusing the locals for everything except extension receivers.
// TODO when stopping at a breakpoint placed in an inline function, arguments which reuse an existing
// local will not be visible in the debugger, so this needs to be reconsidered.
else -> if (irValueParameter.index >= 0)
codegen.genOrGetLocal(argumentExpression, parameterType, irValueParameter.type, blockInfo)
else
codegen.gen(argumentExpression, parameterType, irValueParameter.type, blockInfo)
ValueKind.METHOD_HANDLE_IN_DEFAULT ->
StackValue.constant(null, AsmTypes.OBJECT_TYPE)
ValueKind.DEFAULT_MASK ->
StackValue.constant((argumentExpression as IrConst<*>).value, Type.INT_TYPE)
ValueKind.DEFAULT_PARAMETER, ValueKind.DEFAULT_INLINE_PARAMETER ->
StackValue.createDefaultValue(parameterType)
else -> {
// Here we replicate the old backend: reusing the locals for everything except extension receivers.
// TODO when stopping at a breakpoint placed in an inline function, arguments which reuse an existing
// 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())
@@ -166,8 +175,8 @@ fun IrExpression.isInlineIrExpression() =
when (this) {
is IrBlock -> origin.isInlineIrExpression()
is IrCallableReference<*> -> true.also {
assert((0 until valueArgumentsCount).count { getValueArgument(it) != null } == 0) {
"Expecting 0 value arguments for bounded callable reference: ${dump()}"
assert((0 until valueArgumentsCount).none { getValueArgument(it) != null }) {
"Expecting 0 value arguments for bound callable reference: ${dump()}"
}
}
else -> false