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