Refactor accessors for backing fields in JVM back-end
This commit is contained in:
+17
-8
@@ -19,13 +19,22 @@ package org.jetbrains.kotlin.codegen
|
|||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
abstract class AccessorForPropertyBackingField(property: PropertyDescriptor,
|
class AccessorForPropertyBackingField(
|
||||||
type: KotlinType,
|
property: PropertyDescriptor,
|
||||||
receiverType: KotlinType?,
|
containingDeclaration: DeclarationDescriptor,
|
||||||
dispatchReceiver: ReceiverParameterDescriptor?,
|
delegateType: KotlinType?,
|
||||||
containingDeclaration: DeclarationDescriptor,
|
extensionReceiverParameter: ReceiverParameterDescriptor?,
|
||||||
suffix: String
|
dispatchReceiverParameter: ReceiverParameterDescriptor?,
|
||||||
) : AccessorForPropertyDescriptor(property, type, receiverType, dispatchReceiver, containingDeclaration, null, suffix)
|
nameSuffix: String,
|
||||||
|
val fieldAccessorKind: FieldAccessorKind
|
||||||
|
) : AccessorForPropertyDescriptor(
|
||||||
|
property,
|
||||||
|
delegateType ?: property.type,
|
||||||
|
extensionReceiverParameter?.type,
|
||||||
|
dispatchReceiverParameter,
|
||||||
|
containingDeclaration,
|
||||||
|
null,
|
||||||
|
nameSuffix
|
||||||
|
)
|
||||||
|
|||||||
-28
@@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.codegen
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
|
|
||||||
class AccessorForPropertyBackingFieldFromLocal(property: PropertyDescriptor,
|
|
||||||
containingDeclaration: DeclarationDescriptor,
|
|
||||||
nameSuffix: String
|
|
||||||
) : AccessorForPropertyBackingField(property, property.type,
|
|
||||||
DescriptorUtils.getReceiverParameterType(property.extensionReceiverParameter),
|
|
||||||
property.dispatchReceiverParameter, containingDeclaration, nameSuffix)
|
|
||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.codegen
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
|
|
||||||
class AccessorForPropertyBackingFieldInClassCompanion(property: PropertyDescriptor,
|
|
||||||
containingDeclaration: DeclarationDescriptor,
|
|
||||||
delegationType: KotlinType?,
|
|
||||||
nameSuffix: String
|
|
||||||
) : AccessorForPropertyBackingField(property, delegationType ?: property.type, null, null, containingDeclaration, nameSuffix)
|
|
||||||
@@ -738,6 +738,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
|||||||
|
|
||||||
class PropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased {
|
class PropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased {
|
||||||
private final PropertyAccessorDescriptor callableDescriptor;
|
private final PropertyAccessorDescriptor callableDescriptor;
|
||||||
|
|
||||||
private PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) {
|
private PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) {
|
||||||
super(MemberCodegen.this.state);
|
super(MemberCodegen.this.state);
|
||||||
this.callableDescriptor = callableDescriptor;
|
this.callableDescriptor = callableDescriptor;
|
||||||
@@ -745,7 +746,9 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||||
boolean syntheticBackingField = accessor instanceof AccessorForPropertyBackingFieldFromLocal;
|
boolean syntheticBackingField =
|
||||||
|
accessor instanceof AccessorForPropertyBackingField &&
|
||||||
|
((AccessorForPropertyBackingField) accessor).getFieldAccessorKind() == FieldAccessorKind.FIELD_FROM_LOCAL;
|
||||||
boolean forceFieldForCompanionProperty = JvmAbi.isPropertyWithBackingFieldInOuterClass(original) &&
|
boolean forceFieldForCompanionProperty = JvmAbi.isPropertyWithBackingFieldInOuterClass(original) &&
|
||||||
!isCompanionObject(accessor.getContainingDeclaration());
|
!isCompanionObject(accessor.getContainingDeclaration());
|
||||||
boolean forceField = forceFieldForCompanionProperty ||
|
boolean forceField = forceFieldForCompanionProperty ||
|
||||||
|
|||||||
@@ -434,49 +434,44 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
AccessorKey key = new AccessorKey(descriptor, superCallTarget);
|
AccessorKey key = new AccessorKey(descriptor, superCallTarget);
|
||||||
|
|
||||||
// NB should check for property accessor factory first (or change property accessor tracking under propertyAccessorFactory creation)
|
// NB should check for property accessor factory first (or change property accessor tracking under propertyAccessorFactory creation)
|
||||||
AccessorForPropertyDescriptorFactory propertyAccessorFactory = propertyAccessorFactories.get(key);
|
if (propertyAccessorFactories.containsKey(key)) {
|
||||||
if (propertyAccessorFactory != null) {
|
return (D) propertyAccessorFactories.get(key).getOrCreateAccessorIfNeeded(getterAccessorRequired, setterAccessorRequired);
|
||||||
return (D) propertyAccessorFactory.getOrCreateAccessorIfNeeded(getterAccessorRequired, setterAccessorRequired);
|
|
||||||
}
|
}
|
||||||
AccessorForCallableDescriptor<?> accessor = accessors.get(key);
|
|
||||||
if (accessor != null) {
|
if (accessors.containsKey(key)) {
|
||||||
|
AccessorForCallableDescriptor<?> accessor = accessors.get(key);
|
||||||
assert accessorKind == FieldAccessorKind.NORMAL ||
|
assert accessorKind == FieldAccessorKind.NORMAL ||
|
||||||
accessor instanceof AccessorForPropertyBackingField : "There is already exists accessor with isForBackingField = false in this context";
|
accessor instanceof AccessorForPropertyBackingField : "There is already exists accessor with isForBackingField = false in this context";
|
||||||
return (D) accessor;
|
return (D) accessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
String nameSuffix = SyntheticAccessorUtilKt.getAccessorNameSuffix(descriptor, key.superCallLabelTarget, accessorKind);
|
String nameSuffix = SyntheticAccessorUtilKt.getAccessorNameSuffix(descriptor, key.superCallLabelTarget, accessorKind);
|
||||||
|
AccessorForCallableDescriptor<?> accessor;
|
||||||
if (descriptor instanceof SimpleFunctionDescriptor) {
|
if (descriptor instanceof SimpleFunctionDescriptor) {
|
||||||
accessor = new AccessorForFunctionDescriptor(
|
accessor = new AccessorForFunctionDescriptor((FunctionDescriptor) descriptor, contextDescriptor, superCallTarget, nameSuffix);
|
||||||
(FunctionDescriptor) descriptor, contextDescriptor, superCallTarget, nameSuffix
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else if (descriptor instanceof ClassConstructorDescriptor) {
|
else if (descriptor instanceof ClassConstructorDescriptor) {
|
||||||
accessor = new AccessorForConstructorDescriptor((ClassConstructorDescriptor) descriptor, contextDescriptor, superCallTarget);
|
accessor = new AccessorForConstructorDescriptor((ClassConstructorDescriptor) descriptor, contextDescriptor, superCallTarget);
|
||||||
}
|
}
|
||||||
else if (descriptor instanceof PropertyDescriptor) {
|
else if (descriptor instanceof PropertyDescriptor) {
|
||||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||||
switch (accessorKind) {
|
if (accessorKind == FieldAccessorKind.NORMAL) {
|
||||||
case NORMAL:
|
AccessorForPropertyDescriptorFactory factory =
|
||||||
propertyAccessorFactory = new AccessorForPropertyDescriptorFactory((PropertyDescriptor) descriptor, contextDescriptor,
|
new AccessorForPropertyDescriptorFactory(propertyDescriptor, contextDescriptor, superCallTarget, nameSuffix);
|
||||||
superCallTarget, nameSuffix);
|
propertyAccessorFactories.put(key, factory);
|
||||||
propertyAccessorFactories.put(key, propertyAccessorFactory);
|
|
||||||
|
|
||||||
// Record worst case accessor for accessor methods generation.
|
// Record worst case accessor for accessor methods generation.
|
||||||
AccessorForPropertyDescriptor accessorWithGetterAndSetter =
|
accessors.put(key, factory.getOrCreateAccessorWithSyntheticGetterAndSetter());
|
||||||
propertyAccessorFactory.getOrCreateAccessorWithSyntheticGetterAndSetter();
|
|
||||||
accessors.put(key, accessorWithGetterAndSetter);
|
|
||||||
|
|
||||||
PropertyDescriptor accessorDescriptor =
|
return (D) factory.getOrCreateAccessorIfNeeded(getterAccessorRequired, setterAccessorRequired);
|
||||||
propertyAccessorFactory.getOrCreateAccessorIfNeeded(getterAccessorRequired, setterAccessorRequired);
|
|
||||||
return (D) accessorDescriptor;
|
|
||||||
case IN_CLASS_COMPANION:
|
|
||||||
accessor = new AccessorForPropertyBackingFieldInClassCompanion(propertyDescriptor, contextDescriptor,
|
|
||||||
delegateType, nameSuffix);
|
|
||||||
break;
|
|
||||||
case FIELD_FROM_LOCAL:
|
|
||||||
accessor = new AccessorForPropertyBackingFieldFromLocal(propertyDescriptor, contextDescriptor, nameSuffix);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
accessor = new AccessorForPropertyBackingField(
|
||||||
|
propertyDescriptor, contextDescriptor, delegateType,
|
||||||
|
accessorKind == FieldAccessorKind.IN_CLASS_COMPANION ? null : propertyDescriptor.getExtensionReceiverParameter(),
|
||||||
|
accessorKind == FieldAccessorKind.IN_CLASS_COMPANION ? null : propertyDescriptor.getDispatchReceiverParameter(),
|
||||||
|
nameSuffix, accessorKind
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("Do not know how to create accessor for descriptor " + descriptor);
|
throw new UnsupportedOperationException("Do not know how to create accessor for descriptor " + descriptor);
|
||||||
|
|||||||
@@ -22,26 +22,25 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|||||||
enum class FieldAccessorKind(val suffix: String) {
|
enum class FieldAccessorKind(val suffix: String) {
|
||||||
NORMAL("p"),
|
NORMAL("p"),
|
||||||
IN_CLASS_COMPANION("cp"),
|
IN_CLASS_COMPANION("cp"),
|
||||||
FIELD_FROM_LOCAL("lp");
|
FIELD_FROM_LOCAL("lp"),
|
||||||
|
|
||||||
override fun toString() = suffix
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CallableMemberDescriptor.getJvmName() =
|
private fun CallableMemberDescriptor.getJvmName() =
|
||||||
DescriptorUtils.getJvmName(this) ?: name.asString()
|
DescriptorUtils.getJvmName(this) ?: name.asString()
|
||||||
|
|
||||||
fun getAccessorNameSuffix(descriptor: CallableMemberDescriptor, superCallDescriptor: ClassDescriptor?,
|
fun getAccessorNameSuffix(
|
||||||
accessorKind: FieldAccessorKind): String {
|
descriptor: CallableMemberDescriptor, superCallDescriptor: ClassDescriptor?, accessorKind: FieldAccessorKind
|
||||||
|
): String {
|
||||||
val suffix = when (descriptor) {
|
val suffix = when (descriptor) {
|
||||||
is ConstructorDescriptor ->
|
is ConstructorDescriptor ->
|
||||||
return "will be ignored"
|
return "will be ignored"
|
||||||
is SimpleFunctionDescriptor ->
|
is SimpleFunctionDescriptor ->
|
||||||
descriptor.getJvmName()
|
descriptor.getJvmName()
|
||||||
is PropertyDescriptor ->
|
is PropertyDescriptor ->
|
||||||
descriptor.getJvmName() + "$" + accessorKind
|
descriptor.getJvmName() + "$" + accessorKind.suffix
|
||||||
else ->
|
else ->
|
||||||
throw UnsupportedOperationException("Do not know how to create accessor for descriptor " + descriptor)
|
throw UnsupportedOperationException("Do not know how to create accessor for descriptor " + descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (superCallDescriptor == null) suffix else "$suffix\$s${superCallDescriptor.name.asString().hashCode()}"
|
return if (superCallDescriptor == null) suffix else "$suffix\$s${superCallDescriptor.name.asString().hashCode()}"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user