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); }