Support only integer primitive ranges and progressions in optimized for loop codegen.

Do not call getProgressionFinalElement, use new progression properties 'first' and 'last' instead.
This commit is contained in:
Ilya Gorbunov
2015-11-13 05:29:55 +03:00
parent 5d4e72ed7f
commit 96f301fdec
6 changed files with 44 additions and 113 deletions
@@ -743,6 +743,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
// This method consumes range/progression from stack
// The result is stored to local variable
protected void generateRangeOrProgressionProperty(Type loopRangeType, String getterName, Type elementType, int varToStore) {
v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + elementType.getDescriptor(), false);
v.store(varToStore, elementType);
}
protected void generateRangeOrProgressionBoxedProperty(Type loopRangeType, String getterName, Type elementType, int varToStore) {
Type boxedType = boxType(elementType);
v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + boxedType.getDescriptor(), false);
StackValue.coerce(boxedType, elementType, v);
@@ -901,10 +906,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
private abstract class AbstractForInProgressionOrRangeLoopGenerator extends AbstractForLoopGenerator {
protected int endVar;
// For integer progressions instead of comparing loopParameterVar with endVar at the beginning of an iteration we check whether
// loopParameterVar == finalVar at the end of the iteration (and also if there should be any iterations at all, before the loop)
protected final boolean isIntegerProgression;
private AbstractForInProgressionOrRangeLoopGenerator(@NotNull KtForExpression forExpression) {
super(forExpression);
@@ -914,12 +915,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
case Type.SHORT:
case Type.CHAR:
case Type.LONG:
isIntegerProgression = true;
break;
case Type.DOUBLE:
case Type.FLOAT:
isIntegerProgression = false;
break;
default:
@@ -934,17 +929,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
endVar = createLoopTempVariable(asmElementType);
}
// Index of the local variable holding the actual last value of the loop parameter.
// For ranges it equals end, for progressions it's a function of start, end and increment
protected abstract int getFinalVar();
protected void checkPostCondition(@NotNull Label loopExit) {
int finalVar = getFinalVar();
assert isIntegerProgression && finalVar != -1 :
"Post-condition should be checked only in case of integer progressions, finalVar = " + finalVar;
assert endVar != -1 :
"endVar must be allocated, endVar = " + endVar;
v.load(loopParameterVar, asmElementType);
v.load(finalVar, asmElementType);
v.load(endVar, asmElementType);
if (asmElementType.getSort() == Type.LONG) {
v.lcmp();
v.ifeq(loopExit);
@@ -953,6 +943,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
v.ificmpeq(loopExit);
}
}
@Override
public void checkPreCondition(@NotNull Label loopExit) {
}
}
private abstract class AbstractForInRangeLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator {
@@ -969,25 +963,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
protected abstract void storeRangeStartAndEnd();
@Override
protected int getFinalVar() {
return endVar;
}
@Override
public void checkPreCondition(@NotNull Label loopExit) {
if (isIntegerProgression) return;
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType);
v.cmpg(asmElementType);
v.ifgt(loopExit);
}
@Override
public void checkEmptyLoop(@NotNull Label loopExit) {
if (!isIntegerProgression) return;
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType);
@@ -1006,9 +983,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Override
protected void increment(@NotNull Label loopExit) {
if (isIntegerProgression) {
checkPostCondition(loopExit);
}
checkPostCondition(loopExit);
if (asmElementType == Type.INT_TYPE) {
v.iinc(loopParameterVar, 1);
@@ -1055,8 +1030,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
gen(forExpression.getLoopRange(), asmLoopRangeType);
v.dup();
generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar);
// ranges inherit first and last from corresponding progressions
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, endVar);
}
}
@@ -1064,17 +1040,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
private int incrementVar;
private Type incrementType;
private int finalVar;
private ForInProgressionExpressionLoopGenerator(@NotNull KtForExpression forExpression) {
super(forExpression);
}
@Override
protected int getFinalVar() {
return finalVar;
}
@Override
public void beforeLoop() {
super.beforeLoop();
@@ -1094,66 +1063,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
v.dup();
v.dup();
generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getIncrement", incrementType, incrementVar);
storeFinalVar();
}
private void storeFinalVar() {
if (!isIntegerProgression) {
finalVar = -1;
return;
}
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType);
v.load(incrementVar, incrementType);
Type methodParamType = asmElementType.getSort() == Type.LONG ? Type.LONG_TYPE : Type.INT_TYPE;
v.invokestatic("kotlin/internal/ProgressionUtilKt", "getProgressionFinalElement",
Type.getMethodDescriptor(methodParamType, methodParamType, methodParamType, methodParamType), false);
finalVar = createLoopTempVariable(asmElementType);
v.store(finalVar, asmElementType);
}
@Override
public void checkPreCondition(@NotNull Label loopExit) {
if (isIntegerProgression) return;
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType);
v.load(incrementVar, incrementType);
Label negativeIncrement = new Label();
Label afterIf = new Label();
if (incrementType.getSort() == Type.DOUBLE) {
v.dconst(0.0);
}
else {
v.fconst(0.0f);
}
v.cmpl(incrementType);
v.ifle(negativeIncrement); // if increment < 0, jump
// increment > 0
v.cmpg(asmElementType); // if loop parameter is NaN, exit from loop, as well
v.ifgt(loopExit);
v.goTo(afterIf);
// increment < 0
v.mark(negativeIncrement);
v.cmpl(asmElementType); // if loop parameter is NaN, exit from loop, as well
v.iflt(loopExit);
v.mark(afterIf);
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterVar);
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, endVar);
generateRangeOrProgressionBoxedProperty(asmLoopRangeType, "getIncrement", incrementType, incrementVar);
}
@Override
public void checkEmptyLoop(@NotNull Label loopExit) {
if (!isIntegerProgression) return;
v.load(loopParameterVar, asmElementType);
v.load(endVar, asmElementType);
@@ -1198,9 +1114,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Override
protected void increment(@NotNull Label loopExit) {
if (isIntegerProgression) {
checkPostCondition(loopExit);
}
checkPostCondition(loopExit);
v.load(loopParameterVar, asmElementType);
v.load(incrementVar, asmElementType);
@@ -38,10 +38,21 @@ public class RangeCodegenUtil {
private static final ImmutableMap<FqName, PrimitiveType> RANGE_TO_ELEMENT_TYPE;
private static final ImmutableMap<FqName, PrimitiveType> PROGRESSION_TO_ELEMENT_TYPE;
private static PrimitiveType[] supportedRangeTypes() {
return new PrimitiveType[] {
PrimitiveType.CHAR,
PrimitiveType.INT,
PrimitiveType.LONG,
// deprecated:
PrimitiveType.BYTE,
PrimitiveType.SHORT,
};
}
static {
ImmutableMap.Builder<FqName, PrimitiveType> rangeBuilder = ImmutableMap.builder();
ImmutableMap.Builder<FqName, PrimitiveType> progressionBuilder = ImmutableMap.builder();
for (PrimitiveType primitiveType : PrimitiveType.values()) {
for (PrimitiveType primitiveType : supportedRangeTypes()) {
FqName rangeClassFqName = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(primitiveType.getTypeName() + "Range"));
FqName progressionClassFqName = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(primitiveType.getTypeName() + "Progression"));
rangeBuilder.put(rangeClassFqName, primitiveType);
@@ -5,4 +5,6 @@ fun f() {
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getEnd
// 0 getFirst
// 0 getLast
@@ -5,4 +5,6 @@ fun f(a: Int, b: Int) {
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getEnd
// 0 getFirst
// 0 getLast
@@ -6,6 +6,6 @@ fun f() {
}
// 0 iterator
// 2 getStart
// 2 getEnd
// 2 getFirst
// 2 getLast
// 2 getIncrement
@@ -4,5 +4,7 @@ fun f(r: IntRange) {
}
// 0 iterator
// 1 getStart
// 1 getEnd
// 0 getStart
// 0 getEnd
// 1 getFirst
// 1 getLast