summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2015-11-06 09:31:59 +0100
committerLukas Rytz <lukas.rytz@gmail.com>2015-11-10 11:18:53 +0100
commitf777790250ffe92b65b51c71c7da113659177ad0 (patch)
treeba5c155380e20a8ca016be3e628acb315b850c92 /src/compiler
parent5d4d2cc9f95d88dc4ba19095c6cfe8b60ad1a21d (diff)
downloadscala-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.scala35
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