[JVM IR] Factor out JVM-specific logic from CachedSyntheticDeclarations
This will allow us to use this class in KLIB-based backends (KT-64865)
This commit is contained in:
committed by
Space Team
parent
d137594c77
commit
25be39dcc6
+43
-97
@@ -5,10 +5,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm
|
package org.jetbrains.kotlin.backend.jvm
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||||
import org.jetbrains.kotlin.backend.common.ScopeWithIr
|
import org.jetbrains.kotlin.backend.common.ScopeWithIr
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedString
|
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedString
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.isJvmInterface
|
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
@@ -22,18 +21,19 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
|
|||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates visible synthetic accessor functions for symbols that are otherwise inaccessible, for example,
|
* Generates visible synthetic accessor functions for symbols that are otherwise inaccessible, for example,
|
||||||
* when inlining a function that references a private method of a class outside of that class, or generating a class for a lambda
|
* when inlining a function that references a private method of a class outside of that class, or generating a class for a lambda
|
||||||
* expression that uses a `super` qualifier in its body.
|
* expression that uses a `super` qualifier in its body.
|
||||||
|
*
|
||||||
|
* TODO: Right now this class is only used in the JVM backend. There is an ongoing effort to also generate synthetic
|
||||||
|
* accessors on KLIB-based backends ([KT-64865](https://youtrack.jetbrains.com/issue/KT-64865)).
|
||||||
|
* Please consider this fact when you want to change its implementation.
|
||||||
*/
|
*/
|
||||||
class CachedSyntheticDeclarations(private val context: JvmBackendContext) {
|
open class CachedSyntheticDeclarations<Context : BackendContext>(protected val context: Context) {
|
||||||
private data class FieldKey(val fieldSymbol: IrFieldSymbol, val parent: IrDeclarationParent, val superQualifierSymbol: IrClassSymbol?)
|
private data class FieldKey(val fieldSymbol: IrFieldSymbol, val parent: IrDeclarationParent, val superQualifierSymbol: IrClassSymbol?)
|
||||||
|
|
||||||
private data class FunctionKey(
|
private data class FunctionKey(
|
||||||
@@ -121,33 +121,8 @@ class CachedSyntheticDeclarations(private val context: JvmBackendContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSyntheticConstructorAccessor(
|
protected fun IrConstructor.makeConstructorAccessor(
|
||||||
declaration: IrConstructor,
|
originForConstructorAccessor: IrDeclarationOrigin = IrDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||||
constructorToAccessorMap: ConcurrentHashMap<IrConstructor, IrConstructor>
|
|
||||||
): IrConstructor {
|
|
||||||
return constructorToAccessorMap.getOrPut(declaration) {
|
|
||||||
declaration.makeConstructorAccessor(JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR).also { accessor ->
|
|
||||||
if (declaration.constructedClass.modality != Modality.SEALED) {
|
|
||||||
// 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 accessor. We implement this special case in the JVM IR backend by
|
|
||||||
// attaching the metadata directly to the accessor. We also have to move all annotations
|
|
||||||
// to the accessor. Parameter annotations are already moved by the copyTo method.
|
|
||||||
if (declaration.metadata != null) {
|
|
||||||
accessor.metadata = declaration.metadata
|
|
||||||
declaration.metadata = null
|
|
||||||
}
|
|
||||||
accessor.annotations += declaration.annotations
|
|
||||||
declaration.annotations = emptyList()
|
|
||||||
declaration.valueParameters.forEach { it.annotations = emptyList() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrConstructor.makeConstructorAccessor(
|
|
||||||
originForConstructorAccessor: IrDeclarationOrigin =
|
|
||||||
IrDeclarationOrigin.SYNTHETIC_ACCESSOR
|
|
||||||
): IrConstructor {
|
): IrConstructor {
|
||||||
val source = this
|
val source = this
|
||||||
|
|
||||||
@@ -190,6 +165,8 @@ class CachedSyntheticDeclarations(private val context: JvmBackendContext) {
|
|||||||
copyAllParamsToArgs(it, accessor)
|
copyAllParamsToArgs(it, accessor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun accessorModality(parent: IrDeclarationParent): Modality = Modality.FINAL
|
||||||
|
|
||||||
private fun IrSimpleFunction.makeSimpleFunctionAccessor(
|
private fun IrSimpleFunction.makeSimpleFunctionAccessor(
|
||||||
superQualifierSymbol: IrClassSymbol?, dispatchReceiverType: IrType?, parent: IrDeclarationParent, scopes: List<ScopeWithIr>
|
superQualifierSymbol: IrClassSymbol?, dispatchReceiverType: IrType?, parent: IrDeclarationParent, scopes: List<ScopeWithIr>
|
||||||
): IrSimpleFunction {
|
): IrSimpleFunction {
|
||||||
@@ -201,7 +178,7 @@ class CachedSyntheticDeclarations(private val context: JvmBackendContext) {
|
|||||||
origin = IrDeclarationOrigin.SYNTHETIC_ACCESSOR
|
origin = IrDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||||
name = source.accessorName(superQualifierSymbol, scopes)
|
name = source.accessorName(superQualifierSymbol, scopes)
|
||||||
visibility = DescriptorVisibilities.PUBLIC
|
visibility = DescriptorVisibilities.PUBLIC
|
||||||
modality = if (parent is IrClass && parent.isJvmInterface) Modality.OPEN else Modality.FINAL
|
modality = accessorModality(parent)
|
||||||
isSuspend = source.isSuspend // synthetic accessors of suspend functions are handled in codegen
|
isSuspend = source.isSuspend // synthetic accessors of suspend functions are handled in codegen
|
||||||
}.also { accessor ->
|
}.also { accessor ->
|
||||||
accessor.parent = parent
|
accessor.parent = parent
|
||||||
@@ -382,33 +359,23 @@ class CachedSyntheticDeclarations(private val context: JvmBackendContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case of Java `protected static`, access could be done from a public inline function in the same package,
|
/**
|
||||||
// or a subclass of the Java class. Both cases require an accessor, which we cannot add to the Java class.
|
* In case of Java `protected static`, access could be done from a public inline function in the same package,
|
||||||
private fun IrDeclarationWithVisibility.accessorParent(parent: IrDeclarationParent, scopes: List<ScopeWithIr>) =
|
* or a subclass of the Java class. Both cases require an accessor, which we cannot add to a Java class.
|
||||||
if (visibility == JavaDescriptorVisibilities.PROTECTED_STATIC_VISIBILITY) {
|
*/
|
||||||
val classes = scopes.map { it.irElement }.filterIsInstance<IrClass>()
|
protected open fun IrDeclarationWithVisibility.accessorParent(parent: IrDeclarationParent, scopes: List<ScopeWithIr>) = parent
|
||||||
val companions = classes.mapNotNull(IrClass::companionObject)
|
|
||||||
val objectsInScope =
|
|
||||||
classes.flatMap { it.declarations.filter(IrDeclaration::isAnonymousObject).filterIsInstance<IrClass>() }
|
|
||||||
val candidates = objectsInScope + companions + classes
|
|
||||||
candidates.lastOrNull { parent is IrClass && it.isSubclassOf(parent) } ?: classes.last()
|
|
||||||
} else {
|
|
||||||
parent
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrSimpleFunction.accessorName(superQualifier: IrClassSymbol?, scopes: List<ScopeWithIr>): Name {
|
protected open fun mapFunctionName(function: IrSimpleFunction): String = function.name.asString()
|
||||||
val jvmName = context.defaultMethodSignatureMapper.mapFunctionName(this)
|
|
||||||
val currentClass = scopes.lastOrNull { it.scope.scopeOwnerSymbol is IrClassSymbol }
|
protected open fun functionAccessorSuffix(
|
||||||
val suffix = when {
|
function: IrSimpleFunction,
|
||||||
|
superQualifier: IrClassSymbol?,
|
||||||
|
scopes: List<ScopeWithIr>,
|
||||||
|
): String = function.run {
|
||||||
|
when {
|
||||||
// Accessors for top level functions never need a suffix.
|
// Accessors for top level functions never need a suffix.
|
||||||
isTopLevel -> ""
|
isTopLevel -> ""
|
||||||
|
|
||||||
// The only function accessors placed on interfaces are for private functions and JvmDefault implementations.
|
|
||||||
// The two cannot clash.
|
|
||||||
currentClass?.irElement?.let { element ->
|
|
||||||
element is IrClass && element.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS && element.parentAsClass == parentAsClass
|
|
||||||
} ?: false -> if (!DescriptorVisibilities.isPrivate(visibility)) "\$jd" else ""
|
|
||||||
|
|
||||||
// Accessor for _s_uper-qualified call
|
// Accessor for _s_uper-qualified call
|
||||||
superQualifier != null -> "\$s" + superQualifier.owner.syntheticAccessorToSuperSuffix()
|
superQualifier != null -> "\$s" + superQualifier.owner.syntheticAccessorToSuperSuffix()
|
||||||
|
|
||||||
@@ -419,31 +386,36 @@ class CachedSyntheticDeclarations(private val context: JvmBackendContext) {
|
|||||||
|
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
return Name.identifier("access\$$jvmName$suffix")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrSimpleFunction.accessorName(superQualifier: IrClassSymbol?, scopes: List<ScopeWithIr>): Name {
|
||||||
|
return Name.identifier("access\$${mapFunctionName(this)}${functionAccessorSuffix(this, superQualifier, scopes)}")
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun fieldGetterName(field: IrField): String = "<get-${field.name}>"
|
||||||
|
|
||||||
private fun IrField.accessorNameForGetter(superQualifierSymbol: IrClassSymbol?): Name {
|
private fun IrField.accessorNameForGetter(superQualifierSymbol: IrClassSymbol?): Name {
|
||||||
val getterName = JvmAbi.getterName(name.asString())
|
val getterName = fieldGetterName(this)
|
||||||
return Name.identifier("access\$$getterName\$${fieldAccessorSuffix(superQualifierSymbol)}")
|
return Name.identifier("access\$$getterName\$${fieldAccessorSuffix(this, superQualifierSymbol)}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun fieldSetterName(field: IrField): String = "<set-${field.name}>"
|
||||||
|
|
||||||
private fun IrField.accessorNameForSetter(superQualifierSymbol: IrClassSymbol?): Name {
|
private fun IrField.accessorNameForSetter(superQualifierSymbol: IrClassSymbol?): Name {
|
||||||
val setterName = JvmAbi.setterName(name.asString())
|
val setterName = fieldSetterName(this)
|
||||||
return Name.identifier("access\$$setterName\$${fieldAccessorSuffix(superQualifierSymbol)}")
|
return Name.identifier("access\$$setterName\$${fieldAccessorSuffix(this, superQualifierSymbol)}")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrField.fieldAccessorSuffix(superQualifierSymbol: IrClassSymbol?): String {
|
/**
|
||||||
// Special _c_ompanion _p_roperty suffix for accessing companion backing field moved to outer
|
* For both _reading_ and _writing_ field accessors, the suffix that includes some of [field]'s important properties.
|
||||||
if (origin == JvmLoweredDeclarationOrigin.COMPANION_PROPERTY_BACKING_FIELD && !parentAsClass.isCompanion) {
|
*/
|
||||||
return "cp"
|
protected open fun fieldAccessorSuffix(field: IrField, superQualifierSymbol: IrClassSymbol?): String = field.run {
|
||||||
}
|
|
||||||
|
|
||||||
if (superQualifierSymbol != null) {
|
if (superQualifierSymbol != null) {
|
||||||
return "p\$s${superQualifierSymbol.owner.syntheticAccessorToSuperSuffix()}"
|
return "p\$s${superQualifierSymbol.owner.syntheticAccessorToSuperSuffix()}"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accesses to static protected fields that need an accessor must be due to being inherited, hence accessed on a
|
// Accesses to static protected fields that need an accessor must be due to being inherited, hence accessed on a
|
||||||
// _s_upertype. If the field is static, the super class the access is on can be different and therefore
|
// _s_upertype. If the field is static, the super class the access is on can be different, and therefore
|
||||||
// we generate a suffix to distinguish access to field with different receiver types in the super hierarchy.
|
// we generate a suffix to distinguish access to field with different receiver types in the super hierarchy.
|
||||||
return "p" + if (isStatic && visibility.isProtected) "\$s" + parentAsClass.syntheticAccessorToSuperSuffix() else ""
|
return "p" + if (isStatic && visibility.isProtected) "\$s" + parentAsClass.syntheticAccessorToSuperSuffix() else ""
|
||||||
}
|
}
|
||||||
@@ -452,32 +424,6 @@ class CachedSyntheticDeclarations(private val context: JvmBackendContext) {
|
|||||||
// TODO: change this to `fqNameUnsafe.asString().replace(".", "_")` as soon as we're ready to break compatibility with pre-KT-21178 code
|
// TODO: change this to `fqNameUnsafe.asString().replace(".", "_")` as soon as we're ready to break compatibility with pre-KT-21178 code
|
||||||
name.asString().hashCode().toString()
|
name.asString().hashCode().toString()
|
||||||
|
|
||||||
private val DescriptorVisibility.isProtected
|
protected open val DescriptorVisibility.isProtected
|
||||||
get() = AsmUtil.getVisibilityAccessFlag(delegate) == Opcodes.ACC_PROTECTED
|
get() = this == DescriptorVisibilities.PROTECTED
|
||||||
|
|
||||||
fun isOrShouldBeHiddenSinceHasMangledParams(constructor: IrConstructor): Boolean {
|
|
||||||
if (constructor in context.hiddenConstructorsWithMangledParams.keys) return true
|
|
||||||
return constructor.isOrShouldBeHiddenDueToOrigin &&
|
|
||||||
!DescriptorVisibilities.isPrivate(constructor.visibility) &&
|
|
||||||
!constructor.constructedClass.isValue &&
|
|
||||||
(context.multiFieldValueClassReplacements.originalConstructorForConstructorReplacement[constructor] ?: constructor).hasMangledParameters() &&
|
|
||||||
!constructor.constructedClass.isAnonymousObject
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isOrShouldBeHiddenAsSealedClassConstructor(constructor: IrConstructor): Boolean {
|
|
||||||
if (constructor in context.hiddenConstructorsOfSealedClasses.keys) return true
|
|
||||||
return constructor.isOrShouldBeHiddenDueToOrigin && constructor.visibility != DescriptorVisibilities.PUBLIC && constructor.constructedClass.modality == Modality.SEALED
|
|
||||||
}
|
|
||||||
|
|
||||||
private val IrConstructor.isOrShouldBeHiddenDueToOrigin: Boolean
|
|
||||||
get() = !(origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
|
||||||
origin == IrDeclarationOrigin.SYNTHETIC_ACCESSOR ||
|
|
||||||
origin == JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR ||
|
|
||||||
origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB)
|
|
||||||
|
|
||||||
fun getSyntheticConstructorWithMangledParams(declaration: IrConstructor) =
|
|
||||||
getSyntheticConstructorAccessor(declaration, context.hiddenConstructorsWithMangledParams)
|
|
||||||
|
|
||||||
fun getSyntheticConstructorOfSealedClass(declaration: IrConstructor) =
|
|
||||||
getSyntheticConstructorAccessor(declaration, context.hiddenConstructorsOfSealedClasses)
|
|
||||||
}
|
}
|
||||||
+1
-1
@@ -33,7 +33,7 @@ class JvmCachedDeclarations(
|
|||||||
private val context: JvmBackendContext,
|
private val context: JvmBackendContext,
|
||||||
val fieldsForObjectInstances: CachedFieldsForObjectInstances,
|
val fieldsForObjectInstances: CachedFieldsForObjectInstances,
|
||||||
) {
|
) {
|
||||||
val syntheticAccessorGenerator = CachedSyntheticDeclarations(context)
|
val syntheticAccessorGenerator = JvmSyntheticAccessorGenerator(context)
|
||||||
|
|
||||||
private val singletonFieldDeclarations = ConcurrentHashMap<IrSymbolOwner, IrField>()
|
private val singletonFieldDeclarations = ConcurrentHashMap<IrSymbolOwner, IrField>()
|
||||||
private val staticBackingFields = ConcurrentHashMap<IrProperty, IrField>()
|
private val staticBackingFields = ConcurrentHashMap<IrProperty, IrField>()
|
||||||
|
|||||||
+121
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.jvm
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.ScopeWithIr
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.ir.isJvmInterface
|
||||||
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
|
class JvmSyntheticAccessorGenerator(context: JvmBackendContext) : CachedSyntheticDeclarations<JvmBackendContext>(context) {
|
||||||
|
|
||||||
|
override fun accessorModality(parent: IrDeclarationParent): Modality =
|
||||||
|
if (parent is IrClass && parent.isJvmInterface) Modality.OPEN else Modality.FINAL
|
||||||
|
|
||||||
|
override fun IrDeclarationWithVisibility.accessorParent(parent: IrDeclarationParent, scopes: List<ScopeWithIr>): IrDeclarationParent =
|
||||||
|
if (visibility == JavaDescriptorVisibilities.PROTECTED_STATIC_VISIBILITY) {
|
||||||
|
val classes = scopes.map { it.irElement }.filterIsInstance<IrClass>()
|
||||||
|
val companions = classes.mapNotNull(IrClass::companionObject)
|
||||||
|
val objectsInScope =
|
||||||
|
classes.flatMap { it.declarations.filter(IrDeclaration::isAnonymousObject).filterIsInstance<IrClass>() }
|
||||||
|
val candidates = objectsInScope + companions + classes
|
||||||
|
candidates.lastOrNull { parent is IrClass && it.isSubclassOf(parent) } ?: classes.last()
|
||||||
|
} else {
|
||||||
|
parent
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mapFunctionName(function: IrSimpleFunction): String = context.defaultMethodSignatureMapper.mapFunctionName(function)
|
||||||
|
|
||||||
|
override fun functionAccessorSuffix(function: IrSimpleFunction, superQualifier: IrClassSymbol?, scopes: List<ScopeWithIr>): String {
|
||||||
|
val currentClass = scopes.lastOrNull { it.scope.scopeOwnerSymbol is IrClassSymbol }?.irElement as? IrClass
|
||||||
|
if (currentClass != null &&
|
||||||
|
currentClass.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS &&
|
||||||
|
currentClass.parentAsClass == function.parentAsClass
|
||||||
|
) {
|
||||||
|
// The only function accessors placed on interfaces are for private functions and JvmDefault implementations.
|
||||||
|
// The two cannot clash.
|
||||||
|
return if (DescriptorVisibilities.isPrivate(function.visibility)) "" else "\$jd"
|
||||||
|
}
|
||||||
|
return super.functionAccessorSuffix(function, superQualifier, scopes)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fieldGetterName(field: IrField): String = JvmAbi.getterName(field.name.asString())
|
||||||
|
|
||||||
|
override fun fieldSetterName(field: IrField): String = JvmAbi.setterName(field.name.asString())
|
||||||
|
|
||||||
|
override fun fieldAccessorSuffix(field: IrField, superQualifierSymbol: IrClassSymbol?): String {
|
||||||
|
// Special _c_ompanion _p_roperty suffix for accessing companion backing field moved to outer
|
||||||
|
if (field.origin == JvmLoweredDeclarationOrigin.COMPANION_PROPERTY_BACKING_FIELD && !field.parentAsClass.isCompanion) {
|
||||||
|
return "cp"
|
||||||
|
}
|
||||||
|
return super.fieldAccessorSuffix(field, superQualifierSymbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val DescriptorVisibility.isProtected: Boolean
|
||||||
|
get() = AsmUtil.getVisibilityAccessFlag(delegate) == Opcodes.ACC_PROTECTED
|
||||||
|
|
||||||
|
private fun getSyntheticConstructorAccessor(
|
||||||
|
declaration: IrConstructor,
|
||||||
|
constructorToAccessorMap: ConcurrentHashMap<IrConstructor, IrConstructor>
|
||||||
|
): IrConstructor {
|
||||||
|
return constructorToAccessorMap.getOrPut(declaration) {
|
||||||
|
declaration.makeConstructorAccessor(JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR).also { accessor ->
|
||||||
|
if (declaration.constructedClass.modality != Modality.SEALED) {
|
||||||
|
// 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 accessor. We implement this special case in the JVM IR backend by
|
||||||
|
// attaching the metadata directly to the accessor. We also have to move all annotations
|
||||||
|
// to the accessor. Parameter annotations are already moved by the copyTo method.
|
||||||
|
if (declaration.metadata != null) {
|
||||||
|
accessor.metadata = declaration.metadata
|
||||||
|
declaration.metadata = null
|
||||||
|
}
|
||||||
|
accessor.annotations += declaration.annotations
|
||||||
|
declaration.annotations = emptyList()
|
||||||
|
declaration.valueParameters.forEach { it.annotations = emptyList() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isOrShouldBeHiddenSinceHasMangledParams(constructor: IrConstructor): Boolean {
|
||||||
|
if (constructor in context.hiddenConstructorsWithMangledParams.keys) return true
|
||||||
|
return constructor.isOrShouldBeHiddenDueToOrigin &&
|
||||||
|
!DescriptorVisibilities.isPrivate(constructor.visibility) &&
|
||||||
|
!constructor.constructedClass.isValue &&
|
||||||
|
(context.multiFieldValueClassReplacements.originalConstructorForConstructorReplacement[constructor]
|
||||||
|
?: constructor).hasMangledParameters() &&
|
||||||
|
!constructor.constructedClass.isAnonymousObject
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isOrShouldBeHiddenAsSealedClassConstructor(constructor: IrConstructor): Boolean {
|
||||||
|
if (constructor in context.hiddenConstructorsOfSealedClasses.keys) return true
|
||||||
|
return constructor.isOrShouldBeHiddenDueToOrigin &&
|
||||||
|
constructor.visibility != DescriptorVisibilities.PUBLIC &&
|
||||||
|
constructor.constructedClass.modality == Modality.SEALED
|
||||||
|
}
|
||||||
|
|
||||||
|
private val IrConstructor.isOrShouldBeHiddenDueToOrigin: Boolean
|
||||||
|
get() = !(origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
||||||
|
origin == IrDeclarationOrigin.SYNTHETIC_ACCESSOR ||
|
||||||
|
origin == JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR ||
|
||||||
|
origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB)
|
||||||
|
|
||||||
|
fun getSyntheticConstructorWithMangledParams(declaration: IrConstructor) =
|
||||||
|
getSyntheticConstructorAccessor(declaration, context.hiddenConstructorsWithMangledParams)
|
||||||
|
|
||||||
|
fun getSyntheticConstructorOfSealedClass(declaration: IrConstructor) =
|
||||||
|
getSyntheticConstructorAccessor(declaration, context.hiddenConstructorsOfSealedClasses)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user