correctly coerce values in StackValue.store() (KT-1397)

#KT-1397 fixed
This commit is contained in:
Dmitry Jemerov
2012-06-06 13:40:06 +02:00
parent 5eb11ae754
commit 6b84f5d31a
9 changed files with 82 additions and 49 deletions
@@ -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");
}
}