From 3ad5e74abb65e5b9daec7774a577ce9cf106f6b6 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Wed, 2 Nov 2011 23:51:27 +0100 Subject: [PATCH] multi-index array expressions and related fixes --- .../jet/codegen/ExpressionCodegen.java | 141 ++++++++++-------- .../jet/codegen/FunctionCodegen.java | 3 +- .../jetbrains/jet/codegen/JetTypeMapper.java | 3 + .../org/jetbrains/jet/codegen/StackValue.java | 115 +++++++++----- .../jet/codegen/intrinsics/Increment.java | 2 +- .../jetbrains/jet/codegen/ArrayGenTest.java | 59 ++++++++ 6 files changed, 221 insertions(+), 102 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index ef356283043..545e9f9a791 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -52,7 +52,7 @@ public class ExpressionCodegen extends JetVisitor { private int myLastLineNumber = -1; private final InstructionAdapter v; - private final FrameMap myMap; + private final FrameMap myFrameMap; private final JetTypeMapper typeMapper; private final GenerationState state; @@ -68,7 +68,7 @@ public class ExpressionCodegen extends JetVisitor { Type returnType, ClassContext context, GenerationState state) { - this.myMap = myMap; + this.myFrameMap = myMap; this.typeMapper = state.getTypeMapper(); this.returnType = returnType; this.state = state; @@ -264,7 +264,7 @@ public class ExpressionCodegen extends JetVisitor { JetType paramType = parameterDescriptor.getOutType(); Type asmParamType = typeMapper.mapType(paramType); - int iteratorVar = myMap.enterTemp(); + int iteratorVar = myFrameMap.enterTemp(); gen(expression.getLoopRange(), loopRangeType); invokeFunctionNoParams(iteratorDescriptor, asmIterType, v); v.store(iteratorVar, asmIterType); @@ -289,7 +289,7 @@ public class ExpressionCodegen extends JetVisitor { } v.ifeq(end); - myMap.enter(parameterDescriptor, asmParamType.getSize()); + myFrameMap.enter(parameterDescriptor, asmParamType.getSize()); v.load(iteratorVar, asmIterType); invokeFunctionNoParams(nextDescriptor, asmParamType, v); @@ -304,10 +304,10 @@ public class ExpressionCodegen extends JetVisitor { v.goTo(begin); v.mark(end); - int paramIndex = myMap.leave(parameterDescriptor); + int paramIndex = myFrameMap.leave(parameterDescriptor); //noinspection ConstantConditions v.visitLocalVariable(loopParameter.getName(), asmParamType.getDescriptor(), null, begin, end, paramIndex); - myMap.leaveTemp(); + myFrameMap.leaveTemp(); myBreakTargets.pop(); myContinueTargets.pop(); } @@ -338,7 +338,7 @@ public class ExpressionCodegen extends JetVisitor { JetType paramType = parameterDescriptor.getOutType(); Type asmParamType = typeMapper.mapType(paramType); - myMap.enter(parameterDescriptor, asmParamType.getSize()); + myFrameMap.enter(parameterDescriptor, asmParamType.getSize()); generatePrologue(); Label condition = new Label(); @@ -358,7 +358,7 @@ public class ExpressionCodegen extends JetVisitor { v.mark(end); cleanupTemp(); - final int paramIndex = myMap.leave(parameterDescriptor); + final int paramIndex = myFrameMap.leave(parameterDescriptor); //noinspection ConstantConditions v.visitLocalVariable(expression.getLoopParameter().getName(), asmParamType.getDescriptor(), null, condition, end, paramIndex); myBreakTargets.pop(); @@ -386,11 +386,11 @@ public class ExpressionCodegen extends JetVisitor { @Override protected void generatePrologue() { - myLengthVar = myMap.enterTemp(); + myLengthVar = myFrameMap.enterTemp(); gen(expression.getLoopRange(), loopRangeType); v.arraylength(); v.store(myLengthVar, Type.INT_TYPE); - myIndexVar = myMap.enterTemp(); + myIndexVar = myFrameMap.enterTemp(); v.iconst(0); v.store(myIndexVar, Type.INT_TYPE); } @@ -414,7 +414,7 @@ public class ExpressionCodegen extends JetVisitor { } protected void cleanupTemp() { - myMap.leaveTemp(2); + myFrameMap.leaveTemp(2); } } @@ -427,7 +427,7 @@ public class ExpressionCodegen extends JetVisitor { @Override protected void generatePrologue() { - myEndVar = myMap.enterTemp(); + myEndVar = myFrameMap.enterTemp(); if(isIntRangeExpr(expression.getLoopRange())) { JetBinaryExpression rangeExpression = (JetBinaryExpression) expression.getLoopRange(); //noinspection ConstantConditions @@ -461,7 +461,7 @@ public class ExpressionCodegen extends JetVisitor { @Override protected void cleanupTemp() { - myMap.leaveTemp(1); + myFrameMap.leaveTemp(1); } } @@ -634,7 +634,7 @@ public class ExpressionCodegen extends JetVisitor { final Type sharedVarType = getSharedVarType(variableDescriptor); final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType()); - myMap.enter(variableDescriptor, type.getSize()); + myFrameMap.enter(variableDescriptor, type.getSize()); } } @@ -658,7 +658,7 @@ public class ExpressionCodegen extends JetVisitor { VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var); assert variableDescriptor != null; - int index = myMap.leave(variableDescriptor); + int index = myFrameMap.leave(variableDescriptor); final Type sharedVarType = getSharedVarType(variableDescriptor); final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType()); @@ -859,7 +859,7 @@ public class ExpressionCodegen extends JetVisitor { } public int lookupLocal(DeclarationDescriptor descriptor) { - return myMap.getIndex(descriptor); + return myFrameMap.getIndex(descriptor); } public void invokeFunctionNoParams(FunctionDescriptor functionDescriptor, Type type, InstructionAdapter v) { @@ -1122,8 +1122,8 @@ public class ExpressionCodegen extends JetVisitor { if (isSubclass((ClassDescriptor) curContextType, calleeContainingClass)) break; final StackValue outer; - if (!thisDone && myMap instanceof ConstructorFrameMap) { - outer = StackValue.local(((ConstructorFrameMap) myMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT); + if (!thisDone && myFrameMap instanceof ConstructorFrameMap) { + outer = StackValue.local(((ConstructorFrameMap) myFrameMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT); } else { thisToStack(); @@ -1188,12 +1188,12 @@ public class ExpressionCodegen extends JetVisitor { else if(resolvedValueArgument instanceof VarargValueArgument) { VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument; JetType outType = valueParameterDescriptor.getOutType(); - + Type type = typeMapper.mapType(outType); assert type.getSort() == Type.ARRAY; Type elementType = type.getElementType(); int size = valueArgument.getArgumentExpressions().size(); - + v.iconst(valueArgument.getArgumentExpressions().size()); v.newarray(elementType); for(int i = 0; i != size; ++i) { @@ -1202,7 +1202,7 @@ public class ExpressionCodegen extends JetVisitor { gen(valueArgument.getArgumentExpressions().get(i), elementType); StackValue.arrayElement(elementType, false).store(v); } - + // throw new UnsupportedOperationException("Varargs are not supported yet"); } else { @@ -1631,12 +1631,20 @@ public class ExpressionCodegen extends JetVisitor { DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); final Callable callable = resolveToCallable(op); final JetExpression lhs = expression.getLeft(); + +// if(lhs instanceof JetArrayAccessExpression) { +// JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) lhs; +// if(arrayAccessExpression.getIndexExpressions().size() != 1) { +// throw new UnsupportedOperationException("Augmented assignment with multi-index"); +// } +// } + Type lhsType = expressionType(lhs); //noinspection ConstantConditions if (bindingContext.get(BindingContext.VARIABLE_REASSIGNMENT, expression)) { if (callable instanceof IntrinsicMethod) { StackValue value = gen(lhs); // receiver - value.dupReceiver(v, 0); // receiver receiver + value.dupReceiver(v); // receiver receiver value.put(lhsType, v); // receiver lhs final IntrinsicMethod intrinsic = (IntrinsicMethod) callable; //noinspection NullableProblems @@ -1659,7 +1667,7 @@ public class ExpressionCodegen extends JetVisitor { private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, final boolean keepReturnValue) { StackValue value = gen(expression.getLeft()); if (keepReturnValue) { - value.dupReceiver(v, 0); + value.dupReceiver(v); } value.put(lhsType, v); genToJVMStack(expression.getRight()); @@ -1747,7 +1755,7 @@ public class ExpressionCodegen extends JetVisitor { } } StackValue value = genQualified(receiver, operand); - value.dupReceiver(v, 0); + value.dupReceiver(v); value.put(asmType, v); if (asmType == Type.LONG_TYPE) { //noinspection UnnecessaryBoxing @@ -1914,7 +1922,7 @@ public class ExpressionCodegen extends JetVisitor { } if(args.size() == 2) { - int sizeIndex = myMap.enterTemp(2); + int sizeIndex = myFrameMap.enterTemp(2); int indexIndex = sizeIndex+1; v.dup(); @@ -1946,7 +1954,7 @@ public class ExpressionCodegen extends JetVisitor { v.visitLabel(end); v.pop(); - myMap.leaveTemp(2); + myFrameMap.leaveTemp(2); } } @@ -1956,8 +1964,12 @@ public class ExpressionCodegen extends JetVisitor { JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array); final Type arrayType = type == null ? Type.VOID_TYPE : typeMapper.mapType(type); gen(array, arrayType); - generateArrayIndex(expression); - if (arrayType.getSort() == Type.ARRAY) { + final List indices = expression.getIndexExpressions(); + FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression); + if (arrayType.getSort() == Type.ARRAY && indices.size() == 1 && operationDescriptor.getValueParameters().get(0).getOutType().equals(state.getStandardLibrary().getIntType())) { + for (JetExpression index : indices) { + gen(index, Type.INT_TYPE); + } if(state.getStandardLibrary().getArray().equals(type.getConstructor().getDeclarationDescriptor())) { JetType elementType = type.getArguments().get(0).getType(); Type notBoxed = typeMapper.mapType(elementType); @@ -1969,27 +1981,39 @@ public class ExpressionCodegen extends JetVisitor { } } else { - DeclarationDescriptor operationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression); - CallableMethod accessor = typeMapper.mapToCallableMethod((FunctionDescriptor) operationDescriptor, OwnerKind.IMPLEMENTATION); + CallableMethod accessor = typeMapper.mapToCallableMethod(operationDescriptor, OwnerKind.IMPLEMENTATION); boolean isGetter = accessor.getSignature().getName().equals("get"); + ResolvedCall resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression); + FunctionDescriptor setterDescriptor = resolvedSetCall == null ? null : resolvedSetCall.getResultingDescriptor(); + CallableMethod setter = resolvedSetCall == null ? null : typeMapper.mapToCallableMethod(setterDescriptor, OwnerKind.IMPLEMENTATION); + + ResolvedCall resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression); + FunctionDescriptor getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor(); + CallableMethod getter = resolvedGetCall == null ? null : typeMapper.mapToCallableMethod(getterDescriptor, OwnerKind.IMPLEMENTATION); + + Type asmType; + Type[] argumentTypes = accessor.getSignature().getArgumentTypes(); + int index = 0; if(isGetter) { - ResolvedCall resolvedCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression); - FunctionDescriptor setterDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor(); - return StackValue.collectionElement( - accessor.getSignature().getReturnType(), - accessor, - setterDescriptor != null ? typeMapper.mapToCallableMethod(setterDescriptor, OwnerKind.IMPLEMENTATION) : null); + if(getterDescriptor.getReceiverParameter().exists()) { + index++; + } + asmType = accessor.getSignature().getReturnType(); } else { - ResolvedCall resolvedCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression); - FunctionDescriptor getterDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor(); - return StackValue.collectionElement( - accessor.getSignature().getArgumentTypes()[1], - getterDescriptor != null ? typeMapper.mapToCallableMethod(getterDescriptor, OwnerKind.IMPLEMENTATION) : null, - accessor); + if(setterDescriptor.getReceiverParameter().exists()) { + index++; + } + asmType = argumentTypes[argumentTypes.length-1]; } + + for (JetExpression jetExpression : expression.getIndexExpressions()) { + gen(jetExpression, argumentTypes[index]); + index++; + } + return StackValue.collectionElement(asmType, getter, setter, myFrameMap); } } @@ -2033,13 +2057,6 @@ public class ExpressionCodegen extends JetVisitor { } } - private void generateArrayIndex(JetArrayAccessExpression expression) { - final List indices = expression.getIndexExpressions(); - for (JetExpression index : indices) { - gen(index, Type.INT_TYPE); - } - } - @Override public StackValue visitThrowExpression(JetThrowExpression expression, StackValue receiver) { gen(expression.getThrownExpression(), JetTypeMapper.TYPE_OBJECT); @@ -2082,21 +2099,21 @@ public class ExpressionCodegen extends JetVisitor { VariableDescriptor descriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, clause.getCatchParameter()); assert descriptor != null; Type descriptorType = typeMapper.mapType(descriptor.getOutType()); - myMap.enter(descriptor, 1); + myFrameMap.enter(descriptor, 1); int index = lookupLocal(descriptor); v.store(index, descriptorType); gen(clause.getCatchBody(), Type.VOID_TYPE); v.goTo(end); // TODO don't generate goto if there's no code following try/catch - myMap.leave(descriptor); + myFrameMap.leave(descriptor); v.visitTryCatchBlock(tryStart, tryEnd, clauseStart, descriptorType.getInternalName()); } if (finallyBlock != null) { Label finallyStart = new Label(); v.mark(finallyStart); - int index = myMap.enterTemp(); + int index = myFrameMap.enterTemp(); v.store(index, THROWABLE_TYPE); gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE); @@ -2104,7 +2121,7 @@ public class ExpressionCodegen extends JetVisitor { v.load(index, THROWABLE_TYPE); v.athrow(); - myMap.leaveTemp(); + myFrameMap.leaveTemp(); v.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null); } @@ -2159,7 +2176,7 @@ public class ExpressionCodegen extends JetVisitor { if (pattern instanceof JetTypePattern) { JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference(); JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference); - expressionToMatch.dupReceiver(v, 0); + expressionToMatch.dupReceiver(v); generateInstanceOf(expressionToMatch, jetType, false); StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE); return negated ? StackValue.not(value) : value; @@ -2169,7 +2186,7 @@ public class ExpressionCodegen extends JetVisitor { } else if (pattern instanceof JetExpressionPattern) { final Type subjectType = expressionToMatch.type; - expressionToMatch.dupReceiver(v, 0); + expressionToMatch.dupReceiver(v); expressionToMatch.put(subjectType, v); JetExpression condExpression = ((JetExpressionPattern) pattern).getExpression(); Type condType = isNumberPrimitive(subjectType) ? expressionType(condExpression) : OBJECT_TYPE; @@ -2184,10 +2201,10 @@ public class ExpressionCodegen extends JetVisitor { final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var); assert variableDescriptor != null; final Type varType = typeMapper.mapType(variableDescriptor.getOutType()); - myMap.enter(variableDescriptor, varType.getSize()); - expressionToMatch.dupReceiver(v, 0); + myFrameMap.enter(variableDescriptor, varType.getSize()); + expressionToMatch.dupReceiver(v); expressionToMatch.put(varType, v); - final int varIndex = myMap.getIndex(variableDescriptor); + final int varIndex = myFrameMap.getIndex(variableDescriptor); v.store(varIndex, varType); return generateWhenCondition(varType, varIndex, ((JetBindingPattern) pattern).getCondition(), null); } @@ -2202,7 +2219,7 @@ public class ExpressionCodegen extends JetVisitor { Label lblFail = new Label(); Label lblDone = new Label(); - expressionToMatch.dupReceiver(v, 0); + expressionToMatch.dupReceiver(v); expressionToMatch.put(OBJECT_TYPE, v); v.dup(); final String tupleClassName = "jet/Tuple" + entries.size(); @@ -2384,7 +2401,7 @@ public class ExpressionCodegen extends JetVisitor { public StackValue visitWhenExpression(JetWhenExpression expression, StackValue receiver) { JetExpression expr = expression.getSubjectExpression(); final Type subjectType = expressionType(expr); - final int subjectLocal = myMap.enterTemp(subjectType.getSize()); + final int subjectLocal = myFrameMap.enterTemp(subjectType.getSize()); gen(expr, subjectType); v.store(subjectLocal, subjectType); @@ -2396,7 +2413,7 @@ public class ExpressionCodegen extends JetVisitor { v.mark(nextCondition); } nextCondition = new Label(); - FrameMap.Mark mark = myMap.mark(); + FrameMap.Mark mark = myFrameMap.mark(); Label thisEntry = new Label(); if (!whenEntry.isElse()) { final JetWhenCondition[] conditions = whenEntry.getConditions(); @@ -2424,7 +2441,7 @@ public class ExpressionCodegen extends JetVisitor { } v.mark(end); - myMap.leaveTemp(subjectType.getSize()); + myFrameMap.leaveTemp(subjectType.getSize()); return StackValue.onStack(expressionType(expression)); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index cd05790af27..f71f58aef92 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -81,9 +81,10 @@ public class FunctionCodegen { ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state); Type[] argTypes = jvmSignature.getArgumentTypes(); + int add = functionDescriptor.getReceiverParameter().exists() ? state.getTypeMapper().mapType(functionDescriptor.getReceiverParameter().getType()).getSize() : 0; for (int i = 0; i < paramDescrs.size(); i++) { ValueParameterDescriptor parameter = paramDescrs.get(i); - frameMap.enter(parameter, argTypes[i].getSize()); + frameMap.enter(parameter, argTypes[i+add].getSize()); } for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 0d44f856737..ad1521696de 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -547,6 +547,9 @@ public class JetTypeMapper { } public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) { + if(functionDescriptor == null) + return null; + final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration(); final List valueParameterTypes = new ArrayList(); Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 5b2f2488b08..7938e019941 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -38,7 +38,7 @@ public abstract class StackValue { throw new UnsupportedOperationException("cannot store to value " + this); } - public void dupReceiver(InstructionAdapter v, int below) { + public void dupReceiver(InstructionAdapter v) { } public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { @@ -84,8 +84,8 @@ public abstract class StackValue { return new ArrayElement(type, unbox); } - public static StackValue collectionElement(Type type, CallableMethod getter, CallableMethod setter) { - return new CollectionElement(type, getter, setter); + public static StackValue collectionElement(Type type, CallableMethod getter, CallableMethod setter, FrameMap frame) { + return new CollectionElement(type, getter, setter, frame); } public static StackValue field(Type type, String owner, String name, boolean isStatic) { @@ -456,24 +456,21 @@ public abstract class StackValue { } @Override - public void dupReceiver(InstructionAdapter v, int below) { - if (below == 1) { - v.dup2X1(); - } - else { - v.dup2(); // array and index - } + public void dupReceiver(InstructionAdapter v) { + v.dup2(); // array and index } } private static class CollectionElement extends StackValue { private final CallableMethod getter; private final CallableMethod setter; + private final FrameMap frame; - public CollectionElement(Type type, CallableMethod getter, CallableMethod setter) { + public CollectionElement(Type type, CallableMethod getter, CallableMethod setter, FrameMap frame) { super(type); this.getter = getter; this.setter = setter; + this.frame = frame; } @Override @@ -494,13 +491,70 @@ public abstract class StackValue { } @Override - public void dupReceiver(InstructionAdapter v, int below) { - if (below == 1) { - v.dup2X1(); - } - else { + public void dupReceiver(InstructionAdapter v) { + int size = calcSize(); + + if(size == 2) { v.dup2(); // collection and index } + else { + Method signature = getter.getSignature(); + Type[] argumentTypes = signature.getArgumentTypes(); + + int firstIndex = frame.enterTemp(); + int lastIndex = firstIndex; + frame.leaveTemp(); + + for(int i = argumentTypes.length-1; i >= 0; i--) { + int sz = argumentTypes[i].getSize(); + frame.enterTemp(sz); + lastIndex += sz; + v.store(lastIndex-sz, argumentTypes[i]); + } + + if(getter.getInvokeOpcode() != Opcodes.INVOKESTATIC) { + frame.enterTemp(); + lastIndex++; + v.store(lastIndex-1, JetTypeMapper.TYPE_OBJECT); + } + + firstIndex = lastIndex; + int curIndex = lastIndex; + if(getter.getInvokeOpcode() != Opcodes.INVOKESTATIC) { + v.load(curIndex-1, JetTypeMapper.TYPE_OBJECT); + curIndex--; + } + + for(int i = 0; i != argumentTypes.length; i++) { + int sz = argumentTypes[i].getSize(); + v.load(curIndex-sz, argumentTypes[i]); + curIndex -= sz; + } + + curIndex = firstIndex; + if(getter.getInvokeOpcode() != Opcodes.INVOKESTATIC) { + v.load(curIndex-1, JetTypeMapper.TYPE_OBJECT); + curIndex--; + } + + for(int i = 0; i != argumentTypes.length; i++) { + int sz = argumentTypes[i].getSize(); + v.load(curIndex-sz, argumentTypes[i]); + curIndex -= sz; + } + + frame.leaveTemp(size); + } + } + + private int calcSize() { + assert getter != null; + int size = getter.getInvokeOpcode() == Opcodes.INVOKESTATIC ? 0 : 1; + Method signature = getter.getSignature(); + Type[] argumentTypes = signature.getArgumentTypes(); + for(int i = 0; i != argumentTypes.length; ++i) + size += argumentTypes[i].getSize(); + return size; } } @@ -523,14 +577,9 @@ public abstract class StackValue { } @Override - public void dupReceiver(InstructionAdapter v, int below) { + public void dupReceiver(InstructionAdapter v) { if (!isStatic) { - if (below == 1) { - v.dupX1(); - } - else { - v.dup(); - } + v.dup(); } } @@ -557,7 +606,7 @@ public abstract class StackValue { } @Override - public void dupReceiver(InstructionAdapter v, int below) { + public void dupReceiver(InstructionAdapter v) { } @Override @@ -607,14 +656,9 @@ public abstract class StackValue { } @Override - public void dupReceiver(InstructionAdapter v, int below) { + public void dupReceiver(InstructionAdapter v) { if (!isStatic) { - if (below == 1) { - v.dupX1(); - } - else { - v.dup(); - } + v.dup(); } } } @@ -716,13 +760,8 @@ public abstract class StackValue { } @Override - public void dupReceiver(InstructionAdapter v, int below) { - if (below == 1) { - v.dupX1(); - } - else { - v.dup(); - } + public void dupReceiver(InstructionAdapter v) { + v.dup(); } @Override 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 dfb68c2fd42..8c199a571a3 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Increment.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Increment.java @@ -32,7 +32,7 @@ public class Increment implements IntrinsicMethod { } } StackValue value = codegen.genQualified(receiver, operand); - value.dupReceiver(v, 0); + value. dupReceiver(v); value.put(expectedType, v); if (expectedType == Type.LONG_TYPE) { v.lconst(myDelta); diff --git a/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java index 6628d1d6358..de66903a8e9 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java @@ -107,4 +107,63 @@ public class ArrayGenTest extends CodegenTestCase { Method foo = generateFunction(); assertTrue((Integer)foo.invoke(null) == 12); } + + public void testCollectionAssignGetMultiIndex () throws Exception { + loadText("import java.util.ArrayList\n" + + "fun box() : String { val s = ArrayList(1); s.add(\"\"); s [1, -1] = \"5\"; s[2, -2] += \"7\"; return s[2,-2] }\n" + + "fun ArrayList.get(index1: Int, index2 : Int) = this[index1+index2]\n" + + "fun ArrayList.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem }\n"); + System.out.println(generateToText()); + Method foo = generateFunction("box"); + assertTrue(foo.invoke(null).equals("57")); + } + + public void testArrayGetAssignMultiIndex () throws Exception { + loadText( + "fun box() : String? { val s = Array(1,{ \"\" }); s [1, -1] = \"5\"; s[2, -2] += \"7\"; return s[-3,3] }\n" + + "fun Array.get(index1: Int, index2 : Int) = this[index1+index2]\n" + + "fun Array.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem\n }"); + System.out.println(generateToText()); + Method foo = generateFunction("box"); + assertTrue(foo.invoke(null).equals("57")); + } + + public void testCollectionGetMultiIndex () throws Exception { + loadText("import java.util.ArrayList\n" + + "fun box() : String { val s = ArrayList(1); s.add(\"\"); s [1, -1] = \"5\"; return s[2, -2] }\n" + + "fun ArrayList.get(index1: Int, index2 : Int) = this[index1+index2]\n" + + "fun ArrayList.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem }\n"); + System.out.println(generateToText()); + Method foo = generateFunction("box"); + assertTrue(foo.invoke(null).equals("5")); + } + + public void testArrayGetMultiIndex () throws Exception { + loadText( + "fun box() : String? { val s = Array(1,{ \"\" }); s [1, -1] = \"5\"; return s[-2, 2] }\n" + + "fun Array.get(index1: Int, index2 : Int) = this[index1+index2]\n" + + "fun Array.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem\n }"); + System.out.println(generateToText()); + Method foo = generateFunction("box"); + assertTrue(foo.invoke(null).equals("5")); + } + + public void testMap () throws Exception { + loadText( + "fun box() : Int? { val s = java.util.HashMap(); s[\"239\"] = 239; return s[\"239\"] }\n" + + "fun java.util.HashMap.set(index: String, elem: Int?) { this.put(index, elem) }"); + System.out.println(generateToText()); + Method foo = generateFunction("box"); + assertTrue((Integer)foo.invoke(null) == 239); + } + + public void testLongDouble () throws Exception { + loadText( + "fun box() : Int { var l = IntArray(1); l[0.lng] = 4; l[0.lng] += 6; return l[0.lng];}\n" + + "fun IntArray.set(index: Long, elem: Int) { this[index.int] = elem }\n" + + "fun IntArray.get(index: Long) = this[index.int]"); + System.out.println(generateToText()); + Method foo = generateFunction("box"); + assertTrue((Integer)foo.invoke(null) == 10); + } }