Fix protected call to super method from lambda
Previously JVM back-end had an assumption that if we're calling a method declared in the super class from a lambda via a synthetic accessor, that should be a super call and it must be done with 'invokespecial'. Which is wrong because a method declared in the super class may be open and overridden in the subclass, so 'invokevirtual' should be used. Surprisingly, Java SE verifier allowed both instructions, but on Android only the latter is possible #KT-8899 Fixed #KT-9052 Fixed
This commit is contained in:
@@ -17,9 +17,14 @@
|
|||||||
package org.jetbrains.kotlin.codegen;
|
package org.jetbrains.kotlin.codegen;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
||||||
|
import org.jetbrains.kotlin.psi.JetSuperExpression;
|
||||||
|
|
||||||
public interface AccessorForCallableDescriptor<T extends CallableMemberDescriptor> {
|
public interface AccessorForCallableDescriptor<T extends CallableMemberDescriptor> {
|
||||||
@NotNull
|
@NotNull
|
||||||
T getCalleeDescriptor();
|
T getCalleeDescriptor();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
JetSuperExpression getSuperCallExpression();
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-15
@@ -17,37 +17,35 @@
|
|||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
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.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.JetSuperExpression
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
public class AccessorForConstructorDescriptor(
|
public class AccessorForConstructorDescriptor(
|
||||||
private val calleeDescriptor: ConstructorDescriptor,
|
private val calleeDescriptor: ConstructorDescriptor,
|
||||||
containingDeclaration: DeclarationDescriptor
|
containingDeclaration: DeclarationDescriptor,
|
||||||
) : AbstractAccessorForFunctionDescriptor(containingDeclaration, Name.special("<init>"))
|
private val superCallExpression: JetSuperExpression?
|
||||||
, ConstructorDescriptor
|
) : AbstractAccessorForFunctionDescriptor(containingDeclaration, Name.special("<init>")),
|
||||||
, AccessorForCallableDescriptor<ConstructorDescriptor> {
|
ConstructorDescriptor,
|
||||||
|
AccessorForCallableDescriptor<ConstructorDescriptor> {
|
||||||
override fun getCalleeDescriptor(): ConstructorDescriptor = calleeDescriptor
|
override fun getCalleeDescriptor(): ConstructorDescriptor = calleeDescriptor
|
||||||
|
|
||||||
override fun getContainingDeclaration(): ClassDescriptor = calleeDescriptor.getContainingDeclaration()
|
override fun getContainingDeclaration(): ClassDescriptor = calleeDescriptor.containingDeclaration
|
||||||
|
|
||||||
override fun isPrimary(): Boolean = false
|
override fun isPrimary(): Boolean = false
|
||||||
|
|
||||||
override fun getReturnType(): JetType = super<AbstractAccessorForFunctionDescriptor>.getReturnType()!!
|
override fun getReturnType(): JetType = super.getReturnType()!!
|
||||||
|
|
||||||
|
override fun getSuperCallExpression(): JetSuperExpression? = superCallExpression
|
||||||
|
|
||||||
init {
|
init {
|
||||||
initialize(
|
initialize(
|
||||||
DescriptorUtils.getReceiverParameterType(getExtensionReceiverParameter()),
|
DescriptorUtils.getReceiverParameterType(extensionReceiverParameter),
|
||||||
calleeDescriptor.getDispatchReceiverParameter(),
|
calleeDescriptor.dispatchReceiverParameter,
|
||||||
copyTypeParameters(calleeDescriptor),
|
copyTypeParameters(calleeDescriptor),
|
||||||
copyValueParameters(calleeDescriptor),
|
copyValueParameters(calleeDescriptor),
|
||||||
calleeDescriptor.getReturnType(),
|
calleeDescriptor.returnType,
|
||||||
Modality.FINAL,
|
Modality.FINAL,
|
||||||
Visibilities.INTERNAL
|
Visibilities.INTERNAL
|
||||||
)
|
)
|
||||||
|
|||||||
+11
-2
@@ -17,23 +17,27 @@
|
|||||||
package org.jetbrains.kotlin.codegen;
|
package org.jetbrains.kotlin.codegen;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
|
import org.jetbrains.kotlin.psi.JetSuperExpression;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage;
|
import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage;
|
||||||
|
|
||||||
public class AccessorForFunctionDescriptor extends AbstractAccessorForFunctionDescriptor implements AccessorForCallableDescriptor<FunctionDescriptor> {
|
public class AccessorForFunctionDescriptor extends AbstractAccessorForFunctionDescriptor implements AccessorForCallableDescriptor<FunctionDescriptor> {
|
||||||
|
|
||||||
private final FunctionDescriptor calleeDescriptor;
|
private final FunctionDescriptor calleeDescriptor;
|
||||||
|
private final JetSuperExpression superCallExpression;
|
||||||
|
|
||||||
public AccessorForFunctionDescriptor(
|
public AccessorForFunctionDescriptor(
|
||||||
@NotNull FunctionDescriptor descriptor,
|
@NotNull FunctionDescriptor descriptor,
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor containingDeclaration,
|
||||||
int index
|
int index,
|
||||||
|
@Nullable JetSuperExpression superCallExpression
|
||||||
) {
|
) {
|
||||||
super(containingDeclaration,
|
super(containingDeclaration,
|
||||||
Name.identifier("access$" + (descriptor instanceof ConstructorDescriptor ? "init" : descriptor.getName()) + "$" + index));
|
Name.identifier("access$" + (descriptor instanceof ConstructorDescriptor ? "init" : descriptor.getName()) + "$" + index));
|
||||||
this.calleeDescriptor = descriptor;
|
this.calleeDescriptor = descriptor;
|
||||||
|
this.superCallExpression = superCallExpression;
|
||||||
|
|
||||||
initialize(DescriptorUtils.getReceiverParameterType(descriptor.getExtensionReceiverParameter()),
|
initialize(DescriptorUtils.getReceiverParameterType(descriptor.getExtensionReceiverParameter()),
|
||||||
descriptor instanceof ConstructorDescriptor || AnnotationsPackage.isPlatformStaticInObjectOrClass(descriptor)
|
descriptor instanceof ConstructorDescriptor || AnnotationsPackage.isPlatformStaticInObjectOrClass(descriptor)
|
||||||
@@ -51,4 +55,9 @@ public class AccessorForFunctionDescriptor extends AbstractAccessorForFunctionDe
|
|||||||
public FunctionDescriptor getCalleeDescriptor() {
|
public FunctionDescriptor getCalleeDescriptor() {
|
||||||
return calleeDescriptor;
|
return calleeDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetSuperExpression getSuperCallExpression() {
|
||||||
|
return superCallExpression;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -23,13 +23,12 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
|||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
|
|
||||||
public class AccessorForPropertyBackingFieldInOuterClass extends AccessorForPropertyDescriptor {
|
public class AccessorForPropertyBackingFieldInOuterClass extends AccessorForPropertyDescriptor {
|
||||||
|
|
||||||
public AccessorForPropertyBackingFieldInOuterClass(
|
public AccessorForPropertyBackingFieldInOuterClass(
|
||||||
@NotNull PropertyDescriptor pd,
|
@NotNull PropertyDescriptor property,
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor containingDeclaration,
|
||||||
int index,
|
int index,
|
||||||
@Nullable JetType delegationType
|
@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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-3
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl;
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl;
|
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl;
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
|
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
|
import org.jetbrains.kotlin.psi.JetSuperExpression;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
|
|
||||||
@@ -33,9 +34,16 @@ import java.util.Collections;
|
|||||||
public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implements AccessorForCallableDescriptor<PropertyDescriptor> {
|
public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implements AccessorForCallableDescriptor<PropertyDescriptor> {
|
||||||
private final PropertyDescriptor calleeDescriptor;
|
private final PropertyDescriptor calleeDescriptor;
|
||||||
private final int accessorIndex;
|
private final int accessorIndex;
|
||||||
|
private final JetSuperExpression superCallExpression;
|
||||||
|
|
||||||
public AccessorForPropertyDescriptor(@NotNull PropertyDescriptor pd, @NotNull DeclarationDescriptor containingDeclaration, int index) {
|
public AccessorForPropertyDescriptor(
|
||||||
this(pd, pd.getType(), DescriptorUtils.getReceiverParameterType(pd.getExtensionReceiverParameter()), pd.getDispatchReceiverParameter(), containingDeclaration, index);
|
@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(
|
protected AccessorForPropertyDescriptor(
|
||||||
@@ -44,7 +52,8 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem
|
|||||||
@Nullable JetType receiverType,
|
@Nullable JetType receiverType,
|
||||||
@Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
|
@Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor containingDeclaration,
|
||||||
int index
|
int index,
|
||||||
|
@Nullable JetSuperExpression superCallExpression
|
||||||
) {
|
) {
|
||||||
super(containingDeclaration, null, Annotations.EMPTY, Modality.FINAL, Visibilities.LOCAL,
|
super(containingDeclaration, null, Annotations.EMPTY, Modality.FINAL, Visibilities.LOCAL,
|
||||||
original.isVar(), Name.identifier("access$" + getIndexedAccessorSuffix(original, index)),
|
original.isVar(), Name.identifier("access$" + getIndexedAccessorSuffix(original, index)),
|
||||||
@@ -52,6 +61,7 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem
|
|||||||
|
|
||||||
this.calleeDescriptor = original;
|
this.calleeDescriptor = original;
|
||||||
this.accessorIndex = index;
|
this.accessorIndex = index;
|
||||||
|
this.superCallExpression = superCallExpression;
|
||||||
setType(propertyType, Collections.<TypeParameterDescriptorImpl>emptyList(), dispatchReceiverParameter, receiverType);
|
setType(propertyType, Collections.<TypeParameterDescriptorImpl>emptyList(), dispatchReceiverParameter, receiverType);
|
||||||
initialize(new Getter(this), new Setter(this));
|
initialize(new Getter(this), new Setter(this));
|
||||||
}
|
}
|
||||||
@@ -69,6 +79,12 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem
|
|||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getCalleeDescriptor().getGetter();
|
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getCalleeDescriptor().getGetter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public JetSuperExpression getSuperCallExpression() {
|
||||||
|
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getSuperCallExpression();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Setter extends PropertySetterDescriptorImpl implements AccessorForCallableDescriptor<PropertySetterDescriptor>{
|
public static class Setter extends PropertySetterDescriptorImpl implements AccessorForCallableDescriptor<PropertySetterDescriptor>{
|
||||||
@@ -84,6 +100,12 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem
|
|||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getCalleeDescriptor().getSetter();
|
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getCalleeDescriptor().getSetter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public JetSuperExpression getSuperCallExpression() {
|
||||||
|
return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getSuperCallExpression();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -92,6 +114,11 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implem
|
|||||||
return calleeDescriptor;
|
return calleeDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetSuperExpression getSuperCallExpression() {
|
||||||
|
return superCallExpression;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public String getIndexedAccessorSuffix() {
|
public String getIndexedAccessorSuffix() {
|
||||||
return getIndexedAccessorSuffix(calleeDescriptor, accessorIndex);
|
return getIndexedAccessorSuffix(calleeDescriptor, accessorIndex);
|
||||||
|
|||||||
@@ -356,11 +356,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue visitSuperExpression(@NotNull JetSuperExpression expression, StackValue data) {
|
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
|
@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());
|
PsiElement labelPsi = bindingContext.get(LABEL_TARGET, expression.getTargetLabel());
|
||||||
ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, labelPsi);
|
ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, labelPsi);
|
||||||
DeclarationDescriptor descriptor = bindingContext.get(REFERENCE_TARGET, expression.getInstanceReference());
|
DeclarationDescriptor descriptor = bindingContext.get(REFERENCE_TARGET, expression.getInstanceReference());
|
||||||
@@ -2007,7 +2011,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL;
|
expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL;
|
||||||
JetSuperExpression superExpression =
|
JetSuperExpression superExpression =
|
||||||
resolvedCall == null ? null : CallResolverUtilPackage.getSuperCallExpression(resolvedCall.getCall());
|
resolvedCall == null ? null : CallResolverUtilPackage.getSuperCallExpression(resolvedCall.getCall());
|
||||||
propertyDescriptor = context.accessibleDescriptor(propertyDescriptor);
|
propertyDescriptor = context.accessibleDescriptor(propertyDescriptor, superExpression);
|
||||||
|
|
||||||
if (directToField) {
|
if (directToField) {
|
||||||
receiver = StackValue.receiverWithoutReceiverArgument(receiver);
|
receiver = StackValue.receiverWithoutReceiverArgument(receiver);
|
||||||
@@ -2137,14 +2141,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
@Nullable JetSuperExpression superExpression,
|
@Nullable JetSuperExpression superExpression,
|
||||||
@NotNull StackValue receiver
|
@NotNull StackValue receiver
|
||||||
) {
|
) {
|
||||||
return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, MethodKind.GENERAL, receiver);
|
return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, false, receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackValue.Property intermediateValueForProperty(
|
public StackValue.Property intermediateValueForProperty(
|
||||||
@NotNull PropertyDescriptor propertyDescriptor,
|
@NotNull PropertyDescriptor propertyDescriptor,
|
||||||
boolean forceField,
|
boolean forceField,
|
||||||
@Nullable JetSuperExpression superExpression,
|
@Nullable JetSuperExpression superExpression,
|
||||||
@NotNull MethodKind methodKind,
|
boolean skipAccessorsForPrivateFieldInOuterClass,
|
||||||
StackValue receiver
|
StackValue receiver
|
||||||
) {
|
) {
|
||||||
if (propertyDescriptor instanceof SyntheticJavaPropertyDescriptor) {
|
if (propertyDescriptor instanceof SyntheticJavaPropertyDescriptor) {
|
||||||
@@ -2165,56 +2169,54 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
CallableMethod callableGetter = null;
|
CallableMethod callableGetter = null;
|
||||||
CallableMethod callableSetter = null;
|
CallableMethod callableSetter = null;
|
||||||
|
|
||||||
boolean skipPropertyAccessors = forceField && !isBackingFieldInAnotherClass;
|
CodegenContext backingFieldContext;
|
||||||
|
boolean changeOwnerOnTypeMapping;
|
||||||
CodegenContext backingFieldContext = context.getParentContext();
|
boolean skipPropertyAccessors;
|
||||||
boolean changeOwnerOnTypeMapping = isBackingFieldInAnotherClass;
|
|
||||||
|
|
||||||
if (isBackingFieldInAnotherClass && forceField) {
|
if (isBackingFieldInAnotherClass && forceField) {
|
||||||
backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration());
|
backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration());
|
||||||
int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty);
|
int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty);
|
||||||
skipPropertyAccessors =
|
skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || skipAccessorsForPrivateFieldInOuterClass;
|
||||||
(flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER;
|
|
||||||
if (!skipPropertyAccessors) {
|
if (!skipPropertyAccessors) {
|
||||||
propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(propertyDescriptor, true, delegateType);
|
//noinspection ConstantConditions
|
||||||
changeOwnerOnTypeMapping =
|
propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(
|
||||||
changeOwnerOnTypeMapping && !(propertyDescriptor instanceof AccessorForPropertyBackingFieldInOuterClass);
|
propertyDescriptor, true, delegateType, superExpression
|
||||||
|
);
|
||||||
|
changeOwnerOnTypeMapping = !(propertyDescriptor instanceof AccessorForPropertyBackingFieldInOuterClass);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
changeOwnerOnTypeMapping = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
backingFieldContext = context.getParentContext();
|
||||||
|
changeOwnerOnTypeMapping = isBackingFieldInAnotherClass;
|
||||||
|
skipPropertyAccessors = forceField;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skipPropertyAccessors) {
|
if (!skipPropertyAccessors) {
|
||||||
if (couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context)) {
|
if (!couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context)) {
|
||||||
callableGetter = null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (isSuper && !isInterface(containingDeclaration)) {
|
if (isSuper && !isInterface(containingDeclaration)) {
|
||||||
ClassDescriptor owner = getSuperCallLabelTarget(superExpression);
|
ClassDescriptor owner = getSuperCallLabelTarget(context, superExpression);
|
||||||
CodegenContext c = context.findParentContextWithDescriptor(owner);
|
CodegenContext c = context.findParentContextWithDescriptor(owner);
|
||||||
assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor;
|
assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor;
|
||||||
if (c != context.getParentContext()) {
|
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();
|
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
|
||||||
if (getter != null) {
|
if (getter != null) {
|
||||||
callableGetter =
|
callableGetter = typeMapper.mapToCallableMethod(getter, isSuper, context);
|
||||||
typeMapper.mapToCallableMethod(getter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (propertyDescriptor.isVar()) {
|
if (propertyDescriptor.isVar()) {
|
||||||
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
|
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
|
||||||
if (setter != null) {
|
if (setter != null && !couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context)) {
|
||||||
if (couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context)) {
|
callableSetter = typeMapper.mapToCallableMethod(setter, isSuper, context);
|
||||||
callableSetter = null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callableSetter =
|
|
||||||
typeMapper.mapToCallableMethod(setter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2329,7 +2331,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
descriptor = originalIfSamAdapter;
|
descriptor = originalIfSamAdapter;
|
||||||
}
|
}
|
||||||
// $default method is not private, so you need no accessor to call it
|
// $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) {
|
private static boolean usesDefaultArguments(@NotNull ResolvedCall<?> resolvedCall) {
|
||||||
@@ -2355,11 +2359,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
boolean superCall = superCallExpression != null;
|
boolean superCall = superCallExpression != null;
|
||||||
|
|
||||||
if (superCall && !isInterface(fd.getContainingDeclaration())) {
|
if (superCall && !isInterface(fd.getContainingDeclaration())) {
|
||||||
ClassDescriptor owner = getSuperCallLabelTarget(superCallExpression);
|
ClassDescriptor owner = getSuperCallLabelTarget(context, superCallExpression);
|
||||||
CodegenContext c = context.findParentContextWithDescriptor(owner);
|
CodegenContext c = context.findParentContextWithDescriptor(owner);
|
||||||
assert c != null : "Couldn't find a context for a super-call: " + fd;
|
assert c != null : "Couldn't find a context for a super-call: " + fd;
|
||||||
if (c != context.getParentContext()) {
|
if (c != context.getParentContext()) {
|
||||||
fd = (FunctionDescriptor) c.getAccessor(fd);
|
fd = (FunctionDescriptor) c.getAccessor(fd, superCallExpression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ public class FunctionCodegen {
|
|||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
FunctionDescriptor staticFunctionDescriptor = PlatformStaticGenerator.createStaticFunctionDescriptor(functionDescriptor);
|
FunctionDescriptor staticFunctionDescriptor = PlatformStaticGenerator.createStaticFunctionDescriptor(functionDescriptor);
|
||||||
JvmMethodSignature jvmMethodSignature =
|
JvmMethodSignature jvmMethodSignature =
|
||||||
typeMapper.mapSignature(memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor));
|
typeMapper.mapSignature(memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor, null));
|
||||||
Type owningType = typeMapper.mapClass((ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration());
|
Type owningType = typeMapper.mapClass((ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration());
|
||||||
generateDelegateToMethodBody(false, mv, jvmMethodSignature.getAsmMethod(), owningType.getInternalName());
|
generateDelegateToMethodBody(false, mv, jvmMethodSignature.getAsmMethod(), owningType.getInternalName());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -857,32 +857,31 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void generateSyntheticAccessors() {
|
protected void generateSyntheticAccessors() {
|
||||||
Map<DeclarationDescriptor, DeclarationDescriptor> accessors = ((CodegenContext<?>) context).getAccessors();
|
for (AccessorForCallableDescriptor<?> accessor : ((CodegenContext<?>) context).getAccessors()) {
|
||||||
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) {
|
generateSyntheticAccessor(accessor);
|
||||||
generateSyntheticAccessor(entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateSyntheticAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) {
|
private void generateSyntheticAccessor(@NotNull AccessorForCallableDescriptor<?> accessorForCallableDescriptor) {
|
||||||
if (entry.getValue() instanceof FunctionDescriptor) {
|
if (accessorForCallableDescriptor instanceof FunctionDescriptor) {
|
||||||
final FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
|
final FunctionDescriptor accessor = (FunctionDescriptor) accessorForCallableDescriptor;
|
||||||
final FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
|
final FunctionDescriptor original = (FunctionDescriptor) accessorForCallableDescriptor.getCalleeDescriptor();
|
||||||
functionCodegen.generateMethod(
|
functionCodegen.generateMethod(
|
||||||
Synthetic(null, original), bridge,
|
Synthetic(null, original), accessor,
|
||||||
new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, bridge) {
|
new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, accessor) {
|
||||||
@Override
|
@Override
|
||||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||||
markLineNumberForSyntheticFunction(descriptor, codegen.v);
|
markLineNumberForSyntheticFunction(descriptor, codegen.v);
|
||||||
|
|
||||||
generateMethodCallTo(original, bridge, codegen.v);
|
generateMethodCallTo(original, accessor, codegen.v);
|
||||||
codegen.v.areturn(signature.getReturnType());
|
codegen.v.areturn(signature.getReturnType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (entry.getValue() instanceof PropertyDescriptor) {
|
else if (accessorForCallableDescriptor instanceof AccessorForPropertyDescriptor) {
|
||||||
final PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
|
final AccessorForPropertyDescriptor accessor = (AccessorForPropertyDescriptor) accessorForCallableDescriptor;
|
||||||
final PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
|
final PropertyDescriptor original = accessor.getCalleeDescriptor();
|
||||||
|
|
||||||
class PropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> {
|
class PropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> {
|
||||||
public PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) {
|
public PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) {
|
||||||
@@ -892,10 +891,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
@Override
|
@Override
|
||||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||||
boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) &&
|
boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) &&
|
||||||
!isCompanionObject(bridge.getContainingDeclaration());
|
!isCompanionObject(accessor.getContainingDeclaration());
|
||||||
StackValue property =
|
StackValue property = codegen.intermediateValueForProperty(
|
||||||
codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR,
|
original, forceField, accessor.getSuperCallExpression(), true, StackValue.none()
|
||||||
StackValue.none());
|
);
|
||||||
|
|
||||||
InstructionAdapter iv = codegen.v;
|
InstructionAdapter iv = codegen.v;
|
||||||
|
|
||||||
@@ -920,14 +919,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyGetterDescriptor getter = bridge.getGetter();
|
PropertyGetterDescriptor getter = accessor.getGetter();
|
||||||
assert getter != null;
|
assert getter != null;
|
||||||
functionCodegen.generateMethod(Synthetic(null, original.getGetter() != null ? original.getGetter() : original),
|
functionCodegen.generateMethod(Synthetic(null, original.getGetter() != null ? original.getGetter() : original),
|
||||||
getter, new PropertyAccessorStrategy(getter));
|
getter, new PropertyAccessorStrategy(getter));
|
||||||
|
|
||||||
|
|
||||||
if (bridge.isVar()) {
|
if (accessor.isVar()) {
|
||||||
PropertySetterDescriptor setter = bridge.getSetter();
|
PropertySetterDescriptor setter = accessor.getSetter();
|
||||||
assert setter != null;
|
assert setter != null;
|
||||||
|
|
||||||
functionCodegen.generateMethod(Synthetic(null, original.getSetter() != null ? original.getSetter() : original),
|
functionCodegen.generateMethod(Synthetic(null, original.getSetter() != null ? original.getSetter() : original),
|
||||||
@@ -957,24 +956,25 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
private void generateMethodCallTo(
|
private void generateMethodCallTo(
|
||||||
@NotNull FunctionDescriptor functionDescriptor,
|
@NotNull FunctionDescriptor functionDescriptor,
|
||||||
@Nullable FunctionDescriptor bridgeDescriptor,
|
@Nullable FunctionDescriptor accessorDescriptor,
|
||||||
@NotNull InstructionAdapter iv
|
@NotNull InstructionAdapter iv
|
||||||
) {
|
) {
|
||||||
boolean isConstructor = functionDescriptor instanceof ConstructorDescriptor;
|
boolean isConstructor = functionDescriptor instanceof ConstructorDescriptor;
|
||||||
boolean bridgeIsAccessorConstructor = bridgeDescriptor instanceof AccessorForConstructorDescriptor;
|
boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor;
|
||||||
boolean callFromAccessor = bridgeIsAccessorConstructor
|
|
||||||
|| (bridgeDescriptor != null && JetTypeMapper.isAccessor(bridgeDescriptor));
|
boolean superCall = accessorDescriptor instanceof AccessorForCallableDescriptor &&
|
||||||
|
((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallExpression() != null;
|
||||||
CallableMethod callableMethod = isConstructor ?
|
CallableMethod callableMethod = isConstructor ?
|
||||||
typeMapper.mapToCallableMethod((ConstructorDescriptor) functionDescriptor) :
|
typeMapper.mapToCallableMethod((ConstructorDescriptor) functionDescriptor) :
|
||||||
typeMapper.mapToCallableMethod(functionDescriptor, callFromAccessor, context);
|
typeMapper.mapToCallableMethod(functionDescriptor, superCall, context);
|
||||||
|
|
||||||
int reg = 1;
|
int reg = 1;
|
||||||
if (isConstructor && !bridgeIsAccessorConstructor) {
|
if (isConstructor && !accessorIsConstructor) {
|
||||||
iv.anew(callableMethod.getOwner());
|
iv.anew(callableMethod.getOwner());
|
||||||
iv.dup();
|
iv.dup();
|
||||||
reg = 0;
|
reg = 0;
|
||||||
}
|
}
|
||||||
else if (callFromAccessor) {
|
else if (accessorIsConstructor || (accessorDescriptor != null && JetTypeMapper.isAccessor(accessorDescriptor))) {
|
||||||
if (!AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor)) {
|
if (!AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor)) {
|
||||||
iv.load(0, OBJECT_TYPE);
|
iv.load(0, OBJECT_TYPE);
|
||||||
}
|
}
|
||||||
@@ -989,6 +989,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
reg += argType.getSize();
|
reg += argType.getSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callableMethod.genInvokeInstruction(iv);
|
callableMethod.genInvokeInstruction(iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1074,8 +1075,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
private void generateCompanionObjectInitializer(@NotNull ClassDescriptor companionObject) {
|
private void generateCompanionObjectInitializer(@NotNull ClassDescriptor companionObject) {
|
||||||
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||||
FunctionDescriptor constructor =
|
FunctionDescriptor constructor = (FunctionDescriptor) context.accessibleDescriptor(
|
||||||
(FunctionDescriptor) context.accessibleDescriptor(KotlinPackage.single(companionObject.getConstructors()));
|
KotlinPackage.single(companionObject.getConstructors()), /* superCallExpression = */ null
|
||||||
|
);
|
||||||
generateMethodCallTo(constructor, null, codegen.v);
|
generateMethodCallTo(constructor, null, codegen.v);
|
||||||
codegen.v.dup();
|
codegen.v.dup();
|
||||||
StackValue instance = StackValue.onStack(typeMapper.mapClass(companionObject));
|
StackValue instance = StackValue.onStack(typeMapper.mapClass(companionObject));
|
||||||
|
|||||||
@@ -360,8 +360,7 @@ public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclaratio
|
|||||||
JetExpression initializer = property.getDelegateExpressionOrInitializer();
|
JetExpression initializer = property.getDelegateExpressionOrInitializer();
|
||||||
assert initializer != null : "shouldInitializeProperty must return false if initializer is null";
|
assert initializer != null : "shouldInitializeProperty must return false if initializer is null";
|
||||||
|
|
||||||
StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null, MethodKind.INITIALIZER,
|
StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null, true, StackValue.LOCAL_0);
|
||||||
StackValue.LOCAL_0);
|
|
||||||
|
|
||||||
propValue.store(codegen.gen(initializer), codegen.v);
|
propValue.store(codegen.gen(initializer), codegen.v);
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +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;
|
|
||||||
|
|
||||||
public enum MethodKind {
|
|
||||||
GENERAL,
|
|
||||||
INITIALIZER,
|
|
||||||
SYNTHETIC_ACCESSOR
|
|
||||||
}
|
|
||||||
@@ -23,20 +23,19 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||||
import org.jetbrains.kotlin.psi.JetElement
|
|
||||||
import org.jetbrains.kotlin.psi.JetNamedFunction
|
import org.jetbrains.kotlin.psi.JetNamedFunction
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
import kotlin.platform.platformStatic
|
|
||||||
|
|
||||||
class PlatformStaticGenerator(
|
class PlatformStaticGenerator(
|
||||||
val descriptor: FunctionDescriptor,
|
val descriptor: FunctionDescriptor,
|
||||||
val declarationOrigin: JvmDeclarationOrigin,
|
val declarationOrigin: JvmDeclarationOrigin,
|
||||||
val state: GenerationState
|
val state: GenerationState
|
||||||
) : Function2<ImplementationBodyCodegen, ClassBuilder, Unit> {
|
) : Function2<ImplementationBodyCodegen, ClassBuilder, Unit> {
|
||||||
|
private val typeMapper = state.typeMapper
|
||||||
|
|
||||||
override fun invoke(codegen: ImplementationBodyCodegen, classBuilder: ClassBuilder) {
|
override fun invoke(codegen: ImplementationBodyCodegen, classBuilder: ClassBuilder) {
|
||||||
val staticFunctionDescriptor = createStaticFunctionDescriptor(descriptor)
|
val staticFunctionDescriptor = createStaticFunctionDescriptor(descriptor)
|
||||||
@@ -51,40 +50,37 @@ class PlatformStaticGenerator(
|
|||||||
frameMap: FrameMap,
|
frameMap: FrameMap,
|
||||||
signature: JvmMethodSignature,
|
signature: JvmMethodSignature,
|
||||||
context: MethodContext,
|
context: MethodContext,
|
||||||
parentCodegen: MemberCodegen<out JetElement>
|
parentCodegen: MemberCodegen<*>
|
||||||
) {
|
) {
|
||||||
val typeMapper = parentCodegen.typeMapper
|
|
||||||
|
|
||||||
val iv = InstructionAdapter(mv)
|
val iv = InstructionAdapter(mv)
|
||||||
val classDescriptor = descriptor.getContainingDeclaration() as ClassDescriptor
|
val classDescriptor = descriptor.containingDeclaration as ClassDescriptor
|
||||||
val singletonValue = StackValue.singleton(classDescriptor, typeMapper)
|
val singletonValue = StackValue.singleton(classDescriptor, typeMapper)
|
||||||
singletonValue.put(singletonValue.type, iv);
|
singletonValue.put(singletonValue.type, iv)
|
||||||
var index = 0;
|
var index = 0
|
||||||
val asmMethod = signature.getAsmMethod()
|
val asmMethod = signature.asmMethod
|
||||||
for (paramType in asmMethod.getArgumentTypes()) {
|
for (paramType in asmMethod.argumentTypes) {
|
||||||
iv.load(index, paramType);
|
iv.load(index, paramType)
|
||||||
index += paramType.getSize();
|
index += paramType.size
|
||||||
}
|
}
|
||||||
|
|
||||||
val syntheticOrOriginalMethod = typeMapper.mapToCallableMethod(
|
val syntheticOrOriginalMethod = typeMapper.mapToCallableMethod(
|
||||||
codegen.getContext().accessibleDescriptor(descriptor),
|
codegen.getContext().accessibleDescriptor(descriptor, /* superCallExpression = */ null),
|
||||||
false,
|
false,
|
||||||
codegen.getContext()
|
codegen.getContext()
|
||||||
)
|
)
|
||||||
syntheticOrOriginalMethod.genInvokeInstruction(iv)
|
syntheticOrOriginalMethod.genInvokeInstruction(iv)
|
||||||
iv.areturn(asmMethod.getReturnType());
|
iv.areturn(asmMethod.returnType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if (originElement is JetNamedFunction) {
|
if (originElement is JetNamedFunction) {
|
||||||
codegen.functionCodegen.generateOverloadsWithDefaultValues(originElement, staticFunctionDescriptor, descriptor)
|
codegen.functionCodegen.generateOverloadsWithDefaultValues(originElement, staticFunctionDescriptor, descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@platformStatic
|
@JvmStatic
|
||||||
public fun createStaticFunctionDescriptor(descriptor: FunctionDescriptor): FunctionDescriptor {
|
public fun createStaticFunctionDescriptor(descriptor: FunctionDescriptor): FunctionDescriptor {
|
||||||
val memberDescriptor = if (descriptor is PropertyAccessorDescriptor) descriptor.getCorrespondingProperty() else descriptor
|
val memberDescriptor = if (descriptor is PropertyAccessorDescriptor) descriptor.getCorrespondingProperty() else descriptor
|
||||||
val copies = CodegenUtil.copyFunctions(
|
val copies = CodegenUtil.copyFunctions(
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
|||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
|
import org.jetbrains.kotlin.psi.JetSuperExpression;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
||||||
@@ -47,8 +48,38 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
private final LocalLookup enclosingLocalLookup;
|
private final LocalLookup enclosingLocalLookup;
|
||||||
private final NullableLazyValue<StackValue.Field> outerExpression;
|
private final NullableLazyValue<StackValue.Field> outerExpression;
|
||||||
|
|
||||||
private Map<DeclarationDescriptor, DeclarationDescriptor> accessors;
|
|
||||||
private Map<DeclarationDescriptor, CodegenContext> childContexts;
|
private Map<DeclarationDescriptor, CodegenContext> childContexts;
|
||||||
|
private Map<AccessorKey, AccessorForCallableDescriptor<?>> 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(
|
public CodegenContext(
|
||||||
@NotNull T contextDescriptor,
|
@NotNull T contextDescriptor,
|
||||||
@@ -227,20 +258,28 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public <D extends CallableMemberDescriptor> D getAccessor(@NotNull D descriptor) {
|
public <D extends CallableMemberDescriptor> D getAccessor(@NotNull D descriptor, @Nullable JetSuperExpression superCallExpression) {
|
||||||
return getAccessor(descriptor, false, null);
|
return getAccessor(descriptor, false, null, superCallExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@NotNull
|
@NotNull
|
||||||
public <D extends CallableMemberDescriptor> D getAccessor(
|
public <D extends CallableMemberDescriptor> D getAccessor(
|
||||||
@NotNull D descriptor, boolean isForBackingFieldInOuterClass, @Nullable JetType delegateType
|
@NotNull D possiblySubstitutedDescriptor,
|
||||||
|
boolean isForBackingFieldInOuterClass,
|
||||||
|
@Nullable JetType delegateType,
|
||||||
|
@Nullable JetSuperExpression superCallExpression
|
||||||
) {
|
) {
|
||||||
if (accessors == null) {
|
if (accessors == null) {
|
||||||
accessors = new LinkedHashMap<DeclarationDescriptor, DeclarationDescriptor>();
|
accessors = new LinkedHashMap<AccessorKey, AccessorForCallableDescriptor<?>>();
|
||||||
}
|
}
|
||||||
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) {
|
if (accessor != null) {
|
||||||
assert !isForBackingFieldInOuterClass ||
|
assert !isForBackingFieldInOuterClass ||
|
||||||
accessor instanceof AccessorForPropertyBackingFieldInOuterClass : "There is already exists accessor with isForBackingFieldInOuterClass = false in this context";
|
accessor instanceof AccessorForPropertyBackingFieldInOuterClass : "There is already exists accessor with isForBackingFieldInOuterClass = false in this context";
|
||||||
@@ -249,10 +288,12 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
|
|
||||||
int accessorIndex = accessors.size();
|
int accessorIndex = accessors.size();
|
||||||
if (descriptor instanceof SimpleFunctionDescriptor) {
|
if (descriptor instanceof SimpleFunctionDescriptor) {
|
||||||
accessor = new AccessorForFunctionDescriptor((FunctionDescriptor) descriptor, contextDescriptor, accessorIndex);
|
accessor = new AccessorForFunctionDescriptor(
|
||||||
|
(FunctionDescriptor) descriptor, contextDescriptor, accessorIndex, superCallExpression
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else if (descriptor instanceof ConstructorDescriptor) {
|
else if (descriptor instanceof ConstructorDescriptor) {
|
||||||
accessor = new AccessorForConstructorDescriptor((ConstructorDescriptor) descriptor, contextDescriptor);
|
accessor = new AccessorForConstructorDescriptor((ConstructorDescriptor) descriptor, contextDescriptor, superCallExpression);
|
||||||
}
|
}
|
||||||
else if (descriptor instanceof PropertyDescriptor) {
|
else if (descriptor instanceof PropertyDescriptor) {
|
||||||
if (isForBackingFieldInOuterClass) {
|
if (isForBackingFieldInOuterClass) {
|
||||||
@@ -260,13 +301,16 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
accessorIndex, delegateType);
|
accessorIndex, delegateType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
accessor = new AccessorForPropertyDescriptor((PropertyDescriptor) descriptor, contextDescriptor, accessorIndex);
|
accessor = new AccessorForPropertyDescriptor((PropertyDescriptor) descriptor, contextDescriptor,
|
||||||
|
accessorIndex, superCallExpression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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);
|
||||||
}
|
}
|
||||||
accessors.put(descriptor, accessor);
|
|
||||||
|
accessors.put(key, accessor);
|
||||||
|
|
||||||
return (D) accessor;
|
return (D) accessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,25 +358,29 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Map<DeclarationDescriptor, DeclarationDescriptor> getAccessors() {
|
public Collection<? extends AccessorForCallableDescriptor<?>> getAccessors() {
|
||||||
return accessors == null ? Collections.<DeclarationDescriptor, DeclarationDescriptor>emptyMap() : accessors;
|
return accessors == null ? Collections.<AccessorForCallableDescriptor<CallableMemberDescriptor>>emptySet() : accessors.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public <D extends CallableMemberDescriptor> D accessibleDescriptor(D descriptor) {
|
public <D extends CallableMemberDescriptor> D accessibleDescriptor(
|
||||||
|
@NotNull D descriptor,
|
||||||
|
@Nullable JetSuperExpression superCallExpression
|
||||||
|
) {
|
||||||
DeclarationDescriptor enclosing = descriptor.getContainingDeclaration();
|
DeclarationDescriptor enclosing = descriptor.getContainingDeclaration();
|
||||||
if (!hasThisDescriptor() || enclosing == getThisDescriptor() ||
|
if (!hasThisDescriptor() || enclosing == getThisDescriptor() ||
|
||||||
enclosing == getClassOrPackageParentContext().getContextDescriptor()) {
|
enclosing == getClassOrPackageParentContext().getContextDescriptor()) {
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
return accessibleDescriptorIfNeeded(descriptor);
|
return accessibleDescriptorIfNeeded(descriptor, superCallExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recordSyntheticAccessorIfNeeded(@NotNull CallableMemberDescriptor descriptor, @NotNull BindingContext bindingContext) {
|
public void recordSyntheticAccessorIfNeeded(@NotNull CallableMemberDescriptor descriptor, @NotNull BindingContext bindingContext) {
|
||||||
if (hasThisDescriptor() &&
|
if (hasThisDescriptor() &&
|
||||||
(descriptor instanceof ConstructorDescriptor || Boolean.TRUE.equals(bindingContext.get(NEED_SYNTHETIC_ACCESSOR, descriptor)))) {
|
(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<T extends DeclarationDescriptor> {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@NotNull
|
@NotNull
|
||||||
private <D extends CallableMemberDescriptor> D accessibleDescriptorIfNeeded(@NotNull D descriptor) {
|
private <D extends CallableMemberDescriptor> D accessibleDescriptorIfNeeded(
|
||||||
|
@NotNull D descriptor,
|
||||||
|
@Nullable JetSuperExpression superCallExpression
|
||||||
|
) {
|
||||||
CallableMemberDescriptor unwrappedDescriptor = DescriptorUtils.unwrapFakeOverride(descriptor);
|
CallableMemberDescriptor unwrappedDescriptor = DescriptorUtils.unwrapFakeOverride(descriptor);
|
||||||
int flag = getAccessFlags(unwrappedDescriptor);
|
int flag = getAccessFlags(unwrappedDescriptor);
|
||||||
if ((flag & ACC_PRIVATE) == 0 && (flag & ACC_PROTECTED) == 0) {
|
if ((flag & ACC_PRIVATE) == 0 && (flag & ACC_PROTECTED) == 0) {
|
||||||
@@ -385,7 +436,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (D) descriptorContext.getAccessor(descriptor);
|
return (D) descriptorContext.getAccessor(descriptor, superCallExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addChild(@NotNull CodegenContext child) {
|
private void addChild(@NotNull CodegenContext child) {
|
||||||
|
|||||||
+49
@@ -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()
|
||||||
+13
@@ -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;" }
|
||||||
|
}
|
||||||
+6
@@ -37,6 +37,12 @@ public class BlackBoxMultiFileCodegenTestGenerated extends AbstractBlackBoxCodeg
|
|||||||
doTestMultiFile(fileName);
|
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 {
|
public void testAllFilesPresentInBoxMultiFile() throws Exception {
|
||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxMultiFile"), Pattern.compile("^([^\\.]+)$"), false);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxMultiFile"), Pattern.compile("^([^\\.]+)$"), false);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user