From 8a61ff432543a29234193cd1f7c14abd3f3d31a0 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Wed, 2 Nov 2016 11:08:28 +0100 Subject: Move compiler and compiler tests to compiler dir --- compiler/src/dotty/tools/dotc/core/Uniques.scala | 128 +++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 compiler/src/dotty/tools/dotc/core/Uniques.scala (limited to 'compiler/src/dotty/tools/dotc/core/Uniques.scala') diff --git a/compiler/src/dotty/tools/dotc/core/Uniques.scala b/compiler/src/dotty/tools/dotc/core/Uniques.scala new file mode 100644 index 000000000..cb9670c69 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/core/Uniques.scala @@ -0,0 +1,128 @@ +package dotty.tools.dotc +package core + +import Types._, Contexts._, util.Stats._, Hashable._, Names._ +import config.Config +import util.HashSet + +/** Defines operation `unique` for hash-consing types. + * Also defines specialized hash sets for hash consing uniques of a specific type. + * All sets offer a `enterIfNew` method which checks whether a type + * with the given parts exists already and creates a new one if not. + */ +object Uniques { + + private def recordCaching(tp: Type): Unit = recordCaching(tp.hash, tp.getClass) + private def recordCaching(h: Int, clazz: Class[_]): Unit = + if (h == NotCached) { + record("uncached-types") + record(s"uncached: $clazz") + } else { + record("cached-types") + record(s"cached: $clazz") + } + + def unique[T <: Type](tp: T)(implicit ctx: Context): T = { + if (monitored) recordCaching(tp) + if (tp.hash == NotCached) tp + else if (monitored) { + val size = ctx.uniques.size + val result = ctx.uniques.findEntryOrUpdate(tp).asInstanceOf[T] + if (ctx.uniques.size > size) record(s"fresh unique ${tp.getClass}") + result + } else ctx.uniques.findEntryOrUpdate(tp).asInstanceOf[T] + } /* !!! DEBUG + ensuring ( + result => tp.toString == result.toString || { + println(s"cache mismatch; tp = $tp, cached = $result") + false + } + ) + */ + + final class NamedTypeUniques extends HashSet[NamedType](Config.initialUniquesCapacity) with Hashable { + override def hash(x: NamedType): Int = x.hash + + private def findPrevious(h: Int, prefix: Type, name: Name): NamedType = { + var e = findEntryByHash(h) + while (e != null) { + if ((e.prefix eq prefix) && (e.name eq name)) return e + e = nextEntryByHash(h) + } + e + } + + def enterIfNew(prefix: Type, name: Name): NamedType = { + val h = doHash(name, prefix) + if (monitored) recordCaching(h, classOf[CachedTermRef]) + def newType = + if (name.isTypeName) new CachedTypeRef(prefix, name.asTypeName, h) + else new CachedTermRef(prefix, name.asTermName, h) + if (h == NotCached) newType + else { + val r = findPrevious(h, prefix, name) + if (r ne null) r else addEntryAfterScan(newType) + } + } + } + + final class TypeAliasUniques extends HashSet[TypeAlias](Config.initialUniquesCapacity) with Hashable { + override def hash(x: TypeAlias): Int = x.hash + + private def findPrevious(h: Int, alias: Type, variance: Int): TypeAlias = { + var e = findEntryByHash(h) + while (e != null) { + if ((e.alias eq alias) && (e.variance == variance)) return e + e = nextEntryByHash(h) + } + e + } + + def enterIfNew(alias: Type, variance: Int): TypeAlias = { + val h = doHash(variance, alias) + if (monitored) recordCaching(h, classOf[TypeAlias]) + def newAlias = new CachedTypeAlias(alias, variance, h) + if (h == NotCached) newAlias + else { + val r = findPrevious(h, alias, variance) + if (r ne null) r + else addEntryAfterScan(newAlias) + } + } + } + + final class RefinedUniques extends HashSet[RefinedType](Config.initialUniquesCapacity) with Hashable { + override val hashSeed = classOf[CachedRefinedType].hashCode // some types start life as CachedRefinedTypes, need to have same hash seed + override def hash(x: RefinedType): Int = x.hash + + private def findPrevious(h: Int, parent: Type, refinedName: Name, refinedInfo: Type): RefinedType = { + var e = findEntryByHash(h) + while (e != null) { + if ((e.parent eq parent) && (e.refinedName eq refinedName) && (e.refinedInfo eq refinedInfo)) + return e + e = nextEntryByHash(h) + } + e + } + + def enterIfNew(parent: Type, refinedName: Name, refinedInfo: Type): RefinedType = { + val h = doHash(refinedName, refinedInfo, parent) + def newType = new CachedRefinedType(parent, refinedName, refinedInfo, h) + if (monitored) recordCaching(h, classOf[CachedRefinedType]) + if (h == NotCached) newType + else { + val r = findPrevious(h, parent, refinedName, refinedInfo) + if (r ne null) r else addEntryAfterScan(newType) + } + } + + def enterIfNew(rt: RefinedType) = { + if (monitored) recordCaching(rt) + if (rt.hash == NotCached) rt + else { + val r = findPrevious(rt.hash, rt.parent, rt.refinedName, rt.refinedInfo) + if (r ne null) r else addEntryAfterScan(rt) + } + } + } +} -- cgit v1.2.3