Skip to content

Commit 7b94e98

Browse files
committed
Check single threaded access to Contexts, Scopes, Denotation, HashSets
1 parent e13a6d4 commit 7b94e98

File tree

5 files changed

+47
-4
lines changed

5 files changed

+47
-4
lines changed

src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,8 +623,10 @@ object Contexts {
623623

624624
/** Check that we are on the same thread as before */
625625
def checkSingleThreaded() =
626+
synchronized {
626627
if (thread == null) thread = Thread.currentThread()
627628
else assert(thread == Thread.currentThread(), "illegal multithreaded access to ContextBase")
629+
}
628630
}
629631

630632
object Context {

src/dotty/tools/dotc/core/Scopes.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,16 @@ object Scopes {
174174
*/
175175
private var hashTable: Array[ScopeEntry] = null
176176

177+
private var thread: Thread = null
178+
179+
private def checkSingleThreaded = {
180+
this.synchronized {
181+
if (thread == null)
182+
thread = Thread.currentThread()
183+
else assert(thread == Thread.currentThread())
184+
}
185+
}
186+
177187
/** a cache for all elements, to be used by symbol iterator.
178188
*/
179189
private var elemsCache: List[Symbol] = null
@@ -197,6 +207,7 @@ object Scopes {
197207

198208
/** create and enter a scope entry with given name and symbol */
199209
protected def newScopeEntry(name: Name, sym: Symbol)(implicit ctx: Context): ScopeEntry = {
210+
checkSingleThreaded
200211
ensureCapacity(if (hashTable ne null) hashTable.length else MinHash)
201212
val e = new ScopeEntry(name, sym, this)
202213
e.prev = lastEntry
@@ -212,6 +223,7 @@ object Scopes {
212223
newScopeEntry(sym.name, sym)
213224

214225
private def enterInHash(e: ScopeEntry)(implicit ctx: Context): Unit = {
226+
checkSingleThreaded
215227
val idx = e.name.hashCode & (hashTable.length - 1)
216228
e.tail = hashTable(idx)
217229
assert(e.tail != e)
@@ -247,6 +259,7 @@ object Scopes {
247259

248260
private def enterAllInHash(e: ScopeEntry, n: Int = 0)(implicit ctx: Context): Unit = {
249261
if (e ne null) {
262+
checkSingleThreaded
250263
if (n < MaxRecursions) {
251264
enterAllInHash(e.prev, n + 1)
252265
enterInHash(e)
@@ -264,6 +277,7 @@ object Scopes {
264277

265278
/** Remove entry from this scope (which is required to be present) */
266279
final def unlink(e: ScopeEntry)(implicit ctx: Context): Unit = {
280+
checkSingleThreaded
267281
if (lastEntry == e) {
268282
lastEntry = e.prev
269283
} else {
@@ -298,6 +312,7 @@ object Scopes {
298312
* @pre `prev` and `replacement` have the same name.
299313
*/
300314
final def replace(prev: Symbol, replacement: Symbol)(implicit ctx: Context): Unit = {
315+
checkSingleThreaded
301316
require(prev.name == replacement.name)
302317
var e = lookupEntry(prev.name)
303318
while (e ne null) {

src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,8 +1400,18 @@ object SymDenotations {
14001400

14011401
private[this] var myMemberCache: LRUCache[Name, PreDenotation] = null
14021402
private[this] var myMemberCachePeriod: Period = Nowhere
1403+
private var thread: Thread = null
1404+
1405+
private def checkSingleThreaded = {
1406+
this.synchronized {
1407+
if (thread == null)
1408+
thread = Thread.currentThread()
1409+
else assert(thread == Thread.currentThread())
1410+
}
1411+
}
14031412

14041413
private def memberCache(implicit ctx: Context): LRUCache[Name, PreDenotation] = {
1414+
checkSingleThreaded
14051415
if (myMemberCachePeriod != ctx.period) {
14061416
myMemberCache = new LRUCache
14071417
myMemberCachePeriod = ctx.period
@@ -1416,6 +1426,7 @@ object SymDenotations {
14161426
* If this is EmptyScope, the scope is `decls`.
14171427
*/
14181428
def enter(sym: Symbol, scope: Scope = EmptyScope)(implicit ctx: Context): Unit = {
1429+
checkSingleThreaded
14191430
val mscope = scope match {
14201431
case scope: MutableScope =>
14211432
// if enter gets a scope as an argument,

src/dotty/tools/dotc/util/HashSet.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,11 @@ class HashSet[T >: Null <: AnyRef](initialCapacity: Int, loadFactor: Float = 0.2
100100
}
101101

102102
private def checkTread: Unit = {
103-
if (thread == null)
104-
thread = Thread.currentThread()
105-
else assert(thread == Thread.currentThread())
103+
synchronized {
104+
if (thread == null)
105+
thread = Thread.currentThread()
106+
else assert(thread == Thread.currentThread())
107+
}
106108
}
107109

108110
/** Privileged access: Find first entry with given hashcode */

src/dotty/tools/dotc/util/LRUCache.scala

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ class LRUCache[Key >: Null <: AnyRef : ClassTag, Value >: Null: ClassTag] {
5151
lookupNext(last, first, next)
5252
}
5353

54+
private var thread: Thread = null
55+
56+
private def checkSingleThreaded = {
57+
this.synchronized {
58+
if (thread == null)
59+
thread = Thread.currentThread()
60+
else assert(thread == Thread.currentThread())
61+
}
62+
}
63+
5464
/** Enter key/value in cache at position `last`.
5565
* As a side effect, sets `last` to `lastButOne`.
5666
* If `lastButOne` was set by a preceding unsuccessful `lookup`
@@ -59,6 +69,7 @@ class LRUCache[Key >: Null <: AnyRef : ClassTag, Value >: Null: ClassTag] {
5969
* is inserted at a random position in the queue.
6070
*/
6171
def enter(key: Key, value: Value): Unit = {
72+
checkSingleThreaded
6273
keys(last) = key
6374
values(last) = value
6475
last = lastButOne
@@ -67,11 +78,13 @@ class LRUCache[Key >: Null <: AnyRef : ClassTag, Value >: Null: ClassTag] {
6778
/** Invalidate key. The invalidated element becomes
6879
* the last in the queue.
6980
*/
70-
def invalidate(key: Key): Unit =
81+
def invalidate(key: Key): Unit = {
82+
checkSingleThreaded
7183
if (lookup(key) != null) {
7284
keys(first) = null
7385
last = first
7486
}
87+
}
7588

7689
def indices: Iterator[Int] = Iterator.iterate(first)(next.apply)
7790

0 commit comments

Comments
 (0)