diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/Callable.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/Callable.kt index f40a68e96f6..82bce227228 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/Callable.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/Callable.kt @@ -45,7 +45,7 @@ interface Callable { } } - fun afterReceiverGeneration(v: InstructionAdapter) { + fun afterReceiverGeneration(v: InstructionAdapter, frameMap: FrameMap) { } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 57a3eb15c0e..1702599ce8c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -2262,7 +2262,7 @@ public class ExpressionCodegen extends KtVisitor impleme myFrameMap.leaveTemp(firstReceiverType); } - callableMethod.afterReceiverGeneration(v); + callableMethod.afterReceiverGeneration(v, myFrameMap); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt index d8f0712fc68..1bb7782dd68 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt @@ -377,3 +377,22 @@ fun initializeVariablesForDestructuredLambdaParameters(codegen: ExpressionCodege } fun 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) + } +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/Concat.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/Concat.kt index d6f9441b21b..3d4d532e8f6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/Concat.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/Concat.kt @@ -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", "", "(Ljava/lang/String;)V", false) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/RangeTo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/RangeTo.kt index 27451b5a5a2..e16403198d9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/RangeTo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/RangeTo.kt @@ -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) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Concat.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Concat.kt index ec973056254..ffe869d4719 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Concat.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Concat.kt @@ -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", "", "(Ljava/lang/String;)V", false) } diff --git a/compiler/testData/codegen/box/coroutines/longRangeInSuspendCall.kt b/compiler/testData/codegen/box/coroutines/longRangeInSuspendCall.kt new file mode 100644 index 00000000000..48a506eb0a2 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/longRangeInSuspendCall.kt @@ -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" +} diff --git a/compiler/testData/codegen/box/coroutines/longRangeInSuspendFun.kt b/compiler/testData/codegen/box/coroutines/longRangeInSuspendFun.kt new file mode 100644 index 00000000000..6570d321cb9 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/longRangeInSuspendFun.kt @@ -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" +} diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index d1b1bb49fe5..26a0c6896ed 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index d34206de433..705f8d251e6 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 0a95024fed4..90b9c45f846 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -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"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index b535f4be17a..9942707cf96 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -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");