Optimized iteration over primitive range expression.

This commit is contained in:
Evgeny Gerashchenko
2013-02-11 17:36:15 +04:00
parent 44e14c0a1c
commit 80b21524f4
2 changed files with 17 additions and 37 deletions
@@ -55,6 +55,7 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
import org.jetbrains.jet.lang.resolve.scopes.receivers.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
@@ -478,9 +479,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return StackValue.none(); return StackValue.none();
} }
else { else {
// todo: Only IntRange optimized so far if (RangeCodegenUtil.isRange(loopRangeType)) {
if (RangeCodegenUtil.isIntRange(loopRangeType)) { generateForLoop(new ForInRangeInstanceLoopGenerator(forExpression));
generateForLoop(new ForInIntRangeInstanceLoopGenerator(forExpression));
return StackValue.none(); return StackValue.none();
} }
@@ -909,49 +909,30 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
} }
} }
private class ForInIntRangeInstanceLoopGenerator extends AbstractForLoopGenerator { private class ForInRangeInstanceLoopGenerator extends AbstractForInRangeLoopGenerator {
private int endVar; private ForInRangeInstanceLoopGenerator(@NotNull JetForExpression forExpression) {
private ForInIntRangeInstanceLoopGenerator(
@NotNull JetForExpression forExpression
) {
super(forExpression); super(forExpression);
} }
@Override @Override
public void beforeLoop() { protected void storeRangeStartAndEnd() {
super.beforeLoop();
JetType loopRangeType = bindingContext.get(EXPRESSION_TYPE, forExpression.getLoopRange()); JetType loopRangeType = bindingContext.get(EXPRESSION_TYPE, forExpression.getLoopRange());
assert loopRangeType != null; assert loopRangeType != null;
Type asmLoopRangeType = asmType(loopRangeType); Type asmLoopRangeType = asmType(loopRangeType);
gen(forExpression.getLoopRange(), asmLoopRangeType); gen(forExpression.getLoopRange(), asmLoopRangeType);
v.dup(); v.dup();
v.invokevirtual(JET_INT_RANGE_TYPE.getInternalName(), "getStart", "()Ljava/lang/Integer;"); JvmPrimitiveType primitiveType = JvmPrimitiveType.getByAsmType(asmElementType);
StackValue.coerce(Type.getType("Ljava/lang/Integer;"), Type.INT_TYPE, v); assert primitiveType != null : asmElementType;
v.store(loopParameterVar, Type.INT_TYPE); Type asmWrapperType = primitiveType.getWrapper().getAsmType();
endVar = createLoopTempVariable(Type.INT_TYPE); v.invokevirtual(asmLoopRangeType.getInternalName(), "getStart", "()" + asmWrapperType.getDescriptor());
v.invokevirtual(JET_INT_RANGE_TYPE.getInternalName(), "getEnd", "()Ljava/lang/Integer;"); StackValue.coerce(asmWrapperType, asmElementType, v);
StackValue.coerce(Type.getType("Ljava/lang/Integer;"), Type.INT_TYPE, v); v.store(loopParameterVar, asmElementType);
v.store(endVar, Type.INT_TYPE);
}
@Override v.invokevirtual(asmLoopRangeType.getInternalName(), "getEnd", "()" + asmWrapperType.getDescriptor());
public void conditionAndJump(@NotNull Label loopExit) { StackValue.coerce(asmWrapperType, asmElementType, v);
v.load(loopParameterVar, Type.INT_TYPE); v.store(endVar, asmElementType);
v.load(endVar, Type.INT_TYPE);
v.ificmpgt(loopExit);
}
@Override
protected void assignToLoopParameter() {
}
@Override
protected void increment() {
v.iinc(loopParameterVar, 1);
} }
} }
@@ -42,9 +42,8 @@ public class RangeCodegenUtil {
private RangeCodegenUtil() {} private RangeCodegenUtil() {}
public static boolean isIntRange(JetType rangeType) { public static boolean isRange(JetType rangeType) {
return !rangeType.isNullable() return !rangeType.isNullable() && getPrimitiveRangeElementType(rangeType) != null;
&& KotlinBuiltIns.getInstance().getIntType().equals(getPrimitiveRangeElementType(rangeType));
} }
@Nullable @Nullable