diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/CoveringTryCatchNodeProcessor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/CoveringTryCatchNodeProcessor.kt index 1207f8a2a7c..a01d0fa96b9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/CoveringTryCatchNodeProcessor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/CoveringTryCatchNodeProcessor.kt @@ -23,7 +23,7 @@ import org.jetbrains.org.objectweb.asm.tree.* import java.util.Comparator import java.util.Collections -public abstract class CoveringTryCatchNodeProcessor() { +public abstract class CoveringTryCatchNodeProcessor where T : SplittableInterval { public val tryBlocksMetaInfo: IntervalMetaInfo = IntervalMetaInfo(); @@ -32,18 +32,6 @@ public abstract class CoveringTryCatchNodeProcessor() { public val coveringFromInnermost: List get() = tryBlocksMetaInfo.currentIntervals.reverse() - protected fun addNewTryCatchNode(newInfo: T) { - tryBlocksMetaInfo.addNewInterval(newInfo) - } - - protected fun addNewLocalVar(newInfo: LocalVarNodeWrapper) { - localVarsMetaInfo.addNewInterval(newInfo) - } - - fun remapStartLabel(oldStart: LabelNode, remapped: T) { - tryBlocksMetaInfo.remapStartLabel(oldStart, remapped) - } - public fun getStartNodes(label: LabelNode): List { return tryBlocksMetaInfo.intervalStarts.get(label) } @@ -86,19 +74,14 @@ public abstract class CoveringTryCatchNodeProcessor() { public abstract fun instructionIndex(inst: AbstractInsnNode): Int - - public fun getNonEmptyNodes(): List { - return tryBlocksMetaInfo.getNonEmptyNodes() - } - public fun sortTryCatchBlocks() { val comp = Comparator { t1: T, t2: T -> var result = instructionIndex(t1.handler) - instructionIndex(t2.handler) if (result == 0) { - result = instructionIndex(t1.startLabel) - instructionIndex(t2.startLabel) + result = instructionIndex((t1 as Interval).startLabel) - instructionIndex((t2 as Interval).startLabel) if (result == 0) { assert(false, "Error: support multicatch finallies!") - result = instructionIndex(t1.endLabel) - instructionIndex(t2.endLabel) + result = instructionIndex((t1 as Interval).endLabel) - instructionIndex((t2 as Interval).endLabel) } } result @@ -108,7 +91,7 @@ public abstract class CoveringTryCatchNodeProcessor() { } } -class IntervalMetaInfo { +class IntervalMetaInfo { val intervalStarts = LinkedListMultimap.create() @@ -131,7 +114,18 @@ class IntervalMetaInfo { fun remapEndLabel(oldEnd: LabelNode, remapped: T) { intervalEnds.remove(oldEnd, remapped) - intervalEnds.put(remapped.startLabel, remapped) + intervalEnds.put(remapped.endLabel, remapped) + } + + fun split(interval: SplittableInterval, by : Interval, keepStart: Boolean): SplittedPair { + val splittedPair = interval.split(by, keepStart) + if (!keepStart) { + remapStartLabel((splittedPair.newPart as Interval).startLabel, splittedPair.patchedPart) + } else { + remapEndLabel((splittedPair.newPart as Interval).endLabel, splittedPair.patchedPart) + } + addNewInterval(splittedPair.newPart) + return splittedPair } public fun getNonEmptyNodes(): List { @@ -152,7 +146,7 @@ class IntervalMetaInfo { } } -public class DefaultProcessor(val node: MethodNode) : CoveringTryCatchNodeProcessor() { +public class DefaultProcessor(val node: MethodNode) : CoveringTryCatchNodeProcessor() { init { node.tryCatchBlocks.forEach { addTryNode(it) } @@ -160,11 +154,11 @@ public class DefaultProcessor(val node: MethodNode) : CoveringTryCatchNodeProces } fun addLocalVarNode(it: LocalVariableNode) { - addNewLocalVar(LocalVarNodeWrapper(it)) + localVarsMetaInfo.addNewInterval(LocalVarNodeWrapper(it)) } fun addTryNode(node: TryCatchBlockNode) { - addNewTryCatchNode(TryCatchBlockNodeWrapper(node)) + tryBlocksMetaInfo.addNewInterval(TryCatchBlockNodeInfo(node, false)) } override fun instructionIndex(inst: AbstractInsnNode): Int { @@ -172,20 +166,27 @@ public class DefaultProcessor(val node: MethodNode) : CoveringTryCatchNodeProces } } -public class LocalVarNodeWrapper(val node: LocalVariableNode) : Interval { +public class LocalVarNodeWrapper(val node: LocalVariableNode) : Interval, SplittableInterval { override val startLabel: LabelNode get() = node.start override val endLabel: LabelNode get() = node.end -} -public class TryCatchBlockNodeWrapper(val node: TryCatchBlockNode) : IntervalWithHandler { - override val startLabel: LabelNode - get() = node.start - override val endLabel: LabelNode - get() = node.end - override val handler: LabelNode - get() = node.handler - override val type: String? - get() = node.type -} + override fun split(split: Interval, keepStart: Boolean): SplittedPair { + val newPartInterval = if (keepStart) { + val oldEnd = endLabel + node.end = split.startLabel + Pair(split.endLabel, oldEnd) + } + else { + val oldStart = startLabel + node.start = split.endLabel + Pair(oldStart, split.startLabel) + } + + return SplittedPair(this, LocalVarNodeWrapper( + LocalVariableNode(node.name, node.desc, node.signature, newPartInterval.first, newPartInterval.second, node.index) + )) + } + +} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java index 5f2d9f09c6e..2239fc65aac 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -659,17 +659,9 @@ public class InlineCodegen extends CallGenerator { //Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method InlineCodegenUtil.insertNodeBefore(finallyNode, intoNode, curInstr); - List blocks = processor.getCoveringFromInnermost(); - ListIterator iterator = blocks.listIterator(blocks.size()); - while (iterator.hasPrevious()) { - TryCatchBlockNodeWrapper previous = iterator.previous(); - LabelNode oldStart = previous.getStartLabel(); - TryCatchBlockNode node = previous.getNode(); - node.start = (LabelNode) end.info; - processor.remapStartLabel(oldStart, previous); - - TryCatchBlockNode additionalNode = new TryCatchBlockNode(oldStart, (LabelNode) start.info, node.handler, node.type); - processor.addTryNode(additionalNode); + List blocks = new ArrayList(processor.getTryBlocksMetaInfo().getCurrentIntervals()); + for (TryCatchBlockNodeInfo block : blocks) { + processor.getTryBlocksMetaInfo().split(block, new SimpleInterval((LabelNode) start.info, (LabelNode) end.info), false); } } @@ -677,15 +669,14 @@ public class InlineCodegen extends CallGenerator { } processor.sortTryCatchBlocks(); - Iterable nodes = processor.getNonEmptyNodes(); + Iterable nodes = processor.getNonEmptyNodes(); intoNode.tryCatchBlocks.clear(); - for (TryCatchBlockNodeWrapper node : nodes) { + for (TryCatchBlockNodeInfo node : nodes) { intoNode.tryCatchBlocks.add(node.getNode()); } intoNode.localVariables.clear(); - List intervals = processor.getLocalVarsMetaInfo().getAllIntervals(); - for (LocalVarNodeWrapper interval : intervals) { + for (LocalVarNodeWrapper interval : processor.getLocalVarsMetaInfo().getAllIntervals()) { intoNode.localVariables.add(interval.getNode()); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java index abc0a806c6e..fe3c2b93905 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InternalFinallyBlockInliner.java @@ -81,8 +81,9 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor inlineFunTryBlockInfo) { this.inlineFun = inlineFun; + IntervalMetaInfo info = getTryBlocksMetaInfo(); for (TryCatchBlockNodeInfo block : inlineFunTryBlockInfo) { - addNewTryCatchNode(block); + info.addNewInterval(block); } } @@ -293,6 +294,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor> clusters = InlinePackage.doClustering(tryCatchBlockPresentInFinally); Map> handler2Cluster = new HashMap>(); + IntervalMetaInfo tryBlocksMetaInfo = getTryBlocksMetaInfo(); for (TryBlockCluster cluster : clusters) { List clusterBlocks = cluster.getBlocks(); TryCatchBlockNodePosition block0 = clusterBlocks.get(0); @@ -313,8 +315,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor labelsInsideFinally) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TryBlockClustering.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TryBlockClustering.kt index f0e255d7e8e..f2e81b5220a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TryBlockClustering.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TryBlockClustering.kt @@ -26,15 +26,17 @@ enum class TryCatchPosition { INNER } -public class SplittedPair(val patchedPart: SplittableInterval, val newPart: SplittableInterval) +public class SplittedPair(val patchedPart: T, val newPart: T) + +class SimpleInterval(override val startLabel: LabelNode, override val endLabel: LabelNode ) : Interval trait Interval { val startLabel: LabelNode val endLabel: LabelNode } -trait SplittableInterval : Interval { - fun split(split: Interval, keepStart: Boolean): SplittedPair +trait SplittableInterval : Interval { + fun split(split: Interval, keepStart: Boolean): SplittedPair } @@ -43,31 +45,35 @@ trait IntervalWithHandler : Interval { val type: String? } -class TryCatchBlockNodeInfo(val node: TryCatchBlockNode, val onlyCopyNotProcess: Boolean) : IntervalWithHandler, SplittableInterval { +class TryCatchBlockNodeInfo(val node: TryCatchBlockNode, val onlyCopyNotProcess: Boolean) : IntervalWithHandler, SplittableInterval { override val startLabel: LabelNode - get() = node.start + get() = node.start override val endLabel: LabelNode - get() = node.end + get() = node.end override val handler: LabelNode - get() = node.handler + get() = node.handler override val type: String? - get() = node.type + get() = node.type - override fun split(split: Interval, keepStart: Boolean): SplittedPair { - val newPart = if (keepStart) { + override fun split(by: Interval, keepStart: Boolean): SplittedPair { + val newPartInterval = if (keepStart) { val oldEnd = endLabel - node.end = split.startLabel - TryCatchBlockNodeInfo(TryCatchBlockNode(split.endLabel, oldEnd, handler, type), onlyCopyNotProcess) - } else { - val oldStart = startLabel - node.start = split.endLabel - TryCatchBlockNodeInfo(TryCatchBlockNode(oldStart, split.startLabel, handler, type), onlyCopyNotProcess) + node.end = by.startLabel + Pair(by.endLabel, oldEnd) } - return SplittedPair(this, newPart) + else { + val oldStart = startLabel + node.start = by.endLabel + Pair(oldStart, by.startLabel) + } + return SplittedPair( + this, + TryCatchBlockNodeInfo(TryCatchBlockNode(newPartInterval.first, newPartInterval.second, handler, type), onlyCopyNotProcess) + ) } } -class TryCatchBlockNodePosition(val nodeInfo: TryCatchBlockNodeInfo, var position: TryCatchPosition): IntervalWithHandler by nodeInfo { +class TryCatchBlockNodePosition(val nodeInfo: TryCatchBlockNodeInfo, var position: TryCatchPosition) : IntervalWithHandler by nodeInfo { } @@ -77,13 +83,13 @@ class TryBlockCluster(val blocks: MutableList) { } -fun doClustering(blocks: List) : List> { +fun doClustering(blocks: List): List> { [data] class TryBlockInterval(val startLabel: LabelNode, val endLabel: LabelNode) val clusters = linkedMapOf>() blocks.forEach { block -> val interval = TryBlockInterval(firstLabelInChain(block.startLabel), firstLabelInChain(block.endLabel)) - val cluster = clusters.getOrPut(interval, {TryBlockCluster(arrayListOf())}) + val cluster = clusters.getOrPut(interval, { TryBlockCluster(arrayListOf()) }) cluster.blocks.add(block) }