[IR] Improved tuning of SAM wrapper visibility

This commit is contained in:
Igor Chevdar
2020-06-04 18:44:46 +05:00
parent 1b1e579cbf
commit 66bbd3e102
3 changed files with 21 additions and 9 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.ir.addFakeOverridesViaIncorrectHeuristic import org.jetbrains.kotlin.backend.common.ir.addFakeOverridesViaIncorrectHeuristic
import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
@@ -61,11 +62,12 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
private val inlineCachedImplementations = mutableMapOf<IrType, IrClass>() private val inlineCachedImplementations = mutableMapOf<IrType, IrClass>()
private var enclosingContainer: IrDeclarationContainer? = null private var enclosingContainer: IrDeclarationContainer? = null
open val privateGeneratedWrapperVisibility: Visibility abstract fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List<ScopeWithIr>): Visibility
get() = Visibilities.PRIVATE
abstract fun getSuperTypeForWrapper(typeOperand: IrType): IrType abstract fun getSuperTypeForWrapper(typeOperand: IrType): IrType
open val inInlineFunctionScope get() = allScopes.any { scope -> (scope.irElement as? IrFunction)?.isInline ?: false }
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
cachedImplementations.clear() cachedImplementations.clear()
inlineCachedImplementations.clear() inlineCachedImplementations.clear()
@@ -102,10 +104,9 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
if (invokable.isNullConst()) if (invokable.isNullConst())
return invokable return invokable
val inInlineFunctionScope = allScopes.any { scope -> (scope.irElement as? IrFunction)?.isInline ?: false }
val cache = if (inInlineFunctionScope) inlineCachedImplementations else cachedImplementations val cache = if (inInlineFunctionScope) inlineCachedImplementations else cachedImplementations
val implementation = cache.getOrPut(erasedSuperType) { val implementation = cache.getOrPut(erasedSuperType) {
createObjectProxy(erasedSuperType, inInlineFunctionScope, expression) createObjectProxy(erasedSuperType, getWrapperVisibility(expression, allScopes), expression)
} }
return if (superType.isNullable() && invokable.type.isNullable()) { return if (superType.isNullable() && invokable.type.isNullable()) {
@@ -136,14 +137,14 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
// Construct a class that wraps an invokable object into an implementation of an interface: // Construct a class that wraps an invokable object into an implementation of an interface:
// class sam$n(private val invokable: F) : Interface { override fun method(...) = invokable(...) } // class sam$n(private val invokable: F) : Interface { override fun method(...) = invokable(...) }
private fun createObjectProxy(superType: IrType, generatePublicWrapper: Boolean, createFor: IrElement): IrClass { private fun createObjectProxy(superType: IrType, wrapperVisibility: Visibility, createFor: IrElement): IrClass {
val superClass = superType.classifierOrFail.owner as IrClass val superClass = superType.classifierOrFail.owner as IrClass
// The language documentation prohibits casting lambdas to classes, but if it was allowed, // The language documentation prohibits casting lambdas to classes, but if it was allowed,
// the `irDelegatingConstructorCall` in the constructor below would need to be modified. // the `irDelegatingConstructorCall` in the constructor below would need to be modified.
assert(superClass.kind == ClassKind.INTERFACE) { "SAM conversion to an abstract class not allowed" } assert(superClass.kind == ClassKind.INTERFACE) { "SAM conversion to an abstract class not allowed" }
val superFqName = superClass.fqNameWhenAvailable!!.asString().replace('.', '_') val superFqName = superClass.fqNameWhenAvailable!!.asString().replace('.', '_')
val inlinePrefix = if (generatePublicWrapper) "\$i" else "" val inlinePrefix = if (wrapperVisibility == Visibilities.PUBLIC) "\$i" else ""
val wrapperName = Name.identifier("sam$inlinePrefix\$$superFqName$SAM_WRAPPER_SUFFIX") val wrapperName = Name.identifier("sam$inlinePrefix\$$superFqName$SAM_WRAPPER_SUFFIX")
val superMethod = superClass.functions.single { it.modality == Modality.ABSTRACT } val superMethod = superClass.functions.single { it.modality == Modality.ABSTRACT }
// TODO: have psi2ir cast the argument to the correct function type. Also see the TODO // TODO: have psi2ir cast the argument to the correct function type. Also see the TODO
@@ -155,7 +156,6 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
context.ir.symbols.functionN(superMethod.valueParameters.size).owner context.ir.symbols.functionN(superMethod.valueParameters.size).owner
val wrappedFunctionType = wrappedFunctionClass.defaultType val wrappedFunctionType = wrappedFunctionClass.defaultType
val wrapperVisibility = if (generatePublicWrapper) Visibilities.PUBLIC else privateGeneratedWrapperVisibility
val subclass = buildClass { val subclass = buildClass {
name = wrapperName name = wrapperName
origin = IrDeclarationOrigin.GENERATED_SAM_IMPLEMENTATION origin = IrDeclarationOrigin.GENERATED_SAM_IMPLEMENTATION
@@ -5,14 +5,22 @@
package org.jetbrains.kotlin.ir.backend.js.lower package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.lower.SingleAbstractMethodLowering import org.jetbrains.kotlin.backend.common.lower.SingleAbstractMethodLowering
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
class JsSingleAbstractMethodLowering(context: JsIrBackendContext) : SingleAbstractMethodLowering(context) { class JsSingleAbstractMethodLowering(context: JsIrBackendContext) : SingleAbstractMethodLowering(context) {
override fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List<ScopeWithIr>): Visibility {
return Visibilities.PRIVATE
}
override fun getSuperTypeForWrapper(typeOperand: IrType): IrType { override fun getSuperTypeForWrapper(typeOperand: IrType): IrType {
// FE doesn't allow type parameters for now. // FE doesn't allow type parameters for now.
// And since there is a to-do in common SingleAbstractMethodLowering (at function visitTypeOperator), // And since there is a to-do in common SingleAbstractMethodLowering (at function visitTypeOperator),
@@ -5,11 +5,13 @@
package org.jetbrains.kotlin.backend.jvm.lower package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.lower.SingleAbstractMethodLowering import org.jetbrains.kotlin.backend.common.lower.SingleAbstractMethodLowering
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addFunction import org.jetbrains.kotlin.ir.builders.declarations.addFunction
@@ -17,8 +19,10 @@ import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.types.typeWith
@@ -35,8 +39,8 @@ internal val singleAbstractMethodPhase = makeIrFilePhase(
private class JvmSingleAbstractMethodLowering(context: JvmBackendContext) : SingleAbstractMethodLowering(context) { private class JvmSingleAbstractMethodLowering(context: JvmBackendContext) : SingleAbstractMethodLowering(context) {
private val jvmContext: JvmBackendContext get() = context as JvmBackendContext private val jvmContext: JvmBackendContext get() = context as JvmBackendContext
override val privateGeneratedWrapperVisibility: Visibility override fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List<ScopeWithIr>) =
get() = JavaVisibilities.PACKAGE_VISIBILITY if (inInlineFunctionScope) Visibilities.PUBLIC else JavaVisibilities.PACKAGE_VISIBILITY
override fun getSuperTypeForWrapper(typeOperand: IrType): IrType = override fun getSuperTypeForWrapper(typeOperand: IrType): IrType =
typeOperand.erasedUpperBound.defaultType typeOperand.erasedUpperBound.defaultType