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.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
abstract class AccessorForPropertyBackingField(property: PropertyDescriptor,
|
||||
type: KotlinType,
|
||||
receiverType: KotlinType?,
|
||||
dispatchReceiver: ReceiverParameterDescriptor?,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
suffix: String
|
||||
) : AccessorForPropertyDescriptor(property, type, receiverType, dispatchReceiver, containingDeclaration, null, suffix)
|
||||
class AccessorForPropertyBackingField(
|
||||
property: PropertyDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
delegateType: KotlinType?,
|
||||
extensionReceiverParameter: ReceiverParameterDescriptor?,
|
||||
dispatchReceiverParameter: ReceiverParameterDescriptor?,
|
||||
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 {
|
||||
private final PropertyAccessorDescriptor callableDescriptor;
|
||||
|
||||
private PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) {
|
||||
super(MemberCodegen.this.state);
|
||||
this.callableDescriptor = callableDescriptor;
|
||||
@@ -745,7 +746,9 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
|
||||
@Override
|
||||
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) &&
|
||||
!isCompanionObject(accessor.getContainingDeclaration());
|
||||
boolean forceField = forceFieldForCompanionProperty ||
|
||||
|
||||
@@ -434,49 +434,44 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
AccessorKey key = new AccessorKey(descriptor, superCallTarget);
|
||||
|
||||
// NB should check for property accessor factory first (or change property accessor tracking under propertyAccessorFactory creation)
|
||||
AccessorForPropertyDescriptorFactory propertyAccessorFactory = propertyAccessorFactories.get(key);
|
||||
if (propertyAccessorFactory != null) {
|
||||
return (D) propertyAccessorFactory.getOrCreateAccessorIfNeeded(getterAccessorRequired, setterAccessorRequired);
|
||||
if (propertyAccessorFactories.containsKey(key)) {
|
||||
return (D) propertyAccessorFactories.get(key).getOrCreateAccessorIfNeeded(getterAccessorRequired, setterAccessorRequired);
|
||||
}
|
||||
AccessorForCallableDescriptor<?> accessor = accessors.get(key);
|
||||
if (accessor != null) {
|
||||
|
||||
if (accessors.containsKey(key)) {
|
||||
AccessorForCallableDescriptor<?> accessor = accessors.get(key);
|
||||
assert accessorKind == FieldAccessorKind.NORMAL ||
|
||||
accessor instanceof AccessorForPropertyBackingField : "There is already exists accessor with isForBackingField = false in this context";
|
||||
return (D) accessor;
|
||||
}
|
||||
|
||||
String nameSuffix = SyntheticAccessorUtilKt.getAccessorNameSuffix(descriptor, key.superCallLabelTarget, accessorKind);
|
||||
AccessorForCallableDescriptor<?> accessor;
|
||||
if (descriptor instanceof SimpleFunctionDescriptor) {
|
||||
accessor = new AccessorForFunctionDescriptor(
|
||||
(FunctionDescriptor) descriptor, contextDescriptor, superCallTarget, nameSuffix
|
||||
);
|
||||
accessor = new AccessorForFunctionDescriptor((FunctionDescriptor) descriptor, contextDescriptor, superCallTarget, nameSuffix);
|
||||
}
|
||||
else if (descriptor instanceof ClassConstructorDescriptor) {
|
||||
accessor = new AccessorForConstructorDescriptor((ClassConstructorDescriptor) descriptor, contextDescriptor, superCallTarget);
|
||||
}
|
||||
else if (descriptor instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
switch (accessorKind) {
|
||||
case NORMAL:
|
||||
propertyAccessorFactory = new AccessorForPropertyDescriptorFactory((PropertyDescriptor) descriptor, contextDescriptor,
|
||||
superCallTarget, nameSuffix);
|
||||
propertyAccessorFactories.put(key, propertyAccessorFactory);
|
||||
if (accessorKind == FieldAccessorKind.NORMAL) {
|
||||
AccessorForPropertyDescriptorFactory factory =
|
||||
new AccessorForPropertyDescriptorFactory(propertyDescriptor, contextDescriptor, superCallTarget, nameSuffix);
|
||||
propertyAccessorFactories.put(key, factory);
|
||||
|
||||
// Record worst case accessor for accessor methods generation.
|
||||
AccessorForPropertyDescriptor accessorWithGetterAndSetter =
|
||||
propertyAccessorFactory.getOrCreateAccessorWithSyntheticGetterAndSetter();
|
||||
accessors.put(key, accessorWithGetterAndSetter);
|
||||
// Record worst case accessor for accessor methods generation.
|
||||
accessors.put(key, factory.getOrCreateAccessorWithSyntheticGetterAndSetter());
|
||||
|
||||
PropertyDescriptor accessorDescriptor =
|
||||
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;
|
||||
return (D) factory.getOrCreateAccessorIfNeeded(getterAccessorRequired, setterAccessorRequired);
|
||||
}
|
||||
|
||||
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 {
|
||||
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) {
|
||||
NORMAL("p"),
|
||||
IN_CLASS_COMPANION("cp"),
|
||||
FIELD_FROM_LOCAL("lp");
|
||||
|
||||
override fun toString() = suffix
|
||||
FIELD_FROM_LOCAL("lp"),
|
||||
}
|
||||
|
||||
private fun CallableMemberDescriptor.getJvmName() =
|
||||
DescriptorUtils.getJvmName(this) ?: name.asString()
|
||||
|
||||
fun getAccessorNameSuffix(descriptor: CallableMemberDescriptor, superCallDescriptor: ClassDescriptor?,
|
||||
accessorKind: FieldAccessorKind): String {
|
||||
fun getAccessorNameSuffix(
|
||||
descriptor: CallableMemberDescriptor, superCallDescriptor: ClassDescriptor?, accessorKind: FieldAccessorKind
|
||||
): String {
|
||||
val suffix = when (descriptor) {
|
||||
is ConstructorDescriptor ->
|
||||
return "will be ignored"
|
||||
is SimpleFunctionDescriptor ->
|
||||
descriptor.getJvmName()
|
||||
is PropertyDescriptor ->
|
||||
descriptor.getJvmName() + "$" + accessorKind
|
||||
descriptor.getJvmName() + "$" + accessorKind.suffix
|
||||
else ->
|
||||
throw UnsupportedOperationException("Do not know how to create accessor for descriptor " + descriptor)
|
||||
}
|
||||
|
||||
return if (superCallDescriptor == null) suffix else "$suffix\$s${superCallDescriptor.name.asString().hashCode()}"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user