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() {
|
||||
return receiverParameterType != null;
|
||||
}
|
||||
|
||||
public Type getReturnType() {
|
||||
return signature.getAsmMethod().getReturnType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1650,7 +1650,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
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<StackValue, StackValue> {
|
||||
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<StackValue, StackValue> {
|
||||
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<StackValue, StackValue> {
|
||||
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<StackValue, StackValue> {
|
||||
}
|
||||
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<? 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());
|
||||
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<StackValue, StackValue> {
|
||||
|
||||
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<StackValue, StackValue> {
|
||||
v.iconst(increment);
|
||||
}
|
||||
v.add(asmType);
|
||||
value.store(v);
|
||||
value.store(asmType, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
blackBoxFile("regressions/kt1634.kt");
|
||||
}
|
||||
|
||||
public void testKt1397() {
|
||||
blackBoxFile("regressions/kt1397.kt");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user