diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index e9368f9682b..6410c478cfb 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -30,6 +30,7 @@ import org.jetbrains.jet.codegen.binding.MutableClosure; import org.jetbrains.jet.codegen.bridges.BridgesPackage; import org.jetbrains.jet.codegen.context.ClassContext; import org.jetbrains.jet.codegen.context.ConstructorContext; +import org.jetbrains.jet.codegen.context.FieldOwnerContext; import org.jetbrains.jet.codegen.context.MethodContext; import org.jetbrains.jet.codegen.signature.BothSignatureWriter; import org.jetbrains.jet.codegen.state.GenerationState; @@ -643,6 +644,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { KotlinBuiltIns.getInstance().getBoolean(), KotlinBuiltIns.getInstance().getAny() ); + MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(equalsFunction); MethodVisitor mv = v.newMethod(OtherOrigin(equalsFunction), ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null); InstructionAdapter iv = new InstructionAdapter(mv); @@ -665,8 +667,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { for (PropertyDescriptor propertyDescriptor : properties) { Type asmType = typeMapper.mapType(propertyDescriptor); - genPropertyOnStack(iv, propertyDescriptor, 0); - genPropertyOnStack(iv, propertyDescriptor, 2); + genPropertyOnStack(iv, context, propertyDescriptor, 0); + genPropertyOnStack(iv, context, propertyDescriptor, 2); if (asmType.getSort() == Type.ARRAY) { Type elementType = correctElementType(asmType); @@ -702,6 +704,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { descriptor, Name.identifier(CodegenUtil.HASH_CODE_METHOD_NAME), KotlinBuiltIns.getInstance().getInt() ); + MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(hashCodeFunction); MethodVisitor mv = v.newMethod(OtherOrigin(hashCodeFunction), ACC_PUBLIC, "hashCode", "()I", null, null); InstructionAdapter iv = new InstructionAdapter(mv); @@ -713,7 +716,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.mul(Type.INT_TYPE); } - genPropertyOnStack(iv, propertyDescriptor, 0); + genPropertyOnStack(iv, context, propertyDescriptor, 0); Label ifNull = null; Type asmType = typeMapper.mapType(propertyDescriptor); @@ -753,6 +756,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { descriptor, Name.identifier(CodegenUtil.TO_STRING_METHOD_NAME), KotlinBuiltIns.getInstance().getString() ); + MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(toString); MethodVisitor mv = v.newMethod(OtherOrigin(toString), ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null); InstructionAdapter iv = new InstructionAdapter(mv); @@ -770,7 +774,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } genInvokeAppendMethod(iv, JAVA_STRING_TYPE); - Type type = genPropertyOnStack(iv, propertyDescriptor, 0); + Type type = genPropertyOnStack(iv, context, propertyDescriptor, 0); if (type.getSort() == Type.ARRAY) { Type elementType = correctElementType(type); @@ -797,13 +801,20 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { FunctionCodegen.endVisit(mv, "toString", myClass); } - private Type genPropertyOnStack(InstructionAdapter iv, PropertyDescriptor propertyDescriptor, int index) { + private Type genPropertyOnStack(InstructionAdapter iv, MethodContext context, PropertyDescriptor propertyDescriptor, int index) { iv.load(index, classAsmType); - //noinspection ConstantConditions - Method method = typeMapper.mapSignature(propertyDescriptor.getGetter()).getAsmMethod(); - - iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor()); - return method.getReturnType(); + if (couldUseDirectAccessToProperty(propertyDescriptor, /* forGetter = */ true, /* isDelegated = */ false, context)) { + Type type = typeMapper.mapType(propertyDescriptor.getType()); + String fieldName = ((FieldOwnerContext) context.getParentContext()).getFieldName(propertyDescriptor, false); + iv.getfield(classAsmType.getInternalName(), fieldName, type.getDescriptor()); + return type.getReturnType(); + } + else { + //noinspection ConstantConditions + Method method = typeMapper.mapSignature(propertyDescriptor.getGetter()).getAsmMethod(); + iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor()); + return method.getReturnType(); + } } @Override diff --git a/compiler/testData/codegen/boxWithStdlib/dataClasses/privateValParams.kt b/compiler/testData/codegen/boxWithStdlib/dataClasses/privateValParams.kt new file mode 100644 index 00000000000..2996bb8839d --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/dataClasses/privateValParams.kt @@ -0,0 +1,10 @@ +data class D(private val x: Long, private val y: Char) + +fun box(): String { + val d1 = D(42L, 'a') + val d2 = D(42L, 'a') + if (d1 != d2) return "Fail equals" + if (d1.hashCode() != d2.hashCode()) return "Fail hashCode" + if (d1.toString() != d2.toString()) return "Fail toString" + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 79e3a9a8e6b..f9fa1e95ff6 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -633,6 +633,11 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/dataClasses/overriddenProperty.kt"); } + @TestMetadata("privateValParams.kt") + public void testPrivateValParams() throws Exception { + doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/dataClasses/privateValParams.kt"); + } + @TestMetadata("twoValParams.kt") public void testTwoValParams() throws Exception { doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/dataClasses/twoValParams.kt");