diff options
author | Lukas Rytz <lukas.rytz@gmail.com> | 2015-11-06 09:31:59 +0100 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2015-11-10 11:18:53 +0100 |
commit | f777790250ffe92b65b51c71c7da113659177ad0 (patch) | |
tree | ba5c155380e20a8ca016be3e628acb315b850c92 /src/compiler | |
parent | 5d4d2cc9f95d88dc4ba19095c6cfe8b60ad1a21d (diff) | |
download | scala-f777790250ffe92b65b51c71c7da113659177ad0.tar.gz scala-f777790250ffe92b65b51c71c7da113659177ad0.tar.bz2 scala-f777790250ffe92b65b51c71c7da113659177ad0.zip |
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.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/analysis/AliasingFrame.scala | 35 |
1 files changed, 22 insertions, 13 deletions
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 |