summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala25
-rw-r--r--src/library/scala/collection/mutable/HashTable.scala32
-rw-r--r--src/library/scala/collection/parallel/mutable/ParHashMap.scala10
-rw-r--r--test/files/jvm/serialization.check8
-rw-r--r--test/files/run/synchronized.check128
-rw-r--r--test/files/run/synchronized.flags1
-rw-r--r--test/files/run/synchronized.scala449
-rw-r--r--test/files/run/t5293-map.scala88
-rw-r--r--test/files/specialized/SI-5005.check33
-rw-r--r--test/files/specialized/SI-5005.scala23
10 files changed, 777 insertions, 20 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 05f5dbc379..8c34a9139d 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -69,7 +69,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
ScalaValueClasses, isValueClass, isScalaValueType,
SpecializedClass, RepeatedParamClass, JavaRepeatedParamClass,
AnyRefClass, ObjectClass, AnyRefModule,
- GroupOfSpecializable, uncheckedVarianceClass
+ GroupOfSpecializable, uncheckedVarianceClass, ScalaInlineClass
}
/** TODO - this is a lot of maps.
@@ -832,7 +832,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
log("-->d SETTING PRIVATE WITHIN TO " + sym.enclosingPackage + " for " + sym)
}
- sym.resetFlag(FINAL)
val specMember = subst(outerEnv)(specializedOverload(owner, sym, spec))
typeEnv(specMember) = typeEnv(sym) ++ outerEnv ++ spec
wasSpecializedForTypeVars(specMember) ++= spec collect { case (s, tp) if s.tpe == tp => s }
@@ -1733,9 +1732,27 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
class SpecializationTransformer(unit: CompilationUnit) extends Transformer {
informProgress("specializing " + unit)
- override def transform(tree: Tree) =
- if (settings.nospecialization.value) tree
+ override def transform(tree: Tree) = {
+ val resultTree = if (settings.nospecialization.value) tree
else atPhase(phase.next)(specializeCalls(unit).transform(tree))
+
+ // Remove the final modifier and @inline annotation from anything in the
+ // original class (since it's being overridden in at least onesubclass).
+ //
+ // We do this here so that the specialized subclasses will correctly copy
+ // final and @inline.
+ info.foreach {
+ case (sym, SpecialOverload(target, _)) => {
+ sym.resetFlag(FINAL)
+ target.resetFlag(FINAL)
+ sym.removeAnnotation(ScalaInlineClass)
+ target.removeAnnotation(ScalaInlineClass)
+ }
+ case _ => {}
+ }
+
+ resultTree
+ }
}
def printSpecStats() {
diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala
index cdf1b78f29..5b3e07b826 100644
--- a/src/library/scala/collection/mutable/HashTable.scala
+++ b/src/library/scala/collection/mutable/HashTable.scala
@@ -52,6 +52,10 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
*/
@transient protected var sizemap: Array[Int] = null
+ @transient var seedvalue: Int = tableSizeSeed
+
+ protected def tableSizeSeed = Integer.bitCount(table.length - 1)
+
protected def initialSize: Int = HashTable.initialSize
private def lastPopulatedIndex = {
@@ -70,14 +74,16 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
private[collection] def init[B](in: java.io.ObjectInputStream, f: (A, B) => Entry) {
in.defaultReadObject
- _loadFactor = in.readInt
+ _loadFactor = in.readInt()
assert(_loadFactor > 0)
- val size = in.readInt
+ val size = in.readInt()
tableSize = 0
assert(size >= 0)
-
- val smDefined = in.readBoolean
+
+ seedvalue = in.readInt()
+
+ val smDefined = in.readBoolean()
table = new Array(capacity(sizeForThreshold(_loadFactor, size)))
threshold = newThreshold(_loadFactor, table.size)
@@ -86,7 +92,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
var index = 0
while (index < size) {
- addEntry(f(in.readObject.asInstanceOf[A], in.readObject.asInstanceOf[B]))
+ addEntry(f(in.readObject().asInstanceOf[A], in.readObject().asInstanceOf[B]))
index += 1
}
}
@@ -103,6 +109,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
out.defaultWriteObject
out.writeInt(_loadFactor)
out.writeInt(tableSize)
+ out.writeInt(seedvalue)
out.writeBoolean(isSizeMapDefined)
foreachEntry { entry =>
out.writeObject(entry.key)
@@ -314,7 +321,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
// this is of crucial importance when populating the table in parallel
protected final def index(hcode: Int) = {
val ones = table.length - 1
- val improved = improve(hcode)
+ val improved = improve(hcode, seedvalue)
val shifted = (improved >> (32 - java.lang.Integer.bitCount(ones))) & ones
shifted
}
@@ -325,6 +332,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
table = c.table
tableSize = c.tableSize
threshold = c.threshold
+ seedvalue = c.seedvalue
sizemap = c.sizemap
}
if (alwaysInitSizeMap && sizemap == null) sizeMapInitAndRebuild
@@ -335,6 +343,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
table,
tableSize,
threshold,
+ seedvalue,
sizemap
)
}
@@ -368,7 +377,7 @@ private[collection] object HashTable {
protected def elemHashCode(key: KeyType) = key.##
- protected final def improve(hcode: Int) = {
+ protected final def improve(hcode: Int, seed: Int) = {
/* Murmur hash
* m = 0x5bd1e995
* r = 24
@@ -396,7 +405,7 @@ private[collection] object HashTable {
* */
var i = hcode * 0x9e3775cd
i = java.lang.Integer.reverseBytes(i)
- i * 0x9e3775cd
+ i = i * 0x9e3775cd
// a slower alternative for byte reversal:
// i = (i << 16) | (i >> 16)
// i = ((i >> 8) & 0x00ff00ff) | ((i << 8) & 0xff00ff00)
@@ -420,6 +429,11 @@ private[collection] object HashTable {
// h = h ^ (h >>> 14)
// h = h + (h << 4)
// h ^ (h >>> 10)
+
+ // the rest of the computation is due to SI-5293
+ val rotation = seed % 32
+ val rotated = (i >>> rotation) | (i << (32 - rotation))
+ rotated
}
}
@@ -442,6 +456,7 @@ private[collection] object HashTable {
val table: Array[HashEntry[A, Entry]],
val tableSize: Int,
val threshold: Int,
+ val seedvalue: Int,
val sizemap: Array[Int]
) {
import collection.DebugUtils._
@@ -452,6 +467,7 @@ private[collection] object HashTable {
append("Table: [" + arrayString(table, 0, table.length) + "]")
append("Table size: " + tableSize)
append("Load factor: " + loadFactor)
+ append("Seedvalue: " + seedvalue)
append("Threshold: " + threshold)
append("Sizemap: [" + arrayString(sizemap, 0, sizemap.length) + "]")
}
diff --git a/src/library/scala/collection/parallel/mutable/ParHashMap.scala b/src/library/scala/collection/parallel/mutable/ParHashMap.scala
index 15ffd3fdd2..21a5b05749 100644
--- a/src/library/scala/collection/parallel/mutable/ParHashMap.scala
+++ b/src/library/scala/collection/parallel/mutable/ParHashMap.scala
@@ -160,10 +160,11 @@ extends collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], DefaultEntr
import collection.parallel.tasksupport._
private var mask = ParHashMapCombiner.discriminantmask
private var nonmasklen = ParHashMapCombiner.nonmasklength
+ private var seedvalue = 27
def +=(elem: (K, V)) = {
sz += 1
- val hc = improve(elemHashCode(elem._1))
+ val hc = improve(elemHashCode(elem._1), seedvalue)
val pos = (hc >>> nonmasklen)
if (buckets(pos) eq null) {
// initialize bucket
@@ -176,7 +177,7 @@ extends collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], DefaultEntr
def result: ParHashMap[K, V] = if (size >= (ParHashMapCombiner.numblocks * sizeMapBucketSize)) { // 1024
// construct table
- val table = new AddingHashTable(size, tableLoadFactor)
+ val table = new AddingHashTable(size, tableLoadFactor, seedvalue)
val bucks = buckets.map(b => if (b ne null) b.headPtr else null)
val insertcount = executeAndWaitResult(new FillBlocks(bucks, table, 0, bucks.length))
table.setSize(insertcount)
@@ -210,11 +211,12 @@ extends collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], DefaultEntr
* and true if the key was successfully inserted. It does not update the number of elements
* in the table.
*/
- private[ParHashMapCombiner] class AddingHashTable(numelems: Int, lf: Int) extends HashTable[K, DefaultEntry[K, V]] {
+ private[ParHashMapCombiner] class AddingHashTable(numelems: Int, lf: Int, _seedvalue: Int) extends HashTable[K, DefaultEntry[K, V]] {
import HashTable._
_loadFactor = lf
table = new Array[HashEntry[K, DefaultEntry[K, V]]](capacity(sizeForThreshold(_loadFactor, numelems)))
tableSize = 0
+ seedvalue = _seedvalue
threshold = newThreshold(_loadFactor, table.length)
sizeMapInit(table.length)
def setSize(sz: Int) = tableSize = sz
@@ -285,7 +287,7 @@ extends collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], DefaultEntr
insertcount
}
private def assertCorrectBlock(block: Int, k: K) {
- val hc = improve(elemHashCode(k))
+ val hc = improve(elemHashCode(k), seedvalue)
if ((hc >>> nonmasklen) != block) {
println(hc + " goes to " + (hc >>> nonmasklen) + ", while expected block is " + block)
assert((hc >>> nonmasklen) == block)
diff --git a/test/files/jvm/serialization.check b/test/files/jvm/serialization.check
index 67b77639a2..81b68f0f5d 100644
--- a/test/files/jvm/serialization.check
+++ b/test/files/jvm/serialization.check
@@ -156,8 +156,8 @@ x = BitSet(0, 8, 9)
y = BitSet(0, 8, 9)
x equals y: true, y equals x: true
-x = Map(C -> 3, B -> 2, A -> 1)
-y = Map(C -> 3, A -> 1, B -> 2)
+x = Map(A -> 1, C -> 3, B -> 2)
+y = Map(A -> 1, C -> 3, B -> 2)
x equals y: true, y equals x: true
x = Set(buffers, title, layers)
@@ -283,8 +283,8 @@ x = ParArray(abc, def, etc)
y = ParArray(abc, def, etc)
x equals y: true, y equals x: true
-x = ParHashMap(1 -> 2, 2 -> 4)
-y = ParHashMap(1 -> 2, 2 -> 4)
+x = ParHashMap(2 -> 4, 1 -> 2)
+y = ParHashMap(2 -> 4, 1 -> 2)
x equals y: true, y equals x: true
x = ParCtrie(1 -> 2, 2 -> 4)
diff --git a/test/files/run/synchronized.check b/test/files/run/synchronized.check
new file mode 100644
index 0000000000..dd9f4ef424
--- /dev/null
+++ b/test/files/run/synchronized.check
@@ -0,0 +1,128 @@
+ .|. c1.f1: OK
+ .|. c1.fi: OK
+ .|... c1.fv: OK
+ .|... c1.ff: OK
+ .|. c1.fl: OK
+ .|... c1.fo: OK
+ |.. c1.g1: OK
+ |.. c1.gi: OK
+ |.... c1.gv: OK
+ |..... c1.gf: OK
+ .|... c1.c.f1: OK
+ .|... c1.c.fi: OK
+ .|..... c1.c.fv: OK
+ .|..... c1.c.ff: OK
+ .|... c1.c.fl: OK
+ .|..... c1.c.fo: OK
+ .|... c1.c.fn: OK
+ |.... c1.c.g1: OK
+ |.... c1.c.gi: OK
+ |...... c1.c.gv: OK
+ |...... c1.c.gf: OK
+ .|... c1.O.f1: OK
+ .|... c1.O.fi: OK
+ .|..... c1.O.fv: OK
+ .|..... c1.O.ff: OK
+ .|... c1.O.fl: OK
+ .|..... c1.O.fo: OK
+ .|... c1.O.fn: OK
+ |.... c1.O.g1: OK
+ |.... c1.O.gi: OK
+ |...... c1.O.gv: OK
+ |...... c1.O.gf: OK
+ .|. O1.f1: OK
+ .|. O1.fi: OK
+ .|... O1.fv: OK
+ .|... O1.ff: OK
+ .|. O1.fl: OK
+ .|... O1.fo: OK
+ |.. O1.g1: OK
+ |.. O1.gi: OK
+ |.... O1.gv: OK
+ |.... O1.gf: OK
+ .|... O1.c.f1: OK
+ .|... O1.c.fi: OK
+ .|..... O1.c.fv: OK
+ .|..... O1.c.ff: OK
+ .|... O1.c.fl: OK
+ .|..... O1.c.fo: OK
+ .|... O1.c.fn: OK
+ |.... O1.c.g1: OK
+ |.... O1.c.gi: OK
+ |...... O1.c.gv: OK
+ |...... O1.c.gf: OK
+ .|... O1.O.f1: OK
+ .|... O1.O.fi: OK
+ .|..... O1.O.fv: OK
+ .|..... O1.O.ff: OK
+ .|... O1.O.fl: OK
+ .|..... O1.O.fo: OK
+ .|... O1.O.fn: OK
+ |.... O1.O.g1: OK
+ |.... O1.O.gi: OK
+ |...... O1.O.gv: OK
+ |...... O1.O.gf: OK
+ .|..... c2.f1: OK
+ .|..... c2.fi: OK
+ .|....... c2.fv: OK
+ .|....... c2.ff: OK
+ .|..... c2.fl: OK
+ .|....... c2.fo: OK
+ |....... c2.g1: OK
+ |....... c2.gi: OK
+ |......... c2.gv: OK
+ |......... c2.gf: OK
+ .|........ c2.c.f1: OK
+ .|........ c2.c.fi: OK
+ .|.......... c2.c.fv: OK
+ .|.......... c2.c.ff: OK
+ .|........ c2.c.fl: OK
+ .|.......... c2.c.fo: OK
+ .|....... c2.c.fn: OK
+ |......... c2.c.g1: OK
+ |......... c2.c.gi: OK
+ |........... c2.c.gv: OK
+ |........... c2.c.gf: OK
+ .|........ c2.O.f1: OK
+ .|........ c2.O.fi: OK
+ .|.......... c2.O.fv: OK
+ .|.......... c2.O.ff: OK
+ .|........ c2.O.fl: OK
+ .|.......... c2.O.fo: OK
+ .|....... c2.O.fn: OK
+ |......... c2.O.g1: OK
+ |......... c2.O.gi: OK
+ |........... c2.O.gv: OK
+ |........... c2.O.gf: OK
+ .|..... O2.f1: OK
+ .|..... O2.fi: OK
+ .|....... O2.fv: OK
+ .|....... O2.ff: OK
+ .|..... O2.fl: OK
+ .|....... O2.fo: OK
+ |....... O2.g1: OK
+ |....... O2.gi: OK
+ |......... O2.gv: OK
+ |......... O2.gf: OK
+ .|........ O2.c.f1: OK
+ .|........ O2.c.fi: OK
+ .|.......... O2.c.fv: OK
+ .|.......... O2.c.ff: OK
+ .|........ O2.c.fl: OK
+ .|.......... O2.c.fo: OK
+ .|....... O2.c.fn: OK
+ |......... O2.c.g1: OK
+ |......... O2.c.gi: OK
+ |........... O2.c.gv: OK
+ |........... O2.c.gf: OK
+ .|........ O2.O.f1: OK
+ .|........ O2.O.fi: OK
+ .|.......... O2.O.fv: OK
+ .|.......... O2.O.ff: OK
+ .|........ O2.O.fl: OK
+ .|.......... O2.O.fo: OK
+ .|....... O2.O.fn: OK
+ |......... O2.O.g1: OK
+ |......... O2.O.gi: OK
+ |........... O2.O.gv: OK
+ |........... O2.O.gf: OK
diff --git a/test/files/run/synchronized.flags b/test/files/run/synchronized.flags
new file mode 100644
index 0000000000..1182725e86
--- /dev/null
+++ b/test/files/run/synchronized.flags
@@ -0,0 +1 @@
+-optimize \ No newline at end of file
diff --git a/test/files/run/synchronized.scala b/test/files/run/synchronized.scala
new file mode 100644
index 0000000000..1f0e32992b
--- /dev/null
+++ b/test/files/run/synchronized.scala
@@ -0,0 +1,449 @@
+import java.lang.Thread.holdsLock
+import scala.collection.mutable.StringBuilder
+
+object Util {
+ def checkLocks(held: AnyRef*)(notHeld: AnyRef*) = {
+ val sb = new StringBuilder
+ for (lock <- held) {
+ sb.append(if (holdsLock(lock)) '.' else '!')
+ }
+ print("%5s|" format sb)
+
+ sb.clear()
+ for (lock <- notHeld) {
+ sb.append(if (holdsLock(lock)) '!' else '.')
+ }
+ print("%-15s " format sb)
+
+ (held forall holdsLock) && !(notHeld exists holdsLock)
+ }
+}
+
+class C1 {
+ import Util._
+
+ val lock = new AnyRef
+
+ def f1 = synchronized { checkLocks(this)(this.getClass) }
+ @inline final def fi = synchronized { checkLocks(this)(this.getClass) }
+ val fv: () => Boolean = () => synchronized { checkLocks(this)(this.getClass, fv, fv.getClass) }
+ def ff = {
+ lazy val ffv: AnyRef => Boolean = lock => synchronized { checkLocks(lock)(ffv, ffv.getClass, lock.getClass) }
+ ffv(this)
+ }
+ def fl = {
+ lazy val flv = synchronized { checkLocks(this)(this.getClass) }
+ flv
+ }
+ def fo = lock.synchronized { checkLocks(lock)(lock.getClass, this, this.getClass) }
+
+ def g1 = checkLocks()(this, this.getClass)
+ @inline final def gi = checkLocks()(this, this.getClass)
+ val gv: () => Boolean = () => checkLocks()(this, this.getClass, gv, gv.getClass)
+ def gf = {
+ lazy val gfv: AnyRef => Boolean = lock => checkLocks()(C1.this, gfv, gfv.getClass, lock, lock.getClass)
+ gfv(this)
+ }
+ def gl = {
+ lazy val glv = checkLocks()(this, this.getClass)
+ glv
+ }
+
+ class C {
+ def f1 = synchronized { checkLocks(this)(this.getClass, C1.this, C1.this.getClass) }
+ @inline final def fi = synchronized { checkLocks(this)(this.getClass, C1.this, C1.this.getClass) }
+ val fv: () => Boolean = () => synchronized { checkLocks(this)(this.getClass, C1.this, C1.this.getClass, fv, fv.getClass) }
+ def ff = {
+ lazy val ffv: AnyRef => Boolean = lock => synchronized { checkLocks(lock)(ffv, ffv.getClass, lock.getClass, C1.this, C1.this.getClass) }
+ ffv(this)
+ }
+ def fl = {
+ lazy val flv = synchronized { checkLocks(this)(this.getClass, C1.this, C1.this.getClass) }
+ flv
+ }
+ def fo = lock.synchronized { checkLocks(lock)(lock.getClass, this, this.getClass, C1.this, C1.this.getClass) }
+ def fn = C1.this.synchronized { checkLocks(C1.this)(C1.this.getClass, this, this.getClass) }
+
+ def g1 = checkLocks()(this, this.getClass, C1.this, C1.this.getClass)
+ @inline final def gi = checkLocks()(this, this.getClass, C1.this, C1.this.getClass)
+ val gv: () => Boolean = () => checkLocks()(this, this.getClass, C1.this, C1.this.getClass, gv, gv.getClass)
+ def gf = {
+ lazy val gfv: AnyRef => Boolean = lock => checkLocks()(gfv, gfv.getClass, lock, lock.getClass, C1.this, C1.this.getClass)
+ gfv(this)
+ }
+ def gl = {
+ lazy val glv = checkLocks()(this, this.getClass, C1.this, C1.this.getClass)
+ glv
+ }
+ }
+ val c = new C
+
+ object O {
+ def f1 = synchronized { checkLocks(this)(this.getClass, C1.this, C1.this.getClass) }
+ @inline final def fi = synchronized { checkLocks(this)(this.getClass, C1.this, C1.this.getClass) }
+ val fv: () => Boolean = () => synchronized { checkLocks(this)(this.getClass, fv, fv.getClass, C1.this, C1.this.getClass) }
+ def ff = {
+ lazy val ffv: AnyRef => Boolean = lock => synchronized { checkLocks(lock)(lock.getClass, ffv, ffv.getClass, C1.this, C1.this.getClass) }
+ ffv(this)
+ }
+ def fl = {
+ lazy val flv = synchronized { checkLocks(this)(this.getClass, C1.this, C1.this.getClass) }
+ flv
+ }
+ def fo = lock.synchronized { checkLocks(lock)(lock.getClass, this, this.getClass, C1.this, C1.this.getClass) }
+ def fn = C1.this.synchronized { checkLocks(C1.this)(C1.this.getClass, this, this.getClass) }
+
+ def g1 = checkLocks()(this, this.getClass, C1.this, C1.this.getClass)
+ @inline final def gi = checkLocks()(this, this.getClass, C1.this, C1.this.getClass)
+ val gv: () => Boolean = () => checkLocks()(this, this.getClass, gv, gv.getClass, C1.this, C1.this.getClass)
+ def gf = {
+ lazy val gfv: AnyRef => Boolean = lock => checkLocks()(lock, lock.getClass, gfv, gfv.getClass, C1.this, C1.this.getClass)
+ gfv(this)
+ }
+ def gl = {
+ lazy val glv = checkLocks()(this, this.getClass, C1.this, C1.this.getClass)
+ glv
+ }
+ }
+}
+
+object O1 {
+ import Util._
+
+ val lock = new AnyRef
+
+ def f1 = synchronized { checkLocks(this)(this.getClass) }
+ @inline final def fi = synchronized { checkLocks(this)(this.getClass) }
+ val fv: () => Boolean = () => synchronized { checkLocks(this)(this.getClass, fv, fv.getClass) }
+ def ff = {
+ lazy val ffv: AnyRef => Boolean = lock => synchronized { checkLocks(lock)(ffv, ffv.getClass, lock.getClass) }
+ ffv(this)
+ }
+ def fl = {
+ lazy val flv = synchronized { checkLocks(this)(this.getClass) }
+ flv
+ }
+ def fo = lock.synchronized { checkLocks(lock)(lock.getClass, this, this.getClass) }
+
+ def g1 = checkLocks()(this, this.getClass)
+ @inline final def gi = checkLocks()(this, this.getClass)
+ val gv: () => Boolean = () => checkLocks()(this, this.getClass, gv, gv.getClass)
+ def gf = {
+ lazy val gfv: AnyRef => Boolean = lock => checkLocks()(gfv, gfv.getClass, lock, lock.getClass)
+ gfv(this)
+ }
+ def gl = {
+ lazy val glv = checkLocks()(this, this.getClass)
+ glv
+ }
+
+ class C {
+ def f1 = synchronized { checkLocks(this)(this.getClass, O1, O1.getClass) }
+ @inline final def fi = synchronized { checkLocks(this)(this.getClass, O1, O1.getClass) }
+ val fv: () => Boolean = () => synchronized { checkLocks(this)(this.getClass, O1, O1.getClass, fv, fv.getClass) }
+ def ff = {
+ lazy val ffv: AnyRef => Boolean = lock => synchronized { checkLocks(lock)(ffv, ffv.getClass, lock.getClass, O1, O1.getClass) }
+ ffv(this)
+ }
+ def fl = {
+ lazy val flv = synchronized { checkLocks(this)(this.getClass, O1, O1.getClass) }
+ flv
+ }
+ def fo = lock.synchronized { checkLocks(lock)(lock.getClass, this, this.getClass, O1, O1.getClass) }
+ def fn = O1.synchronized { checkLocks(O1)(O1.getClass, this, this.getClass) }
+
+ def g1 = checkLocks()(this, this.getClass, O1, O1.getClass)
+ @inline final def gi = checkLocks()(this, this.getClass, O1, O1.getClass)
+ val gv: () => Boolean = () => checkLocks()(this, this.getClass, O1, O1.getClass, gv, gv.getClass)
+ def gf = {
+ lazy val gfv: AnyRef => Boolean = lock => checkLocks()(gfv, gfv.getClass, lock, lock.getClass, O1, O1.getClass)
+ gfv(this)
+ }
+ def gl = {
+ lazy val glv = checkLocks()(this, this.getClass, O1, O1.getClass)
+ glv
+ }
+ }
+ val c = new C
+
+ object O {
+ def f1 = synchronized { checkLocks(this)(this.getClass, O1, O1.getClass) }
+ @inline final def fi = synchronized { checkLocks(this)(this.getClass, O1, O1.getClass) }
+ val fv: () => Boolean = () => synchronized { checkLocks(this)(this.getClass, fv, fv.getClass, O1, O1.getClass) }
+ def ff = {
+ lazy val ffv: AnyRef => Boolean = lock => synchronized { checkLocks(lock)(lock.getClass, ffv, ffv.getClass, O1, O1.getClass) }
+ ffv(this)
+ }
+ def fl = {
+ lazy val flv = synchronized { checkLocks(this)(this.getClass, O1, O1.getClass) }
+ flv
+ }
+ def fo = lock.synchronized { checkLocks(lock)(lock.getClass, this, this.getClass, O1, O1.getClass) }
+ def fn = O1.synchronized { checkLocks(O1)(O1.getClass, this, this.getClass) }
+
+ def g1 = checkLocks()(this, this.getClass, O1, O1.getClass)
+ @inline final def gi = checkLocks()(this, this.getClass, O1, O1.getClass)
+ val gv: () => Boolean = () => checkLocks()(this, this.getClass, gv, gv.getClass, O1, O1.getClass)
+ def gf = {
+ lazy val gfv: AnyRef => Boolean = lock => checkLocks()(lock, lock.getClass, gfv, gfv.getClass, O1, O1.getClass)
+ gfv(this)
+ }
+ def gl = {
+ lazy val glv = checkLocks()(this, this.getClass, O1, O1.getClass)
+ glv
+ }
+ }
+}
+
+trait T {
+ import Util._
+
+ val Tclass = Class.forName("T$class")
+
+ val lock = new AnyRef
+
+ def f1 = synchronized { checkLocks(this)(this.getClass, classOf[T], Tclass, classOf[C2], O2.getClass) }
+ @inline final def fi = synchronized { checkLocks(this)(this.getClass, classOf[T], Tclass, classOf[C2], O2.getClass) }
+ val fv: () => Boolean = () => synchronized { checkLocks(this)(this.getClass, fv, fv.getClass, classOf[T], Tclass, classOf[C2], O2.getClass) }
+ def ff = {
+ lazy val ffv: AnyRef => Boolean = lock => synchronized { checkLocks(lock)(ffv, ffv.getClass, lock.getClass, classOf[T], Tclass, classOf[C2], O2.getClass) }
+ ffv(this)
+ }
+ def fl = {
+ lazy val flv = synchronized { checkLocks(this)(this.getClass, classOf[T], Tclass, classOf[C2], O2.getClass) }
+ flv
+ }
+ def fo = lock.synchronized { checkLocks(lock)(lock.getClass, this, this.getClass, classOf[T], Tclass, classOf[C2], O2.getClass) }
+
+ def g1 = checkLocks()(this, this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ @inline final def gi = checkLocks()(this, this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ val gv: () => Boolean = () => checkLocks()(this, this.getClass, gv, gv.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ def gf = {
+ lazy val gfv: AnyRef => Boolean = lock => checkLocks()(gfv, gfv.getClass, lock, lock.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ gfv(this)
+ }
+ def gl = {
+ lazy val glv = checkLocks()(this, this.getClass, classOf[T], Tclass, classOf[C2], O2.getClass)
+ glv
+ }
+
+ class C {
+ def f1 = synchronized { checkLocks(this)(this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass) }
+ @inline final def fi = synchronized { checkLocks(this)(this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass) }
+ val fv: () => Boolean = () => synchronized { checkLocks(this)(this.getClass, T.this, T.this.getClass, fv, fv.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass) }
+ def ff = {
+ lazy val ffv: AnyRef => Boolean = lock => synchronized { checkLocks(lock)(ffv, ffv.getClass, lock.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass) }
+ ffv(this)
+ }
+ def fl = {
+ lazy val flv = synchronized { checkLocks(this)(this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass) }
+ flv
+ }
+ def fo = lock.synchronized { checkLocks(lock)(lock.getClass, this, this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass) }
+ def fn = T.this.synchronized { checkLocks(T.this)(T.this.getClass, this, this.getClass, classOf[T], Tclass, classOf[C2], O2.getClass) }
+
+ def g1 = checkLocks()(this, this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ @inline final def gi = checkLocks()(this, this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ val gv: () => Boolean = () => checkLocks()(this, this.getClass, T.this, T.this.getClass, gv, gv.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ def gf = {
+ lazy val gfv: AnyRef => Boolean = lock => checkLocks()(gfv, gfv.getClass, lock, lock.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ gfv(this)
+ }
+ def gl = {
+ lazy val glv = checkLocks()(this, this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ glv
+ }
+ }
+ val c = new C
+
+ object O {
+ def f1 = synchronized { checkLocks(this)(this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass) }
+ @inline final def fi = synchronized { checkLocks(this)(this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass) }
+ val fv: () => Boolean = () => synchronized { checkLocks(this)(this.getClass, fv, fv.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass) }
+ def ff = {
+ lazy val ffv: AnyRef => Boolean = lock => synchronized { checkLocks(lock)(lock.getClass, ffv, ffv.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass) }
+ ffv(this)
+ }
+ def fl = {
+ lazy val flv = synchronized { checkLocks(this)(this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass) }
+ flv
+ }
+ def fo = lock.synchronized { checkLocks(lock)(lock.getClass, this, this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass) }
+ def fn = T.this.synchronized { checkLocks(T.this)(T.this.getClass, this, this.getClass, classOf[T], Tclass, classOf[C2], O2.getClass) }
+
+ def g1 = checkLocks()(this, this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ @inline final def gi = checkLocks()(this, this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ val gv: () => Boolean = () => checkLocks()(this, this.getClass, gv, gv.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ def gf = {
+ lazy val gfv: AnyRef => Boolean = lock => checkLocks()(lock, lock.getClass, gfv, gfv.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ gfv(this)
+ }
+ def gl = {
+ lazy val glv = checkLocks()(this, this.getClass, T.this, T.this.getClass, classOf[T], Tclass, classOf[C2], O2, O2.getClass)
+ glv
+ }
+ }
+}
+
+class C2 extends T
+object O2 extends T
+
+object Test extends App {
+ def check(name: String, result: Boolean) {
+ println("%-10s %s" format (name +":", if (result) "OK" else "FAILED"))
+ }
+
+ val c1 = new C1
+ check("c1.f1", c1.f1)
+ check("c1.fi", c1.fi)
+ check("c1.fv", c1.fv())
+ check("c1.ff", c1.ff)
+ check("c1.fl", c1.fl)
+ check("c1.fo", c1.fo)
+ check("c1.g1", c1.g1)
+ check("c1.gi", c1.gi)
+ check("c1.gv", c1.gv())
+ check("c1.gf", c1.gf)
+// check("c1.gl", c1.gl) // FIXME *.gl are failing because of the issue described in SUGGEST-11
+
+ check("c1.c.f1", c1.c.f1)
+ check("c1.c.fi", c1.c.fi)
+ check("c1.c.fv", c1.c.fv())
+ check("c1.c.ff", c1.c.ff)
+ check("c1.c.fl", c1.c.fl)
+ check("c1.c.fo", c1.c.fo)
+ check("c1.c.fn", c1.c.fn)
+ check("c1.c.g1", c1.c.g1)
+ check("c1.c.gi", c1.c.gi)
+ check("c1.c.gv", c1.c.gv())
+ check("c1.c.gf", c1.c.gf)
+// check("c1.c.gl", c1.c.gl)
+
+ check("c1.O.f1", c1.O.f1)
+ check("c1.O.fi", c1.O.fi)
+ check("c1.O.fv", c1.O.fv())
+ check("c1.O.ff", c1.O.ff)
+ check("c1.O.fl", c1.O.fl)
+ check("c1.O.fo", c1.O.fo)
+ check("c1.O.fn", c1.O.fn)
+ check("c1.O.g1", c1.O.g1)
+ check("c1.O.gi", c1.O.gi)
+ check("c1.O.gv", c1.O.gv())
+ check("c1.O.gf", c1.O.gf)
+// check("c1.O.gl", c1.O.gl)
+
+ check("O1.f1", O1.f1)
+ check("O1.fi", O1.fi)
+ check("O1.fv", O1.fv())
+ check("O1.ff", O1.ff)
+ check("O1.fl", O1.fl)
+ check("O1.fo", O1.fo)
+ check("O1.g1", O1.g1)
+ check("O1.gi", O1.gi)
+ check("O1.gv", O1.gv())
+ check("O1.gf", O1.gf)
+// check("O1.gl", O1.gl)
+
+ check("O1.c.f1", O1.c.f1)
+ check("O1.c.fi", O1.c.fi)
+ check("O1.c.fv", O1.c.fv())
+ check("O1.c.ff", O1.c.ff)
+ check("O1.c.fl", O1.c.fl)
+ check("O1.c.fo", O1.c.fo)
+ check("O1.c.fn", O1.c.fn)
+ check("O1.c.g1", O1.c.g1)
+ check("O1.c.gi", O1.c.gi)
+ check("O1.c.gv", O1.c.gv())
+ check("O1.c.gf", O1.c.gf)
+// check("O1.c.gl", O1.c.gl)
+
+ check("O1.O.f1", O1.O.f1)
+ check("O1.O.fi", O1.O.fi)
+ check("O1.O.fv", O1.O.fv())
+ check("O1.O.ff", O1.O.ff)
+ check("O1.O.fl", O1.O.fl)
+ check("O1.O.fo", O1.O.fo)
+ check("O1.O.fn", O1.O.fn)
+ check("O1.O.g1", O1.O.g1)
+ check("O1.O.gi", O1.O.gi)
+ check("O1.O.gv", O1.O.gv())
+ check("O1.O.gf", O1.O.gf)
+// check("O1.O.gl", O1.O.gl)
+
+ val c2 = new C2
+ check("c2.f1", c2.f1)
+ check("c2.fi", c2.fi)
+ check("c2.fv", c2.fv())
+ check("c2.ff", c2.ff)
+ check("c2.fl", c2.fl)
+ check("c2.fo", c2.fo)
+ check("c2.g1", c2.g1)
+ check("c2.gi", c2.gi)
+ check("c2.gv", c2.gv())
+ check("c2.gf", c2.gf)
+// check("c2.gl", c2.gl)
+
+ check("c2.c.f1", c2.c.f1)
+ check("c2.c.fi", c2.c.fi)
+ check("c2.c.fv", c2.c.fv())
+ check("c2.c.ff", c2.c.ff)
+ check("c2.c.fl", c2.c.fl)
+ check("c2.c.fo", c2.c.fo)
+ check("c2.c.fn", c2.c.fn)
+ check("c2.c.g1", c2.c.g1)
+ check("c2.c.gi", c2.c.gi)
+ check("c2.c.gv", c2.c.gv())
+ check("c2.c.gf", c2.c.gf)
+// check("c2.c.gl", c2.c.gl)
+
+ check("c2.O.f1", c2.O.f1)
+ check("c2.O.fi", c2.O.fi)
+ check("c2.O.fv", c2.O.fv())
+ check("c2.O.ff", c2.O.ff)
+ check("c2.O.fl", c2.O.fl)
+ check("c2.O.fo", c2.O.fo)
+ check("c2.O.fn", c2.O.fn)
+ check("c2.O.g1", c2.O.g1)
+ check("c2.O.gi", c2.O.gi)
+ check("c2.O.gv", c2.O.gv())
+ check("c2.O.gf", c2.O.gf)
+// check("c2.O.gl", c2.O.gl)
+
+ check("O2.f1", O2.f1)
+ check("O2.fi", O2.fi)
+ check("O2.fv", O2.fv())
+ check("O2.ff", O2.ff)
+ check("O2.fl", O2.fl)
+ check("O2.fo", O2.fo)
+ check("O2.g1", O2.g1)
+ check("O2.gi", O2.gi)
+ check("O2.gv", O2.gv())
+ check("O2.gf", O2.gf)
+// check("O2.gl", O2.gl)
+
+ check("O2.c.f1", O2.c.f1)
+ check("O2.c.fi", O2.c.fi)
+ check("O2.c.fv", O2.c.fv())
+ check("O2.c.ff", O2.c.ff)
+ check("O2.c.fl", O2.c.fl)
+ check("O2.c.fo", O2.c.fo)
+ check("O2.c.fn", O2.c.fn)
+ check("O2.c.g1", O2.c.g1)
+ check("O2.c.gi", O2.c.gi)
+ check("O2.c.gv", O2.c.gv())
+ check("O2.c.gf", O2.c.gf)
+// check("O2.c.gl", O2.c.gl)
+
+ check("O2.O.f1", O2.O.f1)
+ check("O2.O.fi", O2.O.fi)
+ check("O2.O.fv", O2.O.fv())
+ check("O2.O.ff", O2.O.ff)
+ check("O2.O.fl", O2.O.fl)
+ check("O2.O.fo", O2.O.fo)
+ check("O2.O.fn", O2.O.fn)
+ check("O2.O.g1", O2.O.g1)
+ check("O2.O.gi", O2.O.gi)
+ check("O2.O.gv", O2.O.gv())
+ check("O2.O.gf", O2.O.gf)
+// check("O2.O.gl", O2.O.gl)
+} \ No newline at end of file
diff --git a/test/files/run/t5293-map.scala b/test/files/run/t5293-map.scala
new file mode 100644
index 0000000000..9e186894fc
--- /dev/null
+++ b/test/files/run/t5293-map.scala
@@ -0,0 +1,88 @@
+
+
+
+import scala.collection.JavaConverters._
+
+
+
+object Test extends App {
+
+ def bench(label: String)(body: => Unit): Long = {
+ val start = System.nanoTime
+
+ 0.until(10).foreach(_ => body)
+
+ val end = System.nanoTime
+
+ //println("%s: %s ms".format(label, (end - start) / 1000.0 / 1000.0))
+
+ end - start
+ }
+
+ def benchJava(values: java.util.Map[Int, Int]) = {
+ bench("Java Map") {
+ val m = new java.util.HashMap[Int, Int]
+
+ m.putAll(values)
+ }
+ }
+
+ def benchScala(values: Iterable[(Int, Int)]) = {
+ bench("Scala Map") {
+ val m = new scala.collection.mutable.HashMap[Int, Int]
+
+ m ++= values
+ }
+ }
+
+ def benchScalaSorted(values: Iterable[(Int, Int)]) = {
+ bench("Scala Map sorted") {
+ val m = new scala.collection.mutable.HashMap[Int, Int]
+
+ m ++= values.toArray.sorted
+ }
+ }
+
+ def benchScalaPar(values: Iterable[(Int, Int)]) = {
+ bench("Scala ParMap") {
+ val m = new scala.collection.parallel.mutable.ParHashMap[Int, Int] map { x => x }
+
+ m ++= values
+ }
+ }
+
+ val total = 50000
+ val values = (0 until total) zip (0 until total)
+ val map = scala.collection.mutable.HashMap.empty[Int, Int]
+
+ map ++= values
+
+ // warmup
+ for (x <- 0 until 5) {
+ benchJava(map.asJava)
+ benchScala(map)
+ benchScalaPar(map)
+ benchJava(map.asJava)
+ benchScala(map)
+ benchScalaPar(map)
+ }
+
+ val javamap = benchJava(map.asJava)
+ val scalamap = benchScala(map)
+ val scalaparmap = benchScalaPar(map)
+
+ // println(javamap)
+ // println(scalamap)
+ // println(scalaparmap)
+
+ assert(scalamap < (javamap * 4))
+ assert(scalaparmap < (javamap * 4))
+}
+
+
+
+
+
+
+
+
diff --git a/test/files/specialized/SI-5005.check b/test/files/specialized/SI-5005.check
new file mode 100644
index 0000000000..d2a97512ae
--- /dev/null
+++ b/test/files/specialized/SI-5005.check
@@ -0,0 +1,33 @@
+[[syntax trees at end of specialize]]// Scala source: newSource1
+package <empty> {
+ class C2[@specialized(scala.Boolean) U >: Nothing <: Any] extends Object with ScalaObject {
+ def <init>(): C2[U] = {
+ C2.super.<init>();
+ ()
+ };
+ def apply(x: U): U = x;
+ <specialized> def apply$mcZ$sp(x: Boolean): Boolean = C2.this.apply(x.asInstanceOf[U]()).asInstanceOf[Boolean]()
+ };
+ class B extends Object with ScalaObject {
+ def <init>(): B = {
+ B.super.<init>();
+ ()
+ };
+ new C2$mcZ$sp().apply$mcZ$sp(true)
+ };
+ <specialized> class C2$mcZ$sp extends C2[Boolean] {
+ <specialized> def <init>(): C2$mcZ$sp = {
+ C2$mcZ$sp.super.<init>();
+ ()
+ };
+ @inline final override <specialized> def apply(x: Boolean): Boolean = C2$mcZ$sp.this.apply$mcZ$sp(x);
+ @inline final override <specialized> def apply$mcZ$sp(x: Boolean): Boolean = x
+ }
+}
+
+[log inliner] Analyzing C2.apply count 0 with 1 blocks
+[log inliner] C2.apply blocks before inlining: 1 (2) after: 1 (2)
+[log inliner] Analyzing C2.apply$mcZ$sp count 0 with 1 blocks
+[log inliner] C2.apply$mcZ$sp blocks before inlining: 1 (8) after: 1 (8)
+[log inliner] Not inlining into apply because it is marked @inline.
+[log inliner] Not inlining into apply$mcZ$sp because it is marked @inline.
diff --git a/test/files/specialized/SI-5005.scala b/test/files/specialized/SI-5005.scala
new file mode 100644
index 0000000000..cc9d327b08
--- /dev/null
+++ b/test/files/specialized/SI-5005.scala
@@ -0,0 +1,23 @@
+import scala.tools.partest._
+import java.io._
+
+object Test extends DirectTest {
+
+ override def extraSettings: String = "-usejavacp -Xprint:spec -optimize -Ylog:inliner -d " + testOutput.path
+
+ override def code = """
+ class C2[@specialized(Boolean) U]() {
+ @inline final def apply(x: U): U = x
+ }
+
+ class B {
+ (new C2[Boolean]())(true)
+ }
+ """
+
+ override def show(): Unit = {
+ // redirect err to out, for inliner log
+ System.setErr(new PrintStream(System.out));
+ compile()
+ }
+}