From 39ab8822039706b88373954a7e39919938d79f6f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 22 Dec 2012 18:13:35 +0100 Subject: Refactored ClassInfoType content back to Denotation. Created separate ClassInfo type, which combines a prefix with a ClassInfo denotation. That leads to better regularity elsewhere, because now taking the info of a TypeRef will not lose information: If the info is a TypeBounds, the prefix is already taken account in it, and for ClassInfo we now record it explicitly. --- src/dotty/tools/dotc/core/Denotations.scala | 227 +++++++++++++++++++++++++++- 1 file changed, 225 insertions(+), 2 deletions(-) (limited to 'src/dotty/tools/dotc/core/Denotations.scala') diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 8126ad117..a1ad814ba 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -5,9 +5,12 @@ import Periods._, Contexts._, Symbols._, References._, Names._ import Types._, Flags._, Decorators._ import Scopes.Scope import collection.mutable +import collection.immutable.BitSet trait Denotations { self: Context => + /** A set for hash consing superclass bitsets */ + private val uniqueBits = new util.HashSet[BitSet]("superbits", 1024) } @@ -100,6 +103,228 @@ object Denotations { def newNameFilter: FingerPrint = new Array[Long](DefinedNamesWords) } + class ClassDenotation(val parents: List[Type], val decls: Scope, val clazz: ClassSymbol) extends Denotation { + import NameFilter._ + import util.LRU8Cache + + def typeParams: List[TypeSymbol] = ??? + + private var memberCacheVar: LRU8Cache[Name, RefSet] = null + + private def memberCache: LRU8Cache[Name, RefSet] = { + if (memberCacheVar == null) memberCacheVar = new LRU8Cache + memberCacheVar + } + + private var thisTypeCache: ThisType = null + + def thisType(implicit ctx: Context): Type = { + if (thisTypeCache == null) + thisTypeCache = ThisType(clazz) + thisTypeCache + } + + private var typeConstructorCache: Type = null + + def typeConstructor(implicit ctx: Context): Type = { + if (typeConstructorCache == null) + typeConstructorCache = NamedType(thisType, clazz.name) + typeConstructorCache + } + + private var typeTemplateCache: Type = null + + def typeTemplate(implicit ctx: Context): Type = { + if (typeTemplateCache == null) + AppliedType.make(typeConstructor, typeParams map (_.typeConstructor)) + typeTemplateCache + } + + private var baseClassesVar: List[ClassSymbol] = null + private var superClassBitsVar: BitSet = null + + private def computeSuperClassBits(implicit ctx: Context): Unit = { + val seen = new mutable.BitSet + val locked = new mutable.BitSet + def addBaseClasses(bcs: List[ClassSymbol], to: List[ClassSymbol]) + : List[ClassSymbol] = bcs match { + case bc :: bcs1 => + val id = bc.superId + if (seen contains id) to + else if (locked contains id) throw new CyclicReference(clazz) + else { + locked += id + val bcs1added = addBaseClasses(bcs1, to) + seen += id + if (bcs1added eq bcs1) bcs else bc :: bcs1added + } + case _ => + to + } + def addParentBaseClasses(ps: List[Type], to: List[ClassSymbol]): List[ClassSymbol] = ps match { + case p :: ps1 => + addBaseClasses(p.baseClasses, addParentBaseClasses(ps1, to)) + case _ => + to + } + baseClassesVar = clazz :: addParentBaseClasses(parents, Nil) + superClassBitsVar = ctx.root.uniqueBits.findEntryOrUpdate(seen.toImmutable) + } + + def superClassBits(implicit ctx: Context): BitSet = { + if (superClassBitsVar == null) computeSuperClassBits + superClassBitsVar + } + + def baseClasses(implicit ctx: Context): List[ClassSymbol] = { + if (baseClassesVar == null) computeSuperClassBits + baseClassesVar + } + + /** Is this class a subclass of `clazz`? */ + final def isSubClass(clazz: ClassSymbol)(implicit ctx: Context): Boolean = { + superClassBits contains clazz.superId + } + + private var definedFingerPrintCache: FingerPrint = null + + private def computeDefinedFingerPrint(implicit ctx: Context): FingerPrint = { + var bits = newNameFilter + var e = decls.lastEntry + while (e != null) { + includeName(bits, clazz.name) + e = e.prev + } + var ps = parents + while (ps.nonEmpty) { + val parent = ps.head.typeSymbol + parent.deref match { + case classd: ClassDenotation => + includeFingerPrint(bits, classd.definedFingerPrint) + parent.deref setFlag Frozen + case _ => + } + ps = ps.tail + } + definedFingerPrintCache = bits + bits + } + + /** Enter a symbol in current scope. + * Note: We require that this does not happen after the first time + * someone does a findMember on a subclass. + */ + def enter(sym: Symbol)(implicit ctx: Context) = { + require((clazz.flags & Frozen) == Flags.Empty) + decls enter sym + if (definedFingerPrintCache != null) + includeName(definedFingerPrintCache, sym.name) + if (memberCacheVar != null) + memberCache invalidate sym.name + } + + /** Delete symbol from current scope. + * Note: We require that this does not happen after the first time + * someone does a findMember on a subclass. + */ + def delete(sym: Symbol)(implicit ctx: Context) = { + require((clazz.flags & Frozen) == Flags.Empty) + decls unlink sym + if (definedFingerPrintCache != null) + computeDefinedFingerPrint + if (memberCacheVar != null) + memberCache invalidate sym.name + } + + def definedFingerPrint(implicit ctx: Context): FingerPrint = { + val fp = definedFingerPrintCache + if (fp != null) fp else computeDefinedFingerPrint + } + + final def memberRefsNamed(name: Name)(implicit ctx: Context): RefSet = { + var refs: RefSet = memberCache lookup name + if (refs == null) { + if (containsName(definedFingerPrint, name)) { + val ownRefs = decls.refsNamed(name) + refs = ownRefs + var ps = parents + while (ps.nonEmpty) { + val parentSym = ps.head.typeSymbol + parentSym.deref match { + case parentd: ClassDenotation => + refs = refs union + parentd.memberRefsNamed(name) + .filterExcluded(Flags.Private) + .asSeenFrom(thisType, parentSym) + .filterDisjoint(ownRefs) + case _ => + } + } + } else { + refs = NoRef + } + memberCache enter (name, refs) + } + refs + } + + private var baseTypeCache: java.util.HashMap[UniqueType, Type] = null + + final def baseTypeOf(tp: Type)(implicit ctx: Context): Type = { + + def computeBaseTypeOf(tp: Type): Type = tp match { + case AppliedType(tycon, args) => + baseTypeOf(tycon).subst(tycon.typeParams, args) + case tp: TypeProxy => + baseTypeOf(tp.underlying) + case AndType(tp1, tp2) => + baseTypeOf(tp1) & baseTypeOf(tp2) + case OrType(tp1, tp2) => + baseTypeOf(tp1) | baseTypeOf(tp2) + case tp @ ClassInfo(pre, classd) => + def reduce(bt: Type, ps: List[Type]): Type = ps match { + case p :: ps1 => reduce(bt & baseTypeOf(p), ps1) + case _ => bt + } + if (classd.clazz == clazz) tp.typeTemplate + else reduce(NoType, classd.parents).substThis(classd.clazz, tp.prefix) + } + + if (clazz.isStatic && clazz.typeParams.isEmpty) clazz.typeConstructor + else tp match { + case tp: UniqueType => + if (baseTypeCache == null) + baseTypeCache = new java.util.HashMap[UniqueType, Type] + var basetp = baseTypeCache get tp + if (basetp == null) { + baseTypeCache.put(tp, NoType) + basetp = computeBaseTypeOf(tp) + baseTypeCache.put(tp, basetp) + } else if (basetp == NoType) { + throw new CyclicReference(clazz) + } + basetp + case _ => + computeBaseTypeOf(tp) + } + } + + private var memberNamesCache: Map[NameFilter, Set[Name]] = Map() + + def memberNames(pre: Type, filter: NameFilter)(implicit ctx: Context): Set[Name] = + memberNamesCache get filter match { + case Some(names) => + names + case _ => + val inheritedNames = (parents flatMap (_.memberNames(thisType, filter))).toSet + val ownNames = decls.iterator map (_.name) + val candidates = inheritedNames ++ ownNames + val names = candidates filter (filter(thisType, _)) + memberNamesCache += (filter -> names) + names + } + } + object NoDenotation extends Denotation { override def owner: Symbol = throw new AssertionError("NoDenotation.owner") override def name: Name = BootNameTable.newTermName("") @@ -107,6 +332,4 @@ object Denotations { override def tpe: Type = NoType override def info: Type = NoType } - - } \ No newline at end of file -- cgit v1.2.3