From 224848163dcd0f1d8eadf43a5c305d14164beb02 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Thu, 6 Jul 2017 11:19:58 +0300 Subject: [PATCH] Use InContinuousRangeExpressionGenerator for primitive range intrinsics --- .../kotlin/codegen/RangeCodegenUtil.kt | 21 ++-- .../jetbrains/kotlin/codegen/codegenUtil.kt | 8 +- .../codegen/range/ArrayIndicesRangeValue.kt | 27 ++++- .../range/CharSequenceIndicesRangeValue.kt | 27 ++++- .../range/CollectionIndicesRangeValue.kt | 27 ++++- .../range/ComparableRangeLiteralRangeValue.kt | 4 +- .../range/DownToProgressionRangeValue.kt | 21 +++- ...PrimitiveNumberRangeIntrinsicRangeValue.kt | 3 + .../PrimitiveNumberRangeLiteralRangeValue.kt | 4 +- .../range/PrimitiveNumberUntilRangeValue.kt | 13 ++- .../kotlin/codegen/range/RangeValues.kt | 10 +- .../codegen/range/SimpleBoundedValue.kt | 21 +++- ...PrimitiveNumberRangeExpressionGenerator.kt | 36 ------- ...RangeWithKnownBoundsExpressionGenerator.kt | 98 ------------------- .../inExpression/InArrayIndicesGenerator.kt | 42 -------- .../InCharSequenceIndicesGenerator.kt | 42 -------- .../InCollectionIndicesGenerator.kt | 42 -------- .../InPrimitiveNumberDownToGenerator.kt | 37 ------- .../InPrimitiveNumberUntilGenerator.kt | 37 ------- .../inRangeCheckWithConst.kt | 7 +- 20 files changed, 153 insertions(+), 374 deletions(-) delete mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/AbstractInPrimitiveNumberRangeExpressionGenerator.kt delete mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/AbstractInRangeWithKnownBoundsExpressionGenerator.kt delete mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InArrayIndicesGenerator.kt delete mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InCharSequenceIndicesGenerator.kt delete mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InCollectionIndicesGenerator.kt delete mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InPrimitiveNumberDownToGenerator.kt delete mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InPrimitiveNumberUntilGenerator.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt index cc330bf7de4..5c325f9a319 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt @@ -191,19 +191,24 @@ private fun isTopLevelInPackage(descriptor: DeclarationDescriptor, name: String, return packageName == packageFqName } -fun getAsmRangeElementTypeForPrimitiveRange(rangeCallee: CallableDescriptor): Type { +fun getAsmRangeElementTypeForPrimitiveRangeOrProgression(rangeCallee: CallableDescriptor): Type { val rangeType = rangeCallee.returnType!! getPrimitiveRangeElementType(rangeType)?.let { return AsmTypes.valueTypeForPrimitive(it) } - val floatingPointElementType = getClosedFloatingPointRangeElementType(rangeType) ?: - throw AssertionError("Unexpected range type: $rangeType") - - return when { - KotlinBuiltIns.isDouble(floatingPointElementType) -> Type.DOUBLE_TYPE - KotlinBuiltIns.isFloat(floatingPointElementType) -> Type.FLOAT_TYPE - else -> throw AssertionError("Unexpected ClosedFloatingPointRange element type: $floatingPointElementType") + getPrimitiveProgressionElementType(rangeType)?.let { + return AsmTypes.valueTypeForPrimitive(it) } + + getClosedFloatingPointRangeElementType(rangeType)?.let { + when { + KotlinBuiltIns.isDouble(it) -> return Type.DOUBLE_TYPE + KotlinBuiltIns.isFloat(it) -> return Type.FLOAT_TYPE + else -> {} + } + } + + throw AssertionError("Unexpected range type: $rangeType") } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt index f509e2f2418..9ea01adde0c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt @@ -413,4 +413,10 @@ fun extractReificationArgument(type: KotlinType): Pair): StackValue = + generateReceiverValue(rangeCall.extensionReceiver ?: rangeCall.dispatchReceiver!!, false) + +fun ExpressionCodegen.generateCallSingleArgument(rangeCall: ResolvedCall): StackValue = + gen(ExpressionCodegen.getSingleArgumentExpression(rangeCall)!!) \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/ArrayIndicesRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/ArrayIndicesRangeValue.kt index e80992e0104..a63fbb56db5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/ArrayIndicesRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/ArrayIndicesRangeValue.kt @@ -17,17 +17,38 @@ package org.jetbrains.kotlin.codegen.range import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.codegen.generateCallReceiver +import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForPrimitiveType import org.jetbrains.kotlin.codegen.range.forLoop.ForInArrayIndicesRangeLoopGenerator -import org.jetbrains.kotlin.codegen.range.inExpression.InArrayIndicesGenerator +import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.org.objectweb.asm.Type + +class ArrayIndicesRangeValue( + codegen: ExpressionCodegen, + rangeCall: ResolvedCall +): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { + private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType) + private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall) + + private val boundedValue = + SimpleBoundedValue( + codegen, rangeCall, + lowBound = StackValue.constant(0, asmElementType), + highBound = StackValue.operation(Type.INT_TYPE) { v -> + codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v) + v.arraylength() + } + ) -class ArrayIndicesRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInArrayIndicesRangeLoopGenerator(codegen, forExpression, rangeCall) override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) = - InArrayIndicesGenerator(codegen, operatorReference, rangeCall) + InContinuousRangeExpressionGenerator(operatorReference, boundedValue, comparisonGenerator) } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CharSequenceIndicesRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CharSequenceIndicesRangeValue.kt index 5935705ca19..23520c86b4f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CharSequenceIndicesRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CharSequenceIndicesRangeValue.kt @@ -17,17 +17,38 @@ package org.jetbrains.kotlin.codegen.range import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.codegen.generateCallReceiver +import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForPrimitiveType import org.jetbrains.kotlin.codegen.range.forLoop.ForInCharSequenceIndicesRangeLoopGenerator -import org.jetbrains.kotlin.codegen.range.inExpression.InCharSequenceIndicesGenerator +import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.org.objectweb.asm.Type + +class CharSequenceIndicesRangeValue( + codegen: ExpressionCodegen, + rangeCall: ResolvedCall +): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { + private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType) + private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall) + + private val boundedValue = + SimpleBoundedValue( + codegen, rangeCall, + lowBound = StackValue.constant(0, asmElementType), + highBound = StackValue.operation(Type.INT_TYPE) { v -> + codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v) + v.invokeinterface("java/lang/CharSequence", "length", "()I") + } + ) -class CharSequenceIndicesRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInCharSequenceIndicesRangeLoopGenerator(codegen, forExpression, rangeCall) override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) = - InCharSequenceIndicesGenerator(codegen, operatorReference, rangeCall) + InContinuousRangeExpressionGenerator(operatorReference, boundedValue, comparisonGenerator) } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CollectionIndicesRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CollectionIndicesRangeValue.kt index ba3b7210b7c..6b37bfcb499 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CollectionIndicesRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/CollectionIndicesRangeValue.kt @@ -17,17 +17,38 @@ package org.jetbrains.kotlin.codegen.range import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.codegen.generateCallReceiver +import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForPrimitiveType import org.jetbrains.kotlin.codegen.range.forLoop.ForInCollectionIndicesRangeLoopGenerator -import org.jetbrains.kotlin.codegen.range.inExpression.InCollectionIndicesGenerator +import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.org.objectweb.asm.Type + +class CollectionIndicesRangeValue( + codegen: ExpressionCodegen, + rangeCall: ResolvedCall +): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { + private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType) + private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall) + + private val boundedValue = + SimpleBoundedValue( + codegen, rangeCall, + lowBound = StackValue.constant(0, asmElementType), + highBound = StackValue.operation(Type.INT_TYPE) { v -> + codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v) + v.invokeinterface("java/util/Collection", "size", "()I") + } + ) -class CollectionIndicesRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInCollectionIndicesRangeLoopGenerator(codegen, forExpression, rangeCall) override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) = - InCollectionIndicesGenerator(codegen, operatorReference, rangeCall) + InContinuousRangeExpressionGenerator(operatorReference, boundedValue, comparisonGenerator) } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/ComparableRangeLiteralRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/ComparableRangeLiteralRangeValue.kt index 75cbc362eea..579fbaa689f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/ComparableRangeLiteralRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/ComparableRangeLiteralRangeValue.kt @@ -32,10 +32,10 @@ import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter class ComparableRangeLiteralRangeValue( - private val codegen: ExpressionCodegen, + codegen: ExpressionCodegen, rangeCall: ResolvedCall ) : CallIntrinsicRangeValue(rangeCall) { - private val boundedValue = SimpleBoundedValue(codegen, rangeCall, isLowInclusive = true, isHighInclusive = true) + private val boundedValue = SimpleBoundedValue(codegen, rangeCall) override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = IteratorForLoopGenerator(codegen, forExpression) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/DownToProgressionRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/DownToProgressionRangeValue.kt index dd7fc915885..d159f2b0574 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/DownToProgressionRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/DownToProgressionRangeValue.kt @@ -17,17 +17,32 @@ package org.jetbrains.kotlin.codegen.range import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.generateCallReceiver +import org.jetbrains.kotlin.codegen.generateCallSingleArgument +import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForPrimitiveType import org.jetbrains.kotlin.codegen.range.forLoop.ForInDownToProgressionLoopGenerator -import org.jetbrains.kotlin.codegen.range.inExpression.InPrimitiveNumberDownToGenerator +import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -class DownToProgressionRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { +class DownToProgressionRangeValue( + codegen: ExpressionCodegen, + rangeCall: ResolvedCall +): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { + private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType) + + private val boundedValue = + SimpleBoundedValue( + codegen, rangeCall, + lowBound = codegen.generateCallSingleArgument(rangeCall), + highBound = codegen.generateCallReceiver(rangeCall) + ) + override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInDownToProgressionLoopGenerator(codegen, forExpression, rangeCall) override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) = - InPrimitiveNumberDownToGenerator(codegen, operatorReference, rangeCall) + InContinuousRangeExpressionGenerator(operatorReference, boundedValue, comparisonGenerator) } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeIntrinsicRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeIntrinsicRangeValue.kt index a48c8c2f666..55049555bea 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeIntrinsicRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeIntrinsicRangeValue.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.codegen.range +import org.jetbrains.kotlin.codegen.getAsmRangeElementTypeForPrimitiveRangeOrProgression import org.jetbrains.kotlin.codegen.isClosedFloatingPointRangeContains import org.jetbrains.kotlin.codegen.isIntPrimitiveRangeExtensionForInt import org.jetbrains.kotlin.codegen.isPrimitiveRangeContains @@ -23,6 +24,8 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall abstract class PrimitiveNumberRangeIntrinsicRangeValue(rangeCall: ResolvedCall): CallIntrinsicRangeValue(rangeCall) { + protected val asmElementType = getAsmRangeElementTypeForPrimitiveRangeOrProgression(rangeCall.resultingDescriptor) + override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall) = resolvedCallForIn.resultingDescriptor.let { isPrimitiveRangeContains(it) || diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeLiteralRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeLiteralRangeValue.kt index d41c04bfd6a..d1a307755f7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeLiteralRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeLiteralRangeValue.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.codegen.range import org.jetbrains.kotlin.codegen.ExpressionCodegen -import org.jetbrains.kotlin.codegen.getAsmRangeElementTypeForPrimitiveRange import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForPrimitiveType import org.jetbrains.kotlin.codegen.range.forLoop.ForInRangeLiteralLoopGenerator import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator @@ -30,9 +29,8 @@ class PrimitiveNumberRangeLiteralRangeValue( codegen: ExpressionCodegen, rangeCall: ResolvedCall ): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { - private val asmElementType = getAsmRangeElementTypeForPrimitiveRange(rangeCall.resultingDescriptor) private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType) - private val boundedValue = SimpleBoundedValue(codegen, rangeCall, isLowInclusive = true, isHighInclusive = true) + private val boundedValue = SimpleBoundedValue(codegen, rangeCall) override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInRangeLiteralLoopGenerator(codegen, forExpression, rangeCall) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberUntilRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberUntilRangeValue.kt index 001645b3e2d..08bac0b6684 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberUntilRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberUntilRangeValue.kt @@ -17,17 +17,24 @@ package org.jetbrains.kotlin.codegen.range import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForPrimitiveType import org.jetbrains.kotlin.codegen.range.forLoop.ForInUntilRangeLoopGenerator -import org.jetbrains.kotlin.codegen.range.inExpression.InPrimitiveNumberUntilGenerator +import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { +class PrimitiveNumberUntilRangeValue( + codegen: ExpressionCodegen, + rangeCall: ResolvedCall +): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { + private val comparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType) + private val boundedValue = SimpleBoundedValue(codegen, rangeCall, isLowInclusive = true, isHighInclusive = false) + override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInUntilRangeLoopGenerator(codegen, forExpression, rangeCall) override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression) = - InPrimitiveNumberUntilGenerator(codegen, operatorReference, rangeCall) + InContinuousRangeExpressionGenerator(operatorReference, boundedValue, comparisonGenerator) } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt index 14fc71f006b..9123d48799b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt @@ -86,15 +86,15 @@ private fun ExpressionCodegen.createIntrinsifiedRangeValueOrNull(rangeCall: Reso isPrimitiveNumberRangeTo(rangeCallee) -> PrimitiveNumberRangeLiteralRangeValue(this, rangeCall) isPrimitiveNumberDownTo(rangeCallee) -> - DownToProgressionRangeValue(rangeCall) + DownToProgressionRangeValue(this, rangeCall) isPrimitiveNumberUntil(rangeCallee) -> - PrimitiveNumberUntilRangeValue(rangeCall) + PrimitiveNumberUntilRangeValue(this, rangeCall) isArrayOrPrimitiveArrayIndices(rangeCallee) -> - ArrayIndicesRangeValue(rangeCall) + ArrayIndicesRangeValue(this, rangeCall) isCollectionIndices(rangeCallee) -> - CollectionIndicesRangeValue(rangeCall) + CollectionIndicesRangeValue(this, rangeCall) isCharSequenceIndices(rangeCallee) -> - CharSequenceIndicesRangeValue(rangeCall) + CharSequenceIndicesRangeValue(this, rangeCall) isComparableRangeTo(rangeCallee) -> ComparableRangeLiteralRangeValue(this, rangeCall) else -> diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/SimpleBoundedValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/SimpleBoundedValue.kt index 9a37658d292..5e33222801f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/SimpleBoundedValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/SimpleBoundedValue.kt @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.codegen.range import org.jetbrains.kotlin.codegen.ExpressionCodegen import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.codegen.generateCallReceiver +import org.jetbrains.kotlin.codegen.generateCallSingleArgument import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.org.objectweb.asm.Type @@ -34,17 +36,24 @@ class SimpleBoundedValue( constructor( codegen: ExpressionCodegen, rangeCall: ResolvedCall, - isLowInclusive: Boolean, - isHighInclusive: Boolean + isLowInclusive: Boolean = true, + isHighInclusive: Boolean = true ) : this( codegen, rangeCall, - codegen.generateReceiverValue(rangeCall.extensionReceiver ?: rangeCall.dispatchReceiver!!, false), + codegen.generateCallReceiver(rangeCall), isLowInclusive, - codegen.gen(ExpressionCodegen.getSingleArgumentExpression(rangeCall)!!), + codegen.generateCallSingleArgument(rangeCall), isHighInclusive ) + constructor( + codegen: ExpressionCodegen, + rangeCall: ResolvedCall, + lowBound: StackValue, + highBound: StackValue + ) : this(codegen, rangeCall, lowBound, true, highBound, true) + override val instanceType: Type = codegen.asmType(rangeCall.resultingDescriptor.returnType!!) override fun putInstance(v: InstructionAdapter, type: Type) { @@ -55,4 +64,8 @@ class SimpleBoundedValue( highBound.put(type, v) lowBound.put(type, v) } + + companion object { + + } } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/AbstractInPrimitiveNumberRangeExpressionGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/AbstractInPrimitiveNumberRangeExpressionGenerator.kt deleted file mode 100644 index 9dfa0f966d6..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/AbstractInPrimitiveNumberRangeExpressionGenerator.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.codegen.range.inExpression - -import org.jetbrains.kotlin.codegen.ExpressionCodegen -import org.jetbrains.kotlin.codegen.getAsmRangeElementTypeForPrimitiveRange -import org.jetbrains.kotlin.codegen.range.comparison.* -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.org.objectweb.asm.Type - -abstract class AbstractInPrimitiveNumberRangeExpressionGenerator( - codegen: ExpressionCodegen, - operatorReference: KtSimpleNameExpression, - rangeCall: ResolvedCall<*>, - isInclusiveHighBound: Boolean -) : AbstractInRangeWithKnownBoundsExpressionGenerator( - codegen, operatorReference, isInclusiveHighBound, - getAsmRangeElementTypeForPrimitiveRange(rangeCall.resultingDescriptor) -) { - override val comparisonGenerator: ComparisonGenerator = getComparisonGeneratorForPrimitiveType(asmElementType) -} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/AbstractInRangeWithKnownBoundsExpressionGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/AbstractInRangeWithKnownBoundsExpressionGenerator.kt deleted file mode 100644 index 7c82f8ee57e..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/AbstractInRangeWithKnownBoundsExpressionGenerator.kt +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.codegen.range.inExpression - -import org.jetbrains.kotlin.codegen.* -import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.org.objectweb.asm.Label -import org.jetbrains.org.objectweb.asm.Opcodes -import org.jetbrains.org.objectweb.asm.Type -import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter - -abstract class AbstractInRangeWithKnownBoundsExpressionGenerator( - val codegen: ExpressionCodegen, - operatorReference: KtSimpleNameExpression, - protected val isInclusiveHighBound: Boolean, - protected val asmElementType: Type -) : InExpressionGenerator { - private val isNotIn = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN - - protected abstract fun genLowBound(): StackValue - protected abstract fun genHighBound(): StackValue - - protected abstract val comparisonGenerator: ComparisonGenerator - - override fun generate(argument: StackValue): BranchedValue = - gen(argument).let { if (isNotIn) Invert(it) else it } - - private fun gen(argument: StackValue): BranchedValue = - object : BranchedValue(argument, null, asmElementType, Opcodes.IFEQ) { - override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) { - if (jumpIfFalse) { - // arg1 in low .. high - // arg1 >= low && arg1 <[=] high - val cmpHighLabel = Label() - - arg1.put(operandType, v) - AsmUtil.dup(v, operandType) - - genLowBound().put(operandType, v) - comparisonGenerator.jumpIfGreaterOrEqual(v, cmpHighLabel) - - AsmUtil.pop(v, operandType) - v.goTo(jumpLabel) - - v.mark(cmpHighLabel) - genHighBound().put(operandType, v) - if (isInclusiveHighBound) { - comparisonGenerator.jumpIfGreater(v, jumpLabel) - } - else { - comparisonGenerator.jumpIfGreaterOrEqual(v, jumpLabel) - } - } - else { - // arg1 !in low .. high - // arg1 < low || arg1 >[=] high - val trueLabel1 = Label() - val trueLabel2 = Label() - - arg1.put(operandType, v) - AsmUtil.dup(v, operandType) - - genLowBound().put(operandType, v) - comparisonGenerator.jumpIfLess(v, trueLabel1) - - genHighBound().put(operandType, v) - if (isInclusiveHighBound) { - comparisonGenerator.jumpIfLessOrEqual(v, jumpLabel) - } - else { - comparisonGenerator.jumpIfLess(v, jumpLabel) - } - v.goTo(trueLabel2) - - v.mark(trueLabel1) - AsmUtil.pop(v, operandType) - - v.mark(trueLabel2) - } - } - } -} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InArrayIndicesGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InArrayIndicesGenerator.kt deleted file mode 100644 index 59d45fb07a6..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InArrayIndicesGenerator.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.codegen.range.inExpression - -import org.jetbrains.kotlin.codegen.ExpressionCodegen -import org.jetbrains.kotlin.codegen.StackValue -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.org.objectweb.asm.Type - -class InArrayIndicesGenerator( - codegen: ExpressionCodegen, - operatorReference: KtSimpleNameExpression, - rangeCall: ResolvedCall<*> -) : AbstractInPrimitiveNumberRangeExpressionGenerator(codegen, operatorReference, rangeCall, isInclusiveHighBound = false) { - private val receiverValue: ReceiverValue = rangeCall.extensionReceiver!! - private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall) - - override fun genLowBound(): StackValue = StackValue.constant(0, asmElementType) - - override fun genHighBound(): StackValue = - StackValue.operation(Type.INT_TYPE) { v -> - codegen.generateReceiverValue(receiverValue, false).put(codegen.asmType(expectedReceiverType), v) - v.arraylength() - } -} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InCharSequenceIndicesGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InCharSequenceIndicesGenerator.kt deleted file mode 100644 index a012bae07a6..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InCharSequenceIndicesGenerator.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.codegen.range.inExpression - -import org.jetbrains.kotlin.codegen.ExpressionCodegen -import org.jetbrains.kotlin.codegen.StackValue -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.org.objectweb.asm.Type - -class InCharSequenceIndicesGenerator( - codegen: ExpressionCodegen, - operatorReference: KtSimpleNameExpression, - rangeCall: ResolvedCall<*> -) : AbstractInPrimitiveNumberRangeExpressionGenerator(codegen, operatorReference, rangeCall, isInclusiveHighBound = false) { - private val receiverValue: ReceiverValue = rangeCall.extensionReceiver!! - private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall) - - override fun genLowBound(): StackValue = StackValue.constant(0, asmElementType) - - override fun genHighBound(): StackValue = - StackValue.operation(Type.INT_TYPE) { v -> - codegen.generateReceiverValue(receiverValue, false).put(codegen.asmType(expectedReceiverType), v) - v.invokeinterface("java/lang/CharSequence", "length", "()I") - } -} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InCollectionIndicesGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InCollectionIndicesGenerator.kt deleted file mode 100644 index 87eadd80844..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InCollectionIndicesGenerator.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.codegen.range.inExpression - -import org.jetbrains.kotlin.codegen.ExpressionCodegen -import org.jetbrains.kotlin.codegen.StackValue -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.org.objectweb.asm.Type - -class InCollectionIndicesGenerator( - codegen: ExpressionCodegen, - operatorReference: KtSimpleNameExpression, - rangeCall: ResolvedCall<*> -) : AbstractInPrimitiveNumberRangeExpressionGenerator(codegen, operatorReference, rangeCall, isInclusiveHighBound = false) { - private val receiverValue: ReceiverValue = rangeCall.extensionReceiver!! - private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall) - - override fun genLowBound(): StackValue = StackValue.constant(0, asmElementType) - - override fun genHighBound(): StackValue = - StackValue.operation(Type.INT_TYPE) { v -> - codegen.generateReceiverValue(receiverValue, false).put(codegen.asmType(expectedReceiverType), v) - v.invokeinterface("java/util/Collection", "size", "()I") - } -} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InPrimitiveNumberDownToGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InPrimitiveNumberDownToGenerator.kt deleted file mode 100644 index b40bf3abab6..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InPrimitiveNumberDownToGenerator.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.codegen.range.inExpression - -import org.jetbrains.kotlin.codegen.ExpressionCodegen -import org.jetbrains.kotlin.codegen.StackValue -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue - -class InPrimitiveNumberDownToGenerator( - codegen: ExpressionCodegen, - operatorReference: KtSimpleNameExpression, - rangeCall: ResolvedCall<*> -) : AbstractInPrimitiveNumberRangeExpressionGenerator(codegen, operatorReference, rangeCall, isInclusiveHighBound = true) { - private val from: ReceiverValue = rangeCall.dispatchReceiver!! - private val to: KtExpression = ExpressionCodegen.getSingleArgumentExpression(rangeCall)!! - - override fun genLowBound(): StackValue = codegen.gen(to) - - override fun genHighBound(): StackValue = codegen.generateReceiverValue(from, false) -} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InPrimitiveNumberUntilGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InPrimitiveNumberUntilGenerator.kt deleted file mode 100644 index 78e2eb40776..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InPrimitiveNumberUntilGenerator.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.codegen.range.inExpression - -import org.jetbrains.kotlin.codegen.ExpressionCodegen -import org.jetbrains.kotlin.codegen.StackValue -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue - -class InPrimitiveNumberUntilGenerator( - codegen: ExpressionCodegen, - operatorReference: KtSimpleNameExpression, - rangeCall: ResolvedCall<*> -) : AbstractInPrimitiveNumberRangeExpressionGenerator(codegen, operatorReference, rangeCall, isInclusiveHighBound = false) { - private val from: ReceiverValue = rangeCall.extensionReceiver!! - private val to: KtExpression = ExpressionCodegen.getSingleArgumentExpression(rangeCall)!! - - override fun genLowBound(): StackValue = codegen.generateReceiverValue(from, false) - - override fun genHighBound(): StackValue = codegen.gen(to) -} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/coercionToUnitOptimization/inRangeCheckWithConst.kt b/compiler/testData/codegen/bytecodeText/coercionToUnitOptimization/inRangeCheckWithConst.kt index b2a20820ea2..4146e3d73ea 100644 --- a/compiler/testData/codegen/bytecodeText/coercionToUnitOptimization/inRangeCheckWithConst.kt +++ b/compiler/testData/codegen/bytecodeText/coercionToUnitOptimization/inRangeCheckWithConst.kt @@ -3,5 +3,8 @@ fun testPrimitiveArray(ints: IntArray) = 10 in ints.indices -// 0 DUP -// 0 POP \ No newline at end of file +// We currently fail to optimize this method because of DUP_X1 instruction generated for range check. +// TODO either don't generate DUP_X1/DUP2_X2 instructions for range checks (extra local variable + extra instructions), +// or support DUPn_Xm instructions in PopBackwardPropagationTransformer +// - 0 DUP +// - 0 POP \ No newline at end of file