From 96f301fdecc982ced512b60b1e693ac72e456719 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Fri, 13 Nov 2015 05:29:55 +0300 Subject: [PATCH] Support only integer primitive ranges and progressions in optimized for loop codegen. Do not call getProgressionFinalElement, use new progression properties 'first' and 'last' instead. --- .../kotlin/codegen/ExpressionCodegen.java | 126 +++--------------- .../kotlin/codegen/RangeCodegenUtil.java | 13 +- .../forLoop/primitiveLiteralRange1.kt | 4 +- .../forLoop/primitiveLiteralRange2.kt | 4 +- .../forLoop/primitiveProgression.kt | 4 +- .../bytecodeText/forLoop/primitiveRange.kt | 6 +- 6 files changed, 44 insertions(+), 113 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 63f66027198..88446e6552e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -743,6 +743,11 @@ public class ExpressionCodegen extends KtVisitor 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 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 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 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 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 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 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 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 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 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 impleme @Override protected void increment(@NotNull Label loopExit) { - if (isIntegerProgression) { - checkPostCondition(loopExit); - } + checkPostCondition(loopExit); v.load(loopParameterVar, asmElementType); v.load(incrementVar, asmElementType); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.java index 0299c90bf70..b62455e226d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.java @@ -38,10 +38,21 @@ public class RangeCodegenUtil { private static final ImmutableMap RANGE_TO_ELEMENT_TYPE; private static final ImmutableMap 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 rangeBuilder = ImmutableMap.builder(); ImmutableMap.Builder 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); diff --git a/compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange1.kt b/compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange1.kt index 20fab8f182a..aad6cac37d4 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange1.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange1.kt @@ -5,4 +5,6 @@ fun f() { // 0 iterator // 0 getStart -// 0 getEnd \ No newline at end of file +// 0 getEnd +// 0 getFirst +// 0 getLast \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange2.kt b/compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange2.kt index 1455226d206..112e70eb779 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange2.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange2.kt @@ -5,4 +5,6 @@ fun f(a: Int, b: Int) { // 0 iterator // 0 getStart -// 0 getEnd \ No newline at end of file +// 0 getEnd +// 0 getFirst +// 0 getLast \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/primitiveProgression.kt b/compiler/testData/codegen/bytecodeText/forLoop/primitiveProgression.kt index 2dd83bf5baa..fc45b598102 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/primitiveProgression.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/primitiveProgression.kt @@ -6,6 +6,6 @@ fun f() { } // 0 iterator -// 2 getStart -// 2 getEnd +// 2 getFirst +// 2 getLast // 2 getIncrement \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/primitiveRange.kt b/compiler/testData/codegen/bytecodeText/forLoop/primitiveRange.kt index 2af7d7ff355..535e629cb53 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/primitiveRange.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/primitiveRange.kt @@ -4,5 +4,7 @@ fun f(r: IntRange) { } // 0 iterator -// 1 getStart -// 1 getEnd \ No newline at end of file +// 0 getStart +// 0 getEnd +// 1 getFirst +// 1 getLast \ No newline at end of file