Generate for-in-indices as a precondition loop

Precondition loops are better optimized by HotSpot
(and, quite likely, by ART).
Also, we generate more compact bytecode that way.

KT-17903 Generate 'for-in-indices' as a precondition loop
This commit is contained in:
Dmitry Petrov
2017-05-16 11:06:05 +03:00
parent 793fb65666
commit 899ad7bb53
6 changed files with 33 additions and 16 deletions
@@ -28,21 +28,18 @@ abstract class ForInOptimizedIndicesLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
loopRangeCall: ResolvedCall<*>
) : AbstractForInRangeLoopGenerator(codegen, forExpression) {
) : AbstractForInExclusiveRangeLoopGenerator(codegen, forExpression) {
protected val receiverValue: ReceiverValue = loopRangeCall.extensionReceiver!!
protected val expectedReceiverType: KotlinType = ExpressionCodegen.getExpectedReceiverType(loopRangeCall)
override fun storeRangeStartAndEnd() {
loopParameter().store(StackValue.constant(0, asmElementType), codegen.v)
override fun generateFrom(): StackValue =
StackValue.constant(0, asmElementType)
val receiver = codegen.generateReceiverValue(receiverValue, false)
val receiverType = codegen.asmType(expectedReceiverType)
receiver.put(receiverType, codegen.v)
getReceiverSizeAsInt()
codegen.v.iconst(1)
codegen.v.sub(Type.INT_TYPE)
StackValue.local(endVar, asmElementType).store(StackValue.onStack(Type.INT_TYPE), codegen.v)
}
override fun generateTo(): StackValue =
StackValue.operation(Type.INT_TYPE) { v ->
codegen.generateReceiverValue(receiverValue, false).put(codegen.asmType(expectedReceiverType), v)
getReceiverSizeAsInt()
}
/**
* `(receiver -> size:I)`
@@ -12,4 +12,8 @@ fun test(s: CharSequence): Int {
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getLast
// 0 IF_ICMPGT
// 0 IF_ICMPEQ
// 1 IF_ICMPGE
@@ -12,4 +12,8 @@ fun Collection<Int>.sumIndices(): Int {
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getLast
// 0 IF_ICMPGT
// 0 IF_ICMPEQ
// 1 IF_ICMPGE
@@ -11,4 +11,8 @@ fun test() {
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getLast
// 0 IF_ICMPGT
// 0 IF_ICMPEQ
// 1 IF_ICMPGE
@@ -11,4 +11,8 @@ fun test() {
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getLast
// 0 IF_ICMPGT
// 0 IF_ICMPEQ
// 1 IF_ICMPGE
@@ -11,4 +11,8 @@ fun test() {
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getLast
// 0 IF_ICMPGT
// 0 IF_ICMPEQ
// 1 IF_ICMPGE