JVM: remove more redundant properties from LambdaInfo

This commit is contained in:
pyos
2021-07-06 12:53:37 +02:00
committed by max-kammerer
parent c1c56ca388
commit 717cf2066a
6 changed files with 29 additions and 58 deletions
@@ -421,11 +421,13 @@ class AnonymousObjectTransformer(
}
private fun getMethodParametersWithCaptured(capturedBuilder: ParametersBuilder, sourceNode: MethodNode): Parameters {
val builder = ParametersBuilder.initializeBuilderFrom(
oldObjectType,
sourceNode.desc,
isStatic = sourceNode.access and Opcodes.ACC_STATIC != 0
)
val builder = ParametersBuilder.newBuilder()
if (sourceNode.access and Opcodes.ACC_STATIC == 0) {
builder.addThis(oldObjectType, skipped = false)
}
for (type in Type.getArgumentTypes(sourceNode.desc)) {
builder.addNextParameter(type, false)
}
for (param in capturedBuilder.listCaptured()) {
builder.addCapturedParamCopy(param)
}
@@ -18,10 +18,6 @@ import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
interface FunctionalArgument
abstract class LambdaInfo : FunctionalArgument {
abstract val isBoundCallableReference: Boolean
abstract val isSuspend: Boolean
abstract val lambdaClassType: Type
abstract val invokeMethod: Method
@@ -39,11 +35,17 @@ abstract class LambdaInfo : FunctionalArgument {
val reifiedTypeParametersUsages = ReifiedTypeParametersUsages()
open val hasDispatchReceiver = true
open val hasDispatchReceiver
get() = true
fun addAllParameters(remapper: FieldRemapper): Parameters {
val builder = ParametersBuilder.initializeBuilderFrom(OBJECT_TYPE, invokeMethod.descriptor, this)
val builder = ParametersBuilder.newBuilder()
if (hasDispatchReceiver) {
builder.addThis(lambdaClassType, skipped = true).functionalArgument = this
}
for (type in Type.getArgumentTypes(invokeMethod.descriptor)) {
builder.addNextParameter(type, skipped = false)
}
for (info in capturedVars) {
val field = remapper.findField(FieldInsnNode(0, info.containingLambdaName, info.fieldName, ""))
?: error("Captured field not found: " + info.containingLambdaName + "." + info.fieldName)
@@ -75,9 +77,9 @@ abstract class ExpressionLambda : LambdaInfo() {
}
class DefaultLambda(info: ExtractedDefaultLambda, sourceCompiler: SourceCompilerForInline) : LambdaInfo() {
val isBoundCallableReference: Boolean
override val lambdaClassType: Type = info.type
override val isSuspend: Boolean get() = false // TODO: it should probably be true sometimes, but it never was
override val isBoundCallableReference: Boolean
override val capturedVars: List<CapturedParamDesc>
override val invokeMethod: Method
@@ -228,7 +228,7 @@ class MethodInliner(
val expectedParameters = info.invokeMethod.argumentTypes
val expectedKotlinParameters = info.invokeMethodParameters
val argumentCount = Type.getArgumentTypes(desc).size.let {
if (!inliningContext.root.state.isIrBackend && info.isSuspend && it < expectedParameters.size) {
if (info is PsiExpressionLambda && info.invokeMethodDescriptor.isSuspend && it < expectedParameters.size) {
// Inlining suspend lambda into a function that takes a non-suspend lambda.
// In the IR backend, this cannot happen as inline lambdas are not lowered.
addFakeContinuationMarker(this)
@@ -381,10 +381,7 @@ class MethodInliner(
private fun getNewIndex(`var`: Int): Int {
val lambdaInfo = inliningContext.lambdaInfo
if (reorderIrLambdaParameters && lambdaInfo is IrExpressionLambda) {
val extensionSize =
if (lambdaInfo.isExtensionLambda && !lambdaInfo.isBoundCallableReference)
lambdaInfo.invokeMethod.argumentTypes[0].size
else 0
val extensionSize = if (lambdaInfo.isExtensionLambda) lambdaInfo.invokeMethod.argumentTypes[0].size else 0
return when {
// v-- extensionSize v-- argsSizeOnStack
// |- extension -|- captured -|- real -|- locals -| old descriptor
@@ -637,9 +634,8 @@ class MethodInliner(
private fun replaceContinuationAccessesWithFakeContinuationsIfNeeded(processingNode: MethodNode) {
// in ir backend inline suspend lambdas do not use ALOAD 0 to get continuation, since they are generated as static functions
// instead they get continuation from parameter.
if (inliningContext.state.isIrBackend) return
val lambdaInfo = inliningContext.lambdaInfo ?: return
if (!lambdaInfo.isSuspend) return
if (lambdaInfo !is PsiExpressionLambda || !lambdaInfo.invokeMethodDescriptor.isSuspend) return
val sources = analyzeMethodNodeWithInterpreter(processingNode, Aload0Interpreter(processingNode))
val cfg = ControlFlowGraph.build(processingNode)
val aload0s = processingNode.instructions.asSequence().filter { it.opcode == Opcodes.ALOAD && it.safeAs<VarInsnNode>()?.`var` == 0 }
@@ -107,22 +107,5 @@ class ParametersBuilder private constructor() {
fun newBuilder(): ParametersBuilder {
return ParametersBuilder()
}
@JvmOverloads
@JvmStatic
fun initializeBuilderFrom(
objectType: Type, descriptor: String, inlineLambda: LambdaInfo? = null, isStatic: Boolean = false
): ParametersBuilder {
val builder = newBuilder()
if (inlineLambda?.hasDispatchReceiver != false && !isStatic) {
//skipped this for inlined lambda cause it will be removed
builder.addThis(objectType, inlineLambda != null).functionalArgument = inlineLambda
}
for (type in Type.getArgumentTypes(descriptor)) {
builder.addNextParameter(type, false)
}
return builder
}
}
}
@@ -194,7 +194,7 @@ class PsiExpressionLambda(
expression: KtExpression,
private val state: GenerationState,
val isCrossInline: Boolean,
override val isBoundCallableReference: Boolean
val isBoundCallableReference: Boolean
) : ExpressionLambda() {
override val lambdaClassType: Type
@@ -204,7 +204,7 @@ class PsiExpressionLambda(
override val invokeMethodParameters: List<KotlinType?>
get() {
val actualInvokeDescriptor = if (isSuspend)
val actualInvokeDescriptor = if (invokeMethodDescriptor.isSuspend)
getOrCreateJvmSuspendFunctionView(invokeMethodDescriptor, state)
else
invokeMethodDescriptor
@@ -222,8 +222,6 @@ class PsiExpressionLambda(
override val returnLabels: Map<String, Label?>
override val isSuspend: Boolean
val closure: CalculatedClosure
init {
@@ -252,7 +250,6 @@ class PsiExpressionLambda(
?: throw AssertionError("null closure for lambda ${expression.text}")
returnLabels = getDeclarationLabels(expression, invokeMethodDescriptor).associateWith { null }
invokeMethod = state.typeMapper.mapAsmMethod(invokeMethodDescriptor)
isSuspend = invokeMethodDescriptor.isSuspend
}
// This can only be computed after generating the body, hence `lazy`.
@@ -119,17 +119,11 @@ class IrExpressionLambdaImpl(
val reference: IrFunctionReference,
irValueParameter: IrValueParameter
) : ExpressionLambda(), IrExpressionLambda {
override val isExtensionLambda: Boolean = irValueParameter.type.isExtensionFunctionType
override val isExtensionLambda: Boolean = irValueParameter.type.isExtensionFunctionType && reference.extensionReceiver == null
val function: IrFunction
get() = reference.symbol.owner
override val isBoundCallableReference: Boolean
get() = reference.extensionReceiver != null
override val isSuspend: Boolean
get() = reference.symbol.owner.isSuspend
override val hasDispatchReceiver: Boolean
get() = false
@@ -148,20 +142,17 @@ class IrExpressionLambdaImpl(
init {
val asmMethod = codegen.methodSignatureMapper.mapAsmMethod(function)
val capturedParameters = reference.getArgumentsWithIr()
val (startCapture, endCapture) = when {
isBoundCallableReference -> 0 to 1 // (bound receiver, real parameters...)
isExtensionLambda -> 1 to capturedParameters.size + 1 // (unbound receiver, captures..., real parameters...)
else -> 0 to capturedParameters.size // (captures..., real parameters...)
}
val captureStart = if (isExtensionLambda) 1 else 0 // extension receiver comes before captures
val captureEnd = captureStart + capturedParameters.size
capturedVars = capturedParameters.mapIndexed { index, (parameter, _) ->
val isSuspend = parameter.isInlineParameter() && parameter.type.isSuspendFunctionTypeOrSubtype()
capturedParamDesc(parameter.name.asString(), asmMethod.argumentTypes[startCapture + index], isSuspend)
capturedParamDesc(parameter.name.asString(), asmMethod.argumentTypes[captureStart + index], isSuspend)
}
// The parameter list should include the continuation if this is a suspend lambda. In the IR backend,
// the lambda is suspend iff the inline function's parameter is marked suspend, so FunctionN.invoke call
// inside the inline function already has a (real) continuation value as the last argument.
val freeParameters = function.explicitParameters.let { it.take(startCapture) + it.drop(endCapture) }
val freeAsmParameters = asmMethod.argumentTypes.let { it.take(startCapture) + it.drop(endCapture) }
val freeParameters = function.explicitParameters.let { it.take(captureStart) + it.drop(captureEnd) }
val freeAsmParameters = asmMethod.argumentTypes.let { it.take(captureStart) + it.drop(captureEnd) }
// The return type, on the other hand, should be the original type if this is a suspend lambda that returns
// an unboxed inline class value so that the inliner will box it (FunctionN.invoke should return a boxed value).
val unboxedReturnType = function.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()