diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForCallableDescriptor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForCallableDescriptor.java index e9b5c5360a1..2b4077f13b1 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForCallableDescriptor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForCallableDescriptor.java @@ -17,9 +17,14 @@ package org.jetbrains.kotlin.codegen; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor; +import org.jetbrains.kotlin.psi.JetSuperExpression; public interface AccessorForCallableDescriptor { @NotNull T getCalleeDescriptor(); + + @Nullable + JetSuperExpression getSuperCallExpression(); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForConstructorDescriptor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForConstructorDescriptor.kt index f5bca65b046..f51981ca83f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForConstructorDescriptor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForConstructorDescriptor.kt @@ -17,37 +17,35 @@ package org.jetbrains.kotlin.codegen import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.JetSuperExpression import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.types.JetType -import java.util.* public class AccessorForConstructorDescriptor( private val calleeDescriptor: ConstructorDescriptor, - containingDeclaration: DeclarationDescriptor -) : AbstractAccessorForFunctionDescriptor(containingDeclaration, Name.special("")) - , ConstructorDescriptor - , AccessorForCallableDescriptor { - + containingDeclaration: DeclarationDescriptor, + private val superCallExpression: JetSuperExpression? +) : AbstractAccessorForFunctionDescriptor(containingDeclaration, Name.special("")), + ConstructorDescriptor, + AccessorForCallableDescriptor { override fun getCalleeDescriptor(): ConstructorDescriptor = calleeDescriptor - override fun getContainingDeclaration(): ClassDescriptor = calleeDescriptor.getContainingDeclaration() + override fun getContainingDeclaration(): ClassDescriptor = calleeDescriptor.containingDeclaration override fun isPrimary(): Boolean = false - override fun getReturnType(): JetType = super.getReturnType()!! + override fun getReturnType(): JetType = super.getReturnType()!! + + override fun getSuperCallExpression(): JetSuperExpression? = superCallExpression init { initialize( - DescriptorUtils.getReceiverParameterType(getExtensionReceiverParameter()), - calleeDescriptor.getDispatchReceiverParameter(), + DescriptorUtils.getReceiverParameterType(extensionReceiverParameter), + calleeDescriptor.dispatchReceiverParameter, copyTypeParameters(calleeDescriptor), copyValueParameters(calleeDescriptor), - calleeDescriptor.getReturnType(), + calleeDescriptor.returnType, Modality.FINAL, Visibilities.INTERNAL ) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForFunctionDescriptor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForFunctionDescriptor.java index 559463c1e51..8258740a6e0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForFunctionDescriptor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForFunctionDescriptor.java @@ -17,23 +17,27 @@ package org.jetbrains.kotlin.codegen; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.name.Name; +import org.jetbrains.kotlin.psi.JetSuperExpression; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage; public class AccessorForFunctionDescriptor extends AbstractAccessorForFunctionDescriptor implements AccessorForCallableDescriptor { - private final FunctionDescriptor calleeDescriptor; + private final JetSuperExpression superCallExpression; public AccessorForFunctionDescriptor( @NotNull FunctionDescriptor descriptor, @NotNull DeclarationDescriptor containingDeclaration, - int index + int index, + @Nullable JetSuperExpression superCallExpression ) { super(containingDeclaration, Name.identifier("access$" + (descriptor instanceof ConstructorDescriptor ? "init" : descriptor.getName()) + "$" + index)); this.calleeDescriptor = descriptor; + this.superCallExpression = superCallExpression; initialize(DescriptorUtils.getReceiverParameterType(descriptor.getExtensionReceiverParameter()), descriptor instanceof ConstructorDescriptor || AnnotationsPackage.isPlatformStaticInObjectOrClass(descriptor) @@ -51,4 +55,9 @@ public class AccessorForFunctionDescriptor extends AbstractAccessorForFunctionDe public FunctionDescriptor getCalleeDescriptor() { return calleeDescriptor; } + + @Override + public JetSuperExpression getSuperCallExpression() { + return superCallExpression; + } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForPropertyBackingFieldInOuterClass.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForPropertyBackingFieldInOuterClass.java index 89569f6e430..b09ba5bfce3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForPropertyBackingFieldInOuterClass.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForPropertyBackingFieldInOuterClass.java @@ -23,13 +23,12 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor; import org.jetbrains.kotlin.types.JetType; public class AccessorForPropertyBackingFieldInOuterClass extends AccessorForPropertyDescriptor { - public AccessorForPropertyBackingFieldInOuterClass( - @NotNull PropertyDescriptor pd, + @NotNull PropertyDescriptor property, @NotNull DeclarationDescriptor containingDeclaration, int index, @Nullable JetType delegationType ) { - super(pd, delegationType != null ? delegationType : pd.getType(), null, null, containingDeclaration, index); + super(property, delegationType != null ? delegationType : property.getType(), null, null, containingDeclaration, index, null); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForPropertyDescriptor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForPropertyDescriptor.java index 81130a4a11b..ad16c00293b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForPropertyDescriptor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AccessorForPropertyDescriptor.java @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl; import org.jetbrains.kotlin.name.Name; +import org.jetbrains.kotlin.psi.JetSuperExpression; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.types.JetType; @@ -33,9 +34,16 @@ import java.util.Collections; public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implements AccessorForCallableDescriptor { private final PropertyDescriptor calleeDescriptor; private final int accessorIndex; + private final JetSuperExpression superCallExpression; - public AccessorForPropertyDescriptor(@NotNull PropertyDescriptor pd, @NotNull DeclarationDescriptor containingDeclaration, int index) { - this(pd, pd.getType(), DescriptorUtils.getReceiverParameterType(pd.getExtensionReceiverParameter()), pd.getDispatchReceiverParameter(), containingDeclaration, index); + public AccessorForPropertyDescriptor( + @NotNull PropertyDescriptor property, + @NotNull DeclarationDescriptor containingDeclaration, + int index, + @Nullable JetSuperExpression superCallExpression + ) { + this(property, property.getType(), DescriptorUtils.getReceiverParameterType(property.getExtensionReceiverParameter()), + property.getDispatchReceiverParameter(), containingDeclaration, index, superCallExpression); } protected AccessorForPropertyDescriptor( @@ -44,7 +52,8 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem @Nullable JetType receiverType, @Nullable ReceiverParameterDescriptor dispatchReceiverParameter, @NotNull DeclarationDescriptor containingDeclaration, - int index + int index, + @Nullable JetSuperExpression superCallExpression ) { super(containingDeclaration, null, Annotations.EMPTY, Modality.FINAL, Visibilities.LOCAL, original.isVar(), Name.identifier("access$" + getIndexedAccessorSuffix(original, index)), @@ -52,6 +61,7 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem this.calleeDescriptor = original; this.accessorIndex = index; + this.superCallExpression = superCallExpression; setType(propertyType, Collections.emptyList(), dispatchReceiverParameter, receiverType); initialize(new Getter(this), new Setter(this)); } @@ -69,6 +79,12 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem //noinspection ConstantConditions return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getCalleeDescriptor().getGetter(); } + + @Nullable + @Override + public JetSuperExpression getSuperCallExpression() { + return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getSuperCallExpression(); + } } public static class Setter extends PropertySetterDescriptorImpl implements AccessorForCallableDescriptor{ @@ -84,6 +100,12 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem //noinspection ConstantConditions return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getCalleeDescriptor().getSetter(); } + + @Nullable + @Override + public JetSuperExpression getSuperCallExpression() { + return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getSuperCallExpression(); + } } @NotNull @@ -92,6 +114,11 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem return calleeDescriptor; } + @Override + public JetSuperExpression getSuperCallExpression() { + return superCallExpression; + } + @NotNull public String getIndexedAccessorSuffix() { return getIndexedAccessorSuffix(calleeDescriptor, accessorIndex); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index fdcbf45c376..0295439095f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -356,11 +356,15 @@ public class ExpressionCodegen extends JetVisitor implem @Override public StackValue visitSuperExpression(@NotNull JetSuperExpression expression, StackValue data) { - return StackValue.thisOrOuter(this, getSuperCallLabelTarget(expression), true, true); + return StackValue.thisOrOuter(this, getSuperCallLabelTarget(context, expression), true, true); } @NotNull - private ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression) { + public static ClassDescriptor getSuperCallLabelTarget( + @NotNull CodegenContext context, + @NotNull JetSuperExpression expression + ) { + BindingContext bindingContext = context.getState().getBindingContext(); PsiElement labelPsi = bindingContext.get(LABEL_TARGET, expression.getTargetLabel()); ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, labelPsi); DeclarationDescriptor descriptor = bindingContext.get(REFERENCE_TARGET, expression.getInstanceReference()); @@ -2007,7 +2011,7 @@ public class ExpressionCodegen extends JetVisitor implem expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL; JetSuperExpression superExpression = resolvedCall == null ? null : CallResolverUtilPackage.getSuperCallExpression(resolvedCall.getCall()); - propertyDescriptor = context.accessibleDescriptor(propertyDescriptor); + propertyDescriptor = context.accessibleDescriptor(propertyDescriptor, superExpression); if (directToField) { receiver = StackValue.receiverWithoutReceiverArgument(receiver); @@ -2137,14 +2141,14 @@ public class ExpressionCodegen extends JetVisitor implem @Nullable JetSuperExpression superExpression, @NotNull StackValue receiver ) { - return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, MethodKind.GENERAL, receiver); + return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, false, receiver); } public StackValue.Property intermediateValueForProperty( @NotNull PropertyDescriptor propertyDescriptor, boolean forceField, @Nullable JetSuperExpression superExpression, - @NotNull MethodKind methodKind, + boolean skipAccessorsForPrivateFieldInOuterClass, StackValue receiver ) { if (propertyDescriptor instanceof SyntheticJavaPropertyDescriptor) { @@ -2165,56 +2169,54 @@ public class ExpressionCodegen extends JetVisitor implem CallableMethod callableGetter = null; CallableMethod callableSetter = null; - boolean skipPropertyAccessors = forceField && !isBackingFieldInAnotherClass; - - CodegenContext backingFieldContext = context.getParentContext(); - boolean changeOwnerOnTypeMapping = isBackingFieldInAnotherClass; + CodegenContext backingFieldContext; + boolean changeOwnerOnTypeMapping; + boolean skipPropertyAccessors; if (isBackingFieldInAnotherClass && forceField) { backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration()); int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty); - skipPropertyAccessors = - (flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER; + skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || skipAccessorsForPrivateFieldInOuterClass; if (!skipPropertyAccessors) { - propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(propertyDescriptor, true, delegateType); - changeOwnerOnTypeMapping = - changeOwnerOnTypeMapping && !(propertyDescriptor instanceof AccessorForPropertyBackingFieldInOuterClass); + //noinspection ConstantConditions + propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor( + propertyDescriptor, true, delegateType, superExpression + ); + changeOwnerOnTypeMapping = !(propertyDescriptor instanceof AccessorForPropertyBackingFieldInOuterClass); } + else { + changeOwnerOnTypeMapping = true; + } + } + else { + backingFieldContext = context.getParentContext(); + changeOwnerOnTypeMapping = isBackingFieldInAnotherClass; + skipPropertyAccessors = forceField; } if (!skipPropertyAccessors) { - if (couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context)) { - callableGetter = null; - } - else { + if (!couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context)) { if (isSuper && !isInterface(containingDeclaration)) { - ClassDescriptor owner = getSuperCallLabelTarget(superExpression); + ClassDescriptor owner = getSuperCallLabelTarget(context, superExpression); CodegenContext c = context.findParentContextWithDescriptor(owner); assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor; if (c != context.getParentContext()) { - propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor); + propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor, superExpression); } } - propertyDescriptor = context.accessibleDescriptor(propertyDescriptor); + propertyDescriptor = context.accessibleDescriptor(propertyDescriptor, superExpression); PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); if (getter != null) { - callableGetter = - typeMapper.mapToCallableMethod(getter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context); + callableGetter = typeMapper.mapToCallableMethod(getter, isSuper, context); } } if (propertyDescriptor.isVar()) { PropertySetterDescriptor setter = propertyDescriptor.getSetter(); - if (setter != null) { - if (couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context)) { - callableSetter = null; - } - else { - callableSetter = - typeMapper.mapToCallableMethod(setter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context); - } + if (setter != null && !couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context)) { + callableSetter = typeMapper.mapToCallableMethod(setter, isSuper, context); } } } @@ -2329,7 +2331,9 @@ public class ExpressionCodegen extends JetVisitor implem descriptor = originalIfSamAdapter; } // $default method is not private, so you need no accessor to call it - return usesDefaultArguments(resolvedCall) ? descriptor : context.accessibleDescriptor(descriptor); + return usesDefaultArguments(resolvedCall) + ? descriptor + : context.accessibleDescriptor(descriptor, CallResolverUtilPackage.getSuperCallExpression(resolvedCall.getCall())); } private static boolean usesDefaultArguments(@NotNull ResolvedCall resolvedCall) { @@ -2355,11 +2359,11 @@ public class ExpressionCodegen extends JetVisitor implem boolean superCall = superCallExpression != null; if (superCall && !isInterface(fd.getContainingDeclaration())) { - ClassDescriptor owner = getSuperCallLabelTarget(superCallExpression); + ClassDescriptor owner = getSuperCallLabelTarget(context, superCallExpression); CodegenContext c = context.findParentContextWithDescriptor(owner); assert c != null : "Couldn't find a context for a super-call: " + fd; if (c != context.getParentContext()) { - fd = (FunctionDescriptor) c.getAccessor(fd); + fd = (FunctionDescriptor) c.getAccessor(fd, superCallExpression); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index adbf3bd4a0a..a958cdd3952 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -210,7 +210,7 @@ public class FunctionCodegen { mv.visitCode(); FunctionDescriptor staticFunctionDescriptor = PlatformStaticGenerator.createStaticFunctionDescriptor(functionDescriptor); JvmMethodSignature jvmMethodSignature = - typeMapper.mapSignature(memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor)); + typeMapper.mapSignature(memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor, null)); Type owningType = typeMapper.mapClass((ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration()); generateDelegateToMethodBody(false, mv, jvmMethodSignature.getAsmMethod(), owningType.getInternalName()); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 0e7cd2ece5b..1f8fdea3d48 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -857,32 +857,31 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } protected void generateSyntheticAccessors() { - Map accessors = ((CodegenContext) context).getAccessors(); - for (Map.Entry entry : accessors.entrySet()) { - generateSyntheticAccessor(entry); + for (AccessorForCallableDescriptor accessor : ((CodegenContext) context).getAccessors()) { + generateSyntheticAccessor(accessor); } } - private void generateSyntheticAccessor(Map.Entry entry) { - if (entry.getValue() instanceof FunctionDescriptor) { - final FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue(); - final FunctionDescriptor original = (FunctionDescriptor) entry.getKey(); + private void generateSyntheticAccessor(@NotNull AccessorForCallableDescriptor accessorForCallableDescriptor) { + if (accessorForCallableDescriptor instanceof FunctionDescriptor) { + final FunctionDescriptor accessor = (FunctionDescriptor) accessorForCallableDescriptor; + final FunctionDescriptor original = (FunctionDescriptor) accessorForCallableDescriptor.getCalleeDescriptor(); functionCodegen.generateMethod( - Synthetic(null, original), bridge, - new FunctionGenerationStrategy.CodegenBased(state, bridge) { + Synthetic(null, original), accessor, + new FunctionGenerationStrategy.CodegenBased(state, accessor) { @Override public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { markLineNumberForSyntheticFunction(descriptor, codegen.v); - generateMethodCallTo(original, bridge, codegen.v); + generateMethodCallTo(original, accessor, codegen.v); codegen.v.areturn(signature.getReturnType()); } } ); } - else if (entry.getValue() instanceof PropertyDescriptor) { - final PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue(); - final PropertyDescriptor original = (PropertyDescriptor) entry.getKey(); + else if (accessorForCallableDescriptor instanceof AccessorForPropertyDescriptor) { + final AccessorForPropertyDescriptor accessor = (AccessorForPropertyDescriptor) accessorForCallableDescriptor; + final PropertyDescriptor original = accessor.getCalleeDescriptor(); class PropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased { public PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) { @@ -892,10 +891,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { @Override public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && - !isCompanionObject(bridge.getContainingDeclaration()); - StackValue property = - codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR, - StackValue.none()); + !isCompanionObject(accessor.getContainingDeclaration()); + StackValue property = codegen.intermediateValueForProperty( + original, forceField, accessor.getSuperCallExpression(), true, StackValue.none() + ); InstructionAdapter iv = codegen.v; @@ -920,14 +919,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - PropertyGetterDescriptor getter = bridge.getGetter(); + PropertyGetterDescriptor getter = accessor.getGetter(); assert getter != null; functionCodegen.generateMethod(Synthetic(null, original.getGetter() != null ? original.getGetter() : original), getter, new PropertyAccessorStrategy(getter)); - if (bridge.isVar()) { - PropertySetterDescriptor setter = bridge.getSetter(); + if (accessor.isVar()) { + PropertySetterDescriptor setter = accessor.getSetter(); assert setter != null; functionCodegen.generateMethod(Synthetic(null, original.getSetter() != null ? original.getSetter() : original), @@ -957,24 +956,25 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { private void generateMethodCallTo( @NotNull FunctionDescriptor functionDescriptor, - @Nullable FunctionDescriptor bridgeDescriptor, + @Nullable FunctionDescriptor accessorDescriptor, @NotNull InstructionAdapter iv ) { boolean isConstructor = functionDescriptor instanceof ConstructorDescriptor; - boolean bridgeIsAccessorConstructor = bridgeDescriptor instanceof AccessorForConstructorDescriptor; - boolean callFromAccessor = bridgeIsAccessorConstructor - || (bridgeDescriptor != null && JetTypeMapper.isAccessor(bridgeDescriptor)); + boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor; + + boolean superCall = accessorDescriptor instanceof AccessorForCallableDescriptor && + ((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallExpression() != null; CallableMethod callableMethod = isConstructor ? typeMapper.mapToCallableMethod((ConstructorDescriptor) functionDescriptor) : - typeMapper.mapToCallableMethod(functionDescriptor, callFromAccessor, context); + typeMapper.mapToCallableMethod(functionDescriptor, superCall, context); int reg = 1; - if (isConstructor && !bridgeIsAccessorConstructor) { + if (isConstructor && !accessorIsConstructor) { iv.anew(callableMethod.getOwner()); iv.dup(); reg = 0; } - else if (callFromAccessor) { + else if (accessorIsConstructor || (accessorDescriptor != null && JetTypeMapper.isAccessor(accessorDescriptor))) { if (!AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor)) { iv.load(0, OBJECT_TYPE); } @@ -989,6 +989,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { reg += argType.getSize(); } } + callableMethod.genInvokeInstruction(iv); } @@ -1074,8 +1075,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { private void generateCompanionObjectInitializer(@NotNull ClassDescriptor companionObject) { ExpressionCodegen codegen = createOrGetClInitCodegen(); - FunctionDescriptor constructor = - (FunctionDescriptor) context.accessibleDescriptor(KotlinPackage.single(companionObject.getConstructors())); + FunctionDescriptor constructor = (FunctionDescriptor) context.accessibleDescriptor( + KotlinPackage.single(companionObject.getConstructors()), /* superCallExpression = */ null + ); generateMethodCallTo(constructor, null, codegen.v); codegen.v.dup(); StackValue instance = StackValue.onStack(typeMapper.mapClass(companionObject)); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 8d915a7c4f9..58780d947f4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -360,8 +360,7 @@ public abstract class MemberCodegen { + private val typeMapper = state.typeMapper override fun invoke(codegen: ImplementationBodyCodegen, classBuilder: ClassBuilder) { val staticFunctionDescriptor = createStaticFunctionDescriptor(descriptor) @@ -51,40 +50,37 @@ class PlatformStaticGenerator( frameMap: FrameMap, signature: JvmMethodSignature, context: MethodContext, - parentCodegen: MemberCodegen + parentCodegen: MemberCodegen<*> ) { - val typeMapper = parentCodegen.typeMapper - val iv = InstructionAdapter(mv) - val classDescriptor = descriptor.getContainingDeclaration() as ClassDescriptor + val classDescriptor = descriptor.containingDeclaration as ClassDescriptor val singletonValue = StackValue.singleton(classDescriptor, typeMapper) - singletonValue.put(singletonValue.type, iv); - var index = 0; - val asmMethod = signature.getAsmMethod() - for (paramType in asmMethod.getArgumentTypes()) { - iv.load(index, paramType); - index += paramType.getSize(); + singletonValue.put(singletonValue.type, iv) + var index = 0 + val asmMethod = signature.asmMethod + for (paramType in asmMethod.argumentTypes) { + iv.load(index, paramType) + index += paramType.size } val syntheticOrOriginalMethod = typeMapper.mapToCallableMethod( - codegen.getContext().accessibleDescriptor(descriptor), + codegen.getContext().accessibleDescriptor(descriptor, /* superCallExpression = */ null), false, codegen.getContext() ) syntheticOrOriginalMethod.genInvokeInstruction(iv) - iv.areturn(asmMethod.getReturnType()); + iv.areturn(asmMethod.returnType) } } ) - if (originElement is JetNamedFunction) { codegen.functionCodegen.generateOverloadsWithDefaultValues(originElement, staticFunctionDescriptor, descriptor) } } companion object { - @platformStatic + @JvmStatic public fun createStaticFunctionDescriptor(descriptor: FunctionDescriptor): FunctionDescriptor { val memberDescriptor = if (descriptor is PropertyAccessorDescriptor) descriptor.getCorrespondingProperty() else descriptor val copies = CodegenUtil.copyFunctions( diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/CodegenContext.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/CodegenContext.java index 1be0d8fa702..ed827d3fe16 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/CodegenContext.java @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.binding.MutableClosure; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.psi.JetSuperExpression; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.storage.LockBasedStorageManager; @@ -47,8 +48,38 @@ public abstract class CodegenContext { private final LocalLookup enclosingLocalLookup; private final NullableLazyValue outerExpression; - private Map accessors; private Map childContexts; + private Map> accessors; + + private static class AccessorKey { + public final DeclarationDescriptor descriptor; + public final ClassDescriptor superCallLabelTarget; + + public AccessorKey(@NotNull DeclarationDescriptor descriptor, @Nullable ClassDescriptor superCallLabelTarget) { + this.descriptor = descriptor; + this.superCallLabelTarget = superCallLabelTarget; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof AccessorKey)) return false; + AccessorKey other = (AccessorKey) obj; + return descriptor.equals(other.descriptor) && + (superCallLabelTarget == null + ? other.superCallLabelTarget == null + : superCallLabelTarget.equals(other.superCallLabelTarget)); + } + + @Override + public int hashCode() { + return 31 * descriptor.hashCode() + (superCallLabelTarget == null ? 0 : superCallLabelTarget.hashCode()); + } + + @Override + public String toString() { + return descriptor.toString(); + } + } public CodegenContext( @NotNull T contextDescriptor, @@ -227,20 +258,28 @@ public abstract class CodegenContext { } @NotNull - public D getAccessor(@NotNull D descriptor) { - return getAccessor(descriptor, false, null); + public D getAccessor(@NotNull D descriptor, @Nullable JetSuperExpression superCallExpression) { + return getAccessor(descriptor, false, null, superCallExpression); } @SuppressWarnings("unchecked") @NotNull public D getAccessor( - @NotNull D descriptor, boolean isForBackingFieldInOuterClass, @Nullable JetType delegateType + @NotNull D possiblySubstitutedDescriptor, + boolean isForBackingFieldInOuterClass, + @Nullable JetType delegateType, + @Nullable JetSuperExpression superCallExpression ) { if (accessors == null) { - accessors = new LinkedHashMap(); + accessors = new LinkedHashMap>(); } - descriptor = (D) descriptor.getOriginal(); - DeclarationDescriptor accessor = accessors.get(descriptor); + + D descriptor = (D) possiblySubstitutedDescriptor.getOriginal(); + AccessorKey key = new AccessorKey( + descriptor, superCallExpression == null ? null : ExpressionCodegen.getSuperCallLabelTarget(this, superCallExpression) + ); + + AccessorForCallableDescriptor accessor = accessors.get(key); if (accessor != null) { assert !isForBackingFieldInOuterClass || accessor instanceof AccessorForPropertyBackingFieldInOuterClass : "There is already exists accessor with isForBackingFieldInOuterClass = false in this context"; @@ -249,10 +288,12 @@ public abstract class CodegenContext { int accessorIndex = accessors.size(); if (descriptor instanceof SimpleFunctionDescriptor) { - accessor = new AccessorForFunctionDescriptor((FunctionDescriptor) descriptor, contextDescriptor, accessorIndex); + accessor = new AccessorForFunctionDescriptor( + (FunctionDescriptor) descriptor, contextDescriptor, accessorIndex, superCallExpression + ); } else if (descriptor instanceof ConstructorDescriptor) { - accessor = new AccessorForConstructorDescriptor((ConstructorDescriptor) descriptor, contextDescriptor); + accessor = new AccessorForConstructorDescriptor((ConstructorDescriptor) descriptor, contextDescriptor, superCallExpression); } else if (descriptor instanceof PropertyDescriptor) { if (isForBackingFieldInOuterClass) { @@ -260,13 +301,16 @@ public abstract class CodegenContext { accessorIndex, delegateType); } else { - accessor = new AccessorForPropertyDescriptor((PropertyDescriptor) descriptor, contextDescriptor, accessorIndex); + accessor = new AccessorForPropertyDescriptor((PropertyDescriptor) descriptor, contextDescriptor, + accessorIndex, superCallExpression); } } else { throw new UnsupportedOperationException("Do not know how to create accessor for descriptor " + descriptor); } - accessors.put(descriptor, accessor); + + accessors.put(key, accessor); + return (D) accessor; } @@ -314,25 +358,29 @@ public abstract class CodegenContext { } @NotNull - public Map getAccessors() { - return accessors == null ? Collections.emptyMap() : accessors; + public Collection> getAccessors() { + return accessors == null ? Collections.>emptySet() : accessors.values(); } @NotNull - public D accessibleDescriptor(D descriptor) { + public D accessibleDescriptor( + @NotNull D descriptor, + @Nullable JetSuperExpression superCallExpression + ) { DeclarationDescriptor enclosing = descriptor.getContainingDeclaration(); if (!hasThisDescriptor() || enclosing == getThisDescriptor() || enclosing == getClassOrPackageParentContext().getContextDescriptor()) { return descriptor; } - return accessibleDescriptorIfNeeded(descriptor); + return accessibleDescriptorIfNeeded(descriptor, superCallExpression); } public void recordSyntheticAccessorIfNeeded(@NotNull CallableMemberDescriptor descriptor, @NotNull BindingContext bindingContext) { if (hasThisDescriptor() && (descriptor instanceof ConstructorDescriptor || Boolean.TRUE.equals(bindingContext.get(NEED_SYNTHETIC_ACCESSOR, descriptor)))) { - accessibleDescriptorIfNeeded(descriptor); + // Not a super call because neither constructors nor private members can be targets of super calls + accessibleDescriptorIfNeeded(descriptor, /* superCallExpression = */ null); } } @@ -352,7 +400,10 @@ public abstract class CodegenContext { @SuppressWarnings("unchecked") @NotNull - private D accessibleDescriptorIfNeeded(@NotNull D descriptor) { + private D accessibleDescriptorIfNeeded( + @NotNull D descriptor, + @Nullable JetSuperExpression superCallExpression + ) { CallableMemberDescriptor unwrappedDescriptor = DescriptorUtils.unwrapFakeOverride(descriptor); int flag = getAccessFlags(unwrappedDescriptor); if ((flag & ACC_PRIVATE) == 0 && (flag & ACC_PROTECTED) == 0) { @@ -385,7 +436,7 @@ public abstract class CodegenContext { } } - return (D) descriptorContext.getAccessor(descriptor); + return (D) descriptorContext.getAccessor(descriptor, superCallExpression); } private void addChild(@NotNull CodegenContext child) { diff --git a/compiler/testData/codegen/boxMultiFile/accessorForProtectedInvokeVirtual/1.kt b/compiler/testData/codegen/boxMultiFile/accessorForProtectedInvokeVirtual/1.kt new file mode 100644 index 00000000000..3fabc5a4bdd --- /dev/null +++ b/compiler/testData/codegen/boxMultiFile/accessorForProtectedInvokeVirtual/1.kt @@ -0,0 +1,49 @@ +import test.A +import kotlin.test.assertEquals + +open class B : A() { + fun box(): String { + val overriddenMethod: () -> String = { + method() + } + assertEquals("C.method", overriddenMethod()) + + val superMethod: () -> String = { + super.method() + } + assertEquals("A.method", superMethod()) + + val overriddenPropertyGetter: () -> String = { + property + } + assertEquals("C.property", overriddenPropertyGetter()) + + val superPropertyGetter: () -> String = { + super.property + } + assertEquals("A.property", superPropertyGetter()) + + val overriddenPropertySetter: () -> Unit = { + property = "" + } + overriddenPropertySetter() + + val superPropertySetter: () -> Unit = { + super.property = "" + } + superPropertySetter() + + assertEquals("C.property;A.property;", state) + + return "OK" + } +} + +class C : B() { + override fun method() = "C.method" + override var property: String + get() = "C.property" + set(value) { state += "C.property;" } +} + +fun box() = C().box() diff --git a/compiler/testData/codegen/boxMultiFile/accessorForProtectedInvokeVirtual/2.kt b/compiler/testData/codegen/boxMultiFile/accessorForProtectedInvokeVirtual/2.kt new file mode 100644 index 00000000000..59cb2e4deb1 --- /dev/null +++ b/compiler/testData/codegen/boxMultiFile/accessorForProtectedInvokeVirtual/2.kt @@ -0,0 +1,13 @@ +package test + +abstract class A { + public var state = "" + + // These implementations should not be called, because they are overridden in C + + protected open fun method(): String = "A.method" + + protected open var property: String + get() = "A.property" + set(value) { state += "A.property;" } +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxMultiFileCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxMultiFileCodegenTestGenerated.java index 0d712b66e03..8e55d8224af 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxMultiFileCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxMultiFileCodegenTestGenerated.java @@ -37,6 +37,12 @@ public class BlackBoxMultiFileCodegenTestGenerated extends AbstractBlackBoxCodeg doTestMultiFile(fileName); } + @TestMetadata("accessorForProtectedInvokeVirtual") + public void testAccessorForProtectedInvokeVirtual() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultiFile/accessorForProtectedInvokeVirtual/"); + doTestMultiFile(fileName); + } + public void testAllFilesPresentInBoxMultiFile() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxMultiFile"), Pattern.compile("^([^\\.]+)$"), false); }