KT-3118 NoSuchFieldError on private property without backing field &&

KT-3551 Wrong synthetic accessor implementation
This commit is contained in:
Mikhael Bogdanov
2013-04-30 11:40:27 +04:00
parent b1c2d9035a
commit b0b6728c7e
13 changed files with 180 additions and 142 deletions
@@ -30,7 +30,7 @@ import java.util.Collections;
public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl { public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl {
public AccessorForPropertyDescriptor(PropertyDescriptor pd, DeclarationDescriptor containingDeclaration, int index) { public AccessorForPropertyDescriptor(PropertyDescriptor pd, DeclarationDescriptor containingDeclaration, int index) {
super(containingDeclaration, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.PUBLIC, super(containingDeclaration, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.LOCAL,
pd.isVar(), Name.identifier(pd.getName() + "$b$" + index), pd.isVar(), Name.identifier(pd.getName() + "$b$" + index),
Kind.DECLARATION); Kind.DECLARATION);
@@ -41,7 +41,7 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl {
public static class Getter extends PropertyGetterDescriptorImpl { public static class Getter extends PropertyGetterDescriptorImpl {
public Getter(AccessorForPropertyDescriptor property) { public Getter(AccessorForPropertyDescriptor property) {
super(property, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.PUBLIC, super(property, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.LOCAL,
false, false,
false, Kind.DECLARATION); false, Kind.DECLARATION);
initialize(property.getType()); initialize(property.getType());
@@ -50,7 +50,7 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl {
public static class Setter extends PropertySetterDescriptorImpl { public static class Setter extends PropertySetterDescriptorImpl {
public Setter(AccessorForPropertyDescriptor property) { public Setter(AccessorForPropertyDescriptor property) {
super(property, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.PUBLIC, super(property, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.LOCAL,
false, false,
false, Kind.DECLARATION); false, Kind.DECLARATION);
initializeDefault(); initializeDefault();
@@ -130,11 +130,14 @@ public class AsmUtil {
} }
} }
public static boolean isAbstract(FunctionDescriptor functionDescriptor, OwnerKind kind) { public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
return (functionDescriptor.getModality() == Modality.ABSTRACT return (functionDescriptor.getModality() == Modality.ABSTRACT
|| isInterface(functionDescriptor.getContainingDeclaration())) || isInterface(functionDescriptor.getContainingDeclaration()))
&& !isStatic(kind) && !isStaticMethod(kind, functionDescriptor);
&& kind != OwnerKind.TRAIT_IMPL; }
public static boolean isStaticMethod(OwnerKind kind, FunctionDescriptor functionDescriptor) {
return isStatic(kind) || kind == OwnerKind.TRAIT_IMPL || JetTypeMapper.isAccessor(functionDescriptor);
} }
public static boolean isStatic(OwnerKind kind) { public static boolean isStatic(OwnerKind kind) {
@@ -142,9 +145,6 @@ public class AsmUtil {
} }
public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind) { public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind) {
boolean isStatic = isStatic(kind);
boolean isAbstract = isAbstract(functionDescriptor, kind);
int flags = getCommonCallableFlags(functionDescriptor); int flags = getCommonCallableFlags(functionDescriptor);
if (functionDescriptor.getModality() == Modality.FINAL && !(functionDescriptor instanceof ConstructorDescriptor)) { if (functionDescriptor.getModality() == Modality.FINAL && !(functionDescriptor instanceof ConstructorDescriptor)) {
@@ -155,19 +155,21 @@ public class AsmUtil {
} }
} }
if (isStatic || kind == OwnerKind.TRAIT_IMPL) { if (isStaticMethod(kind, functionDescriptor)) {
flags |= ACC_STATIC; flags |= ACC_STATIC;
} }
if (isAbstract) flags |= ACC_ABSTRACT; if (isAbstractMethod(functionDescriptor, kind)) {
flags |= ACC_ABSTRACT;
}
if (JetTypeMapper.isAccessor(functionDescriptor)) {
flags |= ACC_SYNTHETIC;
}
return flags; return flags;
} }
public static int getConstructorAsmFlags(FunctionDescriptor functionDescriptor) {
return getCommonCallableFlags(functionDescriptor);
}
private static int getCommonCallableFlags(FunctionDescriptor functionDescriptor) { private static int getCommonCallableFlags(FunctionDescriptor functionDescriptor) {
int flags = getVisibilityAccessFlag(functionDescriptor); int flags = getVisibilityAccessFlag(functionDescriptor);
flags |= getVarargsFlag(functionDescriptor); flags |= getVarargsFlag(functionDescriptor);
@@ -262,4 +262,14 @@ public class CodegenUtil {
} }
return false; return false;
} }
public static boolean couldUseDirectAccessToProperty(PropertyDescriptor propertyDescriptor, boolean forGetter, boolean isInsideClass) {
PropertyAccessorDescriptor accessorDescriptor = forGetter ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
return isInsideClass &&
!isExtensionProperty &&
(accessorDescriptor == null ||
accessorDescriptor.isDefault() &&
(!DescriptorUtils.isExternallyAccessible(propertyDescriptor) || accessorDescriptor.getModality() == Modality.FINAL));
}
} }
@@ -297,6 +297,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
} }
private ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression) { private ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression) {
return getSuperCallLabelTarget(expression, bindingContext, context);
}
@NotNull
private static ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression, BindingContext bindingContext, CodegenContext context) {
PsiElement labelPsi = bindingContext.get(BindingContext.LABEL_TARGET, expression.getTargetLabel()); PsiElement labelPsi = bindingContext.get(BindingContext.LABEL_TARGET, expression.getTargetLabel());
ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, labelPsi); ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, labelPsi);
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference()); DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
@@ -305,7 +310,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return labelTarget; return labelTarget;
} }
assert descriptor instanceof ClassDescriptor : "Don't know how to generate super-call to not a class"; assert descriptor instanceof ClassDescriptor : "Don't know how to generate super-call to not a class";
ClassDescriptor target = getParentContextSubclassOf((ClassDescriptor) descriptor).getThisDescriptor(); ClassDescriptor target = getParentContextSubclassOf((ClassDescriptor) descriptor, context).getThisDescriptor();
return target; return target;
} }
@@ -1552,12 +1557,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (descriptor instanceof PropertyDescriptor) { if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
boolean isStatic = container instanceof NamespaceDescriptor;
boolean directToField = boolean directToField =
expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL; expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL;
JetExpression r = getReceiverForSelector(expression); JetExpression r = getReceiverForSelector(expression);
boolean isSuper = r instanceof JetSuperExpression; boolean isSuper = r instanceof JetSuperExpression;
propertyDescriptor = accessablePropertyDescriptor(propertyDescriptor); propertyDescriptor = accessablePropertyDescriptor(context, propertyDescriptor);
StackValue.Property iValue = StackValue.Property iValue =
intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression) r : null); intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression) r : null);
if (directToField) { if (directToField) {
@@ -1662,6 +1666,19 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
boolean forceField, boolean forceField,
@Nullable JetSuperExpression superExpression @Nullable JetSuperExpression superExpression
) { ) {
return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, state, context, false);
}
@NotNull
public static StackValue.Property intermediateValueForProperty(
PropertyDescriptor propertyDescriptor,
boolean forceField,
@Nullable JetSuperExpression superExpression,
@NotNull GenerationState state,
@NotNull CodegenContext context,
@NotNull boolean forceSpecialFlag
) {
JetTypeMapper typeMapper = state.getTypeMapper();
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
assert containingDeclaration != null; assert containingDeclaration != null;
@@ -1670,23 +1687,18 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
boolean isSuper = superExpression != null; boolean isSuper = superExpression != null;
boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context); boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context);
boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context); boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context);
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
CallableMethod callableGetter = null; CallableMethod callableGetter = null;
CallableMethod callableSetter = null; CallableMethod callableSetter = null;
if (!forceField) { if (!forceField) {
//noinspection ConstantConditions //noinspection ConstantConditions
if (isInsideClass && if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass)) {
!isExtensionProperty &&
(propertyDescriptor.getGetter() == null ||
!DescriptorUtils.isExternallyAccessible(propertyDescriptor) ||
propertyDescriptor.getGetter().isDefault() && propertyDescriptor.getGetter().getModality() == Modality.FINAL)) {
callableGetter = null; callableGetter = null;
} }
else { else {
if (isSuper && !isInterface(containingDeclaration)) { if (isSuper && !isInterface(containingDeclaration)) {
ClassDescriptor owner = getSuperCallLabelTarget(superExpression); ClassDescriptor owner = getSuperCallLabelTarget(superExpression, state.getBindingContext(), context);
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()) {
@@ -1694,23 +1706,20 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
} }
} }
propertyDescriptor = accessablePropertyDescriptor(propertyDescriptor); propertyDescriptor = accessablePropertyDescriptor(context, propertyDescriptor);
if (propertyDescriptor.getGetter() != null) { if (propertyDescriptor.getGetter() != null) {
callableGetter = typeMapper.mapToCallableMethod(propertyDescriptor.getGetter(), isSuper, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION); callableGetter = typeMapper.mapToCallableMethod(propertyDescriptor.getGetter(), isSuper || forceSpecialFlag, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
} }
} }
if (propertyDescriptor.isVar()) { if (propertyDescriptor.isVar()) {
if (propertyDescriptor.getSetter() != null) { if (propertyDescriptor.getSetter() != null) {
if (isInsideClass && !isExtensionProperty && if (couldUseDirectAccessToProperty(propertyDescriptor, false, isInsideClass)) {
(!DescriptorUtils.isExternallyAccessible(propertyDescriptor) ||
propertyDescriptor.getSetter().isDefault() &&
propertyDescriptor.getSetter().getModality() == Modality.FINAL)) {
callableSetter = null; callableSetter = null;
} }
else { else {
callableSetter = typeMapper.mapToCallableMethod(propertyDescriptor.getSetter(), isSuper, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION); callableSetter = typeMapper.mapToCallableMethod(propertyDescriptor.getSetter(), isSuper || forceSpecialFlag, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
} }
} }
} }
@@ -1721,13 +1730,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
propertyDescriptor = unwrapFakeOverride(propertyDescriptor); propertyDescriptor = unwrapFakeOverride(propertyDescriptor);
if (callableMethod == null) { if (callableMethod == null) {
owner = typeMapper.getOwner(propertyDescriptor, contextKind(), isInsideModule); owner = typeMapper.getOwner(propertyDescriptor, context.getContextKind(), isInsideModule);
} }
else { else {
owner = callableMethod.getOwner(); owner = callableMethod.getOwner();
} }
return StackValue.property(propertyDescriptor, owner, asmType(propertyDescriptor.getOriginal().getType()), return StackValue.property(propertyDescriptor, owner, typeMapper.mapType(propertyDescriptor.getOriginal().getType()),
isStatic, callableGetter, callableSetter, state); isStatic, callableGetter, callableSetter, state);
} }
@@ -1814,7 +1823,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
} }
} }
private PropertyDescriptor accessablePropertyDescriptor(PropertyDescriptor propertyDescriptor) { private static PropertyDescriptor accessablePropertyDescriptor(CodegenContext context, PropertyDescriptor propertyDescriptor) {
PropertySetterDescriptor setter = propertyDescriptor.getSetter(); PropertySetterDescriptor setter = propertyDescriptor.getSetter();
PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
@@ -1919,7 +1928,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
} }
// Find the first parent of the current context which corresponds to a subclass of a given class // Find the first parent of the current context which corresponds to a subclass of a given class
private CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor) { @NotNull
private static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) {
CodegenContext c = context; CodegenContext c = context;
while (true) { while (true) {
if ((c instanceof ClassContext || c instanceof AnonymousClassContext) && if ((c instanceof ClassContext || c instanceof AnonymousClassContext) &&
@@ -127,7 +127,7 @@ public class FunctionCodegen extends GenerationStateAware {
genJetAnnotations(mv, functionDescriptor, jvmSignature); genJetAnnotations(mv, functionDescriptor, jvmSignature);
} }
if (isAbstract(functionDescriptor, methodContext.getContextKind())) return; if (isAbstractMethod(functionDescriptor, methodContext.getContextKind())) return;
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
genStubCode(mv); genStubCode(mv);
@@ -227,13 +227,13 @@ public class FunctionCodegen extends GenerationStateAware {
List<JvmMethodParameterSignature> params = jvmMethodSignature.getKotlinParameterTypes(); List<JvmMethodParameterSignature> params = jvmMethodSignature.getKotlinParameterTypes();
int shift = 0; int shift = 0;
boolean isStatic = isStatic(ownerKind) || ownerKind == OwnerKind.TRAIT_IMPL; boolean isStatic = AsmUtil.isStaticMethod(ownerKind, functionDescriptor);
if (!isStatic) { if (!isStatic) {
//add this //add this
if (thisType != null) { if (thisType != null) {
mv.visitLocalVariable("this", thisType.getDescriptor(), null, methodBegin, methodEnd, shift); mv.visitLocalVariable("this", thisType.getDescriptor(), null, methodBegin, methodEnd, shift);
} else { } else {
//sometimes there is no thisType for callable reference //TODO: provide thisType for callable reference
} }
shift++; shift++;
} }
@@ -334,14 +334,13 @@ public class FunctionCodegen extends GenerationStateAware {
) { ) {
if (functionDescriptor instanceof PropertyAccessorDescriptor) { if (functionDescriptor instanceof PropertyAccessorDescriptor) {
assert jvmSignature instanceof JvmPropertyAccessorSignature; assert jvmSignature instanceof JvmPropertyAccessorSignature : "jvmSignature for property should have JvmPropertyAccessorSignature type";
PropertyCodegen.generateJetPropertyAnnotation(mv, (JvmPropertyAccessorSignature) jvmSignature, PropertyCodegen.generateJetPropertyAnnotation(mv, (JvmPropertyAccessorSignature) jvmSignature,
((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty(), functionDescriptor.getVisibility()); ((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty(), functionDescriptor.getVisibility());
} }
else if (functionDescriptor instanceof SimpleFunctionDescriptor) { else if (functionDescriptor instanceof SimpleFunctionDescriptor) {
if (jvmSignature instanceof JvmPropertyAccessorSignature) { assert !(jvmSignature instanceof JvmPropertyAccessorSignature) : "jvmSignature for function shouldn't have JvmPropertyAccessorSignature type";
throw new IllegalStateException();
}
Modality modality = functionDescriptor.getModality(); Modality modality = functionDescriptor.getModality();
JetMethodAnnotationWriter aw = JetMethodAnnotationWriter.visitAnnotation(mv); JetMethodAnnotationWriter aw = JetMethodAnnotationWriter.visitAnnotation(mv);
int kotlinFlags = getFlagsForVisibility(functionDescriptor.getVisibility()); int kotlinFlags = getFlagsForVisibility(functionDescriptor.getVisibility());
@@ -86,6 +86,7 @@ public abstract class FunctionGenerationStrategy<T extends CallableDescriptor> {
public abstract static class CodegenBased<T extends CallableDescriptor> extends FunctionGenerationStrategy<T> { public abstract static class CodegenBased<T extends CallableDescriptor> extends FunctionGenerationStrategy<T> {
private final GenerationState state; private final GenerationState state;
protected final T callableDescriptor; protected final T callableDescriptor;
public CodegenBased(@NotNull GenerationState state, T callableDescriptor) { public CodegenBased(@NotNull GenerationState state, T callableDescriptor) {
@@ -36,7 +36,6 @@ import org.jetbrains.jet.codegen.context.ConstructorContext;
import org.jetbrains.jet.codegen.context.MethodContext; import org.jetbrains.jet.codegen.context.MethodContext;
import org.jetbrains.jet.codegen.signature.*; import org.jetbrains.jet.codegen.signature.*;
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter; import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
import org.jetbrains.jet.codegen.signature.kotlin.JetValueParameterAnnotationWriter;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.JetTypeMapper; import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.codegen.state.JetTypeMapperMode; import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
@@ -79,9 +78,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private JetType superClassType; private JetType superClassType;
private final Type classAsmType; private final Type classAsmType;
private final FunctionCodegen functionCodegen;
private final PropertyCodegen propertyCodegen;
public ImplementationBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) { public ImplementationBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
super(aClass, context, v, state); super(aClass, context, v, state);
classAsmType = typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL); this.classAsmType = typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL);
this.functionCodegen = new FunctionCodegen(context, v, state);
this.propertyCodegen = new PropertyCodegen(context, v, this.functionCodegen);
} }
@Override @Override
@@ -440,7 +444,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateTraitMethods(); generateTraitMethods();
generateAccessors(); generateSyntheticAccessors();
generateEnumMethods(); generateEnumMethods();
@@ -798,13 +802,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
} }
private void generateAccessors() { private void generateSyntheticAccessors() {
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : context.getAccessors().entrySet()) { for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : context.getAccessors().entrySet()) {
genAccessor(entry); generateSyntheticAccessor(entry);
} }
} }
private void genAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) { private void generateSyntheticAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) {
if (entry.getValue() instanceof FunctionDescriptor) { if (entry.getValue() instanceof FunctionDescriptor) {
FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue(); FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
FunctionDescriptor original = (FunctionDescriptor) entry.getKey(); FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
@@ -817,7 +821,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Type[] argTypes = method.getArgumentTypes(); Type[] argTypes = method.getArgumentTypes();
String owner = typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION, isCallInsideSameModuleAsDeclared(original, context)).getInternalName(); String owner = typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION, isCallInsideSameModuleAsDeclared(original, context)).getInternalName();
MethodVisitor mv = v.newMethod(null, ACC_BRIDGE | ACC_SYNTHETIC | ACC_STATIC, bridge.getName().getName(), MethodVisitor mv = v.newMethod(null, ACC_SYNTHETIC | ACC_STATIC, bridge.getName().getName(),
method.getDescriptor(), null, null); method.getDescriptor(), null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
genStubCode(mv); genStubCode(mv);
@@ -850,86 +854,46 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
else if (entry.getValue() instanceof PropertyDescriptor) { else if (entry.getValue() instanceof PropertyDescriptor) {
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue(); PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
PropertyDescriptor original = (PropertyDescriptor) entry.getKey(); final PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
final StackValue.Property property = ExpressionCodegen.intermediateValueForProperty(original, false, null, state, context, true);
{
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
JvmPropertyAccessorSignature originalSignature = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
Method originalMethod = originalSignature.getAsmMethod();
MethodVisitor mv =
v.newMethod(null, ACC_BRIDGE | ACC_SYNTHETIC | ACC_STATIC, method.getName(), method.getDescriptor(), null, null);
PropertyGetterDescriptor getter = bridge.getGetter();
assert getter != null;
PropertyCodegen.generateJetPropertyAnnotation(mv,
originalSignature,
original,
getter.getVisibility());
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
PropertyGetterDescriptor getter = bridge.getGetter();
assert getter != null;
functionCodegen.generateMethod(null, typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION), false, getter,
new FunctionGenerationStrategy.CodegenBased<PropertyGetterDescriptor>(state, getter) {
@Override
public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) {
InstructionAdapter iv = codegen.v;
iv.load(0, OBJECT_TYPE); iv.load(0, OBJECT_TYPE);
boolean hasBackingField = Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, original)); property.put(property.type, iv);
boolean isInsideModule = isCallInsideSameModuleAsDeclared(original, context); iv.areturn(signature.getAsmMethod().getReturnType());
if (original.getVisibility() == Visibilities.PRIVATE && hasBackingField) {
iv.getfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION, isInsideModule).getInternalName(), original.getName().getName(),
originalMethod.getReturnType().getDescriptor());
}
else {
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION, isInsideModule).getInternalName(),
originalMethod.getName(), originalMethod.getDescriptor());
}
iv.areturn(method.getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null);
} }
} });
if (bridge.isVar()) { if (bridge.isVar()) {
Method method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
JvmPropertyAccessorSignature originalSignature2 = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
Method originalMethod = originalSignature2.getAsmMethod();
MethodVisitor mv =
v.newMethod(null, ACC_STATIC | ACC_BRIDGE | ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
PropertySetterDescriptor setter = bridge.getSetter(); PropertySetterDescriptor setter = bridge.getSetter();
assert setter != null; assert setter != null;
PropertyCodegen.generateJetPropertyAnnotation(mv,
originalSignature2,
original,
setter.getVisibility());
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); functionCodegen.generateMethod(null, typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION), false, setter,
new FunctionGenerationStrategy.CodegenBased<PropertySetterDescriptor>(state, setter) {
@Override
public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) {
InstructionAdapter iv = codegen.v;
iv.load(0, OBJECT_TYPE); iv.load(0, OBJECT_TYPE);
Type[] argTypes = method.getArgumentTypes(); Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
for (int i = 1, reg = 1; i < argTypes.length; i++) { for (int i = 1, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i]; Type argType = argTypes[i];
iv.load(reg, argType); iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter //noinspection AssignmentToForLoopParameter
reg += argType.getSize(); reg += argType.getSize();
} }
boolean isInsideModule = isCallInsideSameModuleAsDeclared(original, context); property.store(property.type, iv);
if (original.getVisibility() == Visibilities.PRIVATE && original.getModality() == Modality.FINAL) {
iv.putfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION, isInsideModule).getInternalName(), original.getName().getName(),
originalMethod.getArgumentTypes()[0].getDescriptor());
}
else {
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION, isInsideModule).getInternalName(),
originalMethod.getName(), originalMethod.getDescriptor());
}
iv.areturn(method.getReturnType()); iv.areturn(signature.getAsmMethod().getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null); }
} });
} }
} }
else { else {
@@ -979,26 +943,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
assert constructorDescriptor != null; assert constructorDescriptor != null;
FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
functionCodegen.generateMethod(null, constructorMethod, true, constructorDescriptor, constructorContext, functionCodegen.generateMethod(null, constructorMethod, true, constructorDescriptor, constructorContext,
new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) { new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
@NotNull @NotNull
@Override @Override
protected FrameMap createFrameMap( protected FrameMap createFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull CodegenContext context) {
@NotNull JetTypeMapper typeMapper, @NotNull CodegenContext context return new ConstructorFrameMap(callableMethod, callableDescriptor);
) { }
return new ConstructorFrameMap(callableMethod, callableDescriptor);
}
@Override @Override
public void doGenerateBody( public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) {
ExpressionCodegen codegen, JvmMethodSignature signature generatePrimaryConstructorImpl(callableDescriptor, codegen, closure);
) { }
generatePrimaryConstructorImpl(callableDescriptor, codegen, closure); }
} );
});
FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod.getAsmMethod(), constructorDescriptor, FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod.getAsmMethod(), constructorDescriptor,
OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT); OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT);
@@ -1642,9 +1601,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
protected void generateDelegates(ClassDescriptor toClass, StackValue field) { protected void generateDelegates(ClassDescriptor toClass, StackValue field) {
FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen);
for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
if (declaration instanceof CallableMemberDescriptor) { if (declaration instanceof CallableMemberDescriptor) {
CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration; CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration;
@@ -550,7 +550,7 @@ public class JetTypeMapper extends BindingTraceAware {
thisClass, receiverParameterType, null); thisClass, receiverParameterType, null);
} }
private static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) { public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
return descriptor instanceof AccessorForFunctionDescriptor || return descriptor instanceof AccessorForFunctionDescriptor ||
descriptor instanceof AccessorForPropertyDescriptor || descriptor instanceof AccessorForPropertyDescriptor ||
descriptor instanceof AccessorForPropertyDescriptor.Getter || descriptor instanceof AccessorForPropertyDescriptor.Getter ||
@@ -33,7 +33,7 @@ class C {
class D { class D {
private var foo = 1 private var foo = 1
set(i: Int) { set(i: Int) {
foo = i + 1 $foo = i + 1
} }
fun foo() { fun foo() {
@@ -0,0 +1,12 @@
package testing
class Test {
private val hello: String
get() { return "hello" }
fun sayHello() : String = hello
}
fun box(): String {
return if (Test().sayHello() == "hello") "OK" else "fail"
}
@@ -0,0 +1,23 @@
class Identifier() {
private var myNullable : Boolean = false
set(l : Boolean) {
//do nothing
}
fun getValue() : Boolean {
return myNullable
}
class object {
fun init(isNullable : Boolean) : Identifier {
val id = Identifier()
id.myNullable = isNullable
return id
}
}
}
fun box() : String {
val id = Identifier.init(true)
return if (id.getValue() == false) return "OK" else "fail"
}
@@ -0,0 +1,10 @@
class Test {
val a : String = "1"
private val b : String get() = a
fun outer() : Int {
return b.length
}
}
fun box() = if (Test().outer() == 1) "OK" else "fail"
@@ -3386,6 +3386,21 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/properties/kt2892.kt"); doTest("compiler/testData/codegen/box/properties/kt2892.kt");
} }
@TestMetadata("kt3118.kt")
public void testKt3118() throws Exception {
doTest("compiler/testData/codegen/box/properties/kt3118.kt");
}
@TestMetadata("kt3551.kt")
public void testKt3551() throws Exception {
doTest("compiler/testData/codegen/box/properties/kt3551.kt");
}
@TestMetadata("kt3556.kt")
public void testKt3556() throws Exception {
doTest("compiler/testData/codegen/box/properties/kt3556.kt");
}
@TestMetadata("kt613.kt") @TestMetadata("kt613.kt")
public void testKt613() throws Exception { public void testKt613() throws Exception {
doTest("compiler/testData/codegen/box/properties/kt613.kt"); doTest("compiler/testData/codegen/box/properties/kt613.kt");