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.
This commit is contained in:
Dmitry Petrov
2021-07-17 20:51:55 +03:00
committed by teamcityserver
parent 230fce65e5
commit e276dec4de
6 changed files with 101 additions and 5 deletions
@@ -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<BasicValue>(owner, method, OptimizationBasicInterpreter()) {
private inner class InternalAnalyzer(owner: String) :
FlexibleMethodAnalyzer<BasicValue>(owner, method, OptimizationBasicInterpreter()) {
val spilledStacks = hashMapOf<AbstractInsnNode, List<BasicValue>>()
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<out BasicValue>, interpreter: Interpreter<BasicValue>): 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) {
@@ -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 {
@@ -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 += "</$t>"
}
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"
}
@@ -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 {
@@ -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 {
@@ -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");