Do not use non-existing class for suspend markers
As they remain in inline functions now proguard emits a warning about them, even though inline suspend functions are effectively inline-only and these markers can't be executed at runtime #KT-18702 Fixed
This commit is contained in:
@@ -2238,19 +2238,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isSuspendCall) {
|
if (isSuspendCall) {
|
||||||
v.invokestatic(
|
addSuspendMarker(v, true);
|
||||||
CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER,
|
|
||||||
CoroutineCodegenUtilKt.BEFORE_SUSPENSION_POINT_MARKER_NAME,
|
|
||||||
"()V", false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
|
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
|
||||||
|
|
||||||
if (isSuspendCall) {
|
if (isSuspendCall) {
|
||||||
v.invokestatic(
|
addSuspendMarker(v, false);
|
||||||
CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER,
|
|
||||||
CoroutineCodegenUtilKt.AFTER_SUSPENSION_POINT_MARKER_NAME, "()V", false);
|
|
||||||
addInlineMarker(v, false);
|
addInlineMarker(v, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
-17
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.codegen.ClassBuilder
|
|||||||
import org.jetbrains.kotlin.codegen.StackValue
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
||||||
import org.jetbrains.kotlin.codegen.inline.MaxStackFrameSizeAndLocalsCalculator
|
import org.jetbrains.kotlin.codegen.inline.MaxStackFrameSizeAndLocalsCalculator
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.isAfterSuspendMarker
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.isBeforeSuspendMarker
|
||||||
import org.jetbrains.kotlin.codegen.inline.isInlineMarker
|
import org.jetbrains.kotlin.codegen.inline.isInlineMarker
|
||||||
import org.jetbrains.kotlin.codegen.optimization.DeadCodeEliminationMethodTransformer
|
import org.jetbrains.kotlin.codegen.optimization.DeadCodeEliminationMethodTransformer
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.*
|
import org.jetbrains.kotlin.codegen.optimization.common.*
|
||||||
@@ -302,7 +304,7 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
// It doesn't introduce an additional state to the corresponding coroutine's FSM.
|
// It doesn't introduce an additional state to the corresponding coroutine's FSM.
|
||||||
suspensionPoints.forEach {
|
suspensionPoints.forEach {
|
||||||
if (dceResult.isAlive(it.suspensionCallBegin) && dceResult.isRemoved(it.suspensionCallEnd)) {
|
if (dceResult.isAlive(it.suspensionCallBegin) && dceResult.isRemoved(it.suspensionCallEnd)) {
|
||||||
methodNode.instructions.remove(it.suspensionCallBegin)
|
it.removeBeforeSuspendMarker(methodNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,17 +313,15 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
|
|
||||||
private fun collectSuspensionPoints(methodNode: MethodNode): MutableList<SuspensionPoint> {
|
private fun collectSuspensionPoints(methodNode: MethodNode): MutableList<SuspensionPoint> {
|
||||||
val suspensionPoints = mutableListOf<SuspensionPoint>()
|
val suspensionPoints = mutableListOf<SuspensionPoint>()
|
||||||
val beforeSuspensionPointMarkerStack = Stack<MethodInsnNode>()
|
val beforeSuspensionPointMarkerStack = Stack<AbstractInsnNode>()
|
||||||
|
|
||||||
for (methodInsn in methodNode.instructions.toArray().filterIsInstance<MethodInsnNode>()) {
|
for (methodInsn in methodNode.instructions.toArray().filterIsInstance<MethodInsnNode>()) {
|
||||||
if (methodInsn.owner != COROUTINE_MARKER_OWNER) continue
|
when {
|
||||||
|
isBeforeSuspendMarker(methodInsn) -> {
|
||||||
when (methodInsn.name) {
|
beforeSuspensionPointMarkerStack.add(methodInsn.previous)
|
||||||
BEFORE_SUSPENSION_POINT_MARKER_NAME -> {
|
|
||||||
beforeSuspensionPointMarkerStack.add(methodInsn)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AFTER_SUSPENSION_POINT_MARKER_NAME -> {
|
isAfterSuspendMarker(methodInsn) -> {
|
||||||
suspensionPoints.add(SuspensionPoint(beforeSuspensionPointMarkerStack.pop(), methodInsn))
|
suspensionPoints.add(SuspensionPoint(beforeSuspensionPointMarkerStack.pop(), methodInsn))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -335,10 +335,8 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
private fun dropSuspensionMarkers(methodNode: MethodNode, suspensionPoints: List<SuspensionPoint>) {
|
private fun dropSuspensionMarkers(methodNode: MethodNode, suspensionPoints: List<SuspensionPoint>) {
|
||||||
// Drop markers
|
// Drop markers
|
||||||
suspensionPoints.forEach {
|
suspensionPoints.forEach {
|
||||||
// before-marker
|
it.removeBeforeSuspendMarker(methodNode)
|
||||||
methodNode.instructions.remove(it.suspensionCallBegin)
|
it.removeAfterSuspendMarker(methodNode)
|
||||||
// after-marker
|
|
||||||
methodNode.instructions.remove(it.suspensionCallEnd)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,18 +613,30 @@ private fun Type.normalize() =
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Suspension call may consists of several instructions:
|
* Suspension call may consists of several instructions:
|
||||||
* INVOKESTATIC beforeSuspensionMarker
|
* ICONST_0
|
||||||
|
* INVOKESTATIC InlineMarker.mark()
|
||||||
* INVOKEVIRTUAL suspensionMethod()Ljava/lang/Object; // actually it could be some inline method instead of plain call
|
* INVOKEVIRTUAL suspensionMethod()Ljava/lang/Object; // actually it could be some inline method instead of plain call
|
||||||
* CHECKCAST Type
|
* CHECKCAST Type
|
||||||
* INVOKESTATIC afterSuspensionMarker
|
* ICONST_1
|
||||||
|
* INVOKESTATIC InlineMarker.mark()
|
||||||
*/
|
*/
|
||||||
private class SuspensionPoint(
|
private class SuspensionPoint(
|
||||||
// INVOKESTATIC beforeSuspensionMarker
|
// ICONST_0
|
||||||
val suspensionCallBegin: AbstractInsnNode,
|
val suspensionCallBegin: AbstractInsnNode,
|
||||||
// INVOKESTATIC afterSuspensionMarker
|
// INVOKESTATIC InlineMarker.mark()
|
||||||
val suspensionCallEnd: AbstractInsnNode
|
val suspensionCallEnd: AbstractInsnNode
|
||||||
) {
|
) {
|
||||||
lateinit var tryCatchBlocksContinuationLabel: LabelNode
|
lateinit var tryCatchBlocksContinuationLabel: LabelNode
|
||||||
|
|
||||||
|
fun removeBeforeSuspendMarker(methodNode: MethodNode) {
|
||||||
|
methodNode.instructions.remove(suspensionCallBegin.next)
|
||||||
|
methodNode.instructions.remove(suspensionCallBegin)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeAfterSuspendMarker(methodNode: MethodNode) {
|
||||||
|
methodNode.instructions.remove(suspensionCallEnd.previous)
|
||||||
|
methodNode.instructions.remove(suspensionCallEnd)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLastParameterIndex(desc: String, access: Int) =
|
private fun getLastParameterIndex(desc: String, access: Int) =
|
||||||
@@ -747,4 +757,4 @@ private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode):
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val SAFE_OPCODES =
|
private val SAFE_OPCODES =
|
||||||
((Opcodes.DUP..Opcodes.DUP2_X2) + Opcodes.POP + Opcodes.POP2 + (Opcodes.IFEQ..Opcodes.GOTO)).toSet()
|
((Opcodes.DUP..Opcodes.DUP2_X2) + Opcodes.POP + Opcodes.POP2 + (Opcodes.IFEQ..Opcodes.GOTO)).toSet()
|
||||||
|
|||||||
@@ -52,11 +52,6 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
|||||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
|
|
||||||
// These classes do not actually exist at runtime
|
|
||||||
const val COROUTINE_MARKER_OWNER = "kotlin/coroutines/Markers"
|
|
||||||
const val BEFORE_SUSPENSION_POINT_MARKER_NAME = "beforeSuspensionPoint"
|
|
||||||
const val AFTER_SUSPENSION_POINT_MARKER_NAME = "afterSuspensionPoint"
|
|
||||||
|
|
||||||
const val COROUTINE_LABEL_FIELD_NAME = "label"
|
const val COROUTINE_LABEL_FIELD_NAME = "label"
|
||||||
const val SUSPEND_FUNCTION_CREATE_METHOD_NAME = "create"
|
const val SUSPEND_FUNCTION_CREATE_METHOD_NAME = "create"
|
||||||
const val DO_RESUME_METHOD_NAME = "doResume"
|
const val DO_RESUME_METHOD_NAME = "doResume"
|
||||||
|
|||||||
@@ -22,18 +22,19 @@ import org.jetbrains.kotlin.codegen.AsmUtil
|
|||||||
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
|
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
|
||||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||||
|
import org.jetbrains.kotlin.codegen.`when`.WhenByEnumsMapping
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||||
import org.jetbrains.kotlin.codegen.context.CodegenContext
|
import org.jetbrains.kotlin.codegen.context.CodegenContext
|
||||||
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil
|
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil
|
||||||
import org.jetbrains.kotlin.codegen.context.InlineLambdaContext
|
import org.jetbrains.kotlin.codegen.context.InlineLambdaContext
|
||||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.*
|
import org.jetbrains.kotlin.codegen.intrinsics.classId
|
||||||
|
import org.jetbrains.kotlin.codegen.optimization.common.intConstant
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
import org.jetbrains.kotlin.codegen.`when`.WhenByEnumsMapping
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.fileClasses.*
|
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider
|
||||||
|
import org.jetbrains.kotlin.fileClasses.getFileClassType
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryPackageSourceElement
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryPackageSourceElement
|
||||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||||
@@ -44,7 +45,11 @@ import org.jetbrains.kotlin.name.ClassId
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.ENUM_TYPE
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_CLASS_TYPE
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
|
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.org.objectweb.asm.*
|
import org.jetbrains.org.objectweb.asm.*
|
||||||
@@ -53,15 +58,9 @@ import org.jetbrains.org.objectweb.asm.tree.*
|
|||||||
import org.jetbrains.org.objectweb.asm.util.Printer
|
import org.jetbrains.org.objectweb.asm.util.Printer
|
||||||
import org.jetbrains.org.objectweb.asm.util.Textifier
|
import org.jetbrains.org.objectweb.asm.util.Textifier
|
||||||
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor
|
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor
|
||||||
|
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.ENUM_TYPE
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_CLASS_TYPE
|
|
||||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
|
||||||
|
|
||||||
|
|
||||||
const val GENERATE_SMAP = true
|
const val GENERATE_SMAP = true
|
||||||
const val API = Opcodes.ASM5
|
const val API = Opcodes.ASM5
|
||||||
@@ -88,6 +87,8 @@ private const val INLINE_MARKER_AFTER_METHOD_NAME = "afterInlineCall"
|
|||||||
private const val INLINE_MARKER_FINALLY_START = "finallyStart"
|
private const val INLINE_MARKER_FINALLY_START = "finallyStart"
|
||||||
|
|
||||||
private const val INLINE_MARKER_FINALLY_END = "finallyEnd"
|
private const val INLINE_MARKER_FINALLY_END = "finallyEnd"
|
||||||
|
private const val INLINE_MARKER_BEFORE_SUSPEND_ID = 0
|
||||||
|
private const val INLINE_MARKER_AFTER_SUSPEND_ID = 1
|
||||||
|
|
||||||
internal fun getMethodNode(
|
internal fun getMethodNode(
|
||||||
classData: ByteArray,
|
classData: ByteArray,
|
||||||
@@ -430,6 +431,21 @@ internal fun addInlineMarker(v: InstructionAdapter, isStartNotEnd: Boolean) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun addSuspendMarker(v: InstructionAdapter, isStartNotEnd: Boolean) {
|
||||||
|
v.iconst(if (isStartNotEnd) INLINE_MARKER_BEFORE_SUSPEND_ID else INLINE_MARKER_AFTER_SUSPEND_ID)
|
||||||
|
v.visitMethodInsn(
|
||||||
|
Opcodes.INVOKESTATIC, INLINE_MARKER_CLASS_NAME,
|
||||||
|
"mark",
|
||||||
|
"(I)V", false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun isBeforeSuspendMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_BEFORE_SUSPEND_ID)
|
||||||
|
internal fun isAfterSuspendMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_AFTER_SUSPEND_ID)
|
||||||
|
|
||||||
|
private fun isSuspendMarker(insn: AbstractInsnNode, id: Int) =
|
||||||
|
isInlineMarker(insn, "mark") && insn.previous.intConstant == id
|
||||||
|
|
||||||
internal fun isInlineMarker(insn: AbstractInsnNode): Boolean {
|
internal fun isInlineMarker(insn: AbstractInsnNode): Boolean {
|
||||||
return isInlineMarker(insn, null)
|
return isInlineMarker(insn, null)
|
||||||
}
|
}
|
||||||
@@ -581,4 +597,4 @@ class InlineOnlySmapSkipper(codegen: BaseExpressionCodegen) {
|
|||||||
mv.visitLineNumber(callLineNumber, label)
|
mv.visitLineNumber(callLineNumber, label)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user