From e276dec4dea52c5a5b8a5f0bbafa2a0af10b92f9 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Sat, 17 Jul 2021 20:51:55 +0300 Subject: [PATCH] JVM don't merge local values in FixStackAnalyzer We care only about stacks there. This yields about 10-15% in a pathological case such as KT-41510. --- .../optimization/fixStack/FixStackAnalyzer.kt | 38 +++++++++++++--- .../FirBlackBoxCodegenTestGenerated.java | 6 +++ .../box/controlStructures/slowHtmlLikeDsl.kt | 45 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++ .../IrBlackBoxCodegenTestGenerated.java | 6 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ 6 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/codegen/box/controlStructures/slowHtmlLikeDsl.kt 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 755497e209a..31894aff0cc 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 @@ -29,6 +29,7 @@ import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode import org.jetbrains.org.objectweb.asm.tree.JumpInsnNode import org.jetbrains.org.objectweb.asm.tree.LabelNode import org.jetbrains.org.objectweb.asm.tree.MethodNode +import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException 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 @@ -88,7 +89,9 @@ internal class FixStackAnalyzer( private val analyzer = InternalAnalyzer(owner) - private inner class InternalAnalyzer(owner: String) : FlexibleMethodAnalyzer(owner, method, OptimizationBasicInterpreter()) { + private inner class InternalAnalyzer(owner: String) : + FlexibleMethodAnalyzer(owner, method, OptimizationBasicInterpreter()) { + val spilledStacks = hashMapOf>() var maxExtraStackSize = 0; private set @@ -166,13 +169,38 @@ internal class FixStackAnalyzer( } } - override fun getStack(i: Int): BasicValue { - return if (i < super.getMaxStackSize()) { - super.getStack(i) + override fun setStack(i: Int, value: BasicValue) { + if (i < super.getMaxStackSize()) { + super.setStack(i, value) } else { - extraStack[i - maxStackSize] + extraStack[i - maxStackSize] = value } } + + override fun merge(frame: Frame, interpreter: Interpreter): Boolean { + val other = frame as FixStackFrame + if (stackSizeWithExtra != other.stackSizeWithExtra) { + throw AnalyzerException(null, "Incompatible stack heights") + } + var changed = false + for (i in 0 until stackSize) { + val v0 = super.getStack(i) + val vm = interpreter.merge(v0, other.getStack(i)) + if (vm != v0) { + super.setStack(i, vm) + changed = true + } + } + for (i in 0 until extraStack.size) { + val v0 = extraStack[i] + val vm = interpreter.merge(v0, other.extraStack[i]) + if (vm != v0) { + extraStack[i] = vm + changed = true + } + } + return changed + } } private fun FixStackFrame.executeBeforeInlineCallMarker(insn: AbstractInsnNode) { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 563b3a5018d..3e71fbeb1d5 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -8112,6 +8112,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt"); } + @Test + @TestMetadata("slowHtmlLikeDsl.kt") + public void testSlowHtmlLikeDsl() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/slowHtmlLikeDsl.kt"); + } + @Test @TestMetadata("tcbInEliminatedCondition.kt") public void testTcbInEliminatedCondition() throws Exception { diff --git a/compiler/testData/codegen/box/controlStructures/slowHtmlLikeDsl.kt b/compiler/testData/codegen/box/controlStructures/slowHtmlLikeDsl.kt new file mode 100644 index 00000000000..c0d6a5d7872 --- /dev/null +++ b/compiler/testData/codegen/box/controlStructures/slowHtmlLikeDsl.kt @@ -0,0 +1,45 @@ +// TARGET_BACKEND: JVM +// ^ this test might be rather slow + +class Builder(var content: String) + +fun Builder.begin(t: String) { + content += "<$t>" +} + +fun Builder.text(t: String) { + content += t +} + +fun Builder.end(t: String) { + content += "" +} + +fun err(e: Throwable) {} + +inline fun Builder.tag(t: String, body: Builder.() -> Unit) { + begin(t) + try { + body() + } catch (e: Throwable) { + err(e) + } finally { + end(t) + } +} + +inline fun Builder.t2(body: Builder.() -> Unit) { + tag("t", body) + tag("t", body) +} + +val expectedLength = 1906 + +fun box(): String { + val b = Builder("") + b.t2 { t2 { t2 { t2 { t2 { t2 { t2 { text("1") } } } } } } } + if (b.content.length != expectedLength) + return "${b.content.length}" + else + return "OK" +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 0d5d6658304..6f74c77e088 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -8112,6 +8112,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt"); } + @Test + @TestMetadata("slowHtmlLikeDsl.kt") + public void testSlowHtmlLikeDsl() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/slowHtmlLikeDsl.kt"); + } + @Test @TestMetadata("tcbInEliminatedCondition.kt") public void testTcbInEliminatedCondition() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 71bef270ae0..8d7dc582884 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -8112,6 +8112,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt"); } + @Test + @TestMetadata("slowHtmlLikeDsl.kt") + public void testSlowHtmlLikeDsl() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/slowHtmlLikeDsl.kt"); + } + @Test @TestMetadata("tcbInEliminatedCondition.kt") public void testTcbInEliminatedCondition() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 5ec8d11b3e3..59c4421dcdf 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -6217,6 +6217,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt"); } + @TestMetadata("slowHtmlLikeDsl.kt") + public void testSlowHtmlLikeDsl() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/slowHtmlLikeDsl.kt"); + } + @TestMetadata("tcbInEliminatedCondition.kt") public void testTcbInEliminatedCondition() throws Exception { runTest("compiler/testData/codegen/box/controlStructures/tcbInEliminatedCondition.kt");