1
1
package scala .reflect
2
2
package internal
3
+
3
4
import scala .collection .mutable .WeakHashMap
5
+ import scala .ref .WeakReference
4
6
5
7
// SI-6241: move importers to a mirror
6
8
trait Importers extends api.Importers { self : SymbolTable =>
@@ -26,8 +28,12 @@ trait Importers extends api.Importers { self: SymbolTable =>
26
28
27
29
val from : SymbolTable
28
30
29
- lazy val symMap : WeakHashMap [from.Symbol , Symbol ] = new WeakHashMap
30
- lazy val tpeMap : WeakHashMap [from.Type , Type ] = new WeakHashMap
31
+ protected lazy val symMap = new Cache [from.Symbol , Symbol ]()
32
+ protected lazy val tpeMap = new Cache [from.Type , Type ]()
33
+ protected class Cache [K <: AnyRef , V <: AnyRef ] extends WeakHashMap [K , WeakReference [V ]] {
34
+ def weakGet (key : K ): Option [V ] = this get key flatMap WeakReference .unapply
35
+ def weakUpdate (key : K , value : V ) = this .update(key, WeakReference (value))
36
+ }
31
37
32
38
// fixups and maps prevent stackoverflows in importer
33
39
var pendingSyms = 0
@@ -44,79 +50,81 @@ trait Importers extends api.Importers { self: SymbolTable =>
44
50
45
51
object reverse extends from.StandardImporter {
46
52
val from : self.type = self
47
- for ((fromsym, mysym) <- StandardImporter .this .symMap) symMap += ((mysym, fromsym))
48
- for ((fromtpe, mytpe) <- StandardImporter .this .tpeMap) tpeMap += ((mytpe, fromtpe))
53
+ // FIXME this and reverse should be constantly kept in sync
54
+ // not just synced once upon the first usage of reverse
55
+ for ((fromsym, WeakReference (mysym)) <- StandardImporter .this .symMap) symMap += ((mysym, WeakReference (fromsym)))
56
+ for ((fromtpe, WeakReference (mytpe)) <- StandardImporter .this .tpeMap) tpeMap += ((mytpe, WeakReference (fromtpe)))
49
57
}
50
58
51
59
// todo. careful import of positions
52
60
def importPosition (pos : from.Position ): Position =
53
61
pos.asInstanceOf [Position ]
54
62
55
63
def importSymbol (sym0 : from.Symbol ): Symbol = {
56
- def doImport (sym : from.Symbol ): Symbol = {
57
- if (symMap.contains(sym))
58
- return symMap(sym)
59
-
60
- val myowner = importSymbol(sym.owner)
61
- val mypos = importPosition(sym.pos)
62
- val myname = importName(sym.name).toTermName
63
- val myflags = sym.flags
64
- def linkReferenced (mysym : TermSymbol , x : from.TermSymbol , op : from.Symbol => Symbol ): Symbol = {
65
- symMap(x) = mysym
66
- mysym.referenced = op(x.referenced)
67
- mysym
68
- }
69
- val mysym = sym match {
70
- case x : from.MethodSymbol =>
71
- linkReferenced(myowner.newMethod(myname, mypos, myflags), x, importSymbol)
72
- case x : from.ModuleSymbol =>
73
- linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, importSymbol)
74
- case x : from.FreeTermSymbol =>
75
- newFreeTermSymbol(importName(x.name).toTermName, x.value, x.flags, x.origin) setInfo importType(x.info)
76
- case x : from.FreeTypeSymbol =>
77
- newFreeTypeSymbol(importName(x.name).toTypeName, x.flags, x.origin)
78
- case x : from.TermSymbol =>
79
- linkReferenced(myowner.newValue(myname, mypos, myflags), x, importSymbol)
80
- case x : from.TypeSkolem =>
81
- val origin = x.unpackLocation match {
82
- case null => null
83
- case y : from.Tree => importTree(y)
84
- case y : from.Symbol => importSymbol(y)
64
+ def doImport (sym : from.Symbol ): Symbol =
65
+ symMap weakGet sym match {
66
+ case Some (result) => result
67
+ case _ =>
68
+ val myowner = importSymbol(sym.owner)
69
+ val mypos = importPosition(sym.pos)
70
+ val myname = importName(sym.name).toTermName
71
+ val myflags = sym.flags
72
+ def linkReferenced (mysym : TermSymbol , x : from.TermSymbol , op : from.Symbol => Symbol ): Symbol = {
73
+ symMap.weakUpdate(x, mysym)
74
+ mysym.referenced = op(x.referenced)
75
+ mysym
85
76
}
86
- myowner.newTypeSkolemSymbol(myname.toTypeName, origin, mypos, myflags)
87
- case x : from.ModuleClassSymbol =>
88
- val mysym = myowner.newModuleClass(myname.toTypeName, mypos, myflags)
89
- symMap(x) = mysym
90
- mysym.sourceModule = importSymbol(x.sourceModule)
91
- mysym
92
- case x : from.ClassSymbol =>
93
- val mysym = myowner.newClassSymbol(myname.toTypeName, mypos, myflags)
94
- symMap(x) = mysym
95
- if (sym.thisSym != sym) {
96
- mysym.typeOfThis = importType(sym.typeOfThis)
97
- mysym.thisSym setName importName(sym.thisSym.name)
77
+ val mysym = sym match {
78
+ case x : from.MethodSymbol =>
79
+ linkReferenced(myowner.newMethod(myname, mypos, myflags), x, importSymbol)
80
+ case x : from.ModuleSymbol =>
81
+ linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, importSymbol)
82
+ case x : from.FreeTermSymbol =>
83
+ newFreeTermSymbol(importName(x.name).toTermName, x.value, x.flags, x.origin) setInfo importType(x.info)
84
+ case x : from.FreeTypeSymbol =>
85
+ newFreeTypeSymbol(importName(x.name).toTypeName, x.flags, x.origin)
86
+ case x : from.TermSymbol =>
87
+ linkReferenced(myowner.newValue(myname, mypos, myflags), x, importSymbol)
88
+ case x : from.TypeSkolem =>
89
+ val origin = x.unpackLocation match {
90
+ case null => null
91
+ case y : from.Tree => importTree(y)
92
+ case y : from.Symbol => importSymbol(y)
93
+ }
94
+ myowner.newTypeSkolemSymbol(myname.toTypeName, origin, mypos, myflags)
95
+ case x : from.ModuleClassSymbol =>
96
+ val mysym = myowner.newModuleClass(myname.toTypeName, mypos, myflags)
97
+ symMap.weakUpdate(x, mysym)
98
+ mysym.sourceModule = importSymbol(x.sourceModule)
99
+ mysym
100
+ case x : from.ClassSymbol =>
101
+ val mysym = myowner.newClassSymbol(myname.toTypeName, mypos, myflags)
102
+ symMap.weakUpdate(x, mysym)
103
+ if (sym.thisSym != sym) {
104
+ mysym.typeOfThis = importType(sym.typeOfThis)
105
+ mysym.thisSym setName importName(sym.thisSym.name)
106
+ }
107
+ mysym
108
+ case x : from.TypeSymbol =>
109
+ myowner.newTypeSymbol(myname.toTypeName, mypos, myflags)
98
110
}
99
- mysym
100
- case x : from. TypeSymbol =>
101
- myowner.newTypeSymbol(myname.toTypeName, mypos, myflags)
102
- }
103
- symMap(sym) = mysym
104
- mysym setFlag Flags . LOCKED
105
- mysym setInfo {
106
- val mytypeParams = sym.typeParams map importSymbol
107
- new LazyPolyType (mytypeParams) with FlagAgnosticCompleter {
108
- override def complete ( s : Symbol ) {
109
- val result = sym.info match {
110
- case from. PolyType (_, res) => res
111
- case result => result
111
+ symMap.weakUpdate(sym, mysym)
112
+ mysym setFlag Flags . LOCKED
113
+ mysym setInfo {
114
+ val mytypeParams = sym.typeParams map importSymbol
115
+ new LazyPolyType (mytypeParams) with FlagAgnosticCompleter {
116
+ override def complete ( s : Symbol ) {
117
+ val result = sym.info match {
118
+ case from. PolyType (_, res) => res
119
+ case result => result
120
+ }
121
+ s setInfo GenPolyType (mytypeParams, importType(result))
122
+ s setAnnotations (sym.annotations map importAnnotationInfo)
123
+ }
112
124
}
113
- s setInfo GenPolyType (mytypeParams, importType(result))
114
- s setAnnotations (sym.annotations map importAnnotationInfo)
115
125
}
116
- }
117
- }
118
- mysym resetFlag Flags .LOCKED
119
- } // end doImport
126
+ mysym resetFlag Flags .LOCKED
127
+ } // end doImport
120
128
121
129
def importOrRelink : Symbol = {
122
130
val sym = sym0 // makes sym visible in the debugger
@@ -186,17 +194,18 @@ trait Importers extends api.Importers { self: SymbolTable =>
186
194
} // end importOrRelink
187
195
188
196
val sym = sym0
189
- if (symMap contains sym) {
190
- symMap(sym)
191
- } else {
192
- pendingSyms += 1
193
-
194
- try {
195
- symMap getOrElseUpdate (sym, importOrRelink)
196
- } finally {
197
- pendingSyms -= 1
198
- tryFixup()
199
- }
197
+ symMap.weakGet(sym) match {
198
+ case Some (result) => result
199
+ case None =>
200
+ pendingSyms += 1
201
+ try {
202
+ val result = importOrRelink
203
+ symMap.weakUpdate(sym, result)
204
+ result
205
+ } finally {
206
+ pendingSyms -= 1
207
+ tryFixup()
208
+ }
200
209
}
201
210
}
202
211
@@ -258,17 +267,18 @@ trait Importers extends api.Importers { self: SymbolTable =>
258
267
def importOrRelink : Type =
259
268
doImport(tpe)
260
269
261
- if (tpeMap contains tpe) {
262
- tpeMap(tpe)
263
- } else {
264
- pendingTpes += 1
265
-
266
- try {
267
- tpeMap getOrElseUpdate (tpe, importOrRelink)
268
- } finally {
269
- pendingTpes -= 1
270
- tryFixup()
271
- }
270
+ tpeMap.weakGet(tpe) match {
271
+ case Some (result) => result
272
+ case None =>
273
+ pendingTpes += 1
274
+ try {
275
+ val result = importOrRelink
276
+ tpeMap.weakUpdate(tpe, result)
277
+ result
278
+ } finally {
279
+ pendingTpes -= 1
280
+ tryFixup()
281
+ }
272
282
}
273
283
}
274
284
0 commit comments