Simplify generated code for rangeTo/concat intrinsics
The main reason is avoiding complicated operations like dup + dup_x2 + pop2 for instances obtained by NEW instruction. Otherwise it leads to problems in performRefinedTypeAnalysis because code there has a sensible assumption that NEW instances can be only dupped or stored into a local (rare cases) #KT-17457 Fixed
This commit is contained in:
@@ -45,7 +45,7 @@ interface Callable {
|
||||
}
|
||||
}
|
||||
|
||||
fun afterReceiverGeneration(v: InstructionAdapter) {
|
||||
fun afterReceiverGeneration(v: InstructionAdapter, frameMap: FrameMap) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2262,7 +2262,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
myFrameMap.leaveTemp(firstReceiverType);
|
||||
}
|
||||
|
||||
callableMethod.afterReceiverGeneration(v);
|
||||
callableMethod.afterReceiverGeneration(v, myFrameMap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -377,3 +377,22 @@ fun initializeVariablesForDestructuredLambdaParameters(codegen: ExpressionCodege
|
||||
}
|
||||
|
||||
fun <D : CallableDescriptor> D.unwrapFrontendVersion() = unwrapInitialDescriptorForSuspendFunction()
|
||||
|
||||
inline fun FrameMap.useTmpVar(type: Type, block: (index: Int) -> Unit) {
|
||||
val index = enterTemp(type)
|
||||
block(index)
|
||||
leaveTemp(type)
|
||||
}
|
||||
|
||||
fun InstructionAdapter.generateNewInstanceDupAndPlaceBeforeStackTop(
|
||||
frameMap: FrameMap,
|
||||
topStackType: Type,
|
||||
newInstanceInternalName: String
|
||||
) {
|
||||
frameMap.useTmpVar(topStackType) { index ->
|
||||
store(index, topStackType)
|
||||
anew(Type.getObjectType(newInstanceInternalName))
|
||||
dup()
|
||||
load(index, topStackType)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
@@ -83,10 +82,8 @@ class Concat : IntrinsicMethod() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun afterReceiverGeneration(v: InstructionAdapter) {
|
||||
v.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder")
|
||||
v.dupX1()
|
||||
v.swap()
|
||||
override fun afterReceiverGeneration(v: InstructionAdapter, frameMap: FrameMap) {
|
||||
v.generateNewInstanceDupAndPlaceBeforeStackTop(frameMap, AsmTypes.JAVA_STRING_TYPE, "java/lang/StringBuilder")
|
||||
v.invokespecial("java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false)
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ package org.jetbrains.kotlin.codegen.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.codegen.Callable
|
||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.FrameMap
|
||||
import org.jetbrains.kotlin.codegen.generateNewInstanceDupAndPlaceBeforeStackTop
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.Type.*
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
@@ -47,19 +48,8 @@ class RangeTo : IntrinsicMethod() {
|
||||
nullOr(method.dispatchReceiverType, argType),
|
||||
nullOr(method.extensionReceiverType, argType)
|
||||
) {
|
||||
override fun afterReceiverGeneration(v: InstructionAdapter) {
|
||||
v.anew(returnType)
|
||||
when (argType.size) {
|
||||
1 -> {
|
||||
v.dupX1()
|
||||
v.swap()
|
||||
}
|
||||
2 -> {
|
||||
v.dup()
|
||||
v.dup2X2()
|
||||
v.pop2()
|
||||
}
|
||||
}
|
||||
override fun afterReceiverGeneration(v: InstructionAdapter, frameMap: FrameMap) {
|
||||
v.generateNewInstanceDupAndPlaceBeforeStackTop(frameMap, argType, returnType.internalName)
|
||||
}
|
||||
|
||||
override fun invokeIntrinsic(v: InstructionAdapter) {
|
||||
|
||||
@@ -116,10 +116,8 @@ class Concat : IntrinsicMethod() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun afterReceiverGeneration(v: InstructionAdapter) {
|
||||
v.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder")
|
||||
v.dupX1()
|
||||
v.swap()
|
||||
override fun afterReceiverGeneration(v: InstructionAdapter, frameMap: FrameMap) {
|
||||
v.generateNewInstanceDupAndPlaceBeforeStackTop(frameMap, AsmTypes.JAVA_STRING_TYPE, "java/lang/StringBuilder")
|
||||
v.invokespecial("java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import helpers.*
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
suspend fun getLong(): Long = suspendCoroutineOrReturn { x ->
|
||||
x.resume(1234567890123L)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
suspend fun suspendHere(r: LongRange): Long = suspendCoroutineOrReturn { x ->
|
||||
x.resume(r.start + r.endInclusive)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var result = 0L
|
||||
|
||||
builder {
|
||||
result = suspendHere(1L..getLong())
|
||||
}
|
||||
|
||||
if (result != 1234567890124L) return "fail 1: $result"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import helpers.*
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
suspend fun suspendHere(r: LongRange): Long = suspendCoroutineOrReturn { x ->
|
||||
x.resume(r.start + r.endInclusive)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var result = 0L
|
||||
|
||||
builder {
|
||||
result = suspendHere(1L..1234567890123L)
|
||||
}
|
||||
|
||||
if (result != 1234567890124L) return "fail 1: $result"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+12
@@ -5168,6 +5168,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("longRangeInSuspendCall.kt")
|
||||
public void testLongRangeInSuspendCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/longRangeInSuspendCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("longRangeInSuspendFun.kt")
|
||||
public void testLongRangeInSuspendFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/longRangeInSuspendFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("mergeNullAndString.kt")
|
||||
public void testMergeNullAndString() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/mergeNullAndString.kt");
|
||||
|
||||
@@ -5168,6 +5168,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("longRangeInSuspendCall.kt")
|
||||
public void testLongRangeInSuspendCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/longRangeInSuspendCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("longRangeInSuspendFun.kt")
|
||||
public void testLongRangeInSuspendFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/longRangeInSuspendFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("mergeNullAndString.kt")
|
||||
public void testMergeNullAndString() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/mergeNullAndString.kt");
|
||||
|
||||
@@ -5168,6 +5168,18 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("longRangeInSuspendCall.kt")
|
||||
public void testLongRangeInSuspendCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/longRangeInSuspendCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("longRangeInSuspendFun.kt")
|
||||
public void testLongRangeInSuspendFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/longRangeInSuspendFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("mergeNullAndString.kt")
|
||||
public void testMergeNullAndString() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/mergeNullAndString.kt");
|
||||
|
||||
+12
@@ -5876,6 +5876,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("longRangeInSuspendCall.kt")
|
||||
public void testLongRangeInSuspendCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/longRangeInSuspendCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("longRangeInSuspendFun.kt")
|
||||
public void testLongRangeInSuspendFun() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/longRangeInSuspendFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("mergeNullAndString.kt")
|
||||
public void testMergeNullAndString() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/mergeNullAndString.kt");
|
||||
|
||||
Reference in New Issue
Block a user