diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index b0f5b7da5c7..04c0c133ede 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -587,6 +587,7 @@ public class ExpressionCodegen extends KtVisitor impleme blockStackElements.push(new LoopBlockStackElement(breakLabel, continueLabel, targetLabel(expression))); PseudoInsnsKt.fakeAlwaysFalseIfeq(v, continueLabel); + PseudoInsnsKt.fakeAlwaysFalseIfeq(v, breakLabel); KtExpression body = expression.getBody(); KtExpression condition = expression.getCondition(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/OptimizationBasicInterpreter.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/OptimizationBasicInterpreter.java index 7930ad52f01..2b1b7045986 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/OptimizationBasicInterpreter.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/OptimizationBasicInterpreter.java @@ -32,15 +32,8 @@ import java.util.List; import static org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue.*; public class OptimizationBasicInterpreter extends Interpreter implements Opcodes { - private final boolean tolerantToUninitializedValues; - - public OptimizationBasicInterpreter(boolean tolerantToUninitializedValues) { - super(ASM5); - this.tolerantToUninitializedValues = tolerantToUninitializedValues; - } - public OptimizationBasicInterpreter() { - this(false); + super(ASM5); } @Override @@ -362,11 +355,7 @@ public class OptimizationBasicInterpreter extends Interpreter implem ) { if (v.equals(w)) return v; - if (tolerantToUninitializedValues) { - if (v == StrictBasicValue.UNINITIALIZED_VALUE) return w; - if (w == StrictBasicValue.UNINITIALIZED_VALUE) return v; - } - else if (v == StrictBasicValue.UNINITIALIZED_VALUE || w == StrictBasicValue.UNINITIALIZED_VALUE) { + if (v == StrictBasicValue.UNINITIALIZED_VALUE || w == StrictBasicValue.UNINITIALIZED_VALUE) { return StrictBasicValue.UNINITIALIZED_VALUE; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FixStackAnalyzer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FixStackAnalyzer.kt index deaa0ec6fa6..80c1f9ed3ae 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FixStackAnalyzer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FixStackAnalyzer.kt @@ -22,138 +22,191 @@ import org.jetbrains.kotlin.codegen.optimization.common.MethodAnalyzer import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn import org.jetbrains.org.objectweb.asm.Opcodes -import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode -import org.jetbrains.org.objectweb.asm.tree.JumpInsnNode -import org.jetbrains.org.objectweb.asm.tree.MethodNode +import org.jetbrains.org.objectweb.asm.tree.* import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue import org.jetbrains.org.objectweb.asm.tree.analysis.Frame import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter internal class FixStackAnalyzer( owner: String, - methodNode: MethodNode, + val method: MethodNode, val context: FixStackContext -) : MethodAnalyzer(owner, methodNode, OptimizationBasicInterpreter(/* tolerantToUninitializedValues = */true)) { - val savedStacks = hashMapOf>() - var maxExtraStackSize = 0; private set - - override fun visitControlFlowEdge(insn: Int, successor: Int): Boolean { - val insnNode = instructions[insn] - return !(insnNode is JumpInsnNode && context.breakContinueGotoNodes.contains(insnNode)) +) { + companion object { + // Stack size is always non-negative + const val DEAD_CODE_STACK_SIZE = -1 } - override fun newFrame(nLocals: Int, nStack: Int): Frame = - FixStackFrame(nLocals, nStack) + private val expectedStackNode = hashMapOf() - private fun indexOf(node: AbstractInsnNode) = method.instructions.indexOf(node) + val maxExtraStackSize: Int get() = analyzer.maxExtraStackSize - inner class FixStackFrame(nLocals: Int, nStack: Int) : Frame(nLocals, nStack) { - val extraStack = Stack() + fun getStackToSpill(location: AbstractInsnNode) = analyzer.spilledStacks[location] + fun getActualStack(location: AbstractInsnNode) = getFrame(location)?.getStackContent() + fun getActualStackSize(location: AbstractInsnNode) = getFrame(location)?.stackSizeWithExtra ?: DEAD_CODE_STACK_SIZE + fun getExpectedStackSize(location: AbstractInsnNode) = getExpectedStackFrame(location)?.stackSizeWithExtra ?: DEAD_CODE_STACK_SIZE - override fun init(src: Frame): Frame { - extraStack.clear() - extraStack.addAll((src as FixStackFrame).extraStack) - return super.init(src) + private fun getExpectedStackFrame(location: AbstractInsnNode) = getFrame(expectedStackNode[location] ?: location) + private fun getFrame(location: AbstractInsnNode) = analyzer.getFrame(location) as? InternalAnalyzer.FixStackFrame + + fun analyze() { + preprocess() + analyzer.analyze() + } + + private fun preprocess() { + var current: AbstractInsnNode? = method.instructions.first + while (current != null) { + val next = current.next + if (PseudoInsn.FAKE_ALWAYS_FALSE_IFEQ.isa(current) && next is JumpInsnNode) { + val nop = InsnNode(Opcodes.NOP) + expectedStackNode[next.label] = nop + method.instructions.insert(next, nop) + method.instructions.remove(current) + method.instructions.remove(next) + current = nop.next + } + else { + current = current.next + } } - override fun clearStack() { - extraStack.clear() - super.clearStack() + context.fakeAlwaysFalseIfeqMarkers.clear() + } + + private val analyzer = InternalAnalyzer(owner, method, context) + + private class InternalAnalyzer( + owner: String, + method: MethodNode, + val context: FixStackContext + ) : MethodAnalyzer(owner, method, OptimizationBasicInterpreter()) { + val spilledStacks = hashMapOf>() + var maxExtraStackSize = 0; private set + + override fun visitControlFlowEdge(insn: Int, successor: Int): Boolean { + val insnNode = instructions[insn] + return !(insnNode is JumpInsnNode && context.breakContinueGotoNodes.contains(insnNode)) } - override fun execute(insn: AbstractInsnNode, interpreter: Interpreter) { - when { - PseudoInsn.SAVE_STACK_BEFORE_TRY.isa(insn) -> - executeSaveStackBeforeTry(insn) - PseudoInsn.RESTORE_STACK_IN_TRY_CATCH.isa(insn) -> - executeRestoreStackInTryCatch(insn) - InlineCodegenUtil.isBeforeInlineMarker(insn) -> - executeBeforeInlineCallMarker(insn) - InlineCodegenUtil.isAfterInlineMarker(insn) -> - executeAfterInlineCallMarker(insn) - InlineCodegenUtil.isMarkedReturn(insn) -> { - // KT-9644: might throw "Incompatible return type" on non-local return, in fact we don't care. - if (insn.opcode == Opcodes.RETURN) return + override fun newFrame(nLocals: Int, nStack: Int): Frame = + FixStackFrame(nLocals, nStack) + + private fun indexOf(node: AbstractInsnNode) = method.instructions.indexOf(node) + + inner class FixStackFrame(nLocals: Int, nStack: Int) : Frame(nLocals, nStack) { + val extraStack = Stack() + + override fun init(src: Frame): Frame { + extraStack.clear() + extraStack.addAll((src as FixStackFrame).extraStack) + return super.init(src) + } + + override fun clearStack() { + extraStack.clear() + super.clearStack() + } + + override fun execute(insn: AbstractInsnNode, interpreter: Interpreter) { + when { + PseudoInsn.SAVE_STACK_BEFORE_TRY.isa(insn) -> + executeSaveStackBeforeTry(insn) + PseudoInsn.RESTORE_STACK_IN_TRY_CATCH.isa(insn) -> + executeRestoreStackInTryCatch(insn) + InlineCodegenUtil.isBeforeInlineMarker(insn) -> + executeBeforeInlineCallMarker(insn) + InlineCodegenUtil.isAfterInlineMarker(insn) -> + executeAfterInlineCallMarker(insn) + InlineCodegenUtil.isMarkedReturn(insn) -> { + // KT-9644: might throw "Incompatible return type" on non-local return, in fact we don't care. + if (insn.opcode == Opcodes.RETURN) return + } + } + + super.execute(insn, interpreter) + } + + val stackSizeWithExtra: Int get() = super.getStackSize() + extraStack.size + + fun getStackContent(): List { + val savedStack = arrayListOf() + IntRange(0, super.getStackSize() - 1).mapTo(savedStack) { super.getStack(it) } + savedStack.addAll(extraStack) + return savedStack + } + + override fun push(value: BasicValue) { + if (super.getStackSize() < maxStackSize) { + super.push(value) + } + else { + extraStack.add(value) + maxExtraStackSize = Math.max(maxExtraStackSize, extraStack.size) } } - super.execute(insn, interpreter) - } - - fun getStackContent(): List { - val savedStack = arrayListOf() - IntRange(0, super.getStackSize() - 1).mapTo(savedStack) { super.getStack(it) } - savedStack.addAll(extraStack) - return savedStack - } - - override fun push(value: BasicValue) { - if (super.getStackSize() < maxStackSize) { - super.push(value) + fun pushAll(values: Collection) { + values.forEach { push(it) } } - else { - extraStack.add(value) - maxExtraStackSize = Math.max(maxExtraStackSize, extraStack.size) + + override fun pop(): BasicValue { + if (extraStack.isNotEmpty()) { + return extraStack.pop() + } + else { + return super.pop() + } + } + + override fun getStack(i: Int): BasicValue { + if (i < super.getMaxStackSize()) { + return super.getStack(i) + } + else { + return extraStack[i - maxStackSize] + } } } - fun pushAll(values: Collection) { - values.forEach { push(it) } + private fun FixStackFrame.executeBeforeInlineCallMarker(insn: AbstractInsnNode) { + saveStackAndClear(insn) } - override fun pop(): BasicValue { - if (extraStack.isNotEmpty()) { - return extraStack.pop() - } - else { - return super.pop() - } - } - - override fun getStack(i: Int): BasicValue { - if (i < super.getMaxStackSize()) { - return super.getStack(i) - } - else { - return extraStack[i - maxStackSize] - } - } - } - - private fun FixStackFrame.executeBeforeInlineCallMarker(insn: AbstractInsnNode) { - saveStackAndClear(insn) - } - - private fun FixStackFrame.saveStackAndClear(insn: AbstractInsnNode) { - val savedValues = getStackContent() - savedStacks[insn] = savedValues - clearStack() - } - - private fun FixStackFrame.executeAfterInlineCallMarker(insn: AbstractInsnNode) { - val beforeInlineMarker = context.openingInlineMethodMarker[insn] - if (stackSize > 0) { - val returnValue = pop() + private fun FixStackFrame.saveStackAndClear(insn: AbstractInsnNode) { + val savedValues = getStackContent() + spilledStacks[insn] = savedValues clearStack() - val savedValues = savedStacks[beforeInlineMarker] - pushAll(savedValues!!) - push(returnValue) } - else { - val savedValues = savedStacks[beforeInlineMarker] - pushAll(savedValues!!) + + private fun FixStackFrame.executeAfterInlineCallMarker(insn: AbstractInsnNode) { + val beforeInlineMarker = context.openingInlineMethodMarker[insn] + if (stackSize > 0) { + val returnValue = pop() + clearStack() + val savedValues = spilledStacks[beforeInlineMarker] + pushAll(savedValues!!) + push(returnValue) + } + else { + val savedValues = spilledStacks[beforeInlineMarker] + pushAll(savedValues!!) + } + } + + private fun FixStackFrame.executeRestoreStackInTryCatch(insn: AbstractInsnNode) { + val saveNode = context.saveStackMarkerForRestoreMarker[insn] + val savedValues = spilledStacks.getOrElse(saveNode!!) { + throw AssertionError("${indexOf(insn)}: Restore stack is unavailable for ${indexOf(saveNode)}") + } + pushAll(savedValues) + } + + private fun FixStackFrame.executeSaveStackBeforeTry(insn: AbstractInsnNode) { + saveStackAndClear(insn) } } - private fun FixStackFrame.executeRestoreStackInTryCatch(insn: AbstractInsnNode) { - val saveNode = context.saveStackMarkerForRestoreMarker[insn] - val savedValues = savedStacks.getOrElse(saveNode!!) { - throw AssertionError("${indexOf(insn)}: Restore stack is unavailable for ${indexOf(saveNode)}") - } - pushAll(savedValues) - } - private fun FixStackFrame.executeSaveStackBeforeTry(insn: AbstractInsnNode) { - saveStackAndClear(insn) - } + } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FixStackMethodTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FixStackMethodTransformer.kt index 923bb6ea321..a2545583e5a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FixStackMethodTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FixStackMethodTransformer.kt @@ -72,16 +72,18 @@ class FixStackMethodTransformer : MethodTransformer() { val gotoIndex = methodNode.instructions.indexOf(gotoNode) val labelIndex = methodNode.instructions.indexOf(gotoNode.label) - val DEAD_CODE = -1 // Stack size is always non-negative - val actualStackSize = analyzer.frames[gotoIndex]?.stackSize ?: DEAD_CODE - val expectedStackSize = analyzer.frames[labelIndex]?.stackSize ?: DEAD_CODE + val actualStackSize = analyzer.getActualStackSize(gotoNode) + val expectedStackSize = analyzer.getExpectedStackSize(gotoNode.label) - if (actualStackSize != DEAD_CODE && expectedStackSize != DEAD_CODE) { - assert(expectedStackSize <= actualStackSize) { "Label at $labelIndex, jump at $gotoIndex: stack underflow: $expectedStackSize > $actualStackSize" } - val frame = analyzer.frames[gotoIndex]!! - actions.add({ replaceMarkerWithPops(methodNode, gotoNode.previous, expectedStackSize, frame) }) + if (actualStackSize >= 0 && expectedStackSize >= 0) { + assert(expectedStackSize <= actualStackSize) { + "Label at $labelIndex, jump at $gotoIndex: stack underflow: $expectedStackSize > $actualStackSize" + } + val actualStackContent = analyzer.getActualStack(gotoNode) + ?: throw AssertionError("Jump at $gotoIndex should be alive") + actions.add({ replaceMarkerWithPops(methodNode, gotoNode.previous, expectedStackSize, actualStackContent) }) } - else if (actualStackSize != DEAD_CODE && expectedStackSize == DEAD_CODE) { + else if (actualStackSize >= 0 && expectedStackSize < 0) { throw AssertionError("Live jump $gotoIndex to dead label $labelIndex") } else { @@ -120,7 +122,7 @@ class FixStackMethodTransformer : MethodTransformer() { marker: AbstractInsnNode, localVariablesManager: LocalVariablesManager ) { - val savedStackValues = analyzer.savedStacks[marker] + val savedStackValues = analyzer.getStackToSpill(marker) if (savedStackValues != null) { val savedStackDescriptor = localVariablesManager.allocateVariablesForSaveStackMarker(marker, savedStackValues) actions.add({ saveStack(methodNode, marker, savedStackDescriptor, false) }) @@ -151,20 +153,21 @@ class FixStackMethodTransformer : MethodTransformer() { localVariablesManager: LocalVariablesManager ) { val savedStackDescriptor = localVariablesManager.getBeforeInlineDescriptor(inlineMarker) - val afterInlineFrame = analyzer.getFrame(inlineMarker) as FixStackAnalyzer.FixStackFrame? - if (afterInlineFrame != null && savedStackDescriptor.isNotEmpty()) { - assert(afterInlineFrame.stackSize <= 1) { "Inline method should not leave more than 1 value on stack" } - if (afterInlineFrame.stackSize == 1) { - val afterInlineStackValues = afterInlineFrame.getStackContent() - val returnValue = afterInlineStackValues.last() - val returnValueLocalVarIndex = localVariablesManager.createReturnValueVariable(returnValue) - actions.add({ - restoreStackWithReturnValue(methodNode, inlineMarker, savedStackDescriptor, - returnValue, returnValueLocalVarIndex) - }) - } - else { - actions.add({ restoreStack(methodNode, inlineMarker, savedStackDescriptor) }) + val stackContentAfterInline = analyzer.getActualStack(inlineMarker) + if (stackContentAfterInline != null && savedStackDescriptor.isNotEmpty()) { + when (stackContentAfterInline.size) { + 1 -> { + val returnValue = stackContentAfterInline.last() + val returnValueLocalVarIndex = localVariablesManager.createReturnValueVariable(returnValue) + actions.add({ + restoreStackWithReturnValue(methodNode, inlineMarker, savedStackDescriptor, + returnValue, returnValueLocalVarIndex) + }) + } + 0 -> + actions.add({ restoreStack(methodNode, inlineMarker, savedStackDescriptor) }) + else -> + throw AssertionError("Inline method should not leave more than 1 value on stack") } } else { @@ -181,7 +184,7 @@ class FixStackMethodTransformer : MethodTransformer() { inlineMarker: AbstractInsnNode, localVariablesManager: LocalVariablesManager ) { - val savedStackValues = analyzer.savedStacks[inlineMarker] + val savedStackValues = analyzer.getStackToSpill(inlineMarker) if (savedStackValues != null) { val savedStackDescriptor = localVariablesManager.allocateVariablesForBeforeInlineMarker(inlineMarker, savedStackValues) actions.add({ saveStack(methodNode, inlineMarker, savedStackDescriptor, false) }) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/StackTransformationUtils.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/StackTransformationUtils.kt index ffb626dd573..0e5d35a8683 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/StackTransformationUtils.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/StackTransformationUtils.kt @@ -115,11 +115,10 @@ fun replaceAlwaysTrueIfeqWithGoto(methodNode: MethodNode, node: AbstractInsnNode } } -fun replaceMarkerWithPops(methodNode: MethodNode, node: AbstractInsnNode, expectedStackSize: Int, frame: Frame) { +fun replaceMarkerWithPops(methodNode: MethodNode, node: AbstractInsnNode, expectedStackSize: Int, stackContent: List) { with (methodNode.instructions) { - while (frame.stackSize > expectedStackSize) { - val top = frame.pop() - insertBefore(node, getPopInstruction(top)) + for (stackValue in stackContent.subList(expectedStackSize, stackContent.size)) { + insert(node, getPopInstruction(stackValue)) } remove(node) } diff --git a/compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/pathologicalDoWhile.kt b/compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/pathologicalDoWhile.kt new file mode 100644 index 00000000000..4e97011ed2c --- /dev/null +++ b/compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/pathologicalDoWhile.kt @@ -0,0 +1,8 @@ +fun box(): String { + var flag = false + do { + if (flag) break + continue + } while (false) + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/fullJdk/regressions/kt15112.kt b/compiler/testData/codegen/box/fullJdk/regressions/kt15112.kt new file mode 100644 index 00000000000..d5cd0d9603d --- /dev/null +++ b/compiler/testData/codegen/box/fullJdk/regressions/kt15112.kt @@ -0,0 +1,29 @@ +// FULL_JDK +// WITH_RUNTIME +// IGNORE_BACKEND: JS + +import java.util.concurrent.locks.ReentrantReadWriteLock +import kotlin.concurrent.read +import kotlin.concurrent.write + +private val evalStateLock = ReentrantReadWriteLock() +private val classLoaderLock = ReentrantReadWriteLock() +val compiledClasses = arrayListOf("") + +fun box(): String = evalStateLock.write { + classLoaderLock.read { + classLoaderLock.write { + "write" + } + + compiledClasses.forEach { + it + } + } + + classLoaderLock.read { + compiledClasses.map { it } + } + + "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/light-analysis/controlStructures/breakContinueInExpressions/pathologicalDoWhile.txt b/compiler/testData/codegen/light-analysis/controlStructures/breakContinueInExpressions/pathologicalDoWhile.txt new file mode 100644 index 00000000000..7340ba7e986 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/controlStructures/breakContinueInExpressions/pathologicalDoWhile.txt @@ -0,0 +1,4 @@ +@kotlin.Metadata +public final class PathologicalDoWhileKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} diff --git a/compiler/testData/codegen/light-analysis/fullJdk/regressions/kt15112.txt b/compiler/testData/codegen/light-analysis/fullJdk/regressions/kt15112.txt new file mode 100644 index 00000000000..dd4bd36baaf --- /dev/null +++ b/compiler/testData/codegen/light-analysis/fullJdk/regressions/kt15112.txt @@ -0,0 +1,8 @@ +@kotlin.Metadata +public final class Kt15112Kt { + private final static field classLoaderLock: java.util.concurrent.locks.ReentrantReadWriteLock + private final static @org.jetbrains.annotations.NotNull field compiledClasses: java.util.ArrayList + private final static field evalStateLock: java.util.concurrent.locks.ReentrantReadWriteLock + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static @org.jetbrains.annotations.NotNull method getCompiledClasses(): java.util.ArrayList +} diff --git a/compiler/testData/lineNumber/custom/beforeGotoToWhileStart.kt b/compiler/testData/lineNumber/custom/beforeGotoToWhileStart.kt index 6427ee7de86..0cb7ee0dfd4 100644 --- a/compiler/testData/lineNumber/custom/beforeGotoToWhileStart.kt +++ b/compiler/testData/lineNumber/custom/beforeGotoToWhileStart.kt @@ -10,4 +10,4 @@ fun testSome(): Boolean { return false } -// 2 +3 4 2 7 10 \ No newline at end of file +// 2 3 4 2 7 10 \ No newline at end of file diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 3fa615fe50a..1e4b45ca2cf 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -4345,6 +4345,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("pathologicalDoWhile.kt") + public void testPathologicalDoWhile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/pathologicalDoWhile.kt"); + doTest(fileName); + } + @TestMetadata("popSizes.kt") public void testPopSizes() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/popSizes.kt"); @@ -7465,6 +7471,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/fullJdk/regressions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("kt15112.kt") + public void testKt15112() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/fullJdk/regressions/kt15112.kt"); + doTest(fileName); + } + @TestMetadata("kt1770.kt") public void testKt1770() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/fullJdk/regressions/kt1770.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 517ab47713d..fa1f482c583 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -4345,6 +4345,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("pathologicalDoWhile.kt") + public void testPathologicalDoWhile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/pathologicalDoWhile.kt"); + doTest(fileName); + } + @TestMetadata("popSizes.kt") public void testPopSizes() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/popSizes.kt"); @@ -7465,6 +7471,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/fullJdk/regressions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("kt15112.kt") + public void testKt15112() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/fullJdk/regressions/kt15112.kt"); + doTest(fileName); + } + @TestMetadata("kt1770.kt") public void testKt1770() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/fullJdk/regressions/kt1770.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java index c24d6787d4b..1dd2c4d6894 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java @@ -4345,6 +4345,12 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis doTest(fileName); } + @TestMetadata("pathologicalDoWhile.kt") + public void testPathologicalDoWhile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/pathologicalDoWhile.kt"); + doTest(fileName); + } + @TestMetadata("popSizes.kt") public void testPopSizes() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/popSizes.kt"); @@ -7465,6 +7471,12 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/fullJdk/regressions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("kt15112.kt") + public void testKt15112() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/fullJdk/regressions/kt15112.kt"); + doTest(fileName); + } + @TestMetadata("kt1770.kt") public void testKt1770() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/fullJdk/regressions/kt1770.kt"); diff --git a/idea/testData/debugger/tinyApp/outs/stepOverWhileWithInline.out b/idea/testData/debugger/tinyApp/outs/stepOverWhileWithInline.out index 0a095a36dca..c74ef5b3aef 100644 --- a/idea/testData/debugger/tinyApp/outs/stepOverWhileWithInline.out +++ b/idea/testData/debugger/tinyApp/outs/stepOverWhileWithInline.out @@ -10,13 +10,14 @@ stepOverWhileWithInline.kt:13 stepOverWhileWithInline.kt:14 stepOverWhileWithInline.kt:15 stepOverWhileWithInline.kt:13 +stepOverWhileWithInline.kt:18 stepOverWhileWithInline.kt:19 stepOverWhileWithInline.kt:20 stepOverWhileWithInline.kt:21 +stepOverWhileWithInline.kt:23 stepOverWhileWithInline.kt:24 stepOverWhileWithInline.kt:25 stepOverWhileWithInline.kt:26 -stepOverWhileWithInline.kt:27 Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 9d579919942..28ff1a03716 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -5084,6 +5084,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("pathologicalDoWhile.kt") + public void testPathologicalDoWhile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/pathologicalDoWhile.kt"); + doTest(fileName); + } + @TestMetadata("popSizes.kt") public void testPopSizes() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/controlStructures/breakContinueInExpressions/popSizes.kt"); @@ -8432,6 +8438,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/fullJdk/regressions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); } + @TestMetadata("kt15112.kt") + public void testKt15112() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/fullJdk/regressions/kt15112.kt"); + doTest(fileName); + } + @TestMetadata("kt1770.kt") public void testKt1770() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/fullJdk/regressions/kt1770.kt");