Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Optimize range operations for 'until' extension from stdlib (KT-9900)
NB: for-in-until loop is generated as precondition loop, because the corresponding range is right-exclusive (and thus we have no problems with integer overflows).
- Loading branch information
Showing
27 changed files
with
533 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/ForInUntilRangeLoopGenerator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* 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.forLoop | ||
|
||
import org.jetbrains.kotlin.codegen.ExpressionCodegen | ||
import org.jetbrains.kotlin.codegen.StackValue | ||
import org.jetbrains.kotlin.psi.KtExpression | ||
import org.jetbrains.kotlin.psi.KtForExpression | ||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall | ||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue | ||
import org.jetbrains.org.objectweb.asm.Label | ||
import org.jetbrains.org.objectweb.asm.Type | ||
|
||
class ForInUntilRangeLoopGenerator( | ||
codegen: ExpressionCodegen, | ||
forExpression: KtForExpression, | ||
loopRangeCall: ResolvedCall<*> | ||
) : AbstractForInRangeLoopGenerator(codegen, forExpression) { | ||
private val from: ReceiverValue = loopRangeCall.extensionReceiver!! | ||
private val to: KtExpression = ExpressionCodegen.getSingleArgumentExpression(loopRangeCall)!! | ||
|
||
override fun storeRangeStartAndEnd() { | ||
loopParameter().store(codegen.generateReceiverValue(from, false), v) | ||
StackValue.local(endVar, asmElementType).store(codegen.gen(to), v) | ||
} | ||
|
||
override fun checkEmptyLoop(loopExit: Label) {} | ||
|
||
override fun checkPreCondition(loopExit: Label) { | ||
loopParameter().put(asmElementType, v) | ||
v.load(endVar, asmElementType) | ||
if (asmElementType.sort == Type.LONG) { | ||
v.lcmp() | ||
v.ifge(loopExit) | ||
} | ||
else { | ||
v.ificmpge(loopExit) | ||
} | ||
} | ||
|
||
override fun checkPostConditionAndIncrement(loopExit: Label) { | ||
incrementLoopVariable() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// IGNORE_BACKEND: JS | ||
// see KT-17700 | ||
|
||
// WITH_RUNTIME | ||
|
||
import kotlin.test.assertEquals | ||
|
||
fun box(): String { | ||
testChar() | ||
testNullableChar() | ||
return "OK" | ||
} | ||
|
||
private fun testChar() { | ||
var sum = "" | ||
for (ch in '1' until '5') { | ||
sum = sum + ch | ||
} | ||
assertEquals("1234", sum) | ||
} | ||
|
||
private fun testNullableChar() { | ||
var sum = "" | ||
for (ch: Char? in '1' until '5') { | ||
sum = sum + (ch ?: break) | ||
} | ||
assertEquals("1234", sum) | ||
} |
10 changes: 10 additions & 0 deletions
10
compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar0.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// WITH_RUNTIME | ||
|
||
import kotlin.test.assertEquals | ||
|
||
fun box(): String { | ||
for (ch in (-10).toChar() until '\u0000') { | ||
throw AssertionError("This loop shoud not be executed") | ||
} | ||
return "OK" | ||
} |
25 changes: 25 additions & 0 deletions
25
compiler/testData/codegen/box/ranges/forInUntil/forInUntilInt.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// WITH_RUNTIME | ||
|
||
import kotlin.test.assertEquals | ||
|
||
fun box(): String { | ||
testIntInIntUntilInt() | ||
testNullableIntInIntUntilInt() | ||
return "OK" | ||
} | ||
|
||
private fun testIntInIntUntilInt() { | ||
var sum = 0 | ||
for (i in 1 until 5) { | ||
sum = sum * 10 + i | ||
} | ||
assertEquals(1234, sum) | ||
} | ||
|
||
private fun testNullableIntInIntUntilInt() { | ||
var sum = 0 | ||
for (i: Int? in 1 until 5) { | ||
sum = sum * 10 + (i?.toInt() ?: break) | ||
} | ||
assertEquals(1234, sum) | ||
} |
10 changes: 10 additions & 0 deletions
10
compiler/testData/codegen/box/ranges/forInUntil/forInUntilLesserInt.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// WITH_RUNTIME | ||
|
||
import kotlin.test.assertEquals | ||
|
||
fun box(): String { | ||
for (i in 10 until 0) { | ||
throw AssertionError("This loop should not be executed") | ||
} | ||
return "OK" | ||
} |
43 changes: 43 additions & 0 deletions
43
compiler/testData/codegen/box/ranges/forInUntil/forInUntilLong.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// WITH_RUNTIME | ||
|
||
import kotlin.test.assertEquals | ||
|
||
fun testLongInLongUntilLong() { | ||
var sum = 0 | ||
for (i in 1L until 5L) { | ||
sum = sum * 10 + i.toInt() | ||
} | ||
assertEquals(1234, sum) | ||
} | ||
|
||
fun testLongInLongUntilInt() { | ||
var sum = 0 | ||
for (i in 1L until 5.toInt()) { | ||
sum = sum * 10 + i.toInt() | ||
} | ||
assertEquals(1234, sum) | ||
} | ||
|
||
fun testLongInIntUntilLong() { | ||
var sum = 0 | ||
for (i in 1.toInt() until 5L) { | ||
sum = sum * 10 + i.toInt() | ||
} | ||
assertEquals(1234, sum) | ||
} | ||
|
||
fun testNullableLongInIntUntilLong() { | ||
var sum = 0 | ||
for (i: Long? in 1.toInt() until 5L) { | ||
sum = sum * 10 + (i?.toInt() ?: break) | ||
} | ||
assertEquals(1234, sum) | ||
} | ||
|
||
fun box(): String { | ||
testLongInLongUntilLong() | ||
testLongInIntUntilLong() | ||
testLongInLongUntilInt() | ||
testNullableLongInIntUntilLong() | ||
return "OK" | ||
} |
10 changes: 10 additions & 0 deletions
10
compiler/testData/codegen/box/ranges/forInUntil/forInUntilMaxint.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// WITH_RUNTIME | ||
|
||
import kotlin.test.assertEquals | ||
|
||
fun box(): String { | ||
for (i in Int.MAX_VALUE until Int.MAX_VALUE) { | ||
throw AssertionError("This loop shoud not be executed") | ||
} | ||
return "OK" | ||
} |
10 changes: 10 additions & 0 deletions
10
compiler/testData/codegen/box/ranges/forInUntil/forInUntilMinint.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// WITH_RUNTIME | ||
|
||
import kotlin.test.assertEquals | ||
|
||
fun box(): String { | ||
for (i in 0 until Int.MIN_VALUE) { | ||
throw AssertionError("This loop shoud not be executed") | ||
} | ||
return "OK" | ||
} |
10 changes: 10 additions & 0 deletions
10
compiler/testData/codegen/box/ranges/forInUntil/forInUntilMinlong.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// WITH_RUNTIME | ||
|
||
import kotlin.test.assertEquals | ||
|
||
fun box(): String { | ||
for (i in 0 until Long.MIN_VALUE) { | ||
throw AssertionError("This loop shoud not be executed") | ||
} | ||
return "OK" | ||
} |
21 changes: 21 additions & 0 deletions
21
compiler/testData/codegen/box/ranges/forInUntil/forIntInIntUntilSmartcastInt.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// WITH_RUNTIME | ||
|
||
import kotlin.test.assertEquals | ||
|
||
fun box(): String { | ||
testIntInIntUntilSmartcastInt() | ||
return "OK" | ||
} | ||
|
||
private fun testIntInIntUntilSmartcastInt() { | ||
var sum = 0 | ||
|
||
val a: Any = 5 | ||
if (a is Int) { | ||
for (i: Int in 1 until a) { | ||
sum = sum * 10 + i | ||
} | ||
} | ||
|
||
assertEquals(1234, sum) | ||
} |
16 changes: 16 additions & 0 deletions
16
compiler/testData/codegen/bytecodeText/forLoop/forInUntil.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// WITH_RUNTIME | ||
|
||
fun test(): Int { | ||
var sum = 0 | ||
for (i in 1 until 6) { | ||
sum = sum * 10 + i | ||
} | ||
return sum | ||
} | ||
|
||
// 0 iterator | ||
// 0 getStart | ||
// 0 getEnd | ||
// 0 getFirst | ||
// 0 getLast | ||
// 1 IF |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.