From 728de911403305b9f45c9c312c59e0b3c09b7697 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 8 Jun 2017 21:52:15 +0300 Subject: [PATCH] Refactor generation of metadata for delegated properties In CodegenAnnotatingVisitor, store all delegated properties whose metadata should be generated in each class (identified by ASM Type). Use the stored information later, both in the $$delegatedProperties array generation and in the access to it from property's accessor methods, instead of an heuristical indexOfDelegatedProperty() --- .../kotlin/codegen/MemberCodegen.java | 29 +++---- .../kotlin/codegen/PropertyCodegen.java | 86 ++++++------------- .../binding/CodegenAnnotatingVisitor.java | 14 +++ .../codegen/binding/CodegenBinding.java | 3 + 4 files changed, 53 insertions(+), 79 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index db3688df1a8..4f0805128e0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.backend.common.CodegenUtil; import org.jetbrains.kotlin.codegen.annotation.AnnotatedSimple; +import org.jetbrains.kotlin.codegen.binding.CodegenBinding; import org.jetbrains.kotlin.codegen.context.*; import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper; import org.jetbrains.kotlin.codegen.inline.NameGenerator; @@ -47,7 +48,6 @@ import org.jetbrains.kotlin.name.SpecialNames; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor; import org.jetbrains.kotlin.resolve.BindingContext; -import org.jetbrains.kotlin.resolve.BindingContextUtils; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.constants.ConstantValue; @@ -69,7 +69,10 @@ import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import org.jetbrains.org.objectweb.asm.commons.Method; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; import static org.jetbrains.kotlin.codegen.AsmUtil.*; import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8InterfaceWithDefaultsMember; @@ -524,11 +527,8 @@ public abstract class MemberCodegen delegatedProperties = new ArrayList<>(); - for (KtDeclaration declaration : ((KtDeclarationContainer) element).getDeclarations()) { - if (declaration instanceof KtProperty) { - KtProperty property = (KtProperty) declaration; - if (property.hasDelegate()) { - delegatedProperties.add(property); - } - } - } - if (delegatedProperties.isEmpty()) return; + List delegatedProperties = bindingContext.get(CodegenBinding.DELEGATED_PROPERTIES, thisAsmType); + if (delegatedProperties == null || delegatedProperties.isEmpty()) return; v.newField(NO_ORIGIN, ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, "[" + K_PROPERTY_TYPE, null, null); @@ -629,8 +621,7 @@ public abstract class MemberCodegen resolvedCall, - int indexInPropertyMetadataArray, - int propertyMetadataArgumentIndex - ) { - StackValue.Property receiver = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.LOCAL_0); - return invokeDelegatedPropertyConventionMethodWithReceiver( - codegen, typeMapper, resolvedCall, indexInPropertyMetadataArray, propertyMetadataArgumentIndex, - receiver, propertyDescriptor - ); - } - - public static StackValue invokeDelegatedPropertyConventionMethodWithReceiver( - @NotNull ExpressionCodegen codegen, - @NotNull KotlinTypeMapper typeMapper, - @NotNull ResolvedCall resolvedCall, - int indexInPropertyMetadataArray, - int propertyMetadataArgumentIndex, @Nullable StackValue receiver, @NotNull PropertyDescriptor propertyDescriptor ) { @@ -589,16 +542,29 @@ public class PropertyCodegen { getDelegatedPropertyMetadataOwner(codegen, typeMapper); codegen.tempVariables.put( - resolvedCall.getCall().getValueArguments().get(propertyMetadataArgumentIndex).asElement(), + resolvedCall.getCall().getValueArguments().get(1).asElement(), new StackValue(K_PROPERTY_TYPE) { @Override public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { Field array = StackValue.field( Type.getType("[" + K_PROPERTY_TYPE), owner, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, true, StackValue.none() ); - StackValue.arrayElement( - K_PROPERTY_TYPE, array, StackValue.constant(indexInPropertyMetadataArray, Type.INT_TYPE) - ).put(type, v); + int index = findDelegatedProperty(typeMapper.getBindingContext(), owner, propertyDescriptor); + StackValue.arrayElement(K_PROPERTY_TYPE, array, StackValue.constant(index, Type.INT_TYPE)).put(type, v); + } + + private int findDelegatedProperty( + @NotNull BindingContext bindingContext, + @NotNull Type owner, + @NotNull PropertyDescriptor propertyDescriptor + ) { + List allDelegatedProperties = bindingContext.get(DELEGATED_PROPERTIES, owner); + int result = allDelegatedProperties == null ? -1 : allDelegatedProperties.indexOf(propertyDescriptor); + if (result < 0) { + throw new AssertionError("Delegated property not found in " + owner + ": " + propertyDescriptor); + } + + return result; } } ); @@ -623,13 +589,11 @@ public class PropertyCodegen { } private static class DelegatedPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased { - private final int index; private final PropertyAccessorDescriptor propertyAccessorDescriptor; - public DelegatedPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor, int index) { + public DelegatedPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor) { super(state); - this.index = index; - propertyAccessorDescriptor = descriptor; + this.propertyAccessorDescriptor = descriptor; } @Override @@ -641,8 +605,10 @@ public class PropertyCodegen { bindingContext.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, propertyAccessorDescriptor); assert resolvedCall != null : "Resolve call should be recorded for delegate call " + signature.toString(); - StackValue lastValue = invokeDelegatedPropertyConventionMethod(propertyAccessorDescriptor.getCorrespondingProperty(), - codegen, state.getTypeMapper(), resolvedCall, index, 1); + PropertyDescriptor propertyDescriptor = propertyAccessorDescriptor.getCorrespondingProperty(); + StackValue.Property receiver = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.LOCAL_0); + StackValue lastValue = + invokeDelegatedPropertyConventionMethod(codegen, state.getTypeMapper(), resolvedCall, receiver, propertyDescriptor); Type asmType = signature.getReturnType(); lastValue.put(asmType, v); v.areturn(asmType); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java index 5d22a8f160f..ab1aadc244c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java @@ -417,6 +417,20 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { runtimeTypes.getSupertypeForPropertyReference(variableDescriptor, variableDescriptor.isVar(), /* bound = */ false); ClassDescriptor classDescriptor = recordClassForCallable(delegate, variableDescriptor, Collections.singleton(supertype), name); recordClosure(classDescriptor, name); + + if (!(variableDescriptor instanceof LocalVariableDescriptor)) { + ClassDescriptor containerClass = peekFromStack(classStack); + Type containerType = + containerClass != null + ? CodegenBinding.getAsmType(bindingContext, containerClass) + : Type.getObjectType(FileClasses.getFileClassInternalName(fileClassesProvider, property.getContainingKtFile())); + List descriptors = bindingTrace.get(DELEGATED_PROPERTIES, containerType); + if (descriptors == null) { + descriptors = new ArrayList<>(1); + bindingTrace.record(DELEGATED_PROPERTIES, containerType, descriptors); + } + descriptors.add(variableDescriptor); + } } super.visitProperty(property); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java index 957fffbc298..34af164026b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java @@ -69,6 +69,9 @@ public class CodegenBinding { public static final WritableSlice PARAMETER_SYNONYM = Slices.createSimpleSlice(); + public static final WritableSlice> DELEGATED_PROPERTIES = + Slices.createSimpleSlice(); + static { BasicWritableSlice.initSliceDebugNames(CodegenBinding.class); }