11package scala .reflect
22package internal
3+
34import scala .collection .mutable .WeakHashMap
5+ import scala .ref .WeakReference
46
57// SI-6241: move importers to a mirror
68trait Importers extends api.Importers { self : SymbolTable =>
@@ -26,8 +28,20 @@ trait Importers extends api.Importers { self: SymbolTable =>
2628
2729 val from : SymbolTable
2830
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+ def weakGetOrElseUpdate (key : K )(value : => V ): V =
37+ weakGet(key) match {
38+ case Some (result) => result
39+ case None =>
40+ val result = value
41+ this (key) = WeakReference (result)
42+ result
43+ }
44+ }
3145
3246 // fixups and maps prevent stackoverflows in importer
3347 var pendingSyms = 0
@@ -44,79 +58,81 @@ trait Importers extends api.Importers { self: SymbolTable =>
4458
4559 object reverse extends from.StandardImporter {
4660 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))
61+ // FIXME this and reverse should be constantly kept in sync
62+ // not just synced once upon the first usage of reverse
63+ for ((fromsym, WeakReference (mysym)) <- StandardImporter .this .symMap) symMap += ((mysym, WeakReference (fromsym)))
64+ for ((fromtpe, WeakReference (mytpe)) <- StandardImporter .this .tpeMap) tpeMap += ((mytpe, WeakReference (fromtpe)))
4965 }
5066
5167 // todo. careful import of positions
5268 def importPosition (pos : from.Position ): Position =
5369 pos.asInstanceOf [Position ]
5470
5571 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)
72+ def doImport (sym : from.Symbol ): Symbol =
73+ symMap weakGet sym match {
74+ case Some (result) => result
75+ case _ =>
76+ val myowner = importSymbol(sym.owner)
77+ val mypos = importPosition(sym.pos)
78+ val myname = importName(sym.name).toTermName
79+ val myflags = sym.flags
80+ def linkReferenced (mysym : TermSymbol , x : from.TermSymbol , op : from.Symbol => Symbol ): Symbol = {
81+ symMap.weakUpdate(x, mysym)
82+ mysym.referenced = op(x.referenced)
83+ mysym
8584 }
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)
85+ val mysym = sym match {
86+ case x : from.MethodSymbol =>
87+ linkReferenced(myowner.newMethod(myname, mypos, myflags), x, importSymbol)
88+ case x : from.ModuleSymbol =>
89+ linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, importSymbol)
90+ case x : from.FreeTermSymbol =>
91+ newFreeTermSymbol(importName(x.name).toTermName, x.value, x.flags, x.origin) setInfo importType(x.info)
92+ case x : from.FreeTypeSymbol =>
93+ newFreeTypeSymbol(importName(x.name).toTypeName, x.flags, x.origin)
94+ case x : from.TermSymbol =>
95+ linkReferenced(myowner.newValue(myname, mypos, myflags), x, importSymbol)
96+ case x : from.TypeSkolem =>
97+ val origin = x.unpackLocation match {
98+ case null => null
99+ case y : from.Tree => importTree(y)
100+ case y : from.Symbol => importSymbol(y)
101+ }
102+ myowner.newTypeSkolemSymbol(myname.toTypeName, origin, mypos, myflags)
103+ case x : from.ModuleClassSymbol =>
104+ val mysym = myowner.newModuleClass(myname.toTypeName, mypos, myflags)
105+ symMap.weakUpdate(x, mysym)
106+ mysym.sourceModule = importSymbol(x.sourceModule)
107+ mysym
108+ case x : from.ClassSymbol =>
109+ val mysym = myowner.newClassSymbol(myname.toTypeName, mypos, myflags)
110+ symMap.weakUpdate(x, mysym)
111+ if (sym.thisSym != sym) {
112+ mysym.typeOfThis = importType(sym.typeOfThis)
113+ mysym.thisSym setName importName(sym.thisSym.name)
114+ }
115+ mysym
116+ case x : from.TypeSymbol =>
117+ myowner.newTypeSymbol(myname.toTypeName, mypos, myflags)
98118 }
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) {
108- override def complete ( s : Symbol ) {
109- val result = sym.info match {
110- case from. PolyType (_, res) => res
111- case result => result
119+ symMap.weakUpdate(sym, mysym)
120+ mysym setFlag Flags . LOCKED
121+ mysym setInfo {
122+ val mytypeParams = sym.typeParams map importSymbol
123+ new LazyPolyType (mytypeParams) {
124+ override def complete ( s : Symbol ) {
125+ val result = sym.info match {
126+ case from. PolyType (_, res) => res
127+ case result => result
128+ }
129+ s setInfo GenPolyType (mytypeParams, importType(result))
130+ s setAnnotations (sym.annotations map importAnnotationInfo)
131+ }
112132 }
113- s setInfo GenPolyType (mytypeParams, importType(result))
114- s setAnnotations (sym.annotations map importAnnotationInfo)
115133 }
116- }
117- }
118- mysym resetFlag Flags .LOCKED
119- } // end doImport
134+ mysym resetFlag Flags .LOCKED
135+ } // end doImport
120136
121137 def importOrRelink : Symbol = {
122138 val sym = sym0 // makes sym visible in the debugger
@@ -186,14 +202,10 @@ trait Importers extends api.Importers { self: SymbolTable =>
186202 } // end importOrRelink
187203
188204 val sym = sym0
189- if (symMap contains sym) {
190- symMap(sym)
191- } else {
205+ symMap.weakGetOrElseUpdate(sym) {
192206 pendingSyms += 1
193-
194- try {
195- symMap getOrElseUpdate (sym, importOrRelink)
196- } finally {
207+ try importOrRelink
208+ finally {
197209 pendingSyms -= 1
198210 tryFixup()
199211 }
@@ -258,14 +270,10 @@ trait Importers extends api.Importers { self: SymbolTable =>
258270 def importOrRelink : Type =
259271 doImport(tpe)
260272
261- if (tpeMap contains tpe) {
262- tpeMap(tpe)
263- } else {
273+ tpeMap.weakGetOrElseUpdate(tpe) {
264274 pendingTpes += 1
265-
266- try {
267- tpeMap getOrElseUpdate (tpe, importOrRelink)
268- } finally {
275+ try importOrRelink
276+ finally {
269277 pendingTpes -= 1
270278 tryFixup()
271279 }
0 commit comments