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);
|
myFrameMap.leaveTemp(firstReceiverType);
|
||||||
}
|
}
|
||||||
|
|
||||||
callableMethod.afterReceiverGeneration(v);
|
callableMethod.afterReceiverGeneration(v, myFrameMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -377,3 +377,22 @@ fun initializeVariablesForDestructuredLambdaParameters(codegen: ExpressionCodege
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun <D : CallableDescriptor> D.unwrapFrontendVersion() = unwrapInitialDescriptorForSuspendFunction()
|
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.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE
|
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.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
@@ -83,10 +82,8 @@ class Concat : IntrinsicMethod() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun afterReceiverGeneration(v: InstructionAdapter) {
|
override fun afterReceiverGeneration(v: InstructionAdapter, frameMap: FrameMap) {
|
||||||
v.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder")
|
v.generateNewInstanceDupAndPlaceBeforeStackTop(frameMap, AsmTypes.JAVA_STRING_TYPE, "java/lang/StringBuilder")
|
||||||
v.dupX1()
|
|
||||||
v.swap()
|
|
||||||
v.invokespecial("java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false)
|
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.Callable
|
||||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
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.Type.*
|
import org.jetbrains.org.objectweb.asm.Type.*
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
@@ -47,19 +48,8 @@ class RangeTo : IntrinsicMethod() {
|
|||||||
nullOr(method.dispatchReceiverType, argType),
|
nullOr(method.dispatchReceiverType, argType),
|
||||||
nullOr(method.extensionReceiverType, argType)
|
nullOr(method.extensionReceiverType, argType)
|
||||||
) {
|
) {
|
||||||
override fun afterReceiverGeneration(v: InstructionAdapter) {
|
override fun afterReceiverGeneration(v: InstructionAdapter, frameMap: FrameMap) {
|
||||||
v.anew(returnType)
|
v.generateNewInstanceDupAndPlaceBeforeStackTop(frameMap, argType, returnType.internalName)
|
||||||
when (argType.size) {
|
|
||||||
1 -> {
|
|
||||||
v.dupX1()
|
|
||||||
v.swap()
|
|
||||||
}
|
|
||||||
2 -> {
|
|
||||||
v.dup()
|
|
||||||
v.dup2X2()
|
|
||||||
v.pop2()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun invokeIntrinsic(v: InstructionAdapter) {
|
override fun invokeIntrinsic(v: InstructionAdapter) {
|
||||||
|
|||||||
@@ -116,10 +116,8 @@ class Concat : IntrinsicMethod() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun afterReceiverGeneration(v: InstructionAdapter) {
|
override fun afterReceiverGeneration(v: InstructionAdapter, frameMap: FrameMap) {
|
||||||
v.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder")
|
v.generateNewInstanceDupAndPlaceBeforeStackTop(frameMap, AsmTypes.JAVA_STRING_TYPE, "java/lang/StringBuilder")
|
||||||
v.dupX1()
|
|
||||||
v.swap()
|
|
||||||
v.invokespecial("java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false)
|
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);
|
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")
|
@TestMetadata("mergeNullAndString.kt")
|
||||||
public void testMergeNullAndString() throws Exception {
|
public void testMergeNullAndString() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/mergeNullAndString.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/mergeNullAndString.kt");
|
||||||
|
|||||||
@@ -5168,6 +5168,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("mergeNullAndString.kt")
|
||||||
public void testMergeNullAndString() throws Exception {
|
public void testMergeNullAndString() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/mergeNullAndString.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/mergeNullAndString.kt");
|
||||||
|
|||||||
@@ -5168,6 +5168,18 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("mergeNullAndString.kt")
|
||||||
public void testMergeNullAndString() throws Exception {
|
public void testMergeNullAndString() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/mergeNullAndString.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/mergeNullAndString.kt");
|
||||||
|
|||||||
+12
@@ -5876,6 +5876,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("mergeNullAndString.kt")
|
||||||
public void testMergeNullAndString() throws Exception {
|
public void testMergeNullAndString() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/mergeNullAndString.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/mergeNullAndString.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user