diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt index f6beca2bce2..c4a846e2db7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt @@ -319,7 +319,7 @@ class AnonymousObjectTransformer( ), null ) - val result = inliner.doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, ReturnLabelOwner.NOT_APPLICABLE) + val result = inliner.doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf()) result.reifiedTypeParametersUsages.mergeAll(typeParametersToReify) deferringVisitor.visitMaxs(-1, -1) return result 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 7c45a0bfbff..ea97043b650 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -243,12 +243,10 @@ abstract class InlineCodegen( //hack to keep linenumber info, otherwise jdi will skip begin of linenumber chain adapter.visitInsn(Opcodes.NOP) - val result = inliner.doInline(adapter, remapper, true, ReturnLabelOwner.SKIP_ALL) + val result = inliner.doInline(adapter, remapper, true, mapOf()) result.reifiedTypeParametersUsages.mergeAll(reificationResult) - val labels = sourceCompiler.getContextLabels() - - val infos = MethodInliner.processReturns(adapter, ReturnLabelOwner { labels.contains(it) }, true, null) + val infos = MethodInliner.processReturns(adapter, sourceCompiler.getContextLabels(), null) generateAndInsertFinallyBlocks( adapter, infos, (remapper.remap(parameters.argsSizeOnStack + 1).value as StackValue.Local).index ) @@ -319,7 +317,9 @@ abstract class InlineCodegen( frameMap.enterTemp(Type.INT_TYPE) } - sourceCompiler.generateFinallyBlocksIfNeeded(finallyCodegen, extension.returnType, extension.finallyIntervalEnd.label) + sourceCompiler.generateFinallyBlocksIfNeeded( + finallyCodegen, extension.returnType, extension.finallyIntervalEnd.label, extension.jumpTarget + ) //Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method insertNodeBefore(finallyNode, intoNode, curInstr) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt index 2da961b68cd..e20441fa587 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt @@ -30,17 +30,14 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert import org.jetbrains.kotlin.resolve.jvm.AsmTypes.* import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.util.OperatorNameConventions -import org.jetbrains.org.objectweb.asm.ClassReader -import org.jetbrains.org.objectweb.asm.ClassVisitor -import org.jetbrains.org.objectweb.asm.Opcodes -import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.commons.Method import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode import kotlin.properties.Delegates interface FunctionalArgument -abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgument, ReturnLabelOwner { +abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgument { abstract val isBoundCallableReference: Boolean @@ -54,6 +51,9 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu abstract val capturedVars: List + open val returnLabels: Map + get() = mapOf() + lateinit var node: SMAPAndMethodNode abstract fun generateLambdaBody(sourceCompiler: SourceCompilerForInline, reifiedTypeInliner: ReifiedTypeInliner<*>) @@ -129,8 +129,6 @@ abstract class DefaultLambda( final override lateinit var capturedVars: List private set - override fun isReturnFromMe(labelName: String): Boolean = false - var originalBoundReceiverType: Type? = null private set @@ -247,7 +245,7 @@ class PsiExpressionLambda( val functionWithBodyOrCallableReference: KtExpression = (expression as? KtLambdaExpression)?.functionLiteral ?: expression - private val labels: Set + override val returnLabels: Map override val isSuspend: Boolean @@ -284,7 +282,7 @@ class PsiExpressionLambda( closure = it!! } - labels = InlineCodegen.getDeclarationLabels(expression, invokeMethodDescriptor) + returnLabels = InlineCodegen.getDeclarationLabels(expression, invokeMethodDescriptor).associateWith { null } invokeMethod = typeMapper.mapAsmMethod(invokeMethodDescriptor) isSuspend = invokeMethodDescriptor.isSuspend } @@ -324,10 +322,6 @@ class PsiExpressionLambda( } } - override fun isReturnFromMe(labelName: String): Boolean { - return labels.contains(labelName) - } - val isPropertyReference: Boolean get() = propertyReferenceInfo != null diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt index df48334c6e4..970c93c146e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful import org.jetbrains.kotlin.codegen.optimization.fixStack.peek import org.jetbrains.kotlin.codegen.optimization.fixStack.top import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull +import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.ParameterDescriptor @@ -72,9 +73,9 @@ class MethodInliner( adapter: MethodVisitor, remapper: LocalVarRemapper, remapReturn: Boolean, - returnLabelOwner: ReturnLabelOwner + returnLabels: Map ): InlineResult { - return doInline(adapter, remapper, remapReturn, returnLabelOwner, 0) + return doInline(adapter, remapper, remapReturn, returnLabels, 0) } private fun recordTransformation(info: TransformationInfo) { @@ -91,11 +92,11 @@ class MethodInliner( adapter: MethodVisitor, remapper: LocalVarRemapper, remapReturn: Boolean, - returnLabelOwner: ReturnLabelOwner, + returnLabels: Map, finallyDeepShift: Int ): InlineResult { //analyze body - var transformedNode = markPlacesForInlineAndRemoveInlinable(node, returnLabelOwner, finallyDeepShift) + var transformedNode = markPlacesForInlineAndRemoveInlinable(node, returnLabels, finallyDeepShift) if (inliningContext.isInliningLambda && isDefaultLambdaWithReification(inliningContext.lambdaInfo!!)) { //TODO maybe move reification in one place inliningContext.root.inlineMethodReifier.reifyInstructions(transformedNode) @@ -139,7 +140,9 @@ class MethodInliner( ) } - processReturns(resultNode, returnLabelOwner, remapReturn, end) + if (remapReturn) { + processReturns(resultNode, returnLabels, end) + } //flush transformed node to output resultNode.accept(SkipMaxAndEndVisitor(adapter)) return result @@ -297,7 +300,7 @@ class MethodInliner( val varRemapper = LocalVarRemapper(lambdaParameters, valueParamShift) //TODO add skipped this and receiver - val lambdaResult = inliner.doInline(localVariablesSorter, varRemapper, true, info, invokeCall.finallyDepthShift) + val lambdaResult = inliner.doInline(localVariablesSorter, varRemapper, true, info.returnLabels, invokeCall.finallyDepthShift) result.mergeWithNotChangeInfo(lambdaResult) result.reifiedTypeParametersUsages.mergeAll(lambdaResult.reifiedTypeParametersUsages) @@ -486,11 +489,11 @@ class MethodInliner( } private fun markPlacesForInlineAndRemoveInlinable( - node: MethodNode, returnLabelOwner: ReturnLabelOwner, finallyDeepShift: Int + node: MethodNode, returnLabels: Map, finallyDeepShift: Int ): MethodNode { val processingNode = prepareNode(node, finallyDeepShift) - preprocessNodeBeforeInline(processingNode, returnLabelOwner) + preprocessNodeBeforeInline(processingNode, returnLabels) replaceContinuationAccessesWithFakeContinuationsIfNeeded(processingNode) @@ -765,7 +768,7 @@ class MethodInliner( } } - private fun preprocessNodeBeforeInline(node: MethodNode, returnLabelOwner: ReturnLabelOwner) { + private fun preprocessNodeBeforeInline(node: MethodNode, returnLabels: Map) { try { FixStackWithLabelNormalizationMethodTransformer().transform("fake", node) } catch (e: Throwable) { @@ -787,16 +790,13 @@ class MethodInliner( if (!isReturnOpcode(insnNode.opcode)) continue - var insertBeforeInsn = insnNode - // TODO extract isLocalReturn / isNonLocalReturn, see processReturns val labelName = getMarkedReturnLabelOrNull(insnNode) - if (labelName != null) { - if (!returnLabelOwner.isReturnFromMe(labelName)) continue - insertBeforeInsn = insnNode.previous + if (labelName == null) { + localReturnsNormalizer.addLocalReturnToTransform(insnNode, insnNode, frame) + } else if (labelName in returnLabels) { + localReturnsNormalizer.addLocalReturnToTransform(insnNode, insnNode.previous, frame) } - - localReturnsNormalizer.addLocalReturnToTransform(insnNode, insertBeforeInsn, frame) } localReturnsNormalizer.transform(node) @@ -1001,7 +1001,8 @@ class MethodInliner( class PointForExternalFinallyBlocks( @JvmField val beforeIns: AbstractInsnNode, @JvmField val returnType: Type, - @JvmField val finallyIntervalEnd: LabelNode + @JvmField val finallyIntervalEnd: LabelNode, + @JvmField val jumpTarget: Label? ) companion object { @@ -1115,55 +1116,44 @@ class MethodInliner( //process local and global returns (local substituted with goto end-label global kept unchanged) @JvmStatic fun processReturns( - node: MethodNode, returnLabelOwner: ReturnLabelOwner, remapReturn: Boolean, endLabel: Label? + node: MethodNode, returnLabels: Map, endLabel: Label? ): List { - if (!remapReturn) { - return emptyList() - } val result = ArrayList() val instructions = node.instructions var insnNode: AbstractInsnNode? = instructions.first while (insnNode != null) { if (isReturnOpcode(insnNode.opcode)) { - var isLocalReturn = true val labelName = getMarkedReturnLabelOrNull(insnNode) + val returnType = getReturnType(insnNode.opcode) - if (labelName != null) { - isLocalReturn = returnLabelOwner.isReturnFromMe(labelName) - //remove global return flag - if (isLocalReturn) { - instructions.remove(insnNode.previous) - } + val isLocalReturn = labelName == null || labelName in returnLabels + val jumpTarget = returnLabels[labelName] ?: endLabel + + if (isLocalReturn && labelName != null) { + // remove non-local return flag + instructions.remove(insnNode.previous) } - if (isLocalReturn && endLabel != null) { - val nop = InsnNode(Opcodes.NOP) - instructions.insert(insnNode, nop) - - val labelNode = endLabel.info as LabelNode - val jumpInsnNode = JumpInsnNode(Opcodes.GOTO, labelNode) - instructions.insert(nop, jumpInsnNode) - + if (isLocalReturn && jumpTarget != null) { + val jumpInsnNode = JumpInsnNode(Opcodes.GOTO, jumpTarget.info as LabelNode) + instructions.insertBefore(insnNode, InsnNode(Opcodes.NOP)) + if (jumpTarget != endLabel) { + instructions.insertBefore(insnNode, PseudoInsn.FIX_STACK_BEFORE_JUMP.createInsnNode()) + } + instructions.insertBefore(insnNode, jumpInsnNode) instructions.remove(insnNode) insnNode = jumpInsnNode } - //generate finally block before nonLocalReturn flag/return/goto val label = LabelNode() instructions.insert(insnNode, label) - result.add( - PointForExternalFinallyBlocks( - getInstructionToInsertFinallyBefore(insnNode, isLocalReturn), getReturnType(insnNode.opcode), label - ) - ) + // generate finally blocks before the non-local return flag or the stack fixup pseudo instruction + val finallyInsertionPoint = if (isLocalReturn && jumpTarget == endLabel) insnNode else insnNode.previous + result.add(PointForExternalFinallyBlocks(finallyInsertionPoint, returnType, label, jumpTarget)) } insnNode = insnNode.next } return result } - - private fun getInstructionToInsertFinallyBefore(nonLocalReturnOrJump: AbstractInsnNode, isLocal: Boolean): AbstractInsnNode { - return if (isLocal) nonLocalReturnOrJump else nonLocalReturnOrJump.previous - } } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReturnLabelOwner.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReturnLabelOwner.java deleted file mode 100644 index 4b1d1e78cda..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReturnLabelOwner.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2010-2015 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.annotations.NotNull; - -public interface ReturnLabelOwner { - boolean isReturnFromMe(@NotNull String labelName); - - ReturnLabelOwner SKIP_ALL = name -> false; - - ReturnLabelOwner NOT_APPLICABLE = name -> { - throw new RuntimeException("This operation not applicable for current context"); - }; -} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt index e01026264ab..360760bd27b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt @@ -64,7 +64,7 @@ interface SourceCompilerForInline { curFinallyDepth: Int ): BaseExpressionCodegen - fun generateFinallyBlocksIfNeeded(finallyCodegen: BaseExpressionCodegen, returnType: Type, afterReturnLabel: Label) + fun generateFinallyBlocksIfNeeded(codegen: BaseExpressionCodegen, returnType: Type, afterReturnLabel: Label, target: Label?) fun isCallInsideSameModuleAsDeclared(functionDescriptor: FunctionDescriptor): Boolean @@ -74,7 +74,7 @@ interface SourceCompilerForInline { val compilationContextFunctionDescriptor: FunctionDescriptor - fun getContextLabels(): Set + fun getContextLabels(): Map fun reportSuspensionPointInsideMonitor(stackTraceElement: String) } @@ -311,9 +311,10 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid override fun hasFinallyBlocks() = codegen.hasFinallyBlocks() - override fun generateFinallyBlocksIfNeeded(finallyCodegen: BaseExpressionCodegen, returnType: Type, afterReturnLabel: Label) { - require(finallyCodegen is ExpressionCodegen) - finallyCodegen.generateFinallyBlocksIfNeeded(returnType, null, afterReturnLabel) + override fun generateFinallyBlocksIfNeeded(codegen: BaseExpressionCodegen, returnType: Type, afterReturnLabel: Label, target: Label?) { + // TODO use the target label for non-local break/continue + require(codegen is ExpressionCodegen) + codegen.generateFinallyBlocksIfNeeded(returnType, null, afterReturnLabel) } override fun createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(finallyNode: MethodNode, curFinallyDepth: Int) = @@ -337,14 +338,15 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid override val compilationContextFunctionDescriptor get() = codegen.getContext().functionDescriptor - override fun getContextLabels(): Set { + override fun getContextLabels(): Map { val context = codegen.getContext() val parentContext = context.parentContext val descriptor = if (parentContext is ClosureContext && parentContext.originalSuspendLambdaDescriptor != null) { parentContext.originalSuspendLambdaDescriptor!! } else context.contextDescriptor - return InlineCodegen.getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor) + val labels = InlineCodegen.getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor) + return labels.associateWith { null } // TODO add break/continue labels } fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxInlineCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxInlineCodegenTestGenerated.java index 83d79e91a01..25ca6b9f83f 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxInlineCodegenTestGenerated.java @@ -2420,6 +2420,46 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt"); } + @TestMetadata("fromArrayGenerator.kt") + public void testFromArrayGenerator() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGenerator.kt"); + } + + @TestMetadata("fromArrayGeneratorCatch.kt") + public void testFromArrayGeneratorCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorNested.kt") + public void testFromArrayGeneratorNested() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorNested.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCapture.kt") + public void testFromArrayGeneratorWithCapture() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCapture.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCatch.kt") + public void testFromArrayGeneratorWithCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinally.kt") + public void testFromArrayGeneratorWithFinally() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinally.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2.kt") + public void testFromArrayGeneratorWithFinallyX2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2_2.kt") + public void testFromArrayGeneratorWithFinallyX2_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2_2.kt"); + } + @TestMetadata("fromInterfaceDefaultGetter.kt") public void testFromInterfaceDefaultGetter() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt"); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 47e43f02d84..8c9224fac46 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -313,8 +313,6 @@ private val jvmFilePhases = listOf( collectionStubMethodLowering, jvmInlineClassPhase, - sharedVariablesPhase, - makePatchParentsPhase(1), enumWhenPhase, @@ -323,6 +321,7 @@ private val jvmFilePhases = listOf( singleAbstractMethodPhase, assertionPhase, returnableBlocksPhase, + sharedVariablesPhase, localDeclarationsPhase, jvmLocalClassExtractionPhase, staticCallableReferencePhase, diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 70dafe7c487..da0cac1c4f2 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -80,7 +80,7 @@ class TryWithFinallyInfo(val onExit: IrExpression) : TryInfo() class BlockInfo(val parent: BlockInfo? = null) { val variables = mutableListOf() - private val infos: Stack = parent?.infos ?: Stack() + val infos: Stack = parent?.infos ?: Stack() fun hasFinallyBlocks(): Boolean = infos.firstIsInstanceOrNull() != null @@ -869,42 +869,39 @@ class ExpressionCodegen( return unitValue } + private fun generateGlobalReturnFlagIfPossible(expression: IrExpression, label: String) { + if (state.isInlineDisabled) { + context.psiErrorBuilder.at(expression, irFunction).report(Errors.NON_LOCAL_RETURN_IN_DISABLED_INLINE) + genThrow(mv, "java/lang/UnsupportedOperationException", "Non-local returns are not allowed with inlining disabled") + } else { + generateGlobalReturnFlag(mv, label) + } + } + override fun visitReturn(expression: IrReturn, data: BlockInfo): PromisedValue { val returnTarget = expression.returnTargetSymbol.owner - val owner = - returnTarget as? IrFunction - ?: (returnTarget as? IrReturnableBlock)?.inlineFunctionSymbol?.owner - ?: error("Unsupported IrReturnTarget: $returnTarget") - //TODO: should be owner != irFunction - val isNonLocalReturn = - methodSignatureMapper.mapFunctionName(owner) != methodSignatureMapper.mapFunctionName(irFunction) - if (isNonLocalReturn && state.isInlineDisabled) { - context.psiErrorBuilder.at(expression, owner).report(Errors.NON_LOCAL_RETURN_IN_DISABLED_INLINE) - genThrow( - mv, "java/lang/UnsupportedOperationException", - "Non-local returns are not allowed with inlining disabled" - ) - return unitValue - } + val owner = returnTarget as? IrFunction ?: error("Unsupported IrReturnTarget: $returnTarget") + // TODO: should be owner != irFunction + val isNonLocalReturn = methodSignatureMapper.mapFunctionName(owner) != methodSignatureMapper.mapFunctionName(irFunction) var returnType = if (owner == irFunction) signature.returnType else methodSignatureMapper.mapReturnType(owner) var returnIrType = owner.returnType - val unboxedInlineClass = owner.suspendFunctionOriginal().originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass() if (unboxedInlineClass != null) { returnIrType = unboxedInlineClass returnType = unboxedInlineClass.asmType } + val afterReturnLabel = Label() expression.value.accept(this, data).materializeAt(returnType, returnIrType) // In case of non-local return from suspend lambda 'materializeAt' does not box return value, box it manually. if (isNonLocalReturn && owner.isInvokeSuspendOfLambda() && expression.value.type.isKotlinResult()) { StackValue.boxInlineClass(expression.value.type.toIrBasedKotlinType(), mv) } - generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data) + generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data, null) expression.markLineNumber(startOffset = true) if (isNonLocalReturn) { - generateGlobalReturnFlag(mv, owner.name.asString()) + generateGlobalReturnFlagIfPossible(expression, owner.name.asString()) } mv.areturn(returnType) mv.mark(afterReturnLabel) @@ -1012,9 +1009,15 @@ class ExpressionCodegen( } override fun visitWhileLoop(loop: IrWhileLoop, data: BlockInfo): PromisedValue { - val continueLabel = markNewLabel() - val endLabel = Label() - // Mark stack depth for break + // Spill the stack in case the loop contains inline functions that break/continue + // out of it. (The case where a loop is entered with a non-empty stack is rare, but + // possible; basically, you need to either use `Array(n) { ... }` or put a `when` + // containing a loop as an argument to a function call.) + addInlineMarker(mv, true) + val continueLabel = markNewLinkedLabel() + val endLabel = linkedLabel() + // Mark the label as having 0 stack depth, so that `break`/`continue` inside + // expressions pop all elements off it before jumping. mv.fakeAlwaysFalseIfeq(endLabel) loop.condition.markLineNumber(true) loop.condition.accept(this, data).coerceToBoolean().jumpIfFalse(endLabel) @@ -1023,14 +1026,16 @@ class ExpressionCodegen( } mv.goTo(continueLabel) mv.mark(endLabel) + addInlineMarker(mv, false) return unitValue } override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: BlockInfo): PromisedValue { + // See comments in `visitWhileLoop` + addInlineMarker(mv, true) val entry = markNewLabel() - val endLabel = Label() - val continueLabel = Label() - // Mark stack depth for break/continue + val endLabel = linkedLabel() + val continueLabel = linkedLabel() mv.fakeAlwaysFalseIfeq(continueLabel) mv.fakeAlwaysFalseIfeq(endLabel) data.withBlock(LoopInfo(loop, continueLabel, endLabel)) { @@ -1040,6 +1045,7 @@ class ExpressionCodegen( loop.condition.markLineNumber(true) loop.condition.accept(this, data).coerceToBoolean().jumpIfTrue(entry) mv.mark(endLabel) + addInlineMarker(mv, false) return unitValue } @@ -1047,26 +1053,32 @@ class ExpressionCodegen( endLabel: Label, data: BlockInfo, nestedTryWithoutFinally: MutableList = arrayListOf(), - stop: (ExpressionInfo) -> Boolean = { false } - ): ExpressionInfo? { + stop: (LoopInfo) -> Boolean + ): LoopInfo? { return data.handleBlock { - if (it is TryWithFinallyInfo) { - genFinallyBlock(it, null, endLabel, data, nestedTryWithoutFinally) - nestedTryWithoutFinally.clear() - } else if (it is TryInfo) { - nestedTryWithoutFinally.add(it) + when { + it is TryWithFinallyInfo -> { + genFinallyBlock(it, null, endLabel, data, nestedTryWithoutFinally) + nestedTryWithoutFinally.clear() + } + it is TryInfo -> nestedTryWithoutFinally.add(it) + it is LoopInfo && stop(it) -> return it } - return if (stop(it)) it else unwindBlockStack(endLabel, data, nestedTryWithoutFinally, stop) + return unwindBlockStack(endLabel, data, nestedTryWithoutFinally, stop) } } override fun visitBreakContinue(jump: IrBreakContinue, data: BlockInfo): PromisedValue { jump.markLineNumber(startOffset = true) val endLabel = Label() - val stackElement = unwindBlockStack(endLabel, data) { it is LoopInfo && it.loop == jump.loop } as LoopInfo? - ?: throw AssertionError("Target label for break/continue not found") - mv.fixStackAndJump(if (jump is IrBreak) stackElement.breakLabel else stackElement.continueLabel) - mv.mark(endLabel) + val stackElement = unwindBlockStack(endLabel, data) { it.loop == jump.loop } + if (stackElement == null) { + generateGlobalReturnFlagIfPossible(jump, jump.loop.nonLocalReturnLabel(jump is IrBreak)) + mv.areturn(Type.VOID_TYPE) + } else { + mv.fixStackAndJump(if (jump is IrBreak) stackElement.breakLabel else stackElement.continueLabel) + mv.mark(endLabel) + } return unitValue } @@ -1214,16 +1226,16 @@ class ExpressionCodegen( } } - fun generateFinallyBlocksIfNeeded(returnType: Type, afterReturnLabel: Label, data: BlockInfo) { + fun generateFinallyBlocksIfNeeded(returnType: Type, afterReturnLabel: Label, data: BlockInfo, jumpLabel: Label?) { if (data.hasFinallyBlocks()) { if (Type.VOID_TYPE != returnType) { val returnValIndex = frameMap.enterTemp(returnType) mv.store(returnValIndex, returnType) - unwindBlockStack(afterReturnLabel, data) + unwindBlockStack(afterReturnLabel, data) { it.breakLabel == jumpLabel || it.continueLabel == jumpLabel } mv.load(returnValIndex, returnType) frameMap.leaveTemp(returnType) } else { - unwindBlockStack(afterReturnLabel, data) + unwindBlockStack(afterReturnLabel, data) { it.breakLabel == jumpLabel || it.continueLabel == jumpLabel } } } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt index 8cf6c637b0b..7d946c0eb6a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt @@ -181,10 +181,6 @@ class IrExpressionLambdaImpl( override val isSuspend: Boolean = function.isSuspend - override fun isReturnFromMe(labelName: String): Boolean { - return false //always false - } - // This name doesn't actually matter: it is used internally to tell this lambda's captured // arguments apart from any other scope's. So long as it's unique, any value is fine. // This particular string slightly aids in debugging internal compiler errors as it at least diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt index d838d691ed1..14104b2fe10 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt @@ -24,10 +24,10 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.IrBasedSimpleFunctionDescriptor import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression +import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.util.isSuspend import org.jetbrains.kotlin.ir.util.module import org.jetbrains.kotlin.ir.util.parentAsClass -import org.jetbrains.kotlin.load.kotlin.* import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.doNotAnalyze import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.SUSPENSION_POINT_INSIDE_MONITOR @@ -36,7 +36,6 @@ import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.Method import org.jetbrains.org.objectweb.asm.tree.MethodNode -import java.io.File class IrSourceCompilerForInline( override val state: GenerationState, @@ -107,9 +106,9 @@ class IrSourceCompilerForInline( override fun hasFinallyBlocks() = data.hasFinallyBlocks() - override fun generateFinallyBlocksIfNeeded(finallyCodegen: BaseExpressionCodegen, returnType: Type, afterReturnLabel: Label) { - require(finallyCodegen is ExpressionCodegen) - finallyCodegen.generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data) + override fun generateFinallyBlocksIfNeeded(codegen: BaseExpressionCodegen, returnType: Type, afterReturnLabel: Label, target: Label?) { + require(codegen is ExpressionCodegen) + codegen.generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data, target) } override fun createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(finallyNode: MethodNode, curFinallyDepth: Int) = @@ -139,9 +138,15 @@ class IrSourceCompilerForInline( override val compilationContextFunctionDescriptor: FunctionDescriptor get() = generateSequence(codegen) { it.inlinedInto }.last().irFunction.toIrBasedDescriptor() - override fun getContextLabels(): Set { - val name = codegen.irFunction.name.asString() - return setOf(name) + override fun getContextLabels(): Map { + val result = mutableMapOf(codegen.irFunction.name.asString() to null) + for (info in data.infos) { + if (info !is LoopInfo) + continue + result[info.loop.nonLocalReturnLabel(false)] = info.continueLabel + result[info.loop.nonLocalReturnLabel(true)] = info.breakLabel + } + return result } // TODO: Find a way to avoid using PSI here @@ -161,3 +166,6 @@ private tailrec fun IrDeclaration.isInlineOrInsideInline(): Boolean { if (parent !is IrDeclaration) return false return parent.isInlineOrInsideInline() } + +// TODO generate better labels; this is unique (includes the object's address), but not very descriptive +internal fun IrLoop.nonLocalReturnLabel(forBreak: Boolean): String = "$this\$${if (forBreak) "break" else "continue"}" diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGenerator.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGenerator.kt new file mode 100644 index 00000000000..79b5d8d118d --- /dev/null +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGenerator.kt @@ -0,0 +1,5 @@ +// FILE: 1.kt +inline fun runReturning(f: () -> Nothing): Nothing = f() + +// FILE: 2.kt +fun box() = Array(1) { runReturning { return@Array "OK" } }[0] diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorCatch.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorCatch.kt new file mode 100644 index 00000000000..68a4b1488c0 --- /dev/null +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorCatch.kt @@ -0,0 +1,24 @@ +// FILE: 1.kt +inline fun runReturning(f: () -> Nothing): Nothing = f() + +// FILE: 2.kt +fun box(): String { + var r = "" + val x = Array(1) ext@{ + try { + Array(1) { + try { + runReturning { throw RuntimeException() } + } catch (e: Throwable) { + r += "1" + return@ext "OK" + } finally { + r += "2" + } + }[0] + } finally { + r += "3" + } + }[0] + return if (r == "123") x else r +} diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorNested.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorNested.kt new file mode 100644 index 00000000000..a121048e30f --- /dev/null +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorNested.kt @@ -0,0 +1,5 @@ +// FILE: 1.kt +inline fun runReturning(f: () -> Nothing): Nothing = f() + +// FILE: 2.kt +fun box() = Array(1) { run { runReturning { return@Array "OK" } } }[0] diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCapture.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCapture.kt new file mode 100644 index 00000000000..88a7fa26696 --- /dev/null +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCapture.kt @@ -0,0 +1,8 @@ +// FILE: 1.kt +inline fun runReturning(f: () -> Nothing): Nothing = f() + +// FILE: 2.kt +fun box(): String { + val result = "OK" + return Array(1) { run { runReturning { return@Array result } } }[0] +} diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCatch.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCatch.kt new file mode 100644 index 00000000000..8153ab263b0 --- /dev/null +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCatch.kt @@ -0,0 +1,22 @@ +// FILE: 1.kt +inline fun runReturning(f: () -> Nothing): Nothing = f() + +// FILE: 2.kt +fun box(): String { + var r = "" + val x = try { + Array(1) { + try { + runReturning { throw RuntimeException() } + } finally { + r += "1" + } + }[0] + } catch (e: Throwable) { + r += "2" + "OK" + } finally { + r += "3" + } + return if (r == "123") x else r +} diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinally.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinally.kt new file mode 100644 index 00000000000..7b750cace35 --- /dev/null +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinally.kt @@ -0,0 +1,19 @@ +// FILE: 1.kt +inline fun runReturning(f: () -> Nothing): Nothing = f() + +// FILE: 2.kt +fun box(): String { + var r = "" + val x = try { + Array(1) { + try { + runReturning { return@Array "OK" } + } finally { + r += "O" + } + }[0] + } finally { + r += "K" + } + return r +} diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2.kt new file mode 100644 index 00000000000..da8cef6c7e9 --- /dev/null +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2.kt @@ -0,0 +1,25 @@ +// FILE: 1.kt +inline fun runReturning(f: () -> Nothing): Nothing = f() + +// FILE: 2.kt +fun box(): String { + var r = "" + val x = try { + Array(1) ext@{ + try { + Array(1) { + try { + runReturning { return@ext "OK" } + } finally { + r += "1" + } + }[0] + } finally { + r += "2" + } + }[0] + } finally { + r += "3" + } + return if (r == "123") x else r +} diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2_2.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2_2.kt new file mode 100644 index 00000000000..89c0e47d0ad --- /dev/null +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2_2.kt @@ -0,0 +1,25 @@ +// FILE: 1.kt +inline fun runReturning(f: () -> Nothing): Nothing = f() + +// FILE: 2.kt +fun box(): String { + var r = "" + val x = try { + Array(1) ext@{ + try { + Array(1) { + try { + runReturning { return@Array "OK" } + } finally { + r += "1" + } + }[0] + } finally { + r += "2" + } + }[0] + } finally { + r += "3" + } + return if (r == "123") x else r +} diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java index a1c375e4b7f..e0538e0f37e 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -2420,6 +2420,46 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt"); } + @TestMetadata("fromArrayGenerator.kt") + public void testFromArrayGenerator() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGenerator.kt"); + } + + @TestMetadata("fromArrayGeneratorCatch.kt") + public void testFromArrayGeneratorCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorNested.kt") + public void testFromArrayGeneratorNested() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorNested.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCapture.kt") + public void testFromArrayGeneratorWithCapture() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCapture.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCatch.kt") + public void testFromArrayGeneratorWithCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinally.kt") + public void testFromArrayGeneratorWithFinally() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinally.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2.kt") + public void testFromArrayGeneratorWithFinallyX2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2_2.kt") + public void testFromArrayGeneratorWithFinallyX2_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2_2.kt"); + } + @TestMetadata("fromInterfaceDefaultGetter.kt") public void testFromInterfaceDefaultGetter() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index d9bc3ce43a5..d6cd24012ad 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -2420,6 +2420,46 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt"); } + @TestMetadata("fromArrayGenerator.kt") + public void testFromArrayGenerator() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGenerator.kt"); + } + + @TestMetadata("fromArrayGeneratorCatch.kt") + public void testFromArrayGeneratorCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorNested.kt") + public void testFromArrayGeneratorNested() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorNested.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCapture.kt") + public void testFromArrayGeneratorWithCapture() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCapture.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCatch.kt") + public void testFromArrayGeneratorWithCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinally.kt") + public void testFromArrayGeneratorWithFinally() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinally.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2.kt") + public void testFromArrayGeneratorWithFinallyX2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2_2.kt") + public void testFromArrayGeneratorWithFinallyX2_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2_2.kt"); + } + @TestMetadata("fromInterfaceDefaultGetter.kt") public void testFromInterfaceDefaultGetter() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java index 5db3b918dbf..122840b7164 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java @@ -2420,6 +2420,46 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt"); } + @TestMetadata("fromArrayGenerator.kt") + public void testFromArrayGenerator() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGenerator.kt"); + } + + @TestMetadata("fromArrayGeneratorCatch.kt") + public void testFromArrayGeneratorCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorNested.kt") + public void testFromArrayGeneratorNested() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorNested.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCapture.kt") + public void testFromArrayGeneratorWithCapture() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCapture.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCatch.kt") + public void testFromArrayGeneratorWithCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinally.kt") + public void testFromArrayGeneratorWithFinally() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinally.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2.kt") + public void testFromArrayGeneratorWithFinallyX2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2_2.kt") + public void testFromArrayGeneratorWithFinallyX2_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2_2.kt"); + } + @TestMetadata("fromInterfaceDefaultGetter.kt") public void testFromInterfaceDefaultGetter() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java index 50ee263b67e..d65f800fc3c 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java @@ -2420,6 +2420,46 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt"); } + @TestMetadata("fromArrayGenerator.kt") + public void testFromArrayGenerator() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGenerator.kt"); + } + + @TestMetadata("fromArrayGeneratorCatch.kt") + public void testFromArrayGeneratorCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorNested.kt") + public void testFromArrayGeneratorNested() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorNested.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCapture.kt") + public void testFromArrayGeneratorWithCapture() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCapture.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCatch.kt") + public void testFromArrayGeneratorWithCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinally.kt") + public void testFromArrayGeneratorWithFinally() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinally.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2.kt") + public void testFromArrayGeneratorWithFinallyX2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2_2.kt") + public void testFromArrayGeneratorWithFinallyX2_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2_2.kt"); + } + @TestMetadata("fromInterfaceDefaultGetter.kt") public void testFromInterfaceDefaultGetter() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxInlineTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxInlineTestGenerated.java index 7fbe2635784..05cc786a511 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxInlineTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxInlineTestGenerated.java @@ -2420,6 +2420,46 @@ public class JvmIrAgainstOldBoxInlineTestGenerated extends AbstractJvmIrAgainstO runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt"); } + @TestMetadata("fromArrayGenerator.kt") + public void testFromArrayGenerator() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGenerator.kt"); + } + + @TestMetadata("fromArrayGeneratorCatch.kt") + public void testFromArrayGeneratorCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorNested.kt") + public void testFromArrayGeneratorNested() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorNested.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCapture.kt") + public void testFromArrayGeneratorWithCapture() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCapture.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCatch.kt") + public void testFromArrayGeneratorWithCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinally.kt") + public void testFromArrayGeneratorWithFinally() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinally.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2.kt") + public void testFromArrayGeneratorWithFinallyX2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2_2.kt") + public void testFromArrayGeneratorWithFinallyX2_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2_2.kt"); + } + @TestMetadata("fromInterfaceDefaultGetter.kt") public void testFromInterfaceDefaultGetter() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxInlineTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxInlineTestGenerated.java index f66d8be4f83..60080a06436 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxInlineTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxInlineTestGenerated.java @@ -2420,6 +2420,46 @@ public class JvmOldAgainstIrBoxInlineTestGenerated extends AbstractJvmOldAgainst runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt"); } + @TestMetadata("fromArrayGenerator.kt") + public void testFromArrayGenerator() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGenerator.kt"); + } + + @TestMetadata("fromArrayGeneratorCatch.kt") + public void testFromArrayGeneratorCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorNested.kt") + public void testFromArrayGeneratorNested() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorNested.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCapture.kt") + public void testFromArrayGeneratorWithCapture() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCapture.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCatch.kt") + public void testFromArrayGeneratorWithCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinally.kt") + public void testFromArrayGeneratorWithFinally() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinally.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2.kt") + public void testFromArrayGeneratorWithFinallyX2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2_2.kt") + public void testFromArrayGeneratorWithFinallyX2_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2_2.kt"); + } + @TestMetadata("fromInterfaceDefaultGetter.kt") public void testFromInterfaceDefaultGetter() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java index 11e204014bb..63c56be9b9d 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java @@ -2170,6 +2170,46 @@ public class IrJsCodegenInlineES6TestGenerated extends AbstractIrJsCodegenInline runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt"); } + @TestMetadata("fromArrayGenerator.kt") + public void testFromArrayGenerator() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGenerator.kt"); + } + + @TestMetadata("fromArrayGeneratorCatch.kt") + public void testFromArrayGeneratorCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorNested.kt") + public void testFromArrayGeneratorNested() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorNested.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCapture.kt") + public void testFromArrayGeneratorWithCapture() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCapture.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCatch.kt") + public void testFromArrayGeneratorWithCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinally.kt") + public void testFromArrayGeneratorWithFinally() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinally.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2.kt") + public void testFromArrayGeneratorWithFinallyX2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2_2.kt") + public void testFromArrayGeneratorWithFinallyX2_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2_2.kt"); + } + @TestMetadata("fromInterfaceDefaultGetter.kt") public void testFromInterfaceDefaultGetter() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java index 0d6fbc8db9c..0890c06420f 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java @@ -2170,6 +2170,46 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt"); } + @TestMetadata("fromArrayGenerator.kt") + public void testFromArrayGenerator() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGenerator.kt"); + } + + @TestMetadata("fromArrayGeneratorCatch.kt") + public void testFromArrayGeneratorCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorNested.kt") + public void testFromArrayGeneratorNested() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorNested.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCapture.kt") + public void testFromArrayGeneratorWithCapture() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCapture.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCatch.kt") + public void testFromArrayGeneratorWithCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinally.kt") + public void testFromArrayGeneratorWithFinally() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinally.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2.kt") + public void testFromArrayGeneratorWithFinallyX2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2_2.kt") + public void testFromArrayGeneratorWithFinallyX2_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2_2.kt"); + } + @TestMetadata("fromInterfaceDefaultGetter.kt") public void testFromInterfaceDefaultGetter() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java index ac312ac3401..bcc0eb78cff 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java @@ -2170,6 +2170,46 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt"); } + @TestMetadata("fromArrayGenerator.kt") + public void testFromArrayGenerator() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGenerator.kt"); + } + + @TestMetadata("fromArrayGeneratorCatch.kt") + public void testFromArrayGeneratorCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorNested.kt") + public void testFromArrayGeneratorNested() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorNested.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCapture.kt") + public void testFromArrayGeneratorWithCapture() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCapture.kt"); + } + + @TestMetadata("fromArrayGeneratorWithCatch.kt") + public void testFromArrayGeneratorWithCatch() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithCatch.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinally.kt") + public void testFromArrayGeneratorWithFinally() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinally.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2.kt") + public void testFromArrayGeneratorWithFinallyX2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2.kt"); + } + + @TestMetadata("fromArrayGeneratorWithFinallyX2_2.kt") + public void testFromArrayGeneratorWithFinallyX2_2() throws Exception { + runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromArrayGeneratorWithFinallyX2_2.kt"); + } + @TestMetadata("fromInterfaceDefaultGetter.kt") public void testFromInterfaceDefaultGetter() throws Exception { runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt");