Minor: format code in org.jetbrains.kotlin.codegen.range

This commit is contained in:
Dmitry Petrov
2018-01-19 10:10:10 +03:00
parent f77586574f
commit 5c1321a29f
36 changed files with 658 additions and 681 deletions
@@ -24,10 +24,10 @@ import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
abstract class AbstractBoundedValue(
protected val codegen: ExpressionCodegen,
protected val rangeCall: ResolvedCall<out CallableDescriptor>,
override val isLowInclusive: Boolean = true,
override val isHighInclusive: Boolean = true
protected val codegen: ExpressionCodegen,
protected val rangeCall: ResolvedCall<out CallableDescriptor>,
override val isLowInclusive: Boolean = true,
override val isHighInclusive: Boolean = true
) : BoundedValue {
override val instanceType: Type = codegen.asmType(rangeCall.resultingDescriptor.returnType!!)
@@ -29,27 +29,27 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type
class ArrayIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(
codegen, rangeCall,
lowBound = StackValue.constant(0, asmElementType),
isLowInclusive = true,
highBound = StackValue.operation(Type.INT_TYPE) { v ->
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
v.arraylength()
},
isHighInclusive = false
)
SimpleBoundedValue(
codegen, rangeCall,
lowBound = StackValue.constant(0, asmElementType),
isLowInclusive = true,
highBound = StackValue.operation(Type.INT_TYPE) { v ->
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
v.arraylength()
},
isHighInclusive = false
)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen)
)
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen)
)
}
@@ -24,12 +24,12 @@ import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
class ArrayRangeValue(
private val canCacheArrayLength: Boolean,
private val shouldAlwaysStoreArrayInNewVar: Boolean
private val canCacheArrayLength: Boolean,
private val shouldAlwaysStoreArrayInNewVar: Boolean
) : RangeValue {
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInArrayLoopGenerator(codegen, forExpression, canCacheArrayLength, shouldAlwaysStoreArrayInNewVar)
ForInArrayLoopGenerator(codegen, forExpression, canCacheArrayLength, shouldAlwaysStoreArrayInNewVar)
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
CallBasedInExpressionGenerator(codegen, operatorReference)
CallBasedInExpressionGenerator(codegen, operatorReference)
}
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForRangeContainsCall
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
@@ -25,10 +24,14 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
abstract class CallIntrinsicRangeValue(protected val rangeCall: ResolvedCall<out CallableDescriptor>): RangeValue {
abstract class CallIntrinsicRangeValue(protected val rangeCall: ResolvedCall<out CallableDescriptor>) : RangeValue {
protected abstract fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>): Boolean
protected abstract fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression, resolvedCall: ResolvedCall<out CallableDescriptor>): InExpressionGenerator
protected abstract fun createIntrinsicInExpressionGenerator(
codegen: ExpressionCodegen,
operatorReference: KtSimpleNameExpression,
resolvedCall: ResolvedCall<out CallableDescriptor>
): InExpressionGenerator
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator {
val resolvedCall = operatorReference.getResolvedCallWithAssert(codegen.bindingContext)
@@ -28,27 +28,27 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type
class CharSequenceIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(
codegen, rangeCall,
lowBound = StackValue.constant(0, asmElementType),
isLowInclusive = true,
highBound = StackValue.operation(Type.INT_TYPE) { v ->
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
v.invokeinterface("java/lang/CharSequence", "length", "()I")
},
isHighInclusive = false
)
SimpleBoundedValue(
codegen, rangeCall,
lowBound = StackValue.constant(0, asmElementType),
isLowInclusive = true,
highBound = StackValue.operation(Type.INT_TYPE) { v ->
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
v.invokeinterface("java/lang/CharSequence", "length", "()I")
},
isHighInclusive = false
)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen)
)
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen)
)
}
@@ -26,8 +26,8 @@ import org.jetbrains.org.objectweb.asm.Type
class CharSequenceRangeValue(private val canCacheLength: Boolean, private val charSequenceClassType: Type?) : RangeValue {
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInCharSequenceLoopGenerator(codegen, forExpression, canCacheLength, charSequenceClassType)
ForInCharSequenceLoopGenerator(codegen, forExpression, canCacheLength, charSequenceClassType)
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
CallBasedInExpressionGenerator(codegen, operatorReference)
CallBasedInExpressionGenerator(codegen, operatorReference)
}
@@ -28,27 +28,27 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Type
class CollectionIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
private val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(rangeCall)
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(
codegen, rangeCall,
lowBound = StackValue.constant(0, asmElementType),
isLowInclusive = true,
highBound = StackValue.operation(Type.INT_TYPE) { v ->
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
v.invokeinterface("java/util/Collection", "size", "()I")
},
isHighInclusive = false
)
SimpleBoundedValue(
codegen, rangeCall,
lowBound = StackValue.constant(0, asmElementType),
isLowInclusive = true,
highBound = StackValue.operation(Type.INT_TYPE) { v ->
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), v)
v.invokeinterface("java/util/Collection", "size", "()I")
},
isHighInclusive = false
)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen)
)
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen)
)
}
@@ -26,20 +26,20 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
class ComparableRangeLiteralRangeValue(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>
) : CallIntrinsicRangeValue(rangeCall) {
private val boundedValue = SimpleBoundedValue(codegen, rangeCall)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
IteratorForLoopGenerator(codegen, forExpression)
IteratorForLoopGenerator(codegen, forExpression)
override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>) =
isClosedRangeContains(resolvedCallForIn.resultingDescriptor)
isClosedRangeContains(resolvedCallForIn.resultingDescriptor)
override fun createIntrinsicInExpressionGenerator(
codegen: ExpressionCodegen,
operatorReference: KtSimpleNameExpression,
resolvedCall: ResolvedCall<out CallableDescriptor>
codegen: ExpressionCodegen,
operatorReference: KtSimpleNameExpression,
resolvedCall: ResolvedCall<out CallableDescriptor>
) = InContinuousRangeOfComparableExpressionGenerator(operatorReference, boundedValue, codegen.frameMap)
}
@@ -28,49 +28,49 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getReceiverExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
class DownToProgressionRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(
codegen, rangeCall,
lowBound = codegen.generateCallSingleArgument(rangeCall),
highBound = codegen.generateCallReceiver(rangeCall)
)
SimpleBoundedValue(
codegen, rangeCall,
lowBound = codegen.generateCallSingleArgument(rangeCall),
highBound = codegen.generateCallReceiver(rangeCall)
)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
createConstBoundedForInDownToGenerator(codegen, forExpression) ?:
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(codegen, forExpression, getBoundedValue(codegen))
createConstBoundedForInDownToGenerator(codegen, forExpression)
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(codegen, forExpression, getBoundedValue(codegen))
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
createConstBoundedForInReversedDownToGenerator(codegen, forExpression) ?:
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(
createConstBoundedForInReversedDownToGenerator(codegen, forExpression)
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(
codegen, forExpression, getBoundedValue(codegen),
inverseBoundsEvaluationOrder = true
)
)
private fun createConstBoundedForInDownToGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression
codegen: ExpressionCodegen,
forExpression: KtForExpression
): ForLoopGenerator? {
val endExpression = rangeCall.getFirstArgumentExpression() ?: return null
return createConstBoundedForLoopGeneratorOrNull(
codegen, forExpression,
codegen.generateCallReceiver(rangeCall),
endExpression,
-1
codegen, forExpression,
codegen.generateCallReceiver(rangeCall),
endExpression,
-1
)
}
private fun createConstBoundedForInReversedDownToGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression
codegen: ExpressionCodegen,
forExpression: KtForExpression
): ForLoopGenerator? {
val endExpression = rangeCall.getReceiverExpression() ?: return null
return createConstBoundedForLoopGeneratorOrNull(
codegen, forExpression,
codegen.generateCallSingleArgument(rangeCall),
endExpression,
1
codegen, forExpression,
codegen.generateCallSingleArgument(rangeCall),
endExpression,
1
)
}
}
@@ -25,8 +25,8 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
class IterableRangeValue : RangeValue {
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
IteratorForLoopGenerator(codegen, forExpression)
IteratorForLoopGenerator(codegen, forExpression)
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
CallBasedInExpressionGenerator(codegen, operatorReference)
CallBasedInExpressionGenerator(codegen, operatorReference)
}
@@ -34,21 +34,21 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Type
abstract class PrimitiveNumberRangeIntrinsicRangeValue(
rangeCall: ResolvedCall<out CallableDescriptor>
): CallIntrinsicRangeValue(rangeCall) {
rangeCall: ResolvedCall<out CallableDescriptor>
) : CallIntrinsicRangeValue(rangeCall) {
protected val asmElementType = getAsmRangeElementTypeForPrimitiveRangeOrProgression(rangeCall.resultingDescriptor)
override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>) =
resolvedCallForIn.resultingDescriptor.let {
isPrimitiveRangeContains(it) ||
isClosedFloatingPointRangeContains(it) ||
isPrimitiveNumberRangeExtensionContainsPrimitiveNumber(it)
}
resolvedCallForIn.resultingDescriptor.let {
isPrimitiveRangeContains(it) ||
isClosedFloatingPointRangeContains(it) ||
isPrimitiveNumberRangeExtensionContainsPrimitiveNumber(it)
}
override fun createIntrinsicInExpressionGenerator(
codegen: ExpressionCodegen,
operatorReference: KtSimpleNameExpression,
resolvedCall: ResolvedCall<out CallableDescriptor>
codegen: ExpressionCodegen,
operatorReference: KtSimpleNameExpression,
resolvedCall: ResolvedCall<out CallableDescriptor>
): InExpressionGenerator {
val comparisonGenerator = getComparisonGeneratorForRangeContainsCall(codegen, resolvedCall)
val comparedType = comparisonGenerator?.comparedType
@@ -57,14 +57,14 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
comparisonGenerator == null -> CallBasedInExpressionGenerator(codegen, operatorReference)
comparedType == Type.DOUBLE_TYPE || comparedType == Type.FLOAT_TYPE -> {
val rangeLiteral = getBoundedValue(codegen) as? SimpleBoundedValue ?:
throw AssertionError("Floating point intrinsic range value should be a range literal")
val rangeLiteral = getBoundedValue(codegen) as? SimpleBoundedValue
?: throw AssertionError("Floating point intrinsic range value should be a range literal")
InFloatingPointRangeLiteralExpressionGenerator(operatorReference, rangeLiteral, comparisonGenerator, codegen.frameMap)
}
else ->
InIntegralContinuousRangeExpressionGenerator(
operatorReference, getBoundedValue(codegen), comparisonGenerator, codegen.frameMap
operatorReference, getBoundedValue(codegen), comparisonGenerator, codegen.frameMap
)
}
}
@@ -72,12 +72,12 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
protected abstract fun getBoundedValue(codegen: ExpressionCodegen): BoundedValue
protected fun createConstBoundedForLoopGeneratorOrNull(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
startValue: StackValue,
endExpression: KtExpression,
step: Int,
isStartInclusive: Boolean = true
codegen: ExpressionCodegen,
forExpression: KtForExpression,
startValue: StackValue,
endExpression: KtExpression,
step: Int,
isStartInclusive: Boolean = true
): ForLoopGenerator? {
val endConstValue = codegen.getCompileTimeConstant(endExpression).safeAs<IntegerValueConstant<*>>() ?: return null
@@ -127,46 +127,46 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
}
private fun createConstBoundedIntForLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
startValue: StackValue,
endIntValue: Int,
step: Int,
isStartInclusive: Boolean
codegen: ExpressionCodegen,
forExpression: KtForExpression,
startValue: StackValue,
endIntValue: Int,
step: Int,
isStartInclusive: Boolean
): ForLoopGenerator? =
ForInDefinitelySafeSimpleProgressionLoopGenerator(
codegen, forExpression,
startValue = startValue,
isStartInclusive = isStartInclusive,
endValue = StackValue.integerConstant(endIntValue, asmElementType),
isEndInclusive = true,
step = step
)
ForInDefinitelySafeSimpleProgressionLoopGenerator(
codegen, forExpression,
startValue = startValue,
isStartInclusive = isStartInclusive,
endValue = StackValue.integerConstant(endIntValue, asmElementType),
isEndInclusive = true,
step = step
)
private fun createConstBoundedLongForLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
startValue: StackValue,
endLongValue: Long,
step: Int,
isStartInclusive: Boolean
codegen: ExpressionCodegen,
forExpression: KtForExpression,
startValue: StackValue,
endLongValue: Long,
step: Int,
isStartInclusive: Boolean
): ForLoopGenerator? =
ForInDefinitelySafeSimpleProgressionLoopGenerator(
codegen, forExpression,
startValue = startValue,
isStartInclusive = isStartInclusive,
endValue = StackValue.constant(endLongValue, asmElementType),
isEndInclusive = true,
step = step
)
ForInDefinitelySafeSimpleProgressionLoopGenerator(
codegen, forExpression,
startValue = startValue,
isStartInclusive = isStartInclusive,
endValue = StackValue.constant(endLongValue, asmElementType),
isEndInclusive = true,
step = step
)
private fun isProhibitedCharConstEndValue(step: Int, endValue: Char) =
endValue == if (step == 1) java.lang.Character.MAX_VALUE else java.lang.Character.MIN_VALUE
endValue == if (step == 1) java.lang.Character.MAX_VALUE else java.lang.Character.MIN_VALUE
private fun isProhibitedIntConstEndValue(step: Int, endValue: Int) =
endValue == if (step == 1) Int.MAX_VALUE else Int.MIN_VALUE
endValue == if (step == 1) Int.MAX_VALUE else Int.MIN_VALUE
private fun isProhibitedLongConstEndValue(step: Int, endValue: Long) =
endValue == if (step == 1) Long.MAX_VALUE else Long.MIN_VALUE
endValue == if (step == 1) Long.MAX_VALUE else Long.MIN_VALUE
}
@@ -23,52 +23,52 @@ import org.jetbrains.kotlin.codegen.range.forLoop.ForInSimpleProgressionLoopGene
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getReceiverExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getFirstArgumentExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getReceiverExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
class PrimitiveNumberRangeLiteralRangeValue(
rangeCall: ResolvedCall<out CallableDescriptor>
rangeCall: ResolvedCall<out CallableDescriptor>
) : PrimitiveNumberRangeIntrinsicRangeValue(rangeCall),
ReversableRangeValue {
ReversableRangeValue {
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(codegen, rangeCall)
SimpleBoundedValue(codegen, rangeCall)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
createConstBoundedForInRangeLiteralGenerator(codegen, forExpression) ?:
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
createConstBoundedForInRangeLiteralGenerator(codegen, forExpression)
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
createConstBoundedRangeForInReversedRangeLiteralGenerator(codegen, forExpression) ?:
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
createConstBoundedRangeForInReversedRangeLiteralGenerator(codegen, forExpression)
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen),
inverseBoundsEvaluationOrder = true
)
)
private fun createConstBoundedForInRangeLiteralGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression
codegen: ExpressionCodegen,
forExpression: KtForExpression
): ForLoopGenerator? {
val endExpression = rangeCall.getFirstArgumentExpression() ?: return null
return createConstBoundedForLoopGeneratorOrNull(
codegen, forExpression,
codegen.generateCallReceiver(rangeCall),
endExpression,
1
codegen, forExpression,
codegen.generateCallReceiver(rangeCall),
endExpression,
1
)
}
private fun createConstBoundedRangeForInReversedRangeLiteralGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression
codegen: ExpressionCodegen,
forExpression: KtForExpression
): ForLoopGenerator? {
val endExpression = rangeCall.getReceiverExpression() ?: return null
return createConstBoundedForLoopGeneratorOrNull(
codegen, forExpression,
codegen.generateCallSingleArgument(rangeCall),
endExpression,
-1
codegen, forExpression,
codegen.generateCallSingleArgument(rangeCall),
endExpression,
-1
)
}
}
@@ -26,32 +26,32 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getReceiverExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
PrimitiveNumberRangeIntrinsicRangeValue(rangeCall), ReversableRangeValue {
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(codegen, rangeCall, isLowInclusive = true, isHighInclusive = false)
SimpleBoundedValue(codegen, rangeCall, isLowInclusive = true, isHighInclusive = false)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
createConstBoundedForInReversedUntilGenerator(codegen, forExpression) ?:
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
createConstBoundedForInReversedUntilGenerator(codegen, forExpression)
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen),
inverseBoundsEvaluationOrder = true
)
)
private fun createConstBoundedForInReversedUntilGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression
codegen: ExpressionCodegen,
forExpression: KtForExpression
): ForLoopGenerator? {
val endExpression = rangeCall.getReceiverExpression() ?: return null
return createConstBoundedForLoopGeneratorOrNull(
codegen, forExpression,
codegen.generateCallSingleArgument(rangeCall),
endExpression,
step = -1,
isStartInclusive = false
codegen, forExpression,
codegen.generateCallSingleArgument(rangeCall),
endExpression,
step = -1,
isStartInclusive = false
)
}
}
@@ -27,8 +27,8 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
class PrimitiveProgressionRangeValue(private val rangeExpression: KtExpression) : RangeValue {
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInProgressionExpressionLoopGenerator(codegen, forExpression, rangeExpression)
ForInProgressionExpressionLoopGenerator(codegen, forExpression, rangeExpression)
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
CallBasedInExpressionGenerator(codegen, operatorReference)
CallBasedInExpressionGenerator(codegen, operatorReference)
}
@@ -28,11 +28,11 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
class PrimitiveRangeRangeValue(private val rangeExpression: KtExpression) : ReversableRangeValue {
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInRangeInstanceLoopGenerator(codegen, forExpression, rangeExpression, reversed = false)
ForInRangeInstanceLoopGenerator(codegen, forExpression, rangeExpression, reversed = false)
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
CallBasedInExpressionGenerator(codegen, operatorReference)
CallBasedInExpressionGenerator(codegen, operatorReference)
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
ForInRangeInstanceLoopGenerator(codegen, forExpression, rangeExpression, reversed = true)
ForInRangeInstanceLoopGenerator(codegen, forExpression, rangeExpression, reversed = true)
}
@@ -51,8 +51,8 @@ interface BoundedValue {
}
fun BoundedValue.asStackValue(): StackValue =
object : StackValue(instanceType) {
override fun putSelector(type: Type, v: InstructionAdapter) {
putInstance(v, type)
}
object : StackValue(instanceType) {
override fun putSelector(type: Type, v: InstructionAdapter) {
putInstance(v, type)
}
}
@@ -51,10 +51,10 @@ fun ExpressionCodegen.createRangeValueForExpression(rangeExpression: KtExpressio
return when {
asmRangeType.sort == Type.ARRAY -> {
val properForInArraySemantics =
state.languageVersionSettings.supportsFeature(LanguageFeature.ProperForInArrayLoopRangeVariableAssignmentSemantic)
state.languageVersionSettings.supportsFeature(LanguageFeature.ProperForInArrayLoopRangeVariableAssignmentSemantic)
ArrayRangeValue(
properForInArraySemantics || !isLocalVarReference(rangeExpression, bindingContext),
properForInArraySemantics
properForInArraySemantics || !isLocalVarReference(rangeExpression, bindingContext),
properForInArraySemantics
)
}
@@ -75,20 +75,20 @@ fun isLocalVarReference(rangeExpression: KtExpression, bindingContext: BindingCo
if (rangeExpression !is KtSimpleNameExpression) return false
val resultingDescriptor = rangeExpression.getResolvedCall(bindingContext)?.resultingDescriptor ?: return false
return resultingDescriptor is LocalVariableDescriptor &&
resultingDescriptor !is SyntheticFieldDescriptor &&
!resultingDescriptor.isDelegated &&
resultingDescriptor.isVar
resultingDescriptor !is SyntheticFieldDescriptor &&
!resultingDescriptor.isDelegated &&
resultingDescriptor.isVar
}
private fun isSubtypeOfString(type: KotlinType, builtIns: KotlinBuiltIns) =
KotlinTypeChecker.DEFAULT.isSubtypeOf(type, builtIns.stringType)
KotlinTypeChecker.DEFAULT.isSubtypeOf(type, builtIns.stringType)
private fun isSubtypeOfCharSequence(type: KotlinType, builtIns: KotlinBuiltIns) =
KotlinTypeChecker.DEFAULT.isSubtypeOf(type, builtIns.getBuiltInClassByName(Name.identifier("CharSequence")).defaultType)
KotlinTypeChecker.DEFAULT.isSubtypeOf(type, builtIns.getBuiltInClassByName(Name.identifier("CharSequence")).defaultType)
private fun getResolvedCallForRangeExpression(
bindingContext: BindingContext,
rangeExpression: KtExpression
bindingContext: BindingContext,
rangeExpression: KtExpression
): ResolvedCall<out CallableDescriptor>? {
val expression = KtPsiUtil.deparenthesize(rangeExpression) ?: return null
@@ -24,11 +24,11 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
class ReversedRangeValue(private val original: ReversableRangeValue) : RangeValue, ReversableRangeValue {
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
original.createInExpressionGenerator(codegen, operatorReference)
original.createInExpressionGenerator(codegen, operatorReference)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
original.createForInReversedLoopGenerator(codegen, forExpression)
original.createForInReversedLoopGenerator(codegen, forExpression)
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
original.createForLoopGenerator(codegen, forExpression)
original.createForLoopGenerator(codegen, forExpression)
}
@@ -23,40 +23,39 @@ import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class SimpleBoundedValue(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>,
val lowBound: StackValue,
isLowInclusive: Boolean,
val highBound: StackValue,
isHighInclusive: Boolean
) : AbstractBoundedValue(codegen, rangeCall, isLowInclusive, isHighInclusive) {
constructor(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>,
val lowBound: StackValue,
isLowInclusive: Boolean,
val highBound: StackValue,
isHighInclusive: Boolean
): AbstractBoundedValue(codegen, rangeCall, isLowInclusive, isHighInclusive) {
constructor(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>,
isLowInclusive: Boolean = true,
isHighInclusive: Boolean = true
isLowInclusive: Boolean = true,
isHighInclusive: Boolean = true
) : this(
codegen,
rangeCall,
codegen.generateCallReceiver(rangeCall),
isLowInclusive,
codegen.generateCallSingleArgument(rangeCall),
isHighInclusive
codegen,
rangeCall,
codegen.generateCallReceiver(rangeCall),
isLowInclusive,
codegen.generateCallSingleArgument(rangeCall),
isHighInclusive
)
constructor(
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>,
lowBound: StackValue,
highBound: StackValue
codegen: ExpressionCodegen,
rangeCall: ResolvedCall<out CallableDescriptor>,
lowBound: StackValue,
highBound: StackValue
) : this(codegen, rangeCall, lowBound, true, highBound, true)
override fun putHighLow(v: InstructionAdapter, type: Type) {
if (!lowBound.canHaveSideEffects() || !highBound.canHaveSideEffects()) {
highBound.put(type, v)
lowBound.put(type, v)
}
else {
} else {
lowBound.put(type, v)
highBound.put(type, v)
AsmUtil.swap(v, type, type)
@@ -34,15 +34,18 @@ interface ComparisonGenerator {
}
fun getComparisonGeneratorForPrimitiveType(type: Type): ComparisonGenerator =
when {
type.isRepresentedAsPrimitiveInt() -> IntComparisonGenerator
type == Type.LONG_TYPE -> LongComparisonGenerator
type == Type.FLOAT_TYPE -> FloatComparisonGenerator
type == Type.DOUBLE_TYPE -> DoubleComparisonGenerator
else -> throw UnsupportedOperationException("Unexpected primitive type: " + type)
}
when {
type.isRepresentedAsPrimitiveInt() -> IntComparisonGenerator
type == Type.LONG_TYPE -> LongComparisonGenerator
type == Type.FLOAT_TYPE -> FloatComparisonGenerator
type == Type.DOUBLE_TYPE -> DoubleComparisonGenerator
else -> throw UnsupportedOperationException("Unexpected primitive type: " + type)
}
fun getComparisonGeneratorForRangeContainsCall(codegen: ExpressionCodegen, call: ResolvedCall<out CallableDescriptor>): ComparisonGenerator? {
fun getComparisonGeneratorForRangeContainsCall(
codegen: ExpressionCodegen,
call: ResolvedCall<out CallableDescriptor>
): ComparisonGenerator? {
val descriptor = call.resultingDescriptor
val receiverType = descriptor.extensionReceiverParameter?.type ?: descriptor.dispatchReceiverParameter?.type ?: return null
@@ -62,11 +65,11 @@ fun getComparisonGeneratorForRangeContainsCall(codegen: ExpressionCodegen, call:
IntComparisonGenerator
asmElementType.isRepresentedAsPrimitiveInt() && asmValueParameterType == Type.LONG_TYPE ||
asmValueParameterType.isRepresentedAsPrimitiveInt() && asmElementType == Type.LONG_TYPE ->
asmValueParameterType.isRepresentedAsPrimitiveInt() && asmElementType == Type.LONG_TYPE ->
LongComparisonGenerator
asmElementType == Type.FLOAT_TYPE && asmValueParameterType == Type.DOUBLE_TYPE ||
asmElementType == Type.DOUBLE_TYPE && asmValueParameterType == Type.FLOAT_TYPE ->
asmElementType == Type.DOUBLE_TYPE && asmValueParameterType == Type.FLOAT_TYPE ->
DoubleComparisonGenerator
else -> null
@@ -74,4 +77,4 @@ fun getComparisonGeneratorForRangeContainsCall(codegen: ExpressionCodegen, call:
}
private fun Type.isRepresentedAsPrimitiveInt() =
this == Type.INT_TYPE || this == Type.SHORT_TYPE || this == Type.BYTE_TYPE || this == Type.CHAR_TYPE
this == Type.INT_TYPE || this == Type.SHORT_TYPE || this == Type.BYTE_TYPE || this == Type.CHAR_TYPE
@@ -20,7 +20,7 @@ import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
sealed class FloatingPointComparisonGenerator(override val comparedType: Type): ComparisonGenerator {
sealed class FloatingPointComparisonGenerator(override val comparedType: Type) : ComparisonGenerator {
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
v.cmpg(comparedType)
v.ifge(label)
@@ -24,9 +24,8 @@ import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
abstract class AbstractForInProgressionLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression)
: AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression)
{
abstract class AbstractForInProgressionLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) :
AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression) {
protected var incrementVar: Int = -1
protected val asmLoopRangeType: Type
protected val incrementType: Type
@@ -73,8 +72,7 @@ abstract class AbstractForInProgressionLoopGenerator(codegen: ExpressionCodegen,
v.lcmp()
v.iflt(loopExit)
v.mark(afterIf)
}
else {
} else {
v.ifle(negativeIncrement) // if increment < 0, jump
// increment > 0
@@ -22,20 +22,19 @@ import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression)
: AbstractForLoopGenerator(codegen, forExpression)
{
abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) :
AbstractForLoopGenerator(codegen, forExpression) {
protected var endVar: Int = -1
private var loopParameter: StackValue? = null
init {
assert(
asmElementType.sort == Type.INT ||
asmElementType.sort == Type.BYTE ||
asmElementType.sort == Type.SHORT ||
asmElementType.sort == Type.CHAR ||
asmElementType.sort == Type.LONG
asmElementType.sort == Type.INT ||
asmElementType.sort == Type.BYTE ||
asmElementType.sort == Type.SHORT ||
asmElementType.sort == Type.CHAR ||
asmElementType.sort == Type.LONG
) {
"Unexpected range element type: " + asmElementType
}
@@ -56,8 +55,7 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC
if (asmElementType.sort == Type.LONG) {
v.lcmp()
v.ifeq(loopExit)
}
else {
} else {
v.ificmpeq(loopExit)
}
}
@@ -65,5 +63,5 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC
override fun checkPreCondition(loopExit: Label) {}
protected fun loopParameter(): StackValue =
loopParameter ?: StackValue.local(loopParameterVar, loopParameterType).also { loopParameter = it }
loopParameter ?: StackValue.local(loopParameterVar, loopParameterType).also { loopParameter = it }
}
@@ -16,18 +16,17 @@
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.AsmUtil.genIncrement
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.kotlin.codegen.AsmUtil.genIncrement
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
abstract class AbstractForInRangeLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
protected val step: Int
codegen: ExpressionCodegen,
forExpression: KtForExpression,
protected val step: Int
) : AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression) {
override fun beforeLoop() {
@@ -45,16 +44,13 @@ abstract class AbstractForInRangeLoopGenerator(
v.lcmp()
if (step > 0) {
v.ifgt(loopExit)
}
else {
} else {
v.iflt(loopExit)
}
}
else {
} else {
if (step > 0) {
v.ificmpgt(loopExit)
}
else {
} else {
v.ificmplt(loopExit)
}
}
@@ -71,8 +67,7 @@ abstract class AbstractForInRangeLoopGenerator(
protected fun incrementLoopVariable() {
if (loopParameterType === Type.INT_TYPE) {
v.iinc(loopParameterVar, step)
}
else {
} else {
val loopParameter = loopParameter()
loopParameter.put(asmElementType, v)
genIncrement(asmElementType, step, v)
@@ -29,8 +29,8 @@ import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
abstract class AbstractForLoopGenerator(
protected val codegen: ExpressionCodegen,
override val forExpression: KtForExpression
protected val codegen: ExpressionCodegen,
override val forExpression: KtForExpression
) : ForLoopGenerator {
protected val bindingContext = codegen.bindingContext
protected val v = codegen.v!!
@@ -47,8 +47,8 @@ abstract class AbstractForLoopGenerator(
private fun BindingContext.getElementType(forExpression: KtForExpression): KotlinType {
val loopRange = forExpression.loopRange!!
val nextCall = get(BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange) ?:
throw AssertionError("No next() function " + DiagnosticUtils.atLocation(loopRange))
val nextCall = get(BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange)
?: throw AssertionError("No next() function " + DiagnosticUtils.atLocation(loopRange))
return nextCall.resultingDescriptor.returnType!!
}
@@ -59,18 +59,19 @@ abstract class AbstractForLoopGenerator(
// E tmp<e> = tmp<iterator>.next()
loopParameterType = asmElementType
loopParameterVar = createLoopTempVariable(asmElementType)
}
else {
} else {
// E e = tmp<iterator>.next()
val parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, loopParameter)
loopParameterType = codegen.asmType(parameterDescriptor!!.type)
loopParameterVar = codegen.myFrameMap.enter(parameterDescriptor, loopParameterType)
scheduleLeaveVariable(Runnable {
codegen.myFrameMap.leave(parameterDescriptor)
v.visitLocalVariable(parameterDescriptor.name.asString(),
loopParameterType.descriptor, null,
loopParameterStartLabel, bodyEnd,
loopParameterVar)
v.visitLocalVariable(
parameterDescriptor.name.asString(),
loopParameterType.descriptor, null,
loopParameterStartLabel, bodyEnd,
loopParameterVar
)
})
}
}
@@ -95,19 +96,22 @@ abstract class AbstractForLoopGenerator(
val componentVarIndex = codegen.myFrameMap.enter(componentDescriptor, componentAsmType)
scheduleLeaveVariable(Runnable {
codegen.myFrameMap.leave(componentDescriptor)
v.visitLocalVariable(componentDescriptor.name.asString(),
componentAsmType.descriptor, null,
destructuringStartLabel, bodyEnd,
componentVarIndex)
v.visitLocalVariable(
componentDescriptor.name.asString(),
componentAsmType.descriptor, null,
destructuringStartLabel, bodyEnd,
componentVarIndex
)
})
}
v.visitLabel(destructuringStartLabel)
codegen.initializeDestructuringDeclarationVariables(
destructuringDeclaration,
TransientReceiver(elementType),
StackValue.local(loopParameterVar, asmElementType))
destructuringDeclaration,
TransientReceiver(elementType),
StackValue.local(loopParameterVar, asmElementType)
)
}
protected abstract fun assignToLoopParameter()
@@ -145,11 +149,11 @@ abstract class AbstractForLoopGenerator(
// This method consumes range/progression from stack
// The result is stored to local variable
protected fun generateRangeOrProgressionProperty(
loopRangeType: Type,
getterName: String,
getterReturnType: Type,
varType: Type,
varToStore: Int
loopRangeType: Type,
getterName: String,
getterReturnType: Type,
varType: Type,
varToStore: Int
) {
v.invokevirtual(loopRangeType.internalName, getterName, "()" + getterReturnType.descriptor, false)
StackValue.local(varToStore, varType).store(StackValue.onStack(getterReturnType), v)
@@ -27,10 +27,10 @@ import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
class ForInArrayLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val canCacheArrayLength: Boolean,
private val shouldAlwaysStoreArrayInNewVar: Boolean
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val canCacheArrayLength: Boolean,
private val shouldAlwaysStoreArrayInNewVar: Boolean
) : AbstractForLoopGenerator(codegen, forExpression) {
private var indexVar: Int = 0
private var arrayVar: Int = 0
@@ -47,8 +47,7 @@ class ForInArrayLoopGenerator(
val asmLoopRangeType = codegen.asmType(loopRangeType)
if (!shouldAlwaysStoreArrayInNewVar && value is StackValue.Local && value.type == asmLoopRangeType) {
arrayVar = value.index // no need to copy local variable into another variable
}
else {
} else {
arrayVar = createLoopTempVariable(OBJECT_TYPE)
value.put(asmLoopRangeType, v)
v.store(arrayVar, OBJECT_TYPE)
@@ -71,8 +70,7 @@ class ForInArrayLoopGenerator(
v.load(indexVar, Type.INT_TYPE)
if (canCacheArrayLength) {
v.load(arrayLengthVar, Type.INT_TYPE)
}
else {
} else {
v.load(arrayVar, OBJECT_TYPE)
v.arraylength()
}
@@ -25,10 +25,10 @@ import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class ForInCharSequenceLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val canCacheLength: Boolean,
private val charSequenceClassType: Type?
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val canCacheLength: Boolean,
private val charSequenceClassType: Type?
) : AbstractForLoopGenerator(codegen, forExpression) {
private var indexVar: Int = 0
private var charSequenceVar: Int = 0
@@ -70,8 +70,7 @@ class ForInCharSequenceLoopGenerator(
v.load(indexVar, Type.INT_TYPE)
if (canCacheLength) {
v.load(charSequenceLengthVar, Type.INT_TYPE)
}
else {
} else {
v.load(charSequenceVar, charSequenceType)
v.invokeCharSequenceMethod("length", "()I")
}
@@ -94,8 +93,7 @@ class ForInCharSequenceLoopGenerator(
val charSequenceClassType = charSequenceClassType
if (charSequenceClassType != null) {
invokevirtual(charSequenceClassType.internalName, name, desc, false)
}
else {
} else {
invokeinterface(CHAR_SEQUENCE_TYPE.internalName, name, desc)
}
}
@@ -39,35 +39,35 @@ import org.jetbrains.org.objectweb.asm.Type
* This generator is suitable for cases where arithmetic overflow is impossible.
*/
class ForInDefinitelySafeSimpleProgressionLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val startValue: StackValue,
private val isStartInclusive: Boolean,
private val endValue: StackValue,
private val isEndInclusive: Boolean,
step: Int
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val startValue: StackValue,
private val isStartInclusive: Boolean,
private val endValue: StackValue,
private val isEndInclusive: Boolean,
step: Int
) : AbstractForInRangeLoopGenerator(codegen, forExpression, step) {
constructor(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
step: Int
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
step: Int
) : this(
codegen, forExpression,
startValue = if (step == 1) boundedValue.lowBound else boundedValue.highBound,
isStartInclusive = if (step == 1) boundedValue.isLowInclusive else boundedValue.isHighInclusive,
endValue = if (step == 1) boundedValue.highBound else boundedValue.lowBound,
isEndInclusive = if (step == 1) boundedValue.isHighInclusive else boundedValue.isLowInclusive,
step = step
codegen, forExpression,
startValue = if (step == 1) boundedValue.lowBound else boundedValue.highBound,
isStartInclusive = if (step == 1) boundedValue.isLowInclusive else boundedValue.isHighInclusive,
endValue = if (step == 1) boundedValue.highBound else boundedValue.lowBound,
isEndInclusive = if (step == 1) boundedValue.isHighInclusive else boundedValue.isLowInclusive,
step = step
)
companion object {
fun fromBoundedValueWithStep1(codegen: ExpressionCodegen, forExpression: KtForExpression, boundedValue: SimpleBoundedValue) =
ForInDefinitelySafeSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, 1)
ForInDefinitelySafeSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, 1)
fun fromBoundedValueWithStepMinus1(codegen: ExpressionCodegen, forExpression: KtForExpression, boundedValue: SimpleBoundedValue) =
ForInDefinitelySafeSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, -1)
ForInDefinitelySafeSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, -1)
}
override fun storeRangeStartAndEnd() {
@@ -89,34 +89,27 @@ class ForInDefinitelySafeSimpleProgressionLoopGenerator(
if (step > 0) {
if (isEndInclusive) {
v.ifgt(loopExit)
}
else {
} else {
v.ifge(loopExit)
}
}
else {
} else {
if (isEndInclusive) {
v.iflt(loopExit)
}
else {
} else {
v.ifle(loopExit)
}
}
}
else {
} else {
if (step > 0) {
if (isEndInclusive) {
v.ificmpgt(loopExit)
}
else {
} else {
v.ificmpge(loopExit)
}
}
else {
} else {
if (isEndInclusive) {
v.ificmplt(loopExit)
}
else {
} else {
v.ificmple(loopExit)
}
}
@@ -21,9 +21,9 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtForExpression
class ForInProgressionExpressionLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val rangeExpression: KtExpression
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val rangeExpression: KtExpression
) : AbstractForInProgressionLoopGenerator(codegen, forExpression) {
override fun storeProgressionParametersToLocalVars() {
codegen.gen(rangeExpression, asmLoopRangeType)
@@ -21,10 +21,10 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtForExpression
class ForInRangeInstanceLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val rangeExpression: KtExpression,
private val reversed: Boolean
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val rangeExpression: KtExpression,
private val reversed: Boolean
) : AbstractForInRangeLoopGenerator(codegen, forExpression, if (reversed) -1 else 1) {
override fun storeRangeStartAndEnd() {
@@ -37,8 +37,7 @@ class ForInRangeInstanceLoopGenerator(
if (reversed) {
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, loopParameterType, loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, asmElementType, endVar)
}
else {
} else {
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar)
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar)
}
@@ -24,56 +24,55 @@ import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
class ForInSimpleProgressionLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val startValue: StackValue,
private val isStartInclusive: Boolean,
private val endValue: StackValue,
private val isEndInclusive: Boolean,
private val inverseBoundsEvaluationOrder: Boolean,
step: Int
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val startValue: StackValue,
private val isStartInclusive: Boolean,
private val endValue: StackValue,
private val isEndInclusive: Boolean,
private val inverseBoundsEvaluationOrder: Boolean,
step: Int
) : AbstractForInRangeLoopGenerator(codegen, forExpression, step) {
constructor(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
inverseBoundsEvaluationOrder: Boolean,
step: Int
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
inverseBoundsEvaluationOrder: Boolean,
step: Int
) : this(
codegen, forExpression,
startValue = if (step == 1) boundedValue.lowBound else boundedValue.highBound,
isStartInclusive = if (step == 1) boundedValue.isLowInclusive else boundedValue.isHighInclusive,
endValue = if (step == 1) boundedValue.highBound else boundedValue.lowBound,
isEndInclusive = if (step == 1) boundedValue.isHighInclusive else boundedValue.isLowInclusive,
inverseBoundsEvaluationOrder = inverseBoundsEvaluationOrder,
step = step
codegen, forExpression,
startValue = if (step == 1) boundedValue.lowBound else boundedValue.highBound,
isStartInclusive = if (step == 1) boundedValue.isLowInclusive else boundedValue.isHighInclusive,
endValue = if (step == 1) boundedValue.highBound else boundedValue.lowBound,
isEndInclusive = if (step == 1) boundedValue.isHighInclusive else boundedValue.isLowInclusive,
inverseBoundsEvaluationOrder = inverseBoundsEvaluationOrder,
step = step
)
companion object {
fun fromBoundedValueWithStep1(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
inverseBoundsEvaluationOrder: Boolean = false
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
inverseBoundsEvaluationOrder: Boolean = false
) =
ForInSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, inverseBoundsEvaluationOrder, 1)
ForInSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, inverseBoundsEvaluationOrder, 1)
fun fromBoundedValueWithStepMinus1(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
inverseBoundsEvaluationOrder: Boolean = false
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
inverseBoundsEvaluationOrder: Boolean = false
) =
ForInSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, inverseBoundsEvaluationOrder, -1)
ForInSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, inverseBoundsEvaluationOrder, -1)
}
override fun storeRangeStartAndEnd() {
if (inverseBoundsEvaluationOrder) {
StackValue.local(endVar, asmElementType).store(endValue, v)
loopParameter().store(startValue, v)
}
else {
} else {
loopParameter().store(startValue, v)
StackValue.local(endVar, asmElementType).store(endValue, v)
}
@@ -98,16 +97,13 @@ class ForInSimpleProgressionLoopGenerator(
v.lcmp()
if (step > 0) {
v.ifge(loopExit)
}
else {
} else {
v.ifle(loopExit)
}
}
else {
} else {
if (step > 0) {
v.ificmpge(loopExit)
}
else {
} else {
v.ificmple(loopExit)
}
}
@@ -119,8 +115,7 @@ class ForInSimpleProgressionLoopGenerator(
// Otherwise, just increment the loop variable.
if (isEndInclusive) {
super.checkPostConditionAndIncrement(loopExit)
}
else {
} else {
incrementLoopVariable()
}
}
@@ -28,9 +28,8 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
class IteratorForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression)
: AbstractForLoopGenerator(codegen, forExpression)
{
class IteratorForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) :
AbstractForLoopGenerator(codegen, forExpression) {
private var iteratorVarIndex: Int = 0
private val iteratorCall: ResolvedCall<FunctionDescriptor>
private val nextCall: ResolvedCall<FunctionDescriptor>
@@ -38,16 +37,20 @@ class IteratorForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForE
init {
val loopRange = forExpression.loopRange!!
this.iteratorCall = getNotNull(bindingContext,
LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange,
"No .iterator() function " + DiagnosticUtils.atLocation(loopRange))
this.iteratorCall = getNotNull(
bindingContext,
LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange,
"No .iterator() function " + DiagnosticUtils.atLocation(loopRange)
)
val iteratorType = iteratorCall.resultingDescriptor.returnType!!
this.asmTypeForIterator = codegen.asmType(iteratorType)
this.nextCall = getNotNull(bindingContext,
LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange,
"No next() function " + DiagnosticUtils.atLocation(loopRange))
this.nextCall = getNotNull(
bindingContext,
LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange,
"No next() function " + DiagnosticUtils.atLocation(loopRange)
)
}
override fun beforeLoop() {
@@ -65,9 +68,9 @@ class IteratorForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForE
val loopRange = forExpression.loopRange
val hasNextCall = getNotNull(
codegen.bindingContext, LOOP_RANGE_HAS_NEXT_RESOLVED_CALL,
loopRange!!,
"No hasNext() function " + DiagnosticUtils.atLocation(loopRange)
codegen.bindingContext, LOOP_RANGE_HAS_NEXT_RESOLVED_CALL,
loopRange!!,
"No hasNext() function " + DiagnosticUtils.atLocation(loopRange)
)
val fakeCall = codegen.makeFakeCall(TransientReceiver(iteratorCall.resultingDescriptor.returnType!!))
val result = codegen.invokeFunction(fakeCall, hasNextCall, StackValue.local(iteratorVarIndex, asmTypeForIterator))
@@ -16,7 +16,10 @@
package org.jetbrains.kotlin.codegen.range.inExpression
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.BranchedValue
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.Invert
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
@@ -26,30 +29,30 @@ import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class CallBasedInExpressionGenerator(
val codegen: ExpressionCodegen,
operatorReference: KtSimpleNameExpression
val codegen: ExpressionCodegen,
operatorReference: KtSimpleNameExpression
) : InExpressionGenerator {
private val resolvedCall = operatorReference.getResolvedCallWithAssert(codegen.bindingContext)
private val isInverted = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
private val isInverted = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
override fun generate(argument: StackValue): BranchedValue =
gen(argument).let { if (isInverted) Invert(it) else it }
gen(argument).let { if (isInverted) Invert(it) else it }
private fun gen(argument: StackValue): BranchedValue =
object : BranchedValue(argument, null, argument.type, Opcodes.IFEQ) {
override fun putSelector(type: Type, v: InstructionAdapter) {
invokeFunction(v)
coerceTo(type, v)
}
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
invokeFunction(v)
v.visitJumpInsn(if (jumpIfFalse) Opcodes.IFEQ else Opcodes.IFNE, jumpLabel)
}
private fun invokeFunction(v: InstructionAdapter) {
val result = codegen.invokeFunction(resolvedCall.call, resolvedCall, none())
result.put(result.type, v)
}
object : BranchedValue(argument, null, argument.type, Opcodes.IFEQ) {
override fun putSelector(type: Type, v: InstructionAdapter) {
invokeFunction(v)
coerceTo(type, v)
}
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
invokeFunction(v)
v.visitJumpInsn(if (jumpIfFalse) Opcodes.IFEQ else Opcodes.IFNE, jumpLabel)
}
private fun invokeFunction(v: InstructionAdapter) {
val result = codegen.invokeFunction(resolvedCall.call, resolvedCall, none())
result.put(result.type, v)
}
}
}
@@ -26,120 +26,115 @@ import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class InContinuousRangeOfComparableExpressionGenerator(
operatorReference: KtSimpleNameExpression,
private val boundedValue: BoundedValue,
private val frameMap: FrameMap
operatorReference: KtSimpleNameExpression,
private val boundedValue: BoundedValue,
private val frameMap: FrameMap
) : InExpressionGenerator {
private val isNotIn = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
private val comparisonGenerator = ObjectComparisonGenerator
override fun generate(argument: StackValue): BranchedValue =
gen(argument).let { if (isNotIn) Invert(it) else it }
gen(argument).let { if (isNotIn) Invert(it) else it }
private fun gen(argument: StackValue): BranchedValue =
object : BranchedValue(argument, null, comparisonGenerator.comparedType, Opcodes.IFEQ) {
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
if (jumpIfFalse) {
genJumpIfFalse(v, jumpLabel)
object : BranchedValue(argument, null, comparisonGenerator.comparedType, Opcodes.IFEQ) {
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
if (jumpIfFalse) {
genJumpIfFalse(v, jumpLabel)
} else {
genJumpIfTrue(v, jumpLabel)
}
}
private fun genJumpIfTrue(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is in range) goto jumpLabel
frameMap.useTmpVar(operandType) { arg1Var ->
val exitLabel1 = Label()
val exitLabel2 = Label()
boundedValue.putHighLow(v, operandType)
arg1.put(operandType, v)
v.store(arg1Var, operandType)
v.load(arg1Var, operandType)
// On stack: high low arg
// if (low bound is NOT satisfied) goto exitLabel1
if (boundedValue.isLowInclusive) {
// arg < low
v.swap()
comparisonGenerator.jumpIfLess(v, exitLabel1)
} else {
// arg <= low
v.swap()
comparisonGenerator.jumpIfLessOrEqual(v, exitLabel1)
}
else {
genJumpIfTrue(v, jumpLabel)
v.load(arg1Var, operandType)
// On stack: high arg
// if (high bound is satisfied) goto jumpLabel
if (boundedValue.isHighInclusive) {
// arg <= high
v.swap()
comparisonGenerator.jumpIfLessOrEqual(v, jumpLabel)
} else {
// arg < high
v.swap()
comparisonGenerator.jumpIfLess(v, jumpLabel)
}
v.goTo(exitLabel2)
v.mark(exitLabel1)
AsmUtil.pop(v, operandType)
v.mark(exitLabel2)
}
private fun genJumpIfTrue(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is in range) goto jumpLabel
}
frameMap.useTmpVar(operandType) { arg1Var ->
val exitLabel1 = Label()
val exitLabel2 = Label()
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is NOT in range) goto jumpLabel
boundedValue.putHighLow(v, operandType)
frameMap.useTmpVar(operandType) { arg1Var ->
val cmpHighLabel = Label()
arg1.put(operandType, v)
v.store(arg1Var, operandType)
v.load(arg1Var, operandType)
boundedValue.putHighLow(v, operandType)
// On stack: high low arg
// if (low bound is NOT satisfied) goto exitLabel1
if (boundedValue.isLowInclusive) {
// arg < low
v.swap()
comparisonGenerator.jumpIfLess(v, exitLabel1)
}
else {
// arg <= low
v.swap()
comparisonGenerator.jumpIfLessOrEqual(v, exitLabel1)
}
arg1.put(operandType, v)
v.store(arg1Var, operandType)
v.load(arg1Var, operandType)
v.load(arg1Var, operandType)
// On stack: high arg
// if (high bound is satisfied) goto jumpLabel
if (boundedValue.isHighInclusive) {
// arg <= high
v.swap()
comparisonGenerator.jumpIfLessOrEqual(v, jumpLabel)
}
else {
// arg < high
v.swap()
comparisonGenerator.jumpIfLess(v, jumpLabel)
}
v.goTo(exitLabel2)
v.mark(exitLabel1)
AsmUtil.pop(v, operandType)
v.mark(exitLabel2)
// On stack: high low arg
// if ([low bound is satisfied]) goto cmpHighLabel
if (boundedValue.isLowInclusive) {
// arg >= low
v.swap()
comparisonGenerator.jumpIfGreaterOrEqual(v, cmpHighLabel)
} else {
// arg > low
v.swap()
comparisonGenerator.jumpIfGreater(v, cmpHighLabel)
}
}
// Low bound is NOT satisfied, clear stack and goto jumpLabel
AsmUtil.pop(v, operandType)
v.goTo(jumpLabel)
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is NOT in range) goto jumpLabel
frameMap.useTmpVar(operandType) { arg1Var ->
val cmpHighLabel = Label()
boundedValue.putHighLow(v, operandType)
arg1.put(operandType, v)
v.store(arg1Var, operandType)
v.load(arg1Var, operandType)
// On stack: high low arg
// if ([low bound is satisfied]) goto cmpHighLabel
if (boundedValue.isLowInclusive) {
// arg >= low
v.swap()
comparisonGenerator.jumpIfGreaterOrEqual(v, cmpHighLabel)
}
else {
// arg > low
v.swap()
comparisonGenerator.jumpIfGreater(v, cmpHighLabel)
}
// Low bound is NOT satisfied, clear stack and goto jumpLabel
AsmUtil.pop(v, operandType)
v.goTo(jumpLabel)
v.mark(cmpHighLabel)
v.load(arg1Var, operandType)
// On stack: high arg
// if ([high bound is NOT satisfied]) goto jumpLabel
if (boundedValue.isHighInclusive) {
// arg > high
v.swap()
comparisonGenerator.jumpIfGreater(v, jumpLabel)
}
else {
// arg >= high
v.swap()
comparisonGenerator.jumpIfGreaterOrEqual(v, jumpLabel)
}
v.mark(cmpHighLabel)
v.load(arg1Var, operandType)
// On stack: high arg
// if ([high bound is NOT satisfied]) goto jumpLabel
if (boundedValue.isHighInclusive) {
// arg > high
v.swap()
comparisonGenerator.jumpIfGreater(v, jumpLabel)
} else {
// arg >= high
v.swap()
comparisonGenerator.jumpIfGreaterOrEqual(v, jumpLabel)
}
}
}
}
}
@@ -27,10 +27,10 @@ import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class InFloatingPointRangeLiteralExpressionGenerator(
operatorReference: KtSimpleNameExpression,
private val rangeLiteral: SimpleBoundedValue,
private val comparisonGenerator: ComparisonGenerator,
private val frameMap: FrameMap
operatorReference: KtSimpleNameExpression,
private val rangeLiteral: SimpleBoundedValue,
private val comparisonGenerator: ComparisonGenerator,
private val frameMap: FrameMap
) : InExpressionGenerator {
init {
assert(rangeLiteral.isLowInclusive && rangeLiteral.isHighInclusive) { "Floating point range literal bounds should be inclusive" }
@@ -39,79 +39,77 @@ class InFloatingPointRangeLiteralExpressionGenerator(
private val isNotIn = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
override fun generate(argument: StackValue): BranchedValue =
gen(argument).let { if (isNotIn) Invert(it) else it }
gen(argument).let { if (isNotIn) Invert(it) else it }
private fun gen(argument: StackValue): BranchedValue =
object : BranchedValue(argument, null, comparisonGenerator.comparedType, Opcodes.IFEQ) {
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
if (jumpIfFalse) {
genJumpIfFalse(v, jumpLabel)
}
else {
genJumpIfTrue(v, jumpLabel)
}
}
private fun genJumpIfTrue(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is in range) goto jumpLabel
// =>
// if (arg is NOT in range) goto exitLabel
// goto jumpLabel
// exitLabel:
frameMap.useTmpVar(operandType) { argVar ->
val exitLabel = Label()
genJumpIfFalse(v, exitLabel)
v.goTo(jumpLabel)
v.mark(exitLabel)
}
}
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is NOT in range) goto jumpLabel
frameMap.useTmpVar(operandType) { argVar ->
// Evaluate low and high bounds once (unless they have no side effects)
val (lowValue, lowTmpType) = introduceTemporaryIfRequired(v, rangeLiteral.lowBound, operandType)
val (highValue, highTmpType) = introduceTemporaryIfRequired(v, rangeLiteral.highBound, operandType)
val argValue = StackValue.local(argVar, operandType)
argValue.store(arg1, v)
// if (low bound is NOT satisfied) goto jumpLabel
// arg < low
argValue.put(operandType, v)
lowValue.put(operandType, v)
comparisonGenerator.jumpIfLess(v, jumpLabel)
// if (high bound is NOT satisfied) goto jumpLabel
// arg > high
argValue.put(operandType, v)
highValue.put(operandType, v)
comparisonGenerator.jumpIfGreater(v, jumpLabel)
highTmpType?.let { frameMap.leaveTemp(it) }
lowTmpType?.let { frameMap.leaveTemp(it) }
}
}
private fun introduceTemporaryIfRequired(v: InstructionAdapter, value: StackValue, type: Type): Pair<StackValue, Type?> {
val resultValue: StackValue
val resultType: Type?
if (value.canHaveSideEffects()) {
val index = frameMap.enterTemp(type)
resultValue = StackValue.local(index, type)
resultType = type
resultValue.store(value, v)
}
else {
resultValue = value
resultType = null
}
return Pair(resultValue, resultType)
object : BranchedValue(argument, null, comparisonGenerator.comparedType, Opcodes.IFEQ) {
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
if (jumpIfFalse) {
genJumpIfFalse(v, jumpLabel)
} else {
genJumpIfTrue(v, jumpLabel)
}
}
private fun genJumpIfTrue(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is in range) goto jumpLabel
// =>
// if (arg is NOT in range) goto exitLabel
// goto jumpLabel
// exitLabel:
frameMap.useTmpVar(operandType) { argVar ->
val exitLabel = Label()
genJumpIfFalse(v, exitLabel)
v.goTo(jumpLabel)
v.mark(exitLabel)
}
}
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is NOT in range) goto jumpLabel
frameMap.useTmpVar(operandType) { argVar ->
// Evaluate low and high bounds once (unless they have no side effects)
val (lowValue, lowTmpType) = introduceTemporaryIfRequired(v, rangeLiteral.lowBound, operandType)
val (highValue, highTmpType) = introduceTemporaryIfRequired(v, rangeLiteral.highBound, operandType)
val argValue = StackValue.local(argVar, operandType)
argValue.store(arg1, v)
// if (low bound is NOT satisfied) goto jumpLabel
// arg < low
argValue.put(operandType, v)
lowValue.put(operandType, v)
comparisonGenerator.jumpIfLess(v, jumpLabel)
// if (high bound is NOT satisfied) goto jumpLabel
// arg > high
argValue.put(operandType, v)
highValue.put(operandType, v)
comparisonGenerator.jumpIfGreater(v, jumpLabel)
highTmpType?.let { frameMap.leaveTemp(it) }
lowTmpType?.let { frameMap.leaveTemp(it) }
}
}
private fun introduceTemporaryIfRequired(v: InstructionAdapter, value: StackValue, type: Type): Pair<StackValue, Type?> {
val resultValue: StackValue
val resultType: Type?
if (value.canHaveSideEffects()) {
val index = frameMap.enterTemp(type)
resultValue = StackValue.local(index, type)
resultType = type
resultValue.store(value, v)
} else {
resultValue = value
resultType = null
}
return Pair(resultValue, resultType)
}
}
}
@@ -26,111 +26,106 @@ import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class InIntegralContinuousRangeExpressionGenerator(
operatorReference: KtSimpleNameExpression,
private val boundedValue: BoundedValue,
private val comparisonGenerator: ComparisonGenerator,
private val frameMap: FrameMap
operatorReference: KtSimpleNameExpression,
private val boundedValue: BoundedValue,
private val comparisonGenerator: ComparisonGenerator,
private val frameMap: FrameMap
) : InExpressionGenerator {
private val isNotIn = operatorReference.getReferencedNameElementType() == KtTokens.NOT_IN
override fun generate(argument: StackValue): BranchedValue =
gen(argument).let { if (isNotIn) Invert(it) else it }
gen(argument).let { if (isNotIn) Invert(it) else it }
private fun gen(argument: StackValue): BranchedValue =
object : BranchedValue(argument, null, comparisonGenerator.comparedType, Opcodes.IFEQ) {
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
if (jumpIfFalse) {
genJumpIfFalse(v, jumpLabel)
}
else {
genJumpIfTrue(v, jumpLabel)
}
}
private fun genJumpIfTrue(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is in range) goto jumpLabel
frameMap.useTmpVar(operandType) { arg1Var ->
val exitLabel1 = Label()
val exitLabel2 = Label()
boundedValue.putHighLow(v, operandType)
arg1.put(operandType, v)
v.store(arg1Var, operandType)
v.load(arg1Var, operandType)
// On stack: high low arg
// if (low bound is NOT satisfied) goto exitLabel1
if (boundedValue.isLowInclusive) {
// low > arg
comparisonGenerator.jumpIfGreater(v, exitLabel1)
}
else {
// low >= arg
comparisonGenerator.jumpIfGreaterOrEqual(v, exitLabel1)
}
v.load(arg1Var, operandType)
// On stack: high arg
// if (high bound is satisfied) goto jumpLabel
if (boundedValue.isHighInclusive) {
// high >= arg
comparisonGenerator.jumpIfGreaterOrEqual(v, jumpLabel)
}
else {
// high > arg
comparisonGenerator.jumpIfGreater(v, jumpLabel)
}
v.goTo(exitLabel2)
v.mark(exitLabel1)
AsmUtil.pop(v, operandType)
v.mark(exitLabel2)
}
}
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is NOT in range) goto jumpLabel
frameMap.useTmpVar(operandType) { arg1Var ->
val cmpHighLabel = Label()
boundedValue.putHighLow(v, operandType)
arg1.put(operandType, v)
v.store(arg1Var, operandType)
v.load(arg1Var, operandType)
// On stack: high low arg
// if ([low bound is satisfied]) goto cmpHighLabel
if (boundedValue.isLowInclusive) {
// low <= arg
comparisonGenerator.jumpIfLessOrEqual(v, cmpHighLabel)
}
else {
// low < arg
comparisonGenerator.jumpIfLess(v, cmpHighLabel)
}
// Low bound is NOT satisfied, clear stack and goto jumpLabel
AsmUtil.pop(v, operandType)
v.goTo(jumpLabel)
v.mark(cmpHighLabel)
v.load(arg1Var, operandType)
// On stack: high arg
// if ([high bound is NOT satisfied]) goto jumpLabel
if (boundedValue.isHighInclusive) {
// high < arg
comparisonGenerator.jumpIfLess(v, jumpLabel)
}
else {
// high <= arg
comparisonGenerator.jumpIfLessOrEqual(v, jumpLabel)
}
}
object : BranchedValue(argument, null, comparisonGenerator.comparedType, Opcodes.IFEQ) {
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
if (jumpIfFalse) {
genJumpIfFalse(v, jumpLabel)
} else {
genJumpIfTrue(v, jumpLabel)
}
}
private fun genJumpIfTrue(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is in range) goto jumpLabel
frameMap.useTmpVar(operandType) { arg1Var ->
val exitLabel1 = Label()
val exitLabel2 = Label()
boundedValue.putHighLow(v, operandType)
arg1.put(operandType, v)
v.store(arg1Var, operandType)
v.load(arg1Var, operandType)
// On stack: high low arg
// if (low bound is NOT satisfied) goto exitLabel1
if (boundedValue.isLowInclusive) {
// low > arg
comparisonGenerator.jumpIfGreater(v, exitLabel1)
} else {
// low >= arg
comparisonGenerator.jumpIfGreaterOrEqual(v, exitLabel1)
}
v.load(arg1Var, operandType)
// On stack: high arg
// if (high bound is satisfied) goto jumpLabel
if (boundedValue.isHighInclusive) {
// high >= arg
comparisonGenerator.jumpIfGreaterOrEqual(v, jumpLabel)
} else {
// high > arg
comparisonGenerator.jumpIfGreater(v, jumpLabel)
}
v.goTo(exitLabel2)
v.mark(exitLabel1)
AsmUtil.pop(v, operandType)
v.mark(exitLabel2)
}
}
private fun genJumpIfFalse(v: InstructionAdapter, jumpLabel: Label) {
// if (arg is NOT in range) goto jumpLabel
frameMap.useTmpVar(operandType) { arg1Var ->
val cmpHighLabel = Label()
boundedValue.putHighLow(v, operandType)
arg1.put(operandType, v)
v.store(arg1Var, operandType)
v.load(arg1Var, operandType)
// On stack: high low arg
// if ([low bound is satisfied]) goto cmpHighLabel
if (boundedValue.isLowInclusive) {
// low <= arg
comparisonGenerator.jumpIfLessOrEqual(v, cmpHighLabel)
} else {
// low < arg
comparisonGenerator.jumpIfLess(v, cmpHighLabel)
}
// Low bound is NOT satisfied, clear stack and goto jumpLabel
AsmUtil.pop(v, operandType)
v.goTo(jumpLabel)
v.mark(cmpHighLabel)
v.load(arg1Var, operandType)
// On stack: high arg
// if ([high bound is NOT satisfied]) goto jumpLabel
if (boundedValue.isHighInclusive) {
// high < arg
comparisonGenerator.jumpIfLess(v, jumpLabel)
} else {
// high <= arg
comparisonGenerator.jumpIfLessOrEqual(v, jumpLabel)
}
}
}
}
}