From f777790250ffe92b65b51c71c7da113659177ad0 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 6 Nov 2015 09:31:59 +0100 Subject: Fix merging of AliasingFrames By convention (for performance), `aliasingFrame.aliases(slot) == null` means that the value at `slot` has no aliases, so this is isomorphic to having a singleton `AliasSet(slot)`. When merging an AliasingFrame `other` into `this`, at every value slot we have to keep the intersection of the two alias sets. In other words we have to remove from `this.aliases(slot)` those values that are not in `other.aliases(slot)`. This was wrong for the cases where `other.aliases == null` - we did not treat this case as a singleton set. --- .../nsc/backend/jvm/analysis/AliasingFrame.scala | 35 ++++++++++++++-------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/AliasingFrame.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/AliasingFrame.scala index 5aa060e019..086946e4e3 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/AliasingFrame.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/AliasingFrame.scala @@ -28,6 +28,8 @@ class AliasingFrame[V <: Value](nLocals: Int, nStack: Int) extends Frame[V](nLoc init(src) } + override def toString: String = super.toString + " - " + aliases.toList.filter(s => s != null && s.size > 1).map(_.toString).distinct.mkString(",") + /** * For every value the set of values that are aliases of it. * @@ -299,18 +301,25 @@ class AliasingFrame[V <: Value](nLocals: Int, nStack: Int) extends Frame[V](nLoc if (!knownOk(i)) { val thisAliases = this.aliases(i) val otherAliases = aliasingOther.aliases(i) - if (thisAliases != null && otherAliases != null) { - // The iterator yields elements that are in `thisAliases` but not in `otherAliases`. - // As a side-effect, for every index `i` that is in both alias sets, the iterator sets - // `knownOk(i) = true`: the alias sets for these values don't need to be merged again. - val thisNotOtherIt = AliasSet.andNotIterator(thisAliases, otherAliases, knownOk) - if (thisNotOtherIt.hasNext) { - aliasesChanged = true - val newSet = AliasSet.empty - while (thisNotOtherIt.hasNext) { - val next = thisNotOtherIt.next() - newSet += next - setAliasSet(next, newSet) + if (thisAliases != null) { + if (otherAliases == null) { + if (thisAliases.size > 1) { + aliasesChanged = true + removeAlias(i) + } + } else { + // The iterator yields elements that are in `thisAliases` but not in `otherAliases`. + // As a side-effect, for every index `i` that is in both alias sets, the iterator sets + // `knownOk(i) = true`: the alias sets for these values don't need to be merged again. + val thisNotOtherIt = AliasSet.andNotIterator(thisAliases, otherAliases, knownOk) + if (thisNotOtherIt.hasNext) { + aliasesChanged = true + val newSet = AliasSet.empty + while (thisNotOtherIt.hasNext) { + val next = thisNotOtherIt.next() + newSet += next + setAliasSet(next, newSet) + } } } } @@ -416,7 +425,7 @@ abstract class IntIterator extends Iterator[Int] { class AliasSet(var set: Object /*SmallBitSet | Array[Long]*/, var size: Int) { import AliasSet._ - override def toString: String = set.toString + override def toString: String = iterator.toSet.mkString("<", ",", ">") /** * An iterator for the elements of this bit set. Note that only one iterator can be used at a -- cgit v1.2.3