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:
committed by
teamcityserver
parent
230fce65e5
commit
e276dec4de
+33
-5
@@ -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.JumpInsnNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
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.BasicValue
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
|
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
|
||||||
@@ -88,7 +89,9 @@ internal class FixStackAnalyzer(
|
|||||||
|
|
||||||
private val analyzer = InternalAnalyzer(owner)
|
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>>()
|
val spilledStacks = hashMapOf<AbstractInsnNode, List<BasicValue>>()
|
||||||
var maxExtraStackSize = 0; private set
|
var maxExtraStackSize = 0; private set
|
||||||
|
|
||||||
@@ -166,13 +169,38 @@ internal class FixStackAnalyzer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStack(i: Int): BasicValue {
|
override fun setStack(i: Int, value: BasicValue) {
|
||||||
return if (i < super.getMaxStackSize()) {
|
if (i < super.getMaxStackSize()) {
|
||||||
super.getStack(i)
|
super.setStack(i, value)
|
||||||
} else {
|
} 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) {
|
private fun FixStackFrame.executeBeforeInlineCallMarker(insn: AbstractInsnNode) {
|
||||||
|
|||||||
+6
@@ -8112,6 +8112,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt");
|
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
|
@Test
|
||||||
@TestMetadata("tcbInEliminatedCondition.kt")
|
@TestMetadata("tcbInEliminatedCondition.kt")
|
||||||
public void testTcbInEliminatedCondition() throws Exception {
|
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"
|
||||||
|
}
|
||||||
+6
@@ -8112,6 +8112,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt");
|
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
|
@Test
|
||||||
@TestMetadata("tcbInEliminatedCondition.kt")
|
@TestMetadata("tcbInEliminatedCondition.kt")
|
||||||
public void testTcbInEliminatedCondition() throws Exception {
|
public void testTcbInEliminatedCondition() throws Exception {
|
||||||
|
|||||||
+6
@@ -8112,6 +8112,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt");
|
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
|
@Test
|
||||||
@TestMetadata("tcbInEliminatedCondition.kt")
|
@TestMetadata("tcbInEliminatedCondition.kt")
|
||||||
public void testTcbInEliminatedCondition() throws Exception {
|
public void testTcbInEliminatedCondition() throws Exception {
|
||||||
|
|||||||
+5
@@ -6217,6 +6217,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/controlStructures/quicksort.kt");
|
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")
|
@TestMetadata("tcbInEliminatedCondition.kt")
|
||||||
public void testTcbInEliminatedCondition() throws Exception {
|
public void testTcbInEliminatedCondition() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/tcbInEliminatedCondition.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/tcbInEliminatedCondition.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user