Box inline class in resume path of suspend call
#KT-41429
This commit is contained in:
@@ -46,7 +46,6 @@ import org.jetbrains.kotlin.config.ApiVersion;
|
|||||||
import org.jetbrains.kotlin.config.JVMAssertionsMode;
|
import org.jetbrains.kotlin.config.JVMAssertionsMode;
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
|
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
|
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
|
||||||
@@ -2735,8 +2734,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
|
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
|
||||||
|
|
||||||
if (maybeSuspensionPoint) {
|
if (maybeSuspensionPoint) {
|
||||||
|
// The order is important! Do not reorder!
|
||||||
|
// CoroutineTransformerMethodVisitor expects the marker exactly in this order.
|
||||||
addReturnsUnitMarkerIfNecessary(v, resolvedCall);
|
addReturnsUnitMarkerIfNecessary(v, resolvedCall);
|
||||||
addSuspendMarker(v, false, suspensionPointKind == SuspensionPointKind.NOT_INLINE);
|
addSuspendMarker(v, false, suspensionPointKind == SuspensionPointKind.NOT_INLINE);
|
||||||
|
addUnboxInlineClassMarkersIfNeeded(v, resolvedCall.getResultingDescriptor(), typeMapper);
|
||||||
addInlineMarker(v, false);
|
addInlineMarker(v, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -636,6 +636,9 @@ class CoroutineCodegenForNamedFunction private constructor(
|
|||||||
|
|
||||||
override val passArityToSuperClass get() = false
|
override val passArityToSuperClass get() = false
|
||||||
|
|
||||||
|
private val inlineClassToBoxInInvokeSuspend: KotlinType? =
|
||||||
|
originalSuspendFunctionDescriptor.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass(state.typeMapper)
|
||||||
|
|
||||||
override fun generateBridges() {
|
override fun generateBridges() {
|
||||||
// Do not generate any closure bridges
|
// Do not generate any closure bridges
|
||||||
}
|
}
|
||||||
@@ -719,6 +722,22 @@ class CoroutineCodegenForNamedFunction private constructor(
|
|||||||
callableMethod.genInvokeInstruction(codegen.v)
|
callableMethod.genInvokeInstruction(codegen.v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (inlineClassToBoxInInvokeSuspend != null) {
|
||||||
|
with(codegen.v) {
|
||||||
|
// We need to box the returned inline class in resume path.
|
||||||
|
// But first, check for COROUTINE_SUSPENDED, since the function can return it
|
||||||
|
dup()
|
||||||
|
loadCoroutineSuspendedMarker(languageVersionSettings)
|
||||||
|
val elseLabel = Label()
|
||||||
|
ifacmpne(elseLabel)
|
||||||
|
areturn(AsmTypes.OBJECT_TYPE)
|
||||||
|
mark(elseLabel)
|
||||||
|
// Now we box the inline class
|
||||||
|
StackValue.coerce(AsmTypes.OBJECT_TYPE, typeMapper.mapType(inlineClassToBoxInInvokeSuspend), this)
|
||||||
|
StackValue.boxInlineClass(inlineClassToBoxInInvokeSuspend, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
codegen.v.visitInsn(Opcodes.ARETURN)
|
codegen.v.visitInsn(Opcodes.ARETURN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+28
@@ -114,6 +114,7 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
if (examiner.allSuspensionPointsAreTailCalls(suspensionPoints)) {
|
if (examiner.allSuspensionPointsAreTailCalls(suspensionPoints)) {
|
||||||
examiner.replacePopsBeforeSafeUnitInstancesWithCoroutineSuspendedChecks()
|
examiner.replacePopsBeforeSafeUnitInstancesWithCoroutineSuspendedChecks()
|
||||||
dropSuspensionMarkers(methodNode)
|
dropSuspensionMarkers(methodNode)
|
||||||
|
dropUnboxInlineClassMarkers(methodNode, suspensionPoints)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +191,7 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
initializeFakeInlinerVariables(methodNode, stateLabels)
|
initializeFakeInlinerVariables(methodNode, stateLabels)
|
||||||
|
|
||||||
dropSuspensionMarkers(methodNode)
|
dropSuspensionMarkers(methodNode)
|
||||||
|
dropUnboxInlineClassMarkers(methodNode, suspensionPoints)
|
||||||
methodNode.removeEmptyCatchBlocks()
|
methodNode.removeEmptyCatchBlocks()
|
||||||
|
|
||||||
if (languageVersionSettings.isReleaseCoroutines()) {
|
if (languageVersionSettings.isReleaseCoroutines()) {
|
||||||
@@ -599,6 +601,17 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun dropUnboxInlineClassMarkers(methodNode: MethodNode, suspensionPoints: List<SuspensionPoint>) {
|
||||||
|
for (marker in methodNode.instructions.asSequence()
|
||||||
|
.filter { isBeforeUnboxInlineClassMarker(it) || isAfterUnboxInlineClassMarker(it) }.toList()
|
||||||
|
) {
|
||||||
|
methodNode.instructions.removeAll(listOf(marker.previous, marker))
|
||||||
|
}
|
||||||
|
for (suspension in suspensionPoints) {
|
||||||
|
methodNode.instructions.removeAll(suspension.unboxInlineClassInstructions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun spillVariables(suspensionPoints: List<SuspensionPoint>, methodNode: MethodNode): List<List<SpilledVariableAndField>> {
|
private fun spillVariables(suspensionPoints: List<SuspensionPoint>, methodNode: MethodNode): List<List<SpilledVariableAndField>> {
|
||||||
val instructions = methodNode.instructions
|
val instructions = methodNode.instructions
|
||||||
val frames =
|
val frames =
|
||||||
@@ -918,6 +931,11 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
|
|
||||||
// Load continuation argument just like suspending function returns it
|
// Load continuation argument just like suspending function returns it
|
||||||
load(dataIndex, AsmTypes.OBJECT_TYPE)
|
load(dataIndex, AsmTypes.OBJECT_TYPE)
|
||||||
|
// Unbox inline class, since this is the resume path and unlike the direct path
|
||||||
|
// the class is boxed.
|
||||||
|
for (insn in suspension.unboxInlineClassInstructions) {
|
||||||
|
insn.accept(this)
|
||||||
|
}
|
||||||
|
|
||||||
visitLabel(continuationLabelAfterLoadedResult.label)
|
visitLabel(continuationLabelAfterLoadedResult.label)
|
||||||
|
|
||||||
@@ -1117,6 +1135,16 @@ internal class SuspensionPoint(
|
|||||||
) {
|
) {
|
||||||
lateinit var tryCatchBlocksContinuationLabel: LabelNode
|
lateinit var tryCatchBlocksContinuationLabel: LabelNode
|
||||||
|
|
||||||
|
val unboxInlineClassInstructions: List<AbstractInsnNode> = findUnboxInlineClassInstructions()
|
||||||
|
|
||||||
|
private fun findUnboxInlineClassInstructions(): List<AbstractInsnNode> {
|
||||||
|
val beforeMarker = suspensionCallEnd.next?.next ?: return emptyList()
|
||||||
|
if (!isBeforeUnboxInlineClassMarker(beforeMarker)) return emptyList()
|
||||||
|
val afterMarker = beforeMarker.findNextOrNull { isAfterUnboxInlineClassMarker(it) }
|
||||||
|
?: error("Before unbox inline class marker without after unbox inline class marker")
|
||||||
|
return InsnSequence(beforeMarker.next, afterMarker.previous).toList()
|
||||||
|
}
|
||||||
|
|
||||||
operator fun contains(insn: AbstractInsnNode): Boolean {
|
operator fun contains(insn: AbstractInsnNode): Boolean {
|
||||||
for (i in InsnSequence(suspensionCallBegin, suspensionCallEnd.next)) {
|
for (i in InsnSequence(suspensionCallBegin, suspensionCallEnd.next)) {
|
||||||
if (i == insn) return true
|
if (i == insn) return true
|
||||||
|
|||||||
+11
-10
@@ -33,12 +33,14 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
|||||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
|
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
|
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||||
|
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
|
||||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
@@ -111,8 +113,8 @@ fun computeLabelOwner(languageVersionSettings: LanguageVersionSettings, thisName
|
|||||||
else
|
else
|
||||||
languageVersionSettings.coroutinesJvmInternalPackageFqName().child(Name.identifier("CoroutineImpl")).topLevelClassAsmType()
|
languageVersionSettings.coroutinesJvmInternalPackageFqName().child(Name.identifier("CoroutineImpl")).topLevelClassAsmType()
|
||||||
|
|
||||||
private val NORMALIZE_CONTINUATION_METHOD_NAME = "normalizeContinuation"
|
private const val NORMALIZE_CONTINUATION_METHOD_NAME = "normalizeContinuation"
|
||||||
private val GET_CONTEXT_METHOD_NAME = "getContext"
|
private const val GET_CONTEXT_METHOD_NAME = "getContext"
|
||||||
|
|
||||||
data class ResolvedCallWithRealDescriptor(val resolvedCall: ResolvedCall<*>, val fakeContinuationExpression: KtExpression)
|
data class ResolvedCallWithRealDescriptor(val resolvedCall: ResolvedCall<*>, val fakeContinuationExpression: KtExpression)
|
||||||
|
|
||||||
@@ -140,11 +142,11 @@ fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(
|
|||||||
if (this is VariableAsFunctionResolvedCall) {
|
if (this is VariableAsFunctionResolvedCall) {
|
||||||
val replacedFunctionCall =
|
val replacedFunctionCall =
|
||||||
functionCall.replaceSuspensionFunctionWithRealDescriptor(project, bindingContext, isReleaseCoroutines)
|
functionCall.replaceSuspensionFunctionWithRealDescriptor(project, bindingContext, isReleaseCoroutines)
|
||||||
?: return null
|
?: return null
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return replacedFunctionCall.copy(
|
return replacedFunctionCall.copy(
|
||||||
VariableAsFunctionResolvedCallImpl(
|
resolvedCall = VariableAsFunctionResolvedCallImpl(
|
||||||
replacedFunctionCall.resolvedCall as MutableResolvedCall<FunctionDescriptor>,
|
replacedFunctionCall.resolvedCall as MutableResolvedCall<FunctionDescriptor>,
|
||||||
variableCall.asMutableResolvedCall(bindingContext)
|
variableCall.asMutableResolvedCall(bindingContext)
|
||||||
)
|
)
|
||||||
@@ -413,7 +415,8 @@ fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(languageVersionSett
|
|||||||
load(1, OBJECT_TYPE) // continuation
|
load(1, OBJECT_TYPE) // continuation
|
||||||
checkcast(languageVersionSettings.continuationAsmType())
|
checkcast(languageVersionSettings.continuationAsmType())
|
||||||
invokestatic(
|
invokestatic(
|
||||||
languageVersionSettings.coroutinesJvmInternalPackageFqName().child(Name.identifier("DebugProbesKt")).topLevelClassAsmType().internalName,
|
languageVersionSettings.coroutinesJvmInternalPackageFqName().child(Name.identifier("DebugProbesKt"))
|
||||||
|
.topLevelClassAsmType().internalName,
|
||||||
"probeCoroutineSuspended",
|
"probeCoroutineSuspended",
|
||||||
"(${languageVersionSettings.continuationAsmType()})V",
|
"(${languageVersionSettings.continuationAsmType()})V",
|
||||||
false
|
false
|
||||||
@@ -466,7 +469,7 @@ fun FunctionDescriptor.originalReturnTypeOfSuspendFunctionReturningUnboxedInline
|
|||||||
val originalReturnType = originalDescriptor.returnType ?: return null
|
val originalReturnType = originalDescriptor.returnType ?: return null
|
||||||
if (!originalReturnType.isInlineClassType()) return null
|
if (!originalReturnType.isInlineClassType()) return null
|
||||||
// Force boxing for primitives
|
// Force boxing for primitives
|
||||||
if (AsmUtil.isPrimitive(typeMapper.mapType(originalReturnType))) return null
|
if (AsmUtil.isPrimitive(typeMapper.mapType(originalReturnType.makeNotNullable()))) return null
|
||||||
// Force boxing for nullable inline class types with nullable underlying type
|
// Force boxing for nullable inline class types with nullable underlying type
|
||||||
if (originalReturnType.isMarkedNullable && originalReturnType.isNullableUnderlyingType()) return null
|
if (originalReturnType.isMarkedNullable && originalReturnType.isNullableUnderlyingType()) return null
|
||||||
// Force boxing if the function overrides function with return type Any
|
// Force boxing if the function overrides function with return type Any
|
||||||
@@ -474,8 +477,6 @@ fun FunctionDescriptor.originalReturnTypeOfSuspendFunctionReturningUnboxedInline
|
|||||||
(it.original.returnType?.isMarkedNullable == true && it.original.returnType?.isNullableUnderlyingType() == true) ||
|
(it.original.returnType?.isMarkedNullable == true && it.original.returnType?.isNullableUnderlyingType() == true) ||
|
||||||
it.original.returnType?.makeNotNullable() != originalReturnType.makeNotNullable()
|
it.original.returnType?.makeNotNullable() != originalReturnType.makeNotNullable()
|
||||||
}) return null
|
}) return null
|
||||||
// TODO: Do not box `Result`
|
|
||||||
if (originalReturnType.constructor.declarationDescriptor?.fqNameSafe == StandardNames.RESULT_FQ_NAME) return null
|
|
||||||
// Don't box other inline classes
|
// Don't box other inline classes
|
||||||
return originalReturnType
|
return originalReturnType
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ package org.jetbrains.kotlin.codegen.inline
|
|||||||
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.codegen.ASSERTIONS_DISABLED_FIELD_NAME
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
|
||||||
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
|
|
||||||
import org.jetbrains.kotlin.codegen.SamWrapperCodegen.SAM_WRAPPER_SUFFIX
|
import org.jetbrains.kotlin.codegen.SamWrapperCodegen.SAM_WRAPPER_SUFFIX
|
||||||
import org.jetbrains.kotlin.codegen.`when`.WhenByEnumsMapping
|
import org.jetbrains.kotlin.codegen.`when`.WhenByEnumsMapping
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||||
@@ -17,16 +15,14 @@ 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.coroutines.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
|
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.intConstant
|
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.descriptors.ClassifierDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
|
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
|
||||||
@@ -80,6 +76,8 @@ private const val INLINE_MARKER_BEFORE_FAKE_CONTINUATION_CONSTRUCTOR_CALL = 4
|
|||||||
private const val INLINE_MARKER_AFTER_FAKE_CONTINUATION_CONSTRUCTOR_CALL = 5
|
private const val INLINE_MARKER_AFTER_FAKE_CONTINUATION_CONSTRUCTOR_CALL = 5
|
||||||
private const val INLINE_MARKER_BEFORE_INLINE_SUSPEND_ID = 6
|
private const val INLINE_MARKER_BEFORE_INLINE_SUSPEND_ID = 6
|
||||||
private const val INLINE_MARKER_AFTER_INLINE_SUSPEND_ID = 7
|
private const val INLINE_MARKER_AFTER_INLINE_SUSPEND_ID = 7
|
||||||
|
private const val INLINE_MARKER_BEFORE_UNBOX_INLINE_CLASS = 8
|
||||||
|
private const val INLINE_MARKER_AFTER_UNBOX_INLINE_CLASS = 9
|
||||||
|
|
||||||
internal fun getMethodNode(
|
internal fun getMethodNode(
|
||||||
classData: ByteArray,
|
classData: ByteArray,
|
||||||
@@ -413,6 +411,23 @@ fun addInlineMarker(v: InstructionAdapter, isStartNotEnd: Boolean) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun addUnboxInlineClassMarkersIfNeeded(v: InstructionAdapter, descriptor: CallableDescriptor, typeMapper: KotlinTypeMapper) {
|
||||||
|
val inlineClass = (descriptor as? FunctionDescriptor)?.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass(typeMapper)
|
||||||
|
if (inlineClass != null) {
|
||||||
|
addBeforeUnboxInlineClassMarker(v)
|
||||||
|
StackValue.unboxInlineClass(AsmTypes.OBJECT_TYPE, inlineClass, v)
|
||||||
|
addAfterUnboxInlineClassMarker(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addBeforeUnboxInlineClassMarker(v: InstructionAdapter) {
|
||||||
|
v.emitInlineMarker(INLINE_MARKER_BEFORE_UNBOX_INLINE_CLASS)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addAfterUnboxInlineClassMarker(v: InstructionAdapter) {
|
||||||
|
v.emitInlineMarker(INLINE_MARKER_AFTER_UNBOX_INLINE_CLASS)
|
||||||
|
}
|
||||||
|
|
||||||
internal fun addReturnsUnitMarkerIfNecessary(v: InstructionAdapter, resolvedCall: ResolvedCall<*>) {
|
internal fun addReturnsUnitMarkerIfNecessary(v: InstructionAdapter, resolvedCall: ResolvedCall<*>) {
|
||||||
val wrapperDescriptor = resolvedCall.candidateDescriptor.safeAs<FunctionDescriptor>() ?: return
|
val wrapperDescriptor = resolvedCall.candidateDescriptor.safeAs<FunctionDescriptor>() ?: return
|
||||||
val unsubstitutedDescriptor = wrapperDescriptor.unwrapInitialDescriptorForSuspendFunction()
|
val unsubstitutedDescriptor = wrapperDescriptor.unwrapInitialDescriptorForSuspendFunction()
|
||||||
@@ -477,6 +492,8 @@ internal fun isAfterInlineSuspendMarker(insn: AbstractInsnNode) = isSuspendMarke
|
|||||||
internal fun isReturnsUnitMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_RETURNS_UNIT)
|
internal fun isReturnsUnitMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_RETURNS_UNIT)
|
||||||
internal fun isFakeContinuationMarker(insn: AbstractInsnNode) =
|
internal fun isFakeContinuationMarker(insn: AbstractInsnNode) =
|
||||||
insn.previous != null && isSuspendMarker(insn.previous, INLINE_MARKER_FAKE_CONTINUATION) && insn.opcode == Opcodes.ACONST_NULL
|
insn.previous != null && isSuspendMarker(insn.previous, INLINE_MARKER_FAKE_CONTINUATION) && insn.opcode == Opcodes.ACONST_NULL
|
||||||
|
internal fun isBeforeUnboxInlineClassMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_BEFORE_UNBOX_INLINE_CLASS)
|
||||||
|
internal fun isAfterUnboxInlineClassMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_AFTER_UNBOX_INLINE_CLASS)
|
||||||
|
|
||||||
internal fun isBeforeFakeContinuationConstructorCallMarker(insn: AbstractInsnNode) =
|
internal fun isBeforeFakeContinuationConstructorCallMarker(insn: AbstractInsnNode) =
|
||||||
isSuspendMarker(insn, INLINE_MARKER_BEFORE_FAKE_CONTINUATION_CONSTRUCTOR_CALL)
|
isSuspendMarker(insn, INLINE_MARKER_BEFORE_FAKE_CONTINUATION_CONSTRUCTOR_CALL)
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ suspend fun signInFlowStepFirst(): Result<Unit> = try {
|
|||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
builder {
|
builder {
|
||||||
signInFlowStepFirst()
|
val res: Result<Unit> = signInFlowStepFirst()
|
||||||
|
if (res.exceptionOrNull()!!.message != "BOOYA") error("FAIL")
|
||||||
}
|
}
|
||||||
continuation!!.resumeWithException(Exception("BOOYA"))
|
continuation!!.resumeWithException(Exception("BOOYA"))
|
||||||
return "OK"
|
return "OK"
|
||||||
|
|||||||
Reference in New Issue
Block a user