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:
@@ -743,6 +743,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
// This method consumes range/progression from stack
|
// This method consumes range/progression from stack
|
||||||
// The result is stored to local variable
|
// The result is stored to local variable
|
||||||
protected void generateRangeOrProgressionProperty(Type loopRangeType, String getterName, Type elementType, int varToStore) {
|
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);
|
Type boxedType = boxType(elementType);
|
||||||
v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + boxedType.getDescriptor(), false);
|
v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + boxedType.getDescriptor(), false);
|
||||||
StackValue.coerce(boxedType, elementType, v);
|
StackValue.coerce(boxedType, elementType, v);
|
||||||
@@ -901,10 +906,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
private abstract class AbstractForInProgressionOrRangeLoopGenerator extends AbstractForLoopGenerator {
|
private abstract class AbstractForInProgressionOrRangeLoopGenerator extends AbstractForLoopGenerator {
|
||||||
protected int endVar;
|
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) {
|
private AbstractForInProgressionOrRangeLoopGenerator(@NotNull KtForExpression forExpression) {
|
||||||
super(forExpression);
|
super(forExpression);
|
||||||
|
|
||||||
@@ -914,12 +915,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
case Type.SHORT:
|
case Type.SHORT:
|
||||||
case Type.CHAR:
|
case Type.CHAR:
|
||||||
case Type.LONG:
|
case Type.LONG:
|
||||||
isIntegerProgression = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type.DOUBLE:
|
|
||||||
case Type.FLOAT:
|
|
||||||
isIntegerProgression = false;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -934,17 +929,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
endVar = createLoopTempVariable(asmElementType);
|
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) {
|
protected void checkPostCondition(@NotNull Label loopExit) {
|
||||||
int finalVar = getFinalVar();
|
assert endVar != -1 :
|
||||||
assert isIntegerProgression && finalVar != -1 :
|
"endVar must be allocated, endVar = " + endVar;
|
||||||
"Post-condition should be checked only in case of integer progressions, finalVar = " + finalVar;
|
|
||||||
|
|
||||||
v.load(loopParameterVar, asmElementType);
|
v.load(loopParameterVar, asmElementType);
|
||||||
v.load(finalVar, asmElementType);
|
v.load(endVar, asmElementType);
|
||||||
if (asmElementType.getSort() == Type.LONG) {
|
if (asmElementType.getSort() == Type.LONG) {
|
||||||
v.lcmp();
|
v.lcmp();
|
||||||
v.ifeq(loopExit);
|
v.ifeq(loopExit);
|
||||||
@@ -953,6 +943,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
v.ificmpeq(loopExit);
|
v.ificmpeq(loopExit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkPreCondition(@NotNull Label loopExit) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class AbstractForInRangeLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator {
|
private abstract class AbstractForInRangeLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator {
|
||||||
@@ -969,25 +963,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
protected abstract void storeRangeStartAndEnd();
|
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
|
@Override
|
||||||
public void checkEmptyLoop(@NotNull Label loopExit) {
|
public void checkEmptyLoop(@NotNull Label loopExit) {
|
||||||
if (!isIntegerProgression) return;
|
|
||||||
|
|
||||||
v.load(loopParameterVar, asmElementType);
|
v.load(loopParameterVar, asmElementType);
|
||||||
v.load(endVar, asmElementType);
|
v.load(endVar, asmElementType);
|
||||||
@@ -1006,9 +983,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void increment(@NotNull Label loopExit) {
|
protected void increment(@NotNull Label loopExit) {
|
||||||
if (isIntegerProgression) {
|
checkPostCondition(loopExit);
|
||||||
checkPostCondition(loopExit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (asmElementType == Type.INT_TYPE) {
|
if (asmElementType == Type.INT_TYPE) {
|
||||||
v.iinc(loopParameterVar, 1);
|
v.iinc(loopParameterVar, 1);
|
||||||
@@ -1055,8 +1030,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
gen(forExpression.getLoopRange(), asmLoopRangeType);
|
gen(forExpression.getLoopRange(), asmLoopRangeType);
|
||||||
v.dup();
|
v.dup();
|
||||||
|
|
||||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar);
|
// ranges inherit first and last from corresponding progressions
|
||||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar);
|
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 int incrementVar;
|
||||||
private Type incrementType;
|
private Type incrementType;
|
||||||
|
|
||||||
private int finalVar;
|
|
||||||
|
|
||||||
private ForInProgressionExpressionLoopGenerator(@NotNull KtForExpression forExpression) {
|
private ForInProgressionExpressionLoopGenerator(@NotNull KtForExpression forExpression) {
|
||||||
super(forExpression);
|
super(forExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int getFinalVar() {
|
|
||||||
return finalVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeLoop() {
|
public void beforeLoop() {
|
||||||
super.beforeLoop();
|
super.beforeLoop();
|
||||||
@@ -1094,66 +1063,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
v.dup();
|
v.dup();
|
||||||
v.dup();
|
v.dup();
|
||||||
|
|
||||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar);
|
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterVar);
|
||||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar);
|
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, endVar);
|
||||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getIncrement", incrementType, incrementVar);
|
generateRangeOrProgressionBoxedProperty(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkEmptyLoop(@NotNull Label loopExit) {
|
public void checkEmptyLoop(@NotNull Label loopExit) {
|
||||||
if (!isIntegerProgression) return;
|
|
||||||
|
|
||||||
v.load(loopParameterVar, asmElementType);
|
v.load(loopParameterVar, asmElementType);
|
||||||
v.load(endVar, asmElementType);
|
v.load(endVar, asmElementType);
|
||||||
@@ -1198,9 +1114,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void increment(@NotNull Label loopExit) {
|
protected void increment(@NotNull Label loopExit) {
|
||||||
if (isIntegerProgression) {
|
checkPostCondition(loopExit);
|
||||||
checkPostCondition(loopExit);
|
|
||||||
}
|
|
||||||
|
|
||||||
v.load(loopParameterVar, asmElementType);
|
v.load(loopParameterVar, asmElementType);
|
||||||
v.load(incrementVar, 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> RANGE_TO_ELEMENT_TYPE;
|
||||||
private static final ImmutableMap<FqName, PrimitiveType> PROGRESSION_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 {
|
static {
|
||||||
ImmutableMap.Builder<FqName, PrimitiveType> rangeBuilder = ImmutableMap.builder();
|
ImmutableMap.Builder<FqName, PrimitiveType> rangeBuilder = ImmutableMap.builder();
|
||||||
ImmutableMap.Builder<FqName, PrimitiveType> progressionBuilder = 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 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"));
|
FqName progressionClassFqName = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(primitiveType.getTypeName() + "Progression"));
|
||||||
rangeBuilder.put(rangeClassFqName, primitiveType);
|
rangeBuilder.put(rangeClassFqName, primitiveType);
|
||||||
|
|||||||
@@ -5,4 +5,6 @@ fun f() {
|
|||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
|
// 0 getFirst
|
||||||
|
// 0 getLast
|
||||||
@@ -5,4 +5,6 @@ fun f(a: Int, b: Int) {
|
|||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 0 getStart
|
// 0 getStart
|
||||||
// 0 getEnd
|
// 0 getEnd
|
||||||
|
// 0 getFirst
|
||||||
|
// 0 getLast
|
||||||
@@ -6,6 +6,6 @@ fun f() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 2 getStart
|
// 2 getFirst
|
||||||
// 2 getEnd
|
// 2 getLast
|
||||||
// 2 getIncrement
|
// 2 getIncrement
|
||||||
@@ -4,5 +4,7 @@ fun f(r: IntRange) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 0 iterator
|
// 0 iterator
|
||||||
// 1 getStart
|
// 0 getStart
|
||||||
// 1 getEnd
|
// 0 getEnd
|
||||||
|
// 1 getFirst
|
||||||
|
// 1 getLast
|
||||||
Reference in New Issue
Block a user