JVM_IR minor cleanup in inliner
This commit is contained in:
committed by
TeamCityServer
parent
d88a665fa8
commit
ec90649854
+29
-19
@@ -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 ||
|
||||
|
||||
+33
-24
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user