diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java b/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java index dd7f8e3da48..796e548c617 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java @@ -125,4 +125,8 @@ public class CallableMethod implements Callable { public boolean isNeedsReceiver() { return receiverParameterType != null; } + + public Type getReturnType() { + return signature.getAsmMethod().getReturnType(); + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 4a98cd43bdc..9e291e24d36 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -333,7 +333,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { } i += type.getSize(); - StackValue.field(type, name, fieldName, false).store(iv); + StackValue.field(type, name, fieldName, false).store(type, iv); } iv.visitInsn(RETURN); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 94fbd68aeab..d1168e9ae88 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1650,7 +1650,7 @@ public class ExpressionCodegen extends JetVisitor { v.dup(); v.iconst(i); gen(arguments.get(i).getArgumentExpression(), elementType); - StackValue.arrayElement(elementType, false).store(v); + StackValue.arrayElement(elementType, false).store(elementType, v); } } } @@ -2047,7 +2047,7 @@ public class ExpressionCodegen extends JetVisitor { private StackValue generateAssignmentExpression(JetBinaryExpression expression) { StackValue stackValue = gen(expression.getLeft()); gen(expression.getRight(), stackValue.type); - stackValue.store(v); + stackValue.store(stackValue.type, v); return StackValue.none(); } @@ -2072,8 +2072,10 @@ public class ExpressionCodegen extends JetVisitor { value.put(lhsType, v); // receiver lhs final IntrinsicMethod intrinsic = (IntrinsicMethod) callable; //noinspection NullableProblems - intrinsic.generate(this, v, lhsType, expression, Arrays.asList(expression.getRight()), StackValue.onStack(lhsType), state); - value.store(v); + StackValue stackValue = intrinsic.generate(this, v, lhsType, expression, + Arrays.asList(expression.getRight()), + StackValue.onStack(lhsType), state); + value.store(stackValue.type, v); } else { callAugAssignMethod(expression, (CallableMethod) callable, lhsType, true); @@ -2107,7 +2109,7 @@ public class ExpressionCodegen extends JetVisitor { pushMethodArguments(resolvedCall, callable.getValueParameterTypes()); callable.invoke(v); if (keepReturnValue) { - value.store(v); + value.store(callable.getReturnType(), v); } } @@ -2173,8 +2175,9 @@ public class ExpressionCodegen extends JetVisitor { } else { DeclarationDescriptor cls = op.getContainingDeclaration(); + CallableMethod callableMethod = (CallableMethod) callable; if (isNumberPrimitive(cls) || !(op.getName().getName().equals("inc") || op.getName().getName().equals("dec")) ) { - return invokeOperation(expression, (FunctionDescriptor) op, (CallableMethod) callable); + return invokeOperation(expression, (FunctionDescriptor) op, callableMethod); } else { ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); @@ -2186,8 +2189,8 @@ public class ExpressionCodegen extends JetVisitor { Type type = expressionType(expression.getBaseExpression()); value.put(type, v); - ((CallableMethod)callable).invoke(v); - value.store(v); + callableMethod.invoke(v); + value.store(callableMethod.getReturnType(), v); value.put(type, v); return StackValue.onStack(type); } @@ -2280,8 +2283,7 @@ public class ExpressionCodegen extends JetVisitor { CallableMethod callableMethod = (CallableMethod) callable; callableMethod.invoke(v); - StackValue.onStack(callableMethod.getSignature().getAsmMethod().getReturnType()).put(value.type, v); - value.store(v); + value.store(callableMethod.getReturnType(), v); return StackValue.onStack(type); } } @@ -2317,7 +2319,7 @@ public class ExpressionCodegen extends JetVisitor { v.iconst(increment); } v.add(asmType); - value.store(v); + value.store(asmType, v); } @Override diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 5167341dab0..cfec3f43938 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -640,7 +640,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { String fieldDesc = fieldType.getDescriptor(); v.newField(specifier, ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null); StackValue field = StackValue.field(fieldType, classname, delegateField, false); - field.store(iv); + field.store(fieldType, iv); JetClass superClass = (JetClass) BindingContextUtils.classDescriptorToDeclaration(bindingContext, superClassDescriptor); final CodegenContext delegateContext = context.intoClass(superClassDescriptor, @@ -960,8 +960,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { codegen.gen(initializer, type); // @todo write directly to the field. Fix test excloset.jet::test6 JvmClassName owner = typeMapper.getOwner(propertyDescriptor, OwnerKind.IMPLEMENTATION); + Type propType = typeMapper.mapType(propertyDescriptor.getType(), MapTypeMode.VALUE); StackValue.property(propertyDescriptor.getName().getName(), owner, owner, - typeMapper.mapType(propertyDescriptor.getType(), MapTypeMode.VALUE), false, false, false, null, null, 0).store(iv); + propType, false, false, false, null, null, 0).store(propType, iv); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 559d7120bb9..eb70f358d76 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -130,8 +130,8 @@ public class NamespaceCodegen { if(descriptor.getReceiverParameter().exists()) { continue; } - codegen.genToJVMStack(initializer); - codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv)); + StackValue.Property propValue = codegen.intermediateValueForProperty(descriptor, true, null); + propValue.store(propValue.type, new InstructionAdapter(mv)); } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index f90cce4b06f..16cba0e72e0 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -73,7 +73,7 @@ public abstract class StackValue { put(type, v); } - public void store(InstructionAdapter v) { + public void store(Type topOfStackType, InstructionAdapter v) { throw new UnsupportedOperationException("cannot store to value " + this); } @@ -205,54 +205,58 @@ public abstract class StackValue { } } - protected void coerce(Type type, InstructionAdapter v) { - if (type.equals(this.type)) return; + protected void coerce(Type toType, InstructionAdapter v) { + coerce(this.type, toType, v); + } - if (type.getSort() == Type.VOID && this.type.getSort() != Type.VOID) { - if(this.type.getSize() == 1) + protected static void coerce(Type fromType, Type toType, InstructionAdapter v) { + if (toType.equals(fromType)) return; + + if (toType.getSort() == Type.VOID && fromType.getSort() != Type.VOID) { + if(fromType.getSize() == 1) v.pop(); else v.pop2(); } - else if (type.getSort() != Type.VOID && this.type.getSort() == Type.VOID) { - if(type.getSort() == Type.OBJECT) { + else if (toType.getSort() != Type.VOID && fromType.getSort() == Type.VOID) { + if(toType.getSort() == Type.OBJECT) { putTuple0Instance(v); } - else if(type == Type.LONG_TYPE) + else if(toType == Type.LONG_TYPE) v.lconst(0); - else if(type == Type.FLOAT_TYPE) + else if(toType == Type.FLOAT_TYPE) v.fconst(0); - else if(type == Type.DOUBLE_TYPE) + else if(toType == Type.DOUBLE_TYPE) v.dconst(0); else v.iconst(0); } - else if (type.getSort() == Type.OBJECT && this.type.equals(JetTypeMapper.TYPE_OBJECT) || type.getSort() == Type.ARRAY) { - v.checkcast(type); + else if (toType.getSort() == Type.OBJECT && fromType.equals(JetTypeMapper.TYPE_OBJECT) || toType.getSort() == Type.ARRAY) { + v.checkcast(toType); } - else if (type.getSort() == Type.OBJECT) { - if(this.type.getSort() == Type.OBJECT && !type.equals(JetTypeMapper.TYPE_OBJECT)) { - v.checkcast(type); + else if (toType.getSort() == Type.OBJECT) { + if(fromType.getSort() == Type.OBJECT && !toType.equals(JetTypeMapper.TYPE_OBJECT)) { + v.checkcast(toType); } else - box(this.type, type, v); + box(fromType, toType, v); } - else if (this.type.getSort() == Type.OBJECT && type.getSort() <= Type.DOUBLE) { - if (this.type.equals(JetTypeMapper.TYPE_OBJECT)) { - if (type.getSort() == Type.BOOLEAN) { + else if (fromType.getSort() == Type.OBJECT && toType.getSort() <= Type.DOUBLE) { + if (fromType.equals(JetTypeMapper.TYPE_OBJECT)) { + if (toType.getSort() == Type.BOOLEAN) { v.checkcast(JvmPrimitiveType.BOOLEAN.getWrapper().getAsmType()); } - else if (type.getSort() == Type.CHAR) { + else if (toType.getSort() == Type.CHAR) { v.checkcast(JvmPrimitiveType.CHAR.getWrapper().getAsmType()); } else { v.checkcast(JetTypeMapper.JL_NUMBER_TYPE); } } - unbox(type, v); + unbox(toType, v); } else { - v.cast(this.type, type); + v.cast(fromType, toType); } } @@ -329,7 +333,8 @@ public abstract class StackValue { } @Override - public void store(InstructionAdapter v) { + public void store(Type topOfStackType, InstructionAdapter v) { + coerce(topOfStackType, this.type, v); v.store(index, this.type); } } @@ -542,7 +547,7 @@ public abstract class StackValue { } @Override - public void store(InstructionAdapter v) { + public void store(Type topOfStackType, InstructionAdapter v) { onStack(type).coerce(boxed, v); v.astore(boxed); } @@ -594,14 +599,17 @@ public abstract class StackValue { } @Override - public void store(InstructionAdapter v) { + public void store(Type topOfStackType, InstructionAdapter v) { if (setter == null) { throw new UnsupportedOperationException("no setter specified"); } if(setter instanceof CallableMethod) { CallableMethod method = (CallableMethod) setter; + Method asmMethod = method.getSignature().getAsmMethod(); + Type[] argumentTypes = asmMethod.getArgumentTypes(); + coerce(topOfStackType, argumentTypes[argumentTypes.length-1], v); method.invoke(v); - Type returnType = method.getSignature().getAsmMethod().getReturnType(); + Type returnType = asmMethod.getReturnType(); if(returnType != Type.VOID_TYPE) { if(returnType.getSize() == 2) v.pop2(); @@ -816,7 +824,8 @@ public abstract class StackValue { } @Override - public void store(InstructionAdapter v) { + public void store(Type topOfStackType, InstructionAdapter v) { + coerce(topOfStackType, this.type, v); v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner.getInternalName(), name, this.type.getDescriptor()); } } @@ -873,7 +882,7 @@ public abstract class StackValue { } @Override - public void store(InstructionAdapter v) { + public void store(Type topOfStackType, InstructionAdapter v) { if(isSuper && isInterface) { v.visitMethodInsn(Opcodes.INVOKESTATIC, methodOwner.getInternalName(), setter.getName(), setter.getDescriptor().replace("(", "(" + methodOwnerParam.getDescriptor())); } @@ -932,7 +941,7 @@ public abstract class StackValue { } @Override - public void store(InstructionAdapter v) { + public void store(Type topOfStackType, InstructionAdapter v) { v.load(index, JetTypeMapper.TYPE_OBJECT); v.swap(); Type refType = refType(this.type); @@ -1012,7 +1021,8 @@ public abstract class StackValue { } @Override - public void store(InstructionAdapter v) { + public void store(Type topOfStackType, InstructionAdapter v) { + coerce(topOfStackType, v); v.visitFieldInsn(Opcodes.PUTFIELD, sharedTypeForType(type).getInternalName(), "ref", refType(type).getDescriptor()); } } @@ -1034,9 +1044,9 @@ public abstract class StackValue { } @Override - public void store(InstructionAdapter v) { + public void store(Type topOfStackType, InstructionAdapter v) { prefix.put(JetTypeMapper.TYPE_OBJECT, v); - suffix.store(v); + suffix.store(topOfStackType, v); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Increment.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Increment.java index 77c9544bba9..b52b262c5a0 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Increment.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Increment.java @@ -63,7 +63,7 @@ public class Increment implements IntrinsicMethod { value.put(expectedType, v); plusMinus(v, expectedType); - value.store(v); + value.store(expectedType, v); value.put(expectedType, v); } else { diff --git a/compiler/testData/codegen/regressions/kt1397.kt b/compiler/testData/codegen/regressions/kt1397.kt new file mode 100644 index 00000000000..9f61e573ed1 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt1397.kt @@ -0,0 +1,12 @@ +import java.util.ArrayList + +class IntArrayList(): ArrayList() { + override fun get(index: Int): Int = super.get(index)!! +} + +fun box(): String { + val a = IntArrayList() + a.add(1) + a[0]++ + return if (a[0] == 2) "OK" else "fail" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java index 7e587af3167..9556aa0bc59 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java @@ -436,4 +436,8 @@ public class PrimitiveTypesTest extends CodegenTestCase { public void testKt1634() { blackBoxFile("regressions/kt1634.kt"); } + + public void testKt1397() { + blackBoxFile("regressions/kt1397.kt"); + } }