From d300e05be9616e818e61102bd2ae2a7afd3fd3ba Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 15 Feb 2021 16:09:51 +0100 Subject: [PATCH] Remove obsolete code in inliner for experimental coroutines --- .../kotlin/codegen/inline/InlineCodegen.kt | 31 ++--------- .../codegen/inline/LegacyInlineSuspendUtil.kt | 54 ------------------- .../obsoleteInlineSuspend/library.output.txt | 2 - .../obsoleteInlineSuspend/library/a.kt | 31 ----------- .../obsoleteInlineSuspend/output.txt | 2 - .../obsoleteInlineSuspend/source.kt | 36 ------------- .../CompileKotlinAgainstCustomBinariesTest.kt | 46 ---------------- 7 files changed, 5 insertions(+), 197 deletions(-) delete mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LegacyInlineSuspendUtil.kt delete mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/library.output.txt delete mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/library/a.kt delete mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/output.txt delete mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/source.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt index ea97043b650..7fcbc4ea5c1 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.incremental.components.Position import org.jetbrains.kotlin.incremental.components.ScopeKind -import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -42,8 +41,6 @@ import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.Method import org.jetbrains.org.objectweb.asm.tree.* -import java.util.* -import kotlin.collections.HashSet import kotlin.math.max abstract class InlineCodegen( @@ -639,35 +636,17 @@ abstract class InlineCodegen( ?: throw IllegalStateException("Couldn't find declaration file for $containerId") } - val methodNode = getMethodNodeInner(containerId, bytes, asmMethod, callableDescriptor) ?: return null - - // KLUDGE: Inline suspend function built with compiler version less than 1.1.4/1.2-M1 did not contain proper - // before/after suspension point marks, so we detect those functions here and insert the corresponding marks - if (isLegacySuspendInlineFunction(callableDescriptor)) { - insertLegacySuspendInlineMarks(methodNode.node) - } - - return methodNode - } - - private fun getMethodNodeInner( - containerId: ClassId, - bytes: ByteArray, - asmMethod: Method, - callableDescriptor: CallableMemberDescriptor - ): SMAPAndMethodNode? { val classType = AsmUtil.asmTypeByClassId(containerId) - var methodNode = getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, classType) + val methodNode = getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, classType) if (methodNode == null && requiresFunctionNameManglingForReturnType(callableDescriptor)) { val nameWithoutManglingSuffix = asmMethod.name.stripManglingSuffixOrNull() if (nameWithoutManglingSuffix != null) { - methodNode = getMethodNode(bytes, nameWithoutManglingSuffix, asmMethod.descriptor, classType) - } - if (methodNode == null) { - val nameWithImplSuffix = "$nameWithoutManglingSuffix-impl" - methodNode = getMethodNode(bytes, nameWithImplSuffix, asmMethod.descriptor, classType) + val methodWithoutMangling = getMethodNode(bytes, nameWithoutManglingSuffix, asmMethod.descriptor, classType) + if (methodWithoutMangling != null) return methodWithoutMangling } + return getMethodNode(bytes, "$nameWithoutManglingSuffix-impl", asmMethod.descriptor, classType) } + return methodNode } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LegacyInlineSuspendUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LegacyInlineSuspendUtil.kt deleted file mode 100644 index f38d26f6f83..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LegacyInlineSuspendUtil.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.inline - -import org.jetbrains.org.objectweb.asm.Opcodes -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.load.kotlin.getContainingKotlinJvmBinaryClass -import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter -import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode -import org.jetbrains.org.objectweb.asm.tree.MethodNode - -// KLUDGE: Inline suspend function built with compiler version less than 1.1.4/1.2-M1 did not contain proper -// before/after suspension point marks, so we detect those functions here and insert the corresponding marks - -fun insertLegacySuspendInlineMarks(node: MethodNode) { - with(node.instructions) { - // look for return instruction before the end and insert "afterSuspendMarker" there - insertBefore(findLastReturn(last) ?: return, produceSuspendMarker(false).instructions) - // insert "beforeSuspendMarker" at the beginning - insertBefore(first, produceSuspendMarker(true).instructions) - } - node.maxStack = node.maxStack.coerceAtLeast(2) // min stack need for suspend marker before return -} - -fun findLastReturn(node: AbstractInsnNode?): AbstractInsnNode? { - var cur = node - while (cur != null && cur.opcode != Opcodes.ARETURN) cur = cur.previous - return cur -} - -private fun produceSuspendMarker(isStartNotEnd: Boolean): MethodNode = - MethodNode().also { addSuspendMarker(InstructionAdapter(it), isStartNotEnd) } - -fun isLegacySuspendInlineFunction(descriptor: CallableMemberDescriptor): Boolean { - if (descriptor !is FunctionDescriptor) return false - if (!descriptor.isSuspend || !descriptor.isInline) return false - val jvmBytecodeVersion = descriptor.getContainingKotlinJvmBinaryClass()?.classHeader?.bytecodeVersion ?: return false - return !jvmBytecodeVersion.isAtLeast(1, 0, 2) -} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/library.output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/library.output.txt deleted file mode 100644 index 7d53695d487..00000000000 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/library.output.txt +++ /dev/null @@ -1,2 +0,0 @@ -warning: language version 1.2 is deprecated and its support will be removed in a future version of Kotlin -OK diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/library/a.kt deleted file mode 100644 index 0c55e519627..00000000000 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/library/a.kt +++ /dev/null @@ -1,31 +0,0 @@ -package library - -import kotlin.coroutines.experimental.* - -var continuation: Continuation? = null -val sb = java.lang.StringBuilder() - -fun append(s: String) { sb.append(s) } - -val libraryResult: String get() = sb.toString() - -// this is an inline tail-suspend function that should work properly despite being compiler by -// compiler before 1.1.4 version that did not include suspension marks into bytecode. -// In order to test that it works properly it shall actually suspend during its execution -inline suspend fun foo(block: () -> Unit) { - append("(foo)") - block() - return suspendCoroutine { continuation = it } -} - -suspend fun bar() { - append("(bar)") - return suspendCoroutine { continuation = it } -} - -fun resumeLibrary() { - continuation?.let { - continuation = null - it.resume(Unit) - } -} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/output.txt deleted file mode 100644 index 7d53695d487..00000000000 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/output.txt +++ /dev/null @@ -1,2 +0,0 @@ -warning: language version 1.2 is deprecated and its support will be removed in a future version of Kotlin -OK diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/source.kt deleted file mode 100644 index 02c640eeb76..00000000000 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/obsoleteInlineSuspend/source.kt +++ /dev/null @@ -1,36 +0,0 @@ -import library.* -import kotlin.coroutines.experimental.* - -suspend fun test() { - append("[foo]") - foo { // we are inlining foo here - append("(block)") - } - append("[bar]") - bar() // and invoking suspending function bar - append("[test]") -} - -fun runBlockingLibrary(block: suspend () -> Unit): String { - var done = false - block.startCoroutine(object : Continuation { - override val context: CoroutineContext = EmptyCoroutineContext - override fun resume(value: Unit) { done = true } - override fun resumeWithException(exception: Throwable) { throw exception } - }) - var resumeCounter = 0 - while (!done) { - resumeCounter++ - resumeLibrary() - } - return "$libraryResult:resumes=$resumeCounter" -} - -// Retruns array of expected and received string -fun run(): Array { - val result = runBlockingLibrary { - test() - } - return arrayOf("[foo](foo)(block)[bar](bar)[test]:resumes=2", result) -} - diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt index 9d80dc183d5..684b240d6c3 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt @@ -19,9 +19,6 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler import org.jetbrains.kotlin.cli.transformMetadataInClassFile import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime -import org.jetbrains.kotlin.codegen.inline.remove -import org.jetbrains.kotlin.codegen.optimization.common.asSequence -import org.jetbrains.kotlin.codegen.optimization.common.intConstant import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.KotlinCompilerVersion import org.jetbrains.kotlin.config.KotlinCompilerVersion.TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY @@ -43,10 +40,7 @@ import org.jetbrains.kotlin.test.TestJdkKind import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparatorAdaptor.validateAndCompareDescriptorWithFile import org.jetbrains.kotlin.utils.PathUtil import org.jetbrains.org.objectweb.asm.* -import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode import org.jetbrains.org.objectweb.asm.tree.ClassNode -import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode -import org.jetbrains.org.objectweb.asm.tree.MethodNode import java.io.ByteArrayInputStream import java.io.DataInputStream import java.io.File @@ -765,46 +759,6 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration } companion object { - // compiler before 1.1.4 version did not include suspension marks into bytecode. - private fun stripSuspensionMarksToImitateLegacyCompiler(bytes: ByteArray): Pair { - val writer = ClassWriter(0) - var removedCounter = 0 - ClassReader(bytes).accept(object : ClassVisitor(Opcodes.API_VERSION, writer) { - override fun visitMethod( - access: Int, - name: String?, - desc: String?, - signature: String?, - exceptions: Array? - ): MethodVisitor { - val superMV = super.visitMethod(access, name, desc, signature, exceptions) - return object : MethodNode(Opcodes.API_VERSION, access, name, desc, signature, exceptions) { - override fun visitEnd() { - val removeList = instructions.asSequence() - .flatMap { suspendMarkerInsns(it).asSequence() }.toList() - remove(removeList) - removedCounter += removeList.size - accept(superMV) - } - } - } - }, 0) - return writer.toByteArray() to removedCounter - } - - // KLUDGE: here is a simplified copy of compiler's logic for suspend markers - - private fun suspendMarkerInsns(insn: AbstractInsnNode): List = - if (insn is MethodInsnNode - && insn.opcode == Opcodes.INVOKESTATIC - && insn.owner == "kotlin/jvm/internal/InlineMarker" - && insn.name == "mark" - && insn.previous.intConstant in 0..1 - ) listOf(insn, insn.previous) - else emptyList() - - // ----- - private fun copyJarFileWithoutEntry(jarPath: File, vararg entriesToDelete: String): File = transformJar(jarPath, { _, bytes -> bytes }, entriesToDelete.toSet())