JVM IR: Refactor SyntheticAccessorLowering to use a single traversal

This commit is contained in:
Steven Schäfer
2019-10-11 12:47:48 +02:00
committed by Alexander Udalov
parent 3098723406
commit 18940ab0cb
4 changed files with 55 additions and 69 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.ir.isInlineParameter
import org.jetbrains.kotlin.backend.jvm.ir.isLambda
import org.jetbrains.kotlin.codegen.IrExpressionLambda
import org.jetbrains.kotlin.codegen.JvmKotlinType
import org.jetbrains.kotlin.codegen.StackValue
@@ -197,7 +198,7 @@ fun isInlineIrExpression(argumentExpression: IrExpression) =
else -> false
}
fun IrBlock.isInlineIrBlock(): Boolean = origin == IrStatementOrigin.LAMBDA || origin == IrStatementOrigin.ANONYMOUS_FUNCTION
fun IrBlock.isInlineIrBlock(): Boolean = origin.isLambda
fun IrFunction.isInlineFunctionCall(context: JvmBackendContext) =
(!context.state.isInlineDisabled || typeParameters.any { it.isReified }) && isInline
@@ -99,7 +99,7 @@ fun IrType.getArrayElementType(irBuiltIns: IrBuiltIns): IrType =
else
irBuiltIns.primitiveArrayElementTypes.getValue(this.classOrNull!!)
val IrStatementOrigin?.isLambda
val IrStatementOrigin?.isLambda: Boolean
get() = this == IrStatementOrigin.LAMBDA || this == IrStatementOrigin.ANONYMOUS_FUNCTION
val IrConstructor.shouldBeHidden: Boolean
@@ -48,9 +48,6 @@ internal val callableReferencePhase = makeIrFilePhase(
description = "Handle callable references"
)
private val IrStatementOrigin?.isLambda
get() = this == IrStatementOrigin.LAMBDA || this == IrStatementOrigin.ANONYMOUS_FUNCTION
internal class InlineReferenceLocator(private val context: JvmBackendContext) : IrElementVisitorVoidWithContext() {
val inlineReferences = mutableSetOf<IrFunctionReference>()
@@ -379,11 +376,7 @@ internal class CallableReferenceLowering(private val context: JvmBackendContext)
private fun createGetSignatureMethod(superFunction: IrSimpleFunction): IrSimpleFunction = buildOverride(superFunction).apply {
body = context.createJvmIrBuilder(symbol, startOffset, endOffset).run {
irExprBody(irCall(backendContext.ir.symbols.signatureStringIntrinsic).apply {
putValueArgument(0, with(irFunctionReference) {
IrFunctionReferenceImpl(
startOffset, endOffset, type, symbol, descriptor, typeArgumentsCount, valueArgumentsCount, origin
)
})
putValueArgument(0, irFunctionReference.deepCopyWithSymbols(symbol.owner))
})
}
}
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.isSubtypeOfClass
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.JvmAbi
@@ -48,64 +47,6 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
override fun lower(irFile: IrFile) {
inlineLambdaToCallSite.putAll(InlineReferenceLocator.scan(context, irFile).lambdaToCallSite)
// Unconditionally add bridges for hidden constructors
irFile.transformChildrenVoid(object: IrElementTransformerVoid() {
private val hiddenDeclarations = mutableSetOf<IrConstructor>()
private fun handleConstructor(declaration: IrConstructor): IrConstructorSymbol? {
if (declaration.shouldBeHidden) {
declaration.visibility = Visibilities.PRIVATE
hiddenDeclarations += declaration
}
if (declaration !in hiddenDeclarations)
return null
return functionMap.getOrPut(declaration.symbol) {
declaration.makeConstructorAccessor().also { accessor ->
// There's a special case in the JVM backend for serializing the metadata of hidden
// constructors - we serialize the descriptor of the original constructor, but the
// signature of the bridge. We implement this special case in the JVM IR backend by
// attaching the metadata directly to the bridge. We also have to move all annotations
// to the bridge method. Parameter annotations are already moved by the copyTo method.
accessor.metadata = declaration.metadata
declaration.safeAs<IrConstructorImpl>()?.metadata = null
accessor.annotations += declaration.annotations
declaration.annotations.clear()
declaration.valueParameters.forEach { it.annotations.clear() }
}.symbol
} as IrConstructorSymbol
}
override fun visitConstructor(declaration: IrConstructor): IrStatement {
handleConstructor(declaration)
return super.visitConstructor(declaration)
}
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
handleConstructor(expression.symbol.owner)
return super.visitConstructorCall(expression)
}
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
val function = expression.symbol.owner
if (!expression.origin.isLambda && function is IrConstructor) {
handleConstructor(function)?.let { accessor ->
expression.transformChildrenVoid()
return IrFunctionReferenceImpl(
expression.startOffset, expression.endOffset, expression.type,
accessor, accessor.descriptor, accessor.owner.typeParameters.size,
accessor.owner.valueParameters.size, expression.origin
)
}
}
return super.visitFunctionReference(expression)
}
})
irFile.transformChildrenVoid(this)
pendingTransformations.forEach { it() }
}
@@ -147,6 +88,57 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
handleAccess(expression, expression.symbol, setterMap, ::makeSetterAccessorSymbol, ::modifySetterExpression)
)
override fun visitConstructor(declaration: IrConstructor): IrStatement {
handleHiddenConstructor(declaration)
return super.visitConstructor(declaration)
}
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
handleHiddenConstructor(expression.symbol.owner)
return super.visitConstructorCall(expression)
}
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
val function = expression.symbol.owner
if (!expression.origin.isLambda && function is IrConstructor) {
handleHiddenConstructor(function)?.let { accessor ->
expression.transformChildrenVoid()
return IrFunctionReferenceImpl(
expression.startOffset, expression.endOffset, expression.type,
accessor, accessor.descriptor, accessor.owner.typeParameters.size,
accessor.owner.valueParameters.size, expression.origin
)
}
}
return super.visitFunctionReference(expression)
}
private fun handleHiddenConstructor(declaration: IrConstructor): IrConstructorSymbol? {
functionMap[declaration.symbol]?.let { return it as IrConstructorSymbol }
if (!declaration.shouldBeHidden)
return null
declaration.visibility = Visibilities.PRIVATE
return declaration.makeConstructorAccessor().also { accessor ->
functionMap[declaration.symbol] = accessor.symbol
// There's a special case in the JVM backend for serializing the metadata of hidden
// constructors - we serialize the descriptor of the original constructor, but the
// signature of the bridge. We implement this special case in the JVM IR backend by
// attaching the metadata directly to the bridge. We also have to move all annotations
// to the bridge method. Parameter annotations are already moved by the copyTo method.
accessor.metadata = declaration.metadata
declaration.safeAs<IrConstructorImpl>()?.metadata = null
accessor.annotations += declaration.annotations
declaration.annotations.clear()
declaration.valueParameters.forEach { it.annotations.clear() }
}.symbol
}
private inline fun <ExprT : IrDeclarationReference, reified FromSyT : IrSymbol, ToSyT : IrSymbol> handleAccess(
expression: ExprT,
symbol: FromSyT,