JVM: remove more redundant properties from LambdaInfo
This commit is contained in:
+7
-5
@@ -421,11 +421,13 @@ class AnonymousObjectTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getMethodParametersWithCaptured(capturedBuilder: ParametersBuilder, sourceNode: MethodNode): Parameters {
|
private fun getMethodParametersWithCaptured(capturedBuilder: ParametersBuilder, sourceNode: MethodNode): Parameters {
|
||||||
val builder = ParametersBuilder.initializeBuilderFrom(
|
val builder = ParametersBuilder.newBuilder()
|
||||||
oldObjectType,
|
if (sourceNode.access and Opcodes.ACC_STATIC == 0) {
|
||||||
sourceNode.desc,
|
builder.addThis(oldObjectType, skipped = false)
|
||||||
isStatic = sourceNode.access and Opcodes.ACC_STATIC != 0
|
}
|
||||||
)
|
for (type in Type.getArgumentTypes(sourceNode.desc)) {
|
||||||
|
builder.addNextParameter(type, false)
|
||||||
|
}
|
||||||
for (param in capturedBuilder.listCaptured()) {
|
for (param in capturedBuilder.listCaptured()) {
|
||||||
builder.addCapturedParamCopy(param)
|
builder.addCapturedParamCopy(param)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,6 @@ import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
|
|||||||
interface FunctionalArgument
|
interface FunctionalArgument
|
||||||
|
|
||||||
abstract class LambdaInfo : FunctionalArgument {
|
abstract class LambdaInfo : FunctionalArgument {
|
||||||
abstract val isBoundCallableReference: Boolean
|
|
||||||
|
|
||||||
abstract val isSuspend: Boolean
|
|
||||||
|
|
||||||
abstract val lambdaClassType: Type
|
abstract val lambdaClassType: Type
|
||||||
|
|
||||||
abstract val invokeMethod: Method
|
abstract val invokeMethod: Method
|
||||||
@@ -39,11 +35,17 @@ abstract class LambdaInfo : FunctionalArgument {
|
|||||||
|
|
||||||
val reifiedTypeParametersUsages = ReifiedTypeParametersUsages()
|
val reifiedTypeParametersUsages = ReifiedTypeParametersUsages()
|
||||||
|
|
||||||
open val hasDispatchReceiver = true
|
open val hasDispatchReceiver
|
||||||
|
get() = true
|
||||||
|
|
||||||
fun addAllParameters(remapper: FieldRemapper): Parameters {
|
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) {
|
for (info in capturedVars) {
|
||||||
val field = remapper.findField(FieldInsnNode(0, info.containingLambdaName, info.fieldName, ""))
|
val field = remapper.findField(FieldInsnNode(0, info.containingLambdaName, info.fieldName, ""))
|
||||||
?: error("Captured field not found: " + 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() {
|
class DefaultLambda(info: ExtractedDefaultLambda, sourceCompiler: SourceCompilerForInline) : LambdaInfo() {
|
||||||
|
val isBoundCallableReference: Boolean
|
||||||
|
|
||||||
override val lambdaClassType: Type = info.type
|
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 capturedVars: List<CapturedParamDesc>
|
||||||
|
|
||||||
override val invokeMethod: Method
|
override val invokeMethod: Method
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ class MethodInliner(
|
|||||||
val expectedParameters = info.invokeMethod.argumentTypes
|
val expectedParameters = info.invokeMethod.argumentTypes
|
||||||
val expectedKotlinParameters = info.invokeMethodParameters
|
val expectedKotlinParameters = info.invokeMethodParameters
|
||||||
val argumentCount = Type.getArgumentTypes(desc).size.let {
|
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.
|
// 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.
|
// In the IR backend, this cannot happen as inline lambdas are not lowered.
|
||||||
addFakeContinuationMarker(this)
|
addFakeContinuationMarker(this)
|
||||||
@@ -381,10 +381,7 @@ class MethodInliner(
|
|||||||
private fun getNewIndex(`var`: Int): Int {
|
private fun getNewIndex(`var`: Int): Int {
|
||||||
val lambdaInfo = inliningContext.lambdaInfo
|
val lambdaInfo = inliningContext.lambdaInfo
|
||||||
if (reorderIrLambdaParameters && lambdaInfo is IrExpressionLambda) {
|
if (reorderIrLambdaParameters && lambdaInfo is IrExpressionLambda) {
|
||||||
val extensionSize =
|
val extensionSize = if (lambdaInfo.isExtensionLambda) lambdaInfo.invokeMethod.argumentTypes[0].size else 0
|
||||||
if (lambdaInfo.isExtensionLambda && !lambdaInfo.isBoundCallableReference)
|
|
||||||
lambdaInfo.invokeMethod.argumentTypes[0].size
|
|
||||||
else 0
|
|
||||||
return when {
|
return when {
|
||||||
// v-- extensionSize v-- argsSizeOnStack
|
// v-- extensionSize v-- argsSizeOnStack
|
||||||
// |- extension -|- captured -|- real -|- locals -| old descriptor
|
// |- extension -|- captured -|- real -|- locals -| old descriptor
|
||||||
@@ -637,9 +634,8 @@ class MethodInliner(
|
|||||||
private fun replaceContinuationAccessesWithFakeContinuationsIfNeeded(processingNode: MethodNode) {
|
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
|
// 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.
|
// instead they get continuation from parameter.
|
||||||
if (inliningContext.state.isIrBackend) return
|
|
||||||
val lambdaInfo = inliningContext.lambdaInfo ?: 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 sources = analyzeMethodNodeWithInterpreter(processingNode, Aload0Interpreter(processingNode))
|
||||||
val cfg = ControlFlowGraph.build(processingNode)
|
val cfg = ControlFlowGraph.build(processingNode)
|
||||||
val aload0s = processingNode.instructions.asSequence().filter { it.opcode == Opcodes.ALOAD && it.safeAs<VarInsnNode>()?.`var` == 0 }
|
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 {
|
fun newBuilder(): ParametersBuilder {
|
||||||
return 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,
|
expression: KtExpression,
|
||||||
private val state: GenerationState,
|
private val state: GenerationState,
|
||||||
val isCrossInline: Boolean,
|
val isCrossInline: Boolean,
|
||||||
override val isBoundCallableReference: Boolean
|
val isBoundCallableReference: Boolean
|
||||||
) : ExpressionLambda() {
|
) : ExpressionLambda() {
|
||||||
override val lambdaClassType: Type
|
override val lambdaClassType: Type
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@ class PsiExpressionLambda(
|
|||||||
|
|
||||||
override val invokeMethodParameters: List<KotlinType?>
|
override val invokeMethodParameters: List<KotlinType?>
|
||||||
get() {
|
get() {
|
||||||
val actualInvokeDescriptor = if (isSuspend)
|
val actualInvokeDescriptor = if (invokeMethodDescriptor.isSuspend)
|
||||||
getOrCreateJvmSuspendFunctionView(invokeMethodDescriptor, state)
|
getOrCreateJvmSuspendFunctionView(invokeMethodDescriptor, state)
|
||||||
else
|
else
|
||||||
invokeMethodDescriptor
|
invokeMethodDescriptor
|
||||||
@@ -222,8 +222,6 @@ class PsiExpressionLambda(
|
|||||||
|
|
||||||
override val returnLabels: Map<String, Label?>
|
override val returnLabels: Map<String, Label?>
|
||||||
|
|
||||||
override val isSuspend: Boolean
|
|
||||||
|
|
||||||
val closure: CalculatedClosure
|
val closure: CalculatedClosure
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -252,7 +250,6 @@ class PsiExpressionLambda(
|
|||||||
?: throw AssertionError("null closure for lambda ${expression.text}")
|
?: throw AssertionError("null closure for lambda ${expression.text}")
|
||||||
returnLabels = getDeclarationLabels(expression, invokeMethodDescriptor).associateWith { null }
|
returnLabels = getDeclarationLabels(expression, invokeMethodDescriptor).associateWith { null }
|
||||||
invokeMethod = state.typeMapper.mapAsmMethod(invokeMethodDescriptor)
|
invokeMethod = state.typeMapper.mapAsmMethod(invokeMethodDescriptor)
|
||||||
isSuspend = invokeMethodDescriptor.isSuspend
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This can only be computed after generating the body, hence `lazy`.
|
// This can only be computed after generating the body, hence `lazy`.
|
||||||
|
|||||||
+6
-15
@@ -119,17 +119,11 @@ class IrExpressionLambdaImpl(
|
|||||||
val reference: IrFunctionReference,
|
val reference: IrFunctionReference,
|
||||||
irValueParameter: IrValueParameter
|
irValueParameter: IrValueParameter
|
||||||
) : ExpressionLambda(), IrExpressionLambda {
|
) : ExpressionLambda(), IrExpressionLambda {
|
||||||
override val isExtensionLambda: Boolean = irValueParameter.type.isExtensionFunctionType
|
override val isExtensionLambda: Boolean = irValueParameter.type.isExtensionFunctionType && reference.extensionReceiver == null
|
||||||
|
|
||||||
val function: IrFunction
|
val function: IrFunction
|
||||||
get() = reference.symbol.owner
|
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
|
override val hasDispatchReceiver: Boolean
|
||||||
get() = false
|
get() = false
|
||||||
|
|
||||||
@@ -148,20 +142,17 @@ class IrExpressionLambdaImpl(
|
|||||||
init {
|
init {
|
||||||
val asmMethod = codegen.methodSignatureMapper.mapAsmMethod(function)
|
val asmMethod = codegen.methodSignatureMapper.mapAsmMethod(function)
|
||||||
val capturedParameters = reference.getArgumentsWithIr()
|
val capturedParameters = reference.getArgumentsWithIr()
|
||||||
val (startCapture, endCapture) = when {
|
val captureStart = if (isExtensionLambda) 1 else 0 // extension receiver comes before captures
|
||||||
isBoundCallableReference -> 0 to 1 // (bound receiver, real parameters...)
|
val captureEnd = captureStart + capturedParameters.size
|
||||||
isExtensionLambda -> 1 to capturedParameters.size + 1 // (unbound receiver, captures..., real parameters...)
|
|
||||||
else -> 0 to capturedParameters.size // (captures..., real parameters...)
|
|
||||||
}
|
|
||||||
capturedVars = capturedParameters.mapIndexed { index, (parameter, _) ->
|
capturedVars = capturedParameters.mapIndexed { index, (parameter, _) ->
|
||||||
val isSuspend = parameter.isInlineParameter() && parameter.type.isSuspendFunctionTypeOrSubtype()
|
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 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
|
// 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.
|
// 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 freeParameters = function.explicitParameters.let { it.take(captureStart) + it.drop(captureEnd) }
|
||||||
val freeAsmParameters = asmMethod.argumentTypes.let { it.take(startCapture) + it.drop(endCapture) }
|
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
|
// 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).
|
// an unboxed inline class value so that the inliner will box it (FunctionN.invoke should return a boxed value).
|
||||||
val unboxedReturnType = function.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()
|
val unboxedReturnType = function.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass()
|
||||||
|
|||||||
Reference in New Issue
Block a user