JVM IR: generate synthetic $annotations methods for properties
This commit is contained in:
@@ -350,7 +350,7 @@ public class PropertyCodegen {
|
||||
Annotations annotations = descriptor.getAnnotations();
|
||||
if (annotations.isEmpty()) return;
|
||||
|
||||
Method signature = getSyntheticMethodSignature(descriptor);
|
||||
Method signature = typeMapper.mapSyntheticMethodForPropertyAnnotations(descriptor);
|
||||
if (kind != OwnerKind.DEFAULT_IMPLS && CodegenContextUtil.isImplementationOwner(context, descriptor)) {
|
||||
v.getSerializationBindings().put(SYNTHETIC_METHOD_FOR_PROPERTY, descriptor, signature);
|
||||
}
|
||||
@@ -363,14 +363,6 @@ public class PropertyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Method getSyntheticMethodSignature(@NotNull PropertyDescriptor descriptor) {
|
||||
ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter();
|
||||
String name = JvmAbi.getSyntheticMethodNameForAnnotatedProperty(descriptor.getName());
|
||||
String desc = receiver == null ? "()V" : "(" + typeMapper.mapType(receiver.getType()) + ")V";
|
||||
return new Method(name, desc);
|
||||
}
|
||||
|
||||
private void generateBackingField(
|
||||
@NotNull KtNamedDeclaration element,
|
||||
@NotNull PropertyDescriptor propertyDescriptor,
|
||||
|
||||
@@ -1834,6 +1834,14 @@ public class KotlinTypeMapper {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Method mapSyntheticMethodForPropertyAnnotations(@NotNull PropertyDescriptor descriptor) {
|
||||
ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter();
|
||||
String name = JvmAbi.getSyntheticMethodNameForAnnotatedProperty(descriptor.getName());
|
||||
String desc = receiver == null ? "()V" : "(" + mapType(receiver.getType()) + ")V";
|
||||
return new Method(name, desc);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JvmMethodSignature mapScriptSignature(
|
||||
@NotNull ScriptDescriptor script,
|
||||
|
||||
+42
-6
@@ -7,26 +7,35 @@ package org.jetbrains.kotlin.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
|
||||
val propertiesPhase = makeIrFilePhase(
|
||||
::PropertiesLowering,
|
||||
fun makePropertiesPhase(originOfSyntheticMethodForAnnotations: IrDeclarationOrigin?) = makeIrFilePhase(
|
||||
{ context -> PropertiesLowering(context, originOfSyntheticMethodForAnnotations) },
|
||||
name = "Properties",
|
||||
description = "Move fields and accessors for properties to their classes"
|
||||
)
|
||||
|
||||
class PropertiesLowering() : IrElementTransformerVoid(), FileLoweringPass {
|
||||
constructor(@Suppress("UNUSED_PARAMETER") context: BackendContext) : this()
|
||||
|
||||
class PropertiesLowering(
|
||||
private val context: BackendContext,
|
||||
private val originOfSyntheticMethodForAnnotations: IrDeclarationOrigin?
|
||||
) : IrElementTransformerVoid(), FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.accept(this, null)
|
||||
}
|
||||
@@ -45,16 +54,43 @@ class PropertiesLowering() : IrElementTransformerVoid(), FileLoweringPass {
|
||||
|
||||
private fun lowerProperty(declaration: IrDeclaration, kind: ClassKind): List<IrDeclaration>? =
|
||||
if (declaration is IrProperty)
|
||||
ArrayList<IrDeclaration>(3).apply {
|
||||
ArrayList<IrDeclaration>(4).apply {
|
||||
// JvmFields in a companion object refer to companion's owners and should not be generated within companion.
|
||||
if (kind != ClassKind.ANNOTATION_CLASS && declaration.backingField?.parent == declaration.parent) {
|
||||
addIfNotNull(declaration.backingField)
|
||||
}
|
||||
addIfNotNull(declaration.getter)
|
||||
addIfNotNull(declaration.setter)
|
||||
|
||||
if (declaration.annotations.isNotEmpty() && originOfSyntheticMethodForAnnotations != null) {
|
||||
add(createSyntheticMethodForAnnotations(declaration, originOfSyntheticMethodForAnnotations))
|
||||
}
|
||||
}
|
||||
else
|
||||
null
|
||||
|
||||
private fun createSyntheticMethodForAnnotations(declaration: IrProperty, origin: IrDeclarationOrigin): IrFunctionImpl {
|
||||
val descriptor = WrappedSimpleFunctionDescriptor(declaration.descriptor.annotations)
|
||||
val symbol = IrSimpleFunctionSymbolImpl(descriptor)
|
||||
// TODO: ACC_DEPRECATED
|
||||
return IrFunctionImpl(
|
||||
-1, -1, origin,
|
||||
symbol, Name.identifier(JvmAbi.getSyntheticMethodNameForAnnotatedProperty(declaration.name)),
|
||||
Visibilities.PUBLIC, Modality.OPEN, context.irBuiltIns.unitType,
|
||||
isInline = false, isExternal = false, isTailrec = false, isSuspend = false
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
|
||||
extensionReceiverParameter = declaration.getter?.extensionReceiverParameter
|
||||
|
||||
body = IrBlockBodyImpl(-1, -1)
|
||||
|
||||
// TODO: uncomment this and derive annotations from owner in wrapped descriptors
|
||||
// annotations.addAll(declaration.annotations)
|
||||
|
||||
metadata = declaration.metadata
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LocalDelegatedPropertiesLowering : IrElementTransformerVoid(), FileLoweringPass {
|
||||
|
||||
@@ -251,7 +251,7 @@ private val varargLoweringPhase = makeJsModulePhase(
|
||||
)
|
||||
|
||||
private val propertiesLoweringPhase = makeJsModulePhase(
|
||||
{ PropertiesLowering() },
|
||||
{ context -> PropertiesLowering(context, null) },
|
||||
name = "PropertiesLowering",
|
||||
description = "Move fields and accessors out from its property"
|
||||
)
|
||||
|
||||
@@ -30,9 +30,11 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||
object TO_ARRAY : IrDeclarationOriginImpl("TO_ARRAY")
|
||||
object JVM_STATIC_WRAPPER : IrDeclarationOriginImpl("JVM_STATIC_WRAPPER")
|
||||
object JVM_OVERLOADS_WRAPPER : IrDeclarationOriginImpl("JVM_OVERLOADS_WRAPPER")
|
||||
object SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS :
|
||||
IrDeclarationOriginImpl("SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS", isSynthetic = true)
|
||||
}
|
||||
|
||||
interface JvmLoweredStatementOrigin : IrStatementOrigin {
|
||||
object DEFAULT_IMPLS_DELEGATION : IrStatementOriginImpl("DEFAULT_IMPL_DELEGATION")
|
||||
object TO_ARRAY : IrDeclarationOriginImpl("TO_ARRAY")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ internal val jvmPhases = namedIrFilePhase(
|
||||
moveCompanionObjectFieldsPhase then
|
||||
constPhase then
|
||||
propertiesToFieldsPhase then
|
||||
propertiesPhase then
|
||||
makePropertiesPhase(JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS) then
|
||||
renameFieldsPhase then
|
||||
annotationPhase then
|
||||
|
||||
|
||||
+26
-4
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDescriptorWithExtraFlags
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
@@ -240,11 +241,32 @@ open class ClassCodegen protected constructor(
|
||||
private fun generateMethod(method: IrFunction) {
|
||||
if (method.origin == IrDeclarationOrigin.FAKE_OVERRIDE) return
|
||||
|
||||
val signature = FunctionCodegen(method, this).generate()
|
||||
val signature = FunctionCodegen(method, this).generate().asmMethod
|
||||
|
||||
val descriptor = method.metadata?.descriptor
|
||||
if (descriptor != null) {
|
||||
visitor.serializationBindings.put(JvmSerializationBindings.METHOD_FOR_FUNCTION, descriptor, signature.asmMethod)
|
||||
val metadata = method.metadata
|
||||
when (metadata) {
|
||||
is MetadataSource.Property -> {
|
||||
// We can't check for JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS because for interface methods
|
||||
// moved to DefaultImpls, origin is changed to DEFAULT_IMPLS
|
||||
// TODO: fix origin somehow, because otherwise $annotations methods in interfaces also don't have ACC_SYNTHETIC
|
||||
assert(method.name.asString().endsWith(JvmAbi.ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX)) { method.dump() }
|
||||
|
||||
val codegen = if (DescriptorUtils.isInterface(metadata.descriptor.containingDeclaration)) {
|
||||
assert(irClass.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS) { irClass.dump() }
|
||||
parentClassCodegen!!
|
||||
} else {
|
||||
this
|
||||
}
|
||||
codegen.visitor.serializationBindings.put(
|
||||
JvmSerializationBindings.SYNTHETIC_METHOD_FOR_PROPERTY, metadata.descriptor, signature
|
||||
)
|
||||
}
|
||||
is MetadataSource.Function -> {
|
||||
visitor.serializationBindings.put(JvmSerializationBindings.METHOD_FOR_FUNCTION, metadata.descriptor, signature)
|
||||
}
|
||||
null -> {
|
||||
}
|
||||
else -> error("Incorrect metadata source $metadata for:\n${method.dump()}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-15
@@ -13,7 +13,9 @@ import org.jetbrains.kotlin.backend.common.lower.InitializersLowering.Companion.
|
||||
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
@@ -41,29 +43,29 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans
|
||||
irClass.declarations.add(defaultImplsIrClass)
|
||||
val members = defaultImplsIrClass.declarations
|
||||
|
||||
irClass.declarations.filterIsInstance<IrFunction>().forEach {
|
||||
if (it is IrSimpleFunction && it.modality != Modality.ABSTRACT && it.origin != IrDeclarationOrigin.FAKE_OVERRIDE) {
|
||||
val element = context.declarationFactory.getDefaultImplsFunction(it)
|
||||
for (function in irClass.declarations) {
|
||||
if (function !is IrSimpleFunction) continue
|
||||
|
||||
if (function.modality != Modality.ABSTRACT && function.origin != IrDeclarationOrigin.FAKE_OVERRIDE) {
|
||||
val element = context.declarationFactory.getDefaultImplsFunction(function)
|
||||
members.add(element)
|
||||
element.body = it.body
|
||||
it.body = null
|
||||
element.body = function.body
|
||||
function.body = null
|
||||
//TODO reset modality to abstract
|
||||
}
|
||||
}
|
||||
|
||||
irClass.transformChildrenVoid(this)
|
||||
|
||||
//REMOVE private methods
|
||||
val privateToRemove = irClass.declarations.filterIsInstance<IrFunction>().filter {
|
||||
Visibilities.isPrivate(it.visibility) && (it as? IrSimpleFunction)?.name != clinitName
|
||||
irClass.declarations.removeAll {
|
||||
it is IrFunction && shouldRemoveFunction(it)
|
||||
}
|
||||
|
||||
val defaultBodies = irClass.declarations.filterIsInstance<IrFunction>().filter {
|
||||
it.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER
|
||||
}
|
||||
irClass.declarations.removeAll(privateToRemove)
|
||||
irClass.declarations.removeAll(defaultBodies)
|
||||
}
|
||||
|
||||
private fun shouldRemoveFunction(function: IrFunction): Boolean =
|
||||
Visibilities.isPrivate(function.visibility) && function.name != clinitName ||
|
||||
function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
||||
function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS
|
||||
}
|
||||
|
||||
|
||||
@@ -110,5 +112,7 @@ internal fun createStaticFunctionWithReceivers(
|
||||
(listOfNotNull(oldFunction.dispatchReceiverParameter, oldFunction.extensionReceiverParameter) + oldFunction.valueParameters)
|
||||
.zip(valueParameters).toMap()
|
||||
body = oldFunction.body?.transform(VariableRemapper(mapping), null)
|
||||
|
||||
metadata = oldFunction.metadata
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +128,8 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
|
||||
irProperty.getter = generateGetterIfRequired(ktProperty, propertyDescriptor)
|
||||
irProperty.setter = generateSetterIfRequired(ktProperty, propertyDescriptor)
|
||||
|
||||
irProperty.metadata = MetadataSource.Property(propertyDescriptor)
|
||||
}
|
||||
|
||||
fun generateFakeOverrideProperty(propertyDescriptor: PropertyDescriptor, ktElement: KtPureElement): IrProperty? {
|
||||
|
||||
@@ -39,7 +39,7 @@ interface IrFunction :
|
||||
|
||||
var body: IrBody?
|
||||
|
||||
override val metadata: MetadataSource.Function?
|
||||
override val metadata: MetadataSource?
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ abstract class IrFunctionBase(
|
||||
|
||||
final override var body: IrBody? = null
|
||||
|
||||
override var metadata: MetadataSource.Function? = null
|
||||
override var metadata: MetadataSource? = null
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
typeParameters.forEach { it.accept(visitor, data) }
|
||||
|
||||
@@ -19,10 +19,7 @@ package org.jetbrains.kotlin.ir.declarations.impl
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -106,9 +103,11 @@ class IrPropertyImpl(
|
||||
setter?.accept(visitor, data)
|
||||
}
|
||||
|
||||
override var metadata: MetadataSource? = null
|
||||
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||
backingField = backingField?.transform(transformer, data) as? IrField
|
||||
getter = getter?.run { transform(transformer, data) as IrSimpleFunction }
|
||||
setter = setter?.run { transform(transformer, data) as IrSimpleFunction }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
package zzz
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
// FULL_JDK
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KMutableProperty
|
||||
|
||||
Vendored
-2
@@ -1,5 +1,3 @@
|
||||
// !LANGUAGE: +JvmFieldInInterface +NestedClassesInAnnotations
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_REFLECT
|
||||
|
||||
|
||||
Vendored
-2
@@ -1,5 +1,3 @@
|
||||
// !LANGUAGE: +JvmFieldInInterface
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_REFLECT
|
||||
|
||||
|
||||
-2
@@ -1,6 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.*
|
||||
|
||||
@@ -38,7 +38,7 @@ public final class JvmAbi {
|
||||
public static final String DELEGATED_PROPERTIES_ARRAY_NAME = "$$delegatedProperties";
|
||||
public static final String DELEGATE_SUPER_FIELD_PREFIX = "$$delegate_";
|
||||
private static final String ANNOTATIONS_SUFFIX = "$annotations";
|
||||
private static final String ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX = ANNOTATIONS_SUFFIX;
|
||||
public static final String ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX = ANNOTATIONS_SUFFIX;
|
||||
private static final String ANNOTATED_TYPEALIAS_METHOD_NAME_SUFFIX = ANNOTATIONS_SUFFIX;
|
||||
|
||||
public static final String INSTANCE_FIELD = "INSTANCE";
|
||||
|
||||
Reference in New Issue
Block a user