diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-03-01 11:43:01 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-03-01 11:43:01 -0800 |
commit | 5d54cf9e375d796c59b1dd488c15f88f4bfb14d6 (patch) | |
tree | f4581d9fd1878d5b25e17a1bee00296b6c51111a /src/reflect | |
parent | 5834c97a228ecfcabe4044e2bb632b5e7c0ce4f4 (diff) | |
parent | 0420b2d056f6a69f5d944482ba83d4fbee72cfab (diff) | |
download | scala-5d54cf9e375d796c59b1dd488c15f88f4bfb14d6.tar.gz scala-5d54cf9e375d796c59b1dd488c15f88f4bfb14d6.tar.bz2 scala-5d54cf9e375d796c59b1dd488c15f88f4bfb14d6.zip |
Merge pull request #2184 from adriaanm/revert-pr-2083
Revert SI-6240 synchronization for runtime reflection
Diffstat (limited to 'src/reflect')
19 files changed, 308 insertions, 1439 deletions
diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala index 768ebb055b..3c2b128c52 100644 --- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala +++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala @@ -37,7 +37,7 @@ trait BaseTypeSeqs { * This is necessary because when run from reflection every base type sequence needs to have a * SynchronizedBaseTypeSeq as mixin. */ - class BaseTypeSeq protected[reflect] (private[BaseTypeSeqs] val parents: List[Type], private[BaseTypeSeqs] val elems: Array[Type]) { + class BaseTypeSeq protected[BaseTypeSeqs] (private[BaseTypeSeqs] val parents: List[Type], private[BaseTypeSeqs] val elems: Array[Type]) { self => if (Statistics.canEnable) Statistics.incCounter(baseTypeSeqCount) if (Statistics.canEnable) Statistics.incCounter(baseTypeSeqLenTotal, elems.length) diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 7a3bdff1f8..6e4ca76382 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -1189,7 +1189,7 @@ trait Definitions extends api.StandardDefinitions { /** Is the symbol that of a parent which is added during parsing? */ lazy val isPossibleSyntheticParent = ProductClass.toSet[Symbol] + ProductRootClass + SerializableClass - lazy val boxedValueClassesSet = boxedClass.values.toSet[Symbol] + BoxedUnitClass + private lazy val boxedValueClassesSet = boxedClass.values.toSet[Symbol] + BoxedUnitClass /** Is symbol a value class? */ def isPrimitiveValueClass(sym: Symbol) = ScalaValueClasses contains sym @@ -1248,24 +1248,8 @@ trait Definitions extends api.StandardDefinitions { def init() { if (isInitialized) return - // forcing ScalaPackageClass first thing during startup is important, because syntheticCoreClasses such as AnyRefClass - // need to be entered into ScalaPackageClass, which entails calling ScalaPackageClass.info.decls.enter - // if ScalaPackageClass isn't initialized by that moment, the following will happen for runtime reflection: - // 1) initialization of ScalaPackageClass will trigger unpickling - // 2) unpickling will need to load some auxiliary types such as, for example, String - // 3) to load String, runtime reflection will call mirrorDefining(classOf[String]) - // 4) this, in turn, will call runtimeMirror(classOf[String].getClassLoader) - // 5) for some classloader configurations, the resulting mirror will be different from rootMirror - // 6) in that case, initialization of the resulting mirror will try to import definitions.syntheticCoreClasses into the mirror - // 7) this will force all the lazy vals corresponding to syntheticCoreClasses - // 8) by that time, the completer of ScalaPackageClass will have already called setInfo on ScalaPackageClass, so there won't be any stack overflow - // so far so good, but there's a subtle detail. if forcing of ScalaPackageClass was called by a syntheticCoreClasses lazy val, - // then this lazy val will be entered twice: once during step 7 and once when returning from the original call - // to avoid this we need to initialize ScalaPackageClass first and only then synthesize the core classes - ScalaPackageClass.initialize // force initialization of every symbol that is synthesized or hijacked by the compiler - val forced1 = symbolsNotPresentInBytecode - val forced2 = NoSymbol + val forced = symbolsNotPresentInBytecode isInitialized = true } //init diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala index 80c05666af..0beb8e368f 100644 --- a/src/reflect/scala/reflect/internal/Mirrors.scala +++ b/src/reflect/scala/reflect/internal/Mirrors.scala @@ -239,19 +239,6 @@ trait Mirrors extends api.Mirrors { RootClass.info.decls enter EmptyPackage RootClass.info.decls enter RootPackage - - if (rootOwner != NoSymbol) { - // synthetic core classes are only present in root mirrors - // because Definitions.scala, which initializes and enters them, only affects rootMirror - // therefore we need to enter them manually for non-root mirrors - definitions.syntheticCoreClasses foreach (theirSym => { - val theirOwner = theirSym.owner - assert(theirOwner.isPackageClass, s"theirSym = $theirSym, theirOwner = $theirOwner") - val ourOwner = staticPackage(theirOwner.fullName) - val ourSym = theirSym // just copy the symbol into our branch of the symbol table - ourOwner.info.decls enter ourSym - }) - } } } @@ -275,45 +262,34 @@ trait Mirrors extends api.Mirrors { def mirror = thisMirror.asInstanceOf[Mirror] } - class RootPackage extends ModuleSymbol(rootOwner, NoPosition, nme.ROOTPKG) with RootSymbol { + // This is the package _root_. The actual root cannot be referenced at + // the source level, but _root_ is essentially a function => <root>. + final object RootPackage extends ModuleSymbol(rootOwner, NoPosition, nme.ROOTPKG) with RootSymbol { this setInfo NullaryMethodType(RootClass.tpe) RootClass.sourceModule = this override def isRootPackage = true } - - // This is the package _root_. The actual root cannot be referenced at - // the source level, but _root_ is essentially a function => <root>. - lazy val RootPackage = new RootPackage - - class RootClass extends PackageClassSymbol(rootOwner, NoPosition, tpnme.ROOT) with RootSymbol { - this setInfo rootLoader - - override def isRoot = true - override def isEffectiveRoot = true - override def isNestedClass = false - } - // This is <root>, the actual root of everything except the package _root_. // <root> and _root_ (RootPackage and RootClass) should be the only "well known" // symbols owned by NoSymbol. All owner chains should go through RootClass, // although it is probable that some symbols are created as direct children // of NoSymbol to ensure they will not be stumbled upon. (We should designate // a better encapsulated place for that.) - lazy val RootClass = new RootClass + final object RootClass extends PackageClassSymbol(rootOwner, NoPosition, tpnme.ROOT) with RootSymbol { + this setInfo rootLoader - class EmptyPackage extends ModuleSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { - override def isEmptyPackage = true + override def isRoot = true + override def isEffectiveRoot = true + override def isNestedClass = false } - // The empty package, which holds all top level types without given packages. - lazy val EmptyPackage = new EmptyPackage - - class EmptyPackageClass extends PackageClassSymbol(RootClass, NoPosition, tpnme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { + final object EmptyPackage extends ModuleSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { + override def isEmptyPackage = true + } + final object EmptyPackageClass extends PackageClassSymbol(RootClass, NoPosition, tpnme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { override def isEffectiveRoot = true override def isEmptyPackageClass = true } - - lazy val EmptyPackageClass = new EmptyPackageClass } } diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala index 01ad18d3a0..c78ba72dfb 100644 --- a/src/reflect/scala/reflect/internal/Names.scala +++ b/src/reflect/scala/reflect/internal/Names.scala @@ -21,7 +21,7 @@ trait LowPriorityNames { * @author Martin Odersky * @version 1.0, 05/02/2005 */ -trait Names extends api.Names with LowPriorityNames { self => +trait Names extends api.Names with LowPriorityNames { implicit def promoteTermNamesAsNecessary(name: Name): TermName = name.toTermName // Operations ------------------------------------------------------------- @@ -109,26 +109,6 @@ trait Names extends api.Names with LowPriorityNames { self => protected def newTypeName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TypeName = newTermName(cs, offset, len, cachedString).toTypeName - protected def toTypeName(termName: TermName): TypeName = { - val h = hashValue(chrs, termName.index, termName.len) & HASH_MASK - var n = typeHashtable(h) - while ((n ne null) && n.start != termName.index) - n = n.next - - if (n ne null) n - else termName.createCompanionName(h) - } - - protected def toTermName(typeName: TypeName): TermName = { - val h = hashValue(chrs, typeName.index, typeName.len) & HASH_MASK - var n = termHashtable(h) - while ((n ne null) && n.start != typeName.index) - n = n.next - - if (n ne null) n - else typeName.createCompanionName(h) - } - /** Create a term name from string. */ def newTermName(s: String): TermName = newTermName(s.toCharArray(), 0, s.length(), null) @@ -165,7 +145,7 @@ trait Names extends api.Names with LowPriorityNames { self => * or Strings as Names. Give names the key functions the absence of which * make people want Strings all the time. */ - sealed abstract class Name(protected[Names] val index: Int, protected[Names] val len: Int) extends NameApi { + sealed abstract class Name(protected val index: Int, protected val len: Int) extends NameApi { type ThisNameType >: Null <: Name protected[this] def thisName: ThisNameType @@ -483,21 +463,21 @@ trait Names extends api.Names with LowPriorityNames { self => * TermName_R and TypeName_R recreate it each time toString is called. */ private class TermName_S(index0: Int, len0: Int, hash: Int, override val toString: String) extends TermName(index0, len0, hash) { - @inline final def createCompanionName(h: Int): TypeName = new TypeName_S(index, len, h, toString) + protected def createCompanionName(h: Int): TypeName = new TypeName_S(index, len, h, toString) override def newName(str: String): TermName = newTermNameCached(str) } private class TypeName_S(index0: Int, len0: Int, hash: Int, override val toString: String) extends TypeName(index0, len0, hash) { - @inline final def createCompanionName(h: Int): TermName = new TermName_S(index, len, h, toString) + protected def createCompanionName(h: Int): TermName = new TermName_S(index, len, h, toString) override def newName(str: String): TypeName = newTypeNameCached(str) } private class TermName_R(index0: Int, len0: Int, hash: Int) extends TermName(index0, len0, hash) { - @inline final def createCompanionName(h: Int): TypeName = new TypeName_R(index, len, h) + protected def createCompanionName(h: Int): TypeName = new TypeName_R(index, len, h) override def toString = new String(chrs, index, len) } private class TypeName_R(index0: Int, len0: Int, hash: Int) extends TypeName(index0, len0, hash) { - @inline final def createCompanionName(h: Int): TermName = new TermName_R(index, len, h) + protected def createCompanionName(h: Int): TermName = new TermName_R(index, len, h) override def toString = new String(chrs, index, len) } @@ -510,14 +490,22 @@ trait Names extends api.Names with LowPriorityNames { self => def isTermName: Boolean = true def isTypeName: Boolean = false def toTermName: TermName = this - def toTypeName: TypeName = self.toTypeName(this) + def toTypeName: TypeName = { + val h = hashValue(chrs, index, len) & HASH_MASK + var n = typeHashtable(h) + while ((n ne null) && n.start != index) + n = n.next + + if (n ne null) n + else createCompanionName(h) + } def newName(str: String): TermName = newTermName(str) def companionName: TypeName = toTypeName def subName(from: Int, to: Int): TermName = newTermName(chrs, start + from, to - from) def nameKind = "term" - def createCompanionName(h: Int): TypeName + protected def createCompanionName(h: Int): TypeName } implicit val TermNameTag = ClassTag[TermName](classOf[TermName]) @@ -530,7 +518,15 @@ trait Names extends api.Names with LowPriorityNames { self => typeHashtable(hash) = this def isTermName: Boolean = false def isTypeName: Boolean = true - def toTermName: TermName = self.toTermName(this) + def toTermName: TermName = { + val h = hashValue(chrs, index, len) & HASH_MASK + var n = termHashtable(h) + while ((n ne null) && n.start != index) + n = n.next + + if (n ne null) n + else createCompanionName(h) + } def toTypeName: TypeName = this def newName(str: String): TypeName = newTypeName(str) def companionName: TermName = toTermName diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 09d1e649d9..bcda2bc1ae 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -265,8 +265,6 @@ trait StdNames { final val SourceFileATTR: NameType = "SourceFile" final val SyntheticATTR: NameType = "Synthetic" - final val scala_ : NameType = "scala" - def dropSingletonName(name: Name): TypeName = (name dropRight SINGLETON_SUFFIX.length).toTypeName def singletonName(name: Name): TypeName = (name append SINGLETON_SUFFIX).toTypeName def implClassName(name: Name): TypeName = (name append IMPL_CLASS_SUFFIX).toTypeName diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index 5a2156a0a0..5ccf81b4b5 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -208,8 +208,6 @@ abstract class SymbolTable extends macros.Universe finally popPhase(saved) } - def slowButSafeAtPhase[T](ph: Phase)(op: => T): T = - if (isCompilerUniverse) atPhase(ph)(op) else op /** Since when it is to be "at" a phase is inherently ambiguous, * a couple unambiguously named methods. @@ -222,9 +220,6 @@ abstract class SymbolTable extends macros.Universe @inline final def atPhaseNotLaterThan[T](target: Phase)(op: => T): T = if (isAtPhaseAfter(target)) atPhase(target)(op) else op - def slowButSafeAtPhaseNotLaterThan[T](target: Phase)(op: => T): T = - if (isCompilerUniverse) atPhaseNotLaterThan(target)(op) else op - final def isValid(period: Period): Boolean = period != 0 && runId(period) == currentRunId && { val pid = phaseId(period) diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index df17e3b751..d9eb48ff2d 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -91,14 +91,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => children } - def selfType = { - if (!isCompilerUniverse && needsInitialize(isFlagRelated = false, mask = 0)) initialize - typeOfThis - } - def baseClasses = info.baseClasses def module = sourceModule def thisPrefix: Type = thisType + def selfType: Type = typeOfThis def typeSignature: Type = { fullyInitializeSymbol(this); info } def typeSignatureIn(site: Type): Type = { fullyInitializeSymbol(this); site memberInfo this } @@ -112,8 +108,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => def setter: Symbol = setter(owner) } - case class SymbolKind(accurate: String, sanitized: String, abbreviation: String) - /** The class for all symbols */ abstract class Symbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: Name) extends SymbolContextApiImpl @@ -899,13 +893,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isInitialized: Boolean = validTo != NoPeriod - /** Some completers call sym.setInfo when still in-flight and then proceed with initialization (e.g. see LazyPackageType) - * setInfo sets _validTo to current period, which means that after a call to setInfo isInitialized will start returning true. - * Unfortunately, this doesn't mean that info becomes ready to be used, because subsequent initialization might change the info. - * Therefore we need this method to distinguish between initialized and really initialized symbol states. - */ - final def isFullyInitialized: Boolean = _validTo != NoPeriod && (flags & LOCKED) == 0 - /** Can this symbol be loaded by a reflective mirror? * * Scalac relies on `ScalaSignature' annotation to retain symbols across compilation runs. @@ -2261,6 +2248,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => else if (isTerm && (!isParameter || isParamAccessor)) "val" else "" + private case class SymbolKind(accurate: String, sanitized: String, abbreviation: String) private def symbolKind: SymbolKind = { var kind = if (isTermMacro) ("macro method", "macro method", "MAC") @@ -3019,8 +3007,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def thisType: Type = { val period = thisTypePeriod if (period != currentPeriod) { - if (!isValid(period)) thisTypeCache = ThisType(this) thisTypePeriod = currentPeriod + if (!isValid(period)) thisTypeCache = ThisType(this) } thisTypeCache } @@ -3096,9 +3084,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def typeOfThis = { val period = typeOfThisPeriod if (period != currentPeriod) { + typeOfThisPeriod = currentPeriod if (!isValid(period)) typeOfThisCache = singleType(owner.thisType, sourceModule) - typeOfThisPeriod = currentPeriod } typeOfThisCache } @@ -3109,9 +3097,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => // Skip a package object class, because the members are also in // the package and we wish to avoid spurious ambiguities as in pos/t3999. if (!isPackageObjectClass) { - implicitMembersCacheValue = tp.implicitMembers implicitMembersCacheKey1 = tp implicitMembersCacheKey2 = tp.decls.elems + implicitMembersCacheValue = tp.implicitMembers } } implicitMembersCacheValue @@ -3219,11 +3207,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => def name = nme.NO_NAME override def name_=(n: Name) = abort("Cannot set NoSymbol's name to " + n) - // Syncnote: no need to synchronize this, because NoSymbol's initialization is triggered by JavaUniverse.init - // which is called in universe's constructor - something that's inherently single-threaded - setInfo(NoType) - privateWithin = this - + synchronized { + setInfo(NoType) + privateWithin = this + } override def info_=(info: Type) = { infos = TypeHistory(1, NoType, null) unlock() diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 76d6ec80be..546df8a207 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -2066,6 +2066,10 @@ trait Types extends api.Types { self: SymbolTable => def apply(value: Constant) = unique(new UniqueConstantType(value)) } + /* Syncnote: The `volatile` var and `pendingVolatiles` mutable set need not be protected + * with synchronized, because they are accessed only from isVolatile, which is called only from + * Typer. + */ private var volatileRecursions: Int = 0 private val pendingVolatiles = new mutable.HashSet[Symbol] @@ -3926,8 +3930,8 @@ trait Types extends api.Types { self: SymbolTable => /** @PP: Unable to see why these apparently constant types should need vals * in every TypeConstraint, I lifted them out. */ - lazy val numericLoBound = IntClass.tpe - lazy val numericHiBound = intersectionType(List(ByteClass.tpe, CharClass.tpe), ScalaPackageClass) + private lazy val numericLoBound = IntClass.tpe + private lazy val numericHiBound = intersectionType(List(ByteClass.tpe, CharClass.tpe), ScalaPackageClass) /** A class expressing upper and lower bounds constraints of type variables, * as well as their instantiations. diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index 4d61e4178a..603fff4f1c 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -853,7 +853,7 @@ abstract class UnPickler { private val p = phase override def complete(sym: Symbol) : Unit = try { val tp = at(i, () => readType(sym.isTerm)) // after NMT_TRANSITION, revert `() => readType(sym.isTerm)` to `readType` - slowButSafeAtPhase(p)(sym setInfo tp) + atPhase(p) (sym setInfo tp) if (currentRunId != definedAtRunId) sym.setInfo(adaptToNewRunMap(tp)) } @@ -871,7 +871,7 @@ abstract class UnPickler { super.complete(sym) var alias = at(j, readSymbol) if (alias.isOverloaded) - alias = slowButSafeAtPhase(picklerPhase)((alias suchThat (alt => sym.tpe =:= sym.owner.thisType.memberType(alt)))) + alias = atPhase(picklerPhase)((alias suchThat (alt => sym.tpe =:= sym.owner.thisType.memberType(alt)))) sym.asInstanceOf[TermSymbol].setAlias(alias) } diff --git a/src/reflect/scala/reflect/runtime/Gil.scala b/src/reflect/scala/reflect/runtime/Gil.scala deleted file mode 100644 index cf6f1431d7..0000000000 --- a/src/reflect/scala/reflect/runtime/Gil.scala +++ /dev/null @@ -1,25 +0,0 @@ -package scala.reflect -package runtime - -private[reflect] trait Gil { - self: SymbolTable => - - // fixme... please... - // there are the following avenues of optimization we discussed with Roland: - // 1) replace PackageScope locks with ConcurrentHashMap, because PackageScope materializers seem to be idempotent - // 2) unlock unpickling completers by verifying that they are idempotent or moving non-idempotent parts - // 3) remove the necessity in global state for isSubType - lazy val gil = new java.util.concurrent.locks.ReentrantLock - - @inline final def gilSynchronized[T](body: => T): T = { - if (isCompilerUniverse) body - else { - try { - gil.lock() - body - } finally { - gil.unlock() - } - } - } -} diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index b46db66766..3442e3d22e 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -24,9 +24,9 @@ import scala.language.existentials import scala.runtime.{ScalaRunTime, BoxesRunTime} import scala.reflect.internal.util.Collections._ -private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse with TwoWayCaches { thisUniverse: SymbolTable => +private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { thisUniverse: SymbolTable => - lazy val mirrors = new WeakHashMap[ClassLoader, WeakReference[JavaMirror]]() + private lazy val mirrors = new WeakHashMap[ClassLoader, WeakReference[JavaMirror]]() private def createMirror(owner: Symbol, cl: ClassLoader): Mirror = { val jm = new JavaMirror(owner, cl) @@ -46,11 +46,19 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni trait JavaClassCompleter extends FlagAssigningCompleter - def runtimeMirror(cl: ClassLoader): Mirror = gilSynchronized { - mirrors get cl match { - case Some(WeakReference(m)) => m - case _ => createMirror(rootMirror.RootClass, cl) - } + def init() = { + definitions.AnyValClass // force it. + + // establish root association to avoid cyclic dependency errors later + rootMirror.classToScala(classOf[java.lang.Object]).initialize + + // println("initializing definitions") + definitions.init() + } + + def runtimeMirror(cl: ClassLoader): Mirror = mirrors get cl match { + case Some(WeakReference(m)) => m + case _ => createMirror(rootMirror.RootClass, cl) } /** The API of a mirror for a reflective universe */ @@ -63,23 +71,6 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni import definitions._ - override lazy val RootPackage = new RootPackage with SynchronizedTermSymbol - override lazy val RootClass = new RootClass with SynchronizedModuleClassSymbol - override lazy val EmptyPackage = new EmptyPackage with SynchronizedTermSymbol - override lazy val EmptyPackageClass = new EmptyPackageClass with SynchronizedModuleClassSymbol - - override def init() = { - super.init() - - // see an explanation of this in JavaUniverse.init() - RootPackage - RootClass - EmptyPackage - EmptyPackageClass - unpickler - rootLoader - } - /** The lazy type for root. */ override lazy val rootLoader = new LazyType with FlagAgnosticCompleter { @@ -676,7 +667,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni completeRest() } - def completeRest(): Unit = gilSynchronized { + def completeRest(): Unit = thisUniverse.synchronized { val tparams = clazz.rawInfo.typeParams val parents = try { @@ -892,7 +883,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni * The Scala package with given fully qualified name. Unlike `packageNameToScala`, * this one bypasses the cache. */ - private[JavaMirrors] def makeScalaPackage(fullname: String): ModuleSymbol = gilSynchronized { + private[JavaMirrors] def makeScalaPackage(fullname: String): ModuleSymbol = { val split = fullname lastIndexOf '.' val ownerModule: ModuleSymbol = if (split > 0) packageNameToScala(fullname take split) else this.RootPackage @@ -1255,6 +1246,11 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni case _ => abort(s"${sym}.enclosingRootClass = ${sym.enclosingRootClass}, which is not a RootSymbol") } + private lazy val syntheticCoreClasses: Map[(String, Name), Symbol] = { + def mapEntry(sym: Symbol): ((String, Name), Symbol) = (sym.owner.fullName, sym.name) -> sym + Map() ++ (definitions.syntheticCoreClasses map mapEntry) + } + /** 1. If `owner` is a package class (but not the empty package) and `name` is a term name, make a new package * <owner>.<name>, otherwise return NoSymbol. * Exception: If owner is root and a java class with given name exists, create symbol in empty package instead @@ -1264,20 +1260,22 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni override def missingHook(owner: Symbol, name: Name): Symbol = { if (owner.hasPackageFlag) { val mirror = mirrorThatLoaded(owner) + // todo. this makes toolbox tests pass, but it's a mere workaround for SI-5865 +// assert((owner.info decl name) == NoSymbol, s"already exists: $owner . $name") if (owner.isRootSymbol && mirror.tryJavaClass(name.toString).isDefined) return mirror.EmptyPackageClass.info decl name if (name.isTermName && !owner.isEmptyPackageClass) return mirror.makeScalaPackage( if (owner.isRootSymbol) name.toString else owner.fullName+"."+name) - if (name == tpnme.AnyRef && owner.owner.isRoot && owner.name == tpnme.scala_) - // when we synthesize the scala.AnyRef symbol, we need to add it to the scope of the scala package - // the problem is that adding to the scope implies doing something like `owner.info.decls enter anyRef` - // which entails running a completer for the scala package - // which will try to unpickle the stuff in scala/package.class - // which will transitively load scala.AnyRef - // which doesn't exist yet, because it hasn't been added to the scope yet - // this missing hook ties the knot without introducing synchronization problems like before - return definitions.AnyRefClass + syntheticCoreClasses get (owner.fullName, name) match { + case Some(tsym) => + // synthetic core classes are only present in root mirrors + // because Definitions.scala, which initializes and enters them, only affects rootMirror + // therefore we need to enter them manually for non-root mirrors + if (mirror ne thisUniverse.rootMirror) owner.info.decls enter tsym + return tsym + case None => + } } info("*** missing: "+name+"/"+name.isTermName+"/"+owner+"/"+owner.hasPackageFlag+"/"+owner.info.decls.getClass) super.missingHook(owner, name) diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala index cee243fb29..e18435d5b0 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala @@ -17,1040 +17,12 @@ class JavaUniverse extends internal.SymbolTable with ReflectSetup with runtime.S def forInteractive = false def forScaladoc = false - def log(msg: => AnyRef): Unit = if (settings.debug.value) println(" [] "+msg) + def log(msg: => AnyRef): Unit = println(" [] "+msg) type TreeCopier = InternalTreeCopierOps def newStrictTreeCopier: TreeCopier = new StrictTreeCopier def newLazyTreeCopier: TreeCopier = new LazyTreeCopier init() - - def init() { - definitions.init() - - // workaround for http://groups.google.com/group/scala-internals/browse_thread/thread/97840ba4fd37b52e - // constructors are by definition single-threaded, so we initialize all lazy vals (and local object) in advance - // in order to avoid deadlocks later (e.g. one thread holds a global reflection lock and waits for definitions.Something to initialize, - // whereas another thread holds a definitions.Something initialization lock and needs a global reflection lock to complete the initialization) - - // the list of lzycompute methods is mined by a simple python script - // #!/usr/bin/env python - // import os, sys, re, glob, fnmatch - // from subprocess import check_call, check_output - // root = check_output(["git", "rev-parse", "--show-toplevel"]).strip() - // root = os.path.join(root, "build/quick/classes/reflect/scala/reflect") - // classfiles = [] - // for container, dirnames, filenames in os.walk(root): - // for filename in fnmatch.filter(filenames, '*.class'): - // classfiles.append(os.path.join(container, filename)) - // for classfile in classfiles: - // blob = open(classfile).read() - // for found in re.findall(r"[\w\$]+\$lzycompute", blob): - // print found, "in", classfile[len(root) + 1:] - - - // ======== Exprs ======== - // NOFORCE: tree$lzycompute in api/Exprs$ExprImpl.class - // NOFORCE: staticType$lzycompute in api/Exprs$ExprImpl.class - // NOFORCE: value$lzycompute in api/Exprs$ExprImpl.class - // FORCE: Expr$lzycompute in api/Universe.class - // FORCE: FixedMirrorTreeCreator$lzycompute in internal/SymbolTable.class - // probably not used by runtime reflection, but better be safe than sorry - Expr - FixedMirrorTreeCreator - - // ======== Type tags ======== - // FORCE: WeakTypeTag$lzycompute in api/Universe.class - // FORCE: TypeTag$lzycompute in api/Universe.class - // NOFORCE: tpe$lzycompute in api/TypeTags$WeakTypeTagImpl.class - // TODO: validate that scala-reflect never uses TypeTags itself (we have StdTags, but they are in compiler, so it should be okay) - // FORCE: tpe$lzycompute in api/TypeTags$PredefTypeTag.class - // FORCE: FixedMirrorTypeCreator$lzycompute in internal/SymbolTable.class - // probably not used by runtime reflection, but better be safe than sorry - WeakTypeTag - TypeTag - TypeTag.Byte.tpe - TypeTag.Short.tpe - TypeTag.Char.tpe - TypeTag.Int.tpe - TypeTag.Long.tpe - TypeTag.Float.tpe - TypeTag.Double.tpe - TypeTag.Boolean.tpe - TypeTag.Unit.tpe - TypeTag.Any.tpe - TypeTag.AnyVal.tpe - TypeTag.AnyRef.tpe - TypeTag.Object.tpe - TypeTag.Nothing.tpe - TypeTag.Null.tpe - FixedMirrorTypeCreator - - // ======== Annotations ======== - // NOFORCE: isTrivial$lzycompute in internal/AnnotationInfos$AnnotationInfo.class - // looks like isTrivial just calls into Type.isTrivial, which cannot go back to the calling annotationinfo, so we're safe from deadlocks - // NOFORCE: forcedInfo$lzycompute in internal/AnnotationInfos$LazyAnnotationInfo.class - // I can't immediately see that the completer cannot call into one of the methods of the calling AnnotationInfo - // TODO: leaving this as a todo and for now we're at a mercy of chance - // NOFORCE: encodedBytes$lzycompute in internal/AnnotationInfos$ScalaSigBytes.class - // NOFORCE: sevenBitsMayBeZero$lzycompute in internal/AnnotationInfos$ScalaSigBytes.class - // these are just bit/byte twiddling, they don't call into reflection at all - // FORCE: UnmappableAnnotArg$lzycompute in internal/SymbolTable.class - // FORCE: LiteralAnnotArg$lzycompute in internal/SymbolTable.class - // FORCE: ArrayAnnotArg$lzycompute in internal/SymbolTable.class - // FORCE: NestedAnnotArg$lzycompute in internal/SymbolTable.class - // FORCE: ScalaSigBytes$lzycompute in internal/SymbolTable.class - // FORCE: AnnotationInfo$lzycompute in internal/SymbolTable.class - // FORCE: Annotation$lzycompute in internal/SymbolTable.class - // FORCE: UnmappableAnnotation$lzycompute in internal/SymbolTable.class - // FORCE: ThrownException$lzycompute in internal/SymbolTable.class - UnmappableAnnotArg - LiteralAnnotArg - ArrayAnnotArg - NestedAnnotArg - ScalaSigBytes - AnnotationInfo - Annotation - UnmappableAnnotation - ThrownException - - // ======== Importers ======== - // NOFORCE: symMap$lzycompute in internal/Importers$StandardImporter.class - // NOFORCE: tpeMap$lzycompute in internal/Importers$StandardImporter.class - // NOFORCE: fixups$lzycompute in internal/Importers$StandardImporter.class - // NOFORCE: reverse$lzycompute in internal/Importers$StandardImporter.class - // these are simple constructors, which don't call into reflection - // actually the first three of those could be non-lazy - - // ======== Mirrors ======== - // NOFORCE: RootPackage$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: RootClass$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: EmptyPackage$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: EmptyPackageClass$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: RootPackage$lzycompute in internal/Mirrors$Roots.class - // NOFORCE: RootClass$lzycompute in internal/Mirrors$Roots.class - // NOFORCE: EmptyPackage$lzycompute in internal/Mirrors$Roots.class - // NOFORCE: EmptyPackageClass$lzycompute in internal/Mirrors$Roots.class - // NOFORCE: unpickler$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: rootLoader$lzycompute in runtime/JavaMirrors$JavaMirror.class - // these are already forced in JavaMirror.init() - // NOFORCE: universe$lzycompute in runtime/package$.class - // that's the scala.reflect.runtime.universe - // FORCE: 5scala$reflect$runtime$JavaMirrors$$mirrors$lzycompute in runtime/JavaUniverse.class - rootMirror - mirrors - - // ======== Names ======== - // FORCE: tpnme$lzycompute in internal/SymbolTable.class - // FORCE: fulltpnme$lzycompute in internal/SymbolTable.class - // FORCE: binarynme$lzycompute in internal/SymbolTable.class - // FORCE: nme$lzycompute in internal/SymbolTable.class - // FORCE: sn$lzycompute in internal/SymbolTable.class - // FORCE: raw$lzycompute in internal/StdNames$TermNames.class - // FORCE: Ascala$reflect$internal$SymbolTable$$SimpleNameOrdering$lzycompute in internal/SymbolTable.class - // FORCE: 6scala$reflect$internal$StdNames$$compactify$lzycompute in internal/SymbolTable.class - // probably most of these are already initialized by definitions.init() - // but better be safe than sorry - // NOFORCE: GetClassLoader$lzycompute in internal/StdNames$MSILNames.class - // MSIL has been eol'd. probably we shouldn't care anymore - // runtime reflection doesn't support MSIL anyways - tpnme - fulltpnme - binarynme - nme - sn - nme.raw - lowPriorityNameOrdering - nme.flattenedName() - - // ======== Attachments ======== - // FORCE: BackquotedIdentifierAttachment$lzycompute in internal/SymbolTable.class - // FORCE: CompoundTypeTreeOriginalAttachment$lzycompute in internal/SymbolTable.class - // FORCE: MacroExpansionAttachment$lzycompute in internal/SymbolTable.class - // FORCE: SuppressMacroExpansionAttachment$lzycompute in internal/SymbolTable.class - // probably not used by runtime reflection - // but better be safe than sorry - BackquotedIdentifierAttachment - CompoundTypeTreeOriginalAttachment - MacroExpansionAttachment - SuppressMacroExpansionAttachment - - // ======== TreeInfo ======== - // NOFORCE: DynamicUpdate$lzycompute in internal/TreeInfo.class - // NOFORCE: DynamicApplication$lzycompute in internal/TreeInfo.class - // NOFORCE: DynamicApplicationNamed$lzycompute in internal/TreeInfo.class - // NOFORCE: MacroImplReference$lzycompute in internal/TreeInfo.class - // NOFORCE: StripCast$lzycompute in internal/TreeInfo.class - // NOFORCE: Applied$lzycompute in internal/TreeInfo.class - // NOFORCE: IsTrue$lzycompute in internal/TreeInfo.class - // NOFORCE: IsFalse$lzycompute in internal/TreeInfo.class - // NOFORCE: IsIf$lzycompute in internal/TreeInfo.class - // TreeInfo is never instantiated by runtime reflection - - // ======== Miscellaneous ======== - // FORCE: BooleanFlag$lzycompute in api/Universe.class - // FORCE: traceSymbols$lzycompute in internal/SymbolTable.class - // FORCE: perRunCaches$lzycompute in internal/SymbolTable.class - // FORCE: typeDebug$lzycompute in internal/SymbolTable.class - // FORCE: str$lzycompute in internal/TypeDebugging$typeDebug$.class - // FORCE: ConsoleWriter$lzycompute in internal/SymbolTable.class - // FORCE: settings$lzycompute in runtime/JavaUniverse.class - // NOFORCE: Lscala$reflect$internal$util$TraceSymbolActivity$$findErasurePhase$lzycompute in internal/SymbolTable$traceSymbols$.class - // NOFORCE: lineIndices$lzycompute in internal/util/BatchSourceFile.class - // NOFORCE: extension$lzycompute in io/AbstractFile.class - // NOFORCE: in_s$lzycompute in io/File.class - // NOFORCE: out_s$lzycompute in io/File.class - // NOFORCE: in$lzycompute in io/File.class - // NOFORCE: out$lzycompute in io/File.class - // NOFORCE: in$lzycompute in io/Streamable$Bytes$class.class - // noforced guys don't call into reflection, so even when not initialized they don't pose a deadlock threat - // FORCE: Scope$lzycompute in internal/SymbolTable.class - // FORCE: EmptyScope$lzycompute in internal/SymbolTable.class - // FORCE: Flag$lzycompute in internal/SymbolTable.class - // FORCE: KindErrors$lzycompute in internal/SymbolTable.class - BooleanFlag - traceSymbols - perRunCaches - typeDebug - typeDebug.str - ConsoleWriter - settings - Scope - EmptyScope - Flag - KindErrors - - // ======== Transforms ======== - // NOFORCE: ObjectArray$lzycompute in internal/transform/Erasure$ErasureMap.class - // NOFORCE: ErasedObject$lzycompute in internal/transform/Erasure$ErasureMap.class - // too much hassle to force those, and they cannot be called back from reflection => safe from deadlocks - // FORCE: GenericArray$lzycompute in internal/transform/Transforms$$anonfun$3$$anon$1.class - // FORCE: scalaErasure$lzycompute in internal/transform/Transforms$$anonfun$3$$anon$1.class - // FORCE: specialScalaErasure$lzycompute in internal/transform/Transforms$$anonfun$3$$anon$1.class - // FORCE: javaErasure$lzycompute in internal/transform/Transforms$$anonfun$3$$anon$1.class - // FORCE: verifiedJavaErasure$lzycompute in internal/transform/Transforms$$anonfun$3$$anon$1.class - // FORCE: boxingErasure$lzycompute in internal/transform/Transforms$$anonfun$3$$anon$1.class - refChecks - uncurry - erasure - erasure.GenericArray - erasure.scalaErasure - erasure.specialScalaErasure - erasure.javaErasure - erasure.verifiedJavaErasure - erasure.boxingErasure - - // ======== Symbols ======== - // FORCE: NoSymbol$lzycompute in internal/SymbolTable.class - // FORCE: 6scala$reflect$internal$Symbols$$TypeHistory$lzycompute in internal/SymbolTable.class - // FORCE: SymbolKind$lzycompute in internal/Symbols$Symbol.class - NoSymbol - definitions.AnyRefClass.info - SymbolKind - - // ======== Trees ======== - // FORCE: PackageDef$lzycompute in internal/SymbolTable.class - // FORCE: ClassDef$lzycompute in internal/SymbolTable.class - // FORCE: ModuleDef$lzycompute in internal/SymbolTable.class - // FORCE: ValDef$lzycompute in internal/SymbolTable.class - // FORCE: DefDef$lzycompute in internal/SymbolTable.class - // FORCE: TypeDef$lzycompute in internal/SymbolTable.class - // FORCE: LabelDef$lzycompute in internal/SymbolTable.class - // FORCE: ImportSelector$lzycompute in internal/SymbolTable.class - // FORCE: Import$lzycompute in internal/SymbolTable.class - // FORCE: Template$lzycompute in internal/SymbolTable.class - // FORCE: Block$lzycompute in internal/SymbolTable.class - // FORCE: CaseDef$lzycompute in internal/SymbolTable.class - // FORCE: Alternative$lzycompute in internal/SymbolTable.class - // FORCE: Star$lzycompute in internal/SymbolTable.class - // FORCE: Bind$lzycompute in internal/SymbolTable.class - // FORCE: UnApply$lzycompute in internal/SymbolTable.class - // FORCE: ArrayValue$lzycompute in internal/SymbolTable.class - // FORCE: Function$lzycompute in internal/SymbolTable.class - // FORCE: Assign$lzycompute in internal/SymbolTable.class - // FORCE: AssignOrNamedArg$lzycompute in internal/SymbolTable.class - // FORCE: If$lzycompute in internal/SymbolTable.class - // FORCE: Match$lzycompute in internal/SymbolTable.class - // FORCE: Return$lzycompute in internal/SymbolTable.class - // FORCE: Try$lzycompute in internal/SymbolTable.class - // FORCE: Throw$lzycompute in internal/SymbolTable.class - // FORCE: New$lzycompute in internal/SymbolTable.class - // FORCE: Typed$lzycompute in internal/SymbolTable.class - // FORCE: TypeApply$lzycompute in internal/SymbolTable.class - // FORCE: Apply$lzycompute in internal/SymbolTable.class - // FORCE: ApplyDynamic$lzycompute in internal/SymbolTable.class - // FORCE: Super$lzycompute in internal/SymbolTable.class - // FORCE: This$lzycompute in internal/SymbolTable.class - // FORCE: Select$lzycompute in internal/SymbolTable.class - // FORCE: Ident$lzycompute in internal/SymbolTable.class - // FORCE: ReferenceToBoxed$lzycompute in internal/SymbolTable.class - // FORCE: Literal$lzycompute in internal/SymbolTable.class - // FORCE: Annotated$lzycompute in internal/SymbolTable.class - // FORCE: SingletonTypeTree$lzycompute in internal/SymbolTable.class - // FORCE: SelectFromTypeTree$lzycompute in internal/SymbolTable.class - // FORCE: CompoundTypeTree$lzycompute in internal/SymbolTable.class - // FORCE: AppliedTypeTree$lzycompute in internal/SymbolTable.class - // FORCE: TypeBoundsTree$lzycompute in internal/SymbolTable.class - // FORCE: ExistentialTypeTree$lzycompute in internal/SymbolTable.class - // FORCE: TypeTree$lzycompute in internal/SymbolTable.class - // FORCE: Modifiers$lzycompute in internal/SymbolTable.class - // FORCE: Constant$lzycompute in internal/SymbolTable.class - // FORCE: treeBuild$lzycompute in internal/SymbolTable.class - // FORCE: posAssigner$lzycompute in internal/SymbolTable.class - // FORCE: NoMods$lzycompute in api/Universe.class - // FORCE: EmptyTree$lzycompute in internal/SymbolTable.class - // FORCE: emptyValDef$lzycompute in internal/SymbolTable.class - // FORCE: EmptyTreeTypeSubstituter$lzycompute in internal/SymbolTable.class - // FORCE: 3scala$reflect$internal$Trees$$duplicator$lzycompute in internal/SymbolTable.class - PackageDef - ClassDef - ModuleDef - ValDef - DefDef - TypeDef - LabelDef - ImportSelector - Import - Template - Block - CaseDef - Alternative - Star - Bind - UnApply - ArrayValue - Function - Assign - AssignOrNamedArg - If - Match - Return - Try - Throw - New - Typed - TypeApply - Apply - ApplyDynamic - Super - This - Select - Ident - ReferenceToBoxed - Literal - Annotated - SingletonTypeTree - SelectFromTypeTree - CompoundTypeTree - AppliedTypeTree - TypeBoundsTree - ExistentialTypeTree - TypeTree - Modifiers - Constant - treeBuild - posAssigner - NoMods - EmptyTree - emptyValDef - EmptyTreeTypeSubstituter - Literal(Constant(42)).duplicate - - // ======== Types ======== - // FORCE: undoLog$lzycompute in internal/SymbolTable.class - // FORCE: UnmappableTree$lzycompute in internal/SymbolTable.class - // FORCE: NotNullType$lzycompute in internal/SymbolTable.class - // FORCE: ErrorType$lzycompute in internal/SymbolTable.class - // FORCE: WildcardType$lzycompute in internal/SymbolTable.class - // FORCE: BoundedWildcardType$lzycompute in internal/SymbolTable.class - // FORCE: NoType$lzycompute in internal/SymbolTable.class - // FORCE: NoPrefix$lzycompute in internal/SymbolTable.class - // FORCE: ThisType$lzycompute in internal/SymbolTable.class - // FORCE: SingleType$lzycompute in internal/SymbolTable.class - // FORCE: SuperType$lzycompute in internal/SymbolTable.class - // FORCE: TypeBounds$lzycompute in internal/SymbolTable.class - // NOFORCE: annotationArgRewriter$1$lzycompute in internal/Types$AsSeenFromMap.class - // local object => not a problem - // FORCE: RefinedType$lzycompute in internal/SymbolTable.class - // FORCE: ClassInfoType$lzycompute in internal/SymbolTable.class - // FORCE: ConstantType$lzycompute in internal/SymbolTable.class - // FORCE: TypeRef$lzycompute in internal/SymbolTable.class - // FORCE: MethodType$lzycompute in internal/SymbolTable.class - // FORCE: NullaryMethodType$lzycompute in internal/SymbolTable.class - // FORCE: PolyType$lzycompute in internal/SymbolTable.class - // FORCE: ExistentialType$lzycompute in internal/SymbolTable.class - // FORCE: OverloadedType$lzycompute in internal/SymbolTable.class - // FORCE: AntiPolyType$lzycompute in internal/SymbolTable.class - // FORCE: HasTypeMember$lzycompute in internal/SymbolTable.class - // FORCE: HasTypeParams$lzycompute in internal/SymbolTable.class - // FORCE: TypeVar$lzycompute in internal/SymbolTable.class - // FORCE: AnnotatedType$lzycompute in internal/SymbolTable.class - // FORCE: NamedType$lzycompute in internal/SymbolTable.class - // FORCE: DeBruijnIndex$lzycompute in internal/SymbolTable.class - // FORCE: DeBruijnBinder$lzycompute in internal/SymbolTable.class - // FORCE: ErasedValueType$lzycompute in internal/SymbolTable.class - // FORCE: GenPolyType$lzycompute in internal/SymbolTable.class - // FORCE: normalizeAliases$lzycompute in internal/SymbolTable.class - // FORCE: dropSingletonType$lzycompute in internal/SymbolTable.class - // FORCE: dropAllRefinements$lzycompute in internal/SymbolTable.class - // FORCE: dropRepeatedParamType$lzycompute in internal/SymbolTable.class - // FORCE: toDeBruijn$lzycompute in internal/SymbolTable.class - // FORCE: numericLoBound$lzycompute in internal/SymbolTable.class - // FORCE: numericHiBound$lzycompute in internal/SymbolTable.class - // FORCE: TypeConstraint$lzycompute in internal/SymbolTable.class - // FORCE: unwrapToClass$lzycompute in internal/SymbolTable.class - // FORCE: unwrapToStableClass$lzycompute in internal/SymbolTable.class - // FORCE: unwrapWrapperTypes$lzycompute in internal/SymbolTable.class - // FORCE: IsDependentCollector$lzycompute in internal/SymbolTable.class - // FORCE: ApproximateDependentMap$lzycompute in internal/SymbolTable.class - // FORCE: StripAnnotationsMap$lzycompute in internal/SymbolTable.class - // FORCE: wildcardToTypeVarMap$lzycompute in internal/SymbolTable.class - // FORCE: typeVarToOriginMap$lzycompute in internal/SymbolTable.class - // FORCE: ErroneousCollector$lzycompute in internal/SymbolTable.class - // NOFORCE: scala$reflect$internal$Types$$commonOwnerMapObj$lzycompute in internal/SymbolTable.class - // not used in runtime reflection, overridden to provide thread-safety - // FORCE: RecoverableCyclicReference$lzycompute in internal/SymbolTable.class - // FORCE: CyclicReference$lzycompute in internal/SymbolTable.class - // NOFORCE: scala$reflect$internal$Types$ClassInfoType$$enterRefs$lzycompute in internal/Types$ClassInfoType.class - // not used in runtime reflection, only called by typer - // NOFORCE: Jscala$reflect$internal$Types$InstantiateDependentMap$$StableArg$lzycompute in internal/Types$InstantiateDependentMap.class - // NOFORCE: Dscala$reflect$internal$Types$InstantiateDependentMap$$Arg$lzycompute in internal/Types$InstantiateDependentMap.class - // don't call into reflection - // NOFORCE: trans$1$lzycompute in internal/Types$SubstSymMap.class - // NOFORCE: trans$2$lzycompute in internal/Types$SubstTypeMap.class - // NOFORCE: treeTrans$1$lzycompute in internal/Types$InstantiateDependentMap.class - // local objects => we're fine - // FORCE: adaptToNewRunMap$lzycompute in internal/SymbolTable.class - // NOFORCE?! maxDepth$lzycompute in internal/BaseTypeSeqs$BaseTypeSeq.class - // NOFORCE?! maxDepth$lzycompute in runtime/SynchronizedOps$$anon$4.class - // NOFORCE?! maxDepth$lzycompute in runtime/SynchronizedOps$SynchronizedBaseTypeSeq$$anon$3.class - // it's totally not obvious whether typeDepth, which is called by maxDepth, - // can or cannot indirectly call into one of the methods of the calling BaseTypeSeq - // TODO: leaving this for further investigation risking to get a deadlock for now - undoLog - UnmappableTree - NotNullType - ErrorType - WildcardType - BoundedWildcardType - NoType - NoPrefix - ThisType - SingleType - SuperType - TypeBounds - RefinedType - ClassInfoType - ConstantType - TypeRef - MethodType - NullaryMethodType - PolyType - ExistentialType - OverloadedType - AntiPolyType - HasTypeMember - HasTypeParams - TypeVar - AnnotatedType - NamedType - DeBruijnIndex - DeBruijnBinder - ErasedValueType - GenPolyType - normalizeAliases - dropSingletonType - dropAllRefinements - dropRepeatedParamType - toDeBruijn - numericLoBound - numericHiBound - TypeConstraint - unwrapToClass - unwrapToStableClass - unwrapWrapperTypes - IsDependentCollector - ApproximateDependentMap - StripAnnotationsMap - wildcardToTypeVarMap - typeVarToOriginMap - ErroneousCollector - RecoverableCyclicReference - CyclicReference - adaptToNewRunMap - - // ======== JavaMirrors ======== - // NOFORCE: assocs$lzycompute in runtime/JavaMirrors$JavaMirror$JavaAnnotationProxy.class - // NOFORCE: jconstr$lzycompute in runtime/JavaMirrors$JavaMirror$JavaConstructorMirror.class - // NOFORCE: jfield$lzycompute in runtime/JavaMirrors$JavaMirror$JavaFieldMirror.class - // NOFORCE: jmeth$lzycompute in runtime/JavaMirrors$JavaMirror$JavaMethodMirror.class - // NOFORCE: signature$lzycompute in runtime/JavaMirrors$JavaMirror$JavaTemplateMirror.class - // NOFORCE: PrimitiveClass$lzycompute in runtime/JavaMirrors$JavaMirror$toAnnotArg$.class - // NOFORCE: EnumClass$lzycompute in runtime/JavaMirrors$JavaMirror$toAnnotArg$.class - // NOFORCE: ArrayClass$lzycompute in runtime/JavaMirrors$JavaMirror$toAnnotArg$.class - // NOFORCE: AnnotationClass$lzycompute in runtime/JavaMirrors$JavaMirror$toAnnotArg$.class - // NOFORCE: ConstantArg$lzycompute in runtime/JavaMirrors$JavaMirror$toAnnotArg$.class - // NOFORCE: Cscala$reflect$runtime$JavaMirrors$JavaMirror$$toAnnotArg$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: Lscala$reflect$runtime$JavaMirrors$JavaMirror$$JavaAnnotationProxy$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: Bscala$reflect$runtime$TwoWayCaches$TwoWayCache$$SomeRef$lzycompute in runtime/TwoWayCaches$TwoWayCache.class - // NOFORCE: bytecodelessMethodOwners$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: bytecodefulObjectMethods$lzycompute in runtime/JavaMirrors$JavaMirror.class - // functionality from JavaMirrors cannot be called from reflect.internal, so there's no danger of deadlock - - // ======== Locks ======== - // locks in runtime reflection look like `lazy val XXXlock = new Object` - // since initializers don't call into reflection, there's no problem in not forcing those lazy vals here - - // ======== Definitions ======== - // FORCE: definitions$lzycompute in internal/SymbolTable.class - // FORCE: JavaLangPackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaLangPackageClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaPackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaPackageClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RuntimePackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RuntimePackageClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaLangEnumClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: anyparam$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: anyvalparam$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: anyrefparam$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyRefClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ObjectClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyRefTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ObjectTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyRefModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyValClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyValTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RuntimeNothingClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RuntimeNullClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NothingClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NullClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NothingTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NullTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ClassCastExceptionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: IndexOutOfBoundsExceptionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: InvocationTargetExceptionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MatchErrorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NonLocalReturnControlClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: $NullPointerExceptionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ThrowableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UninitializedErrorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: PartialFunctionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AbstractPartialFunctionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SymbolClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StringClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StringModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ClassClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DynamicClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SysPackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UnqualifiedModules$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UnqualifiedOwners$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: PredefModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: PredefModuleClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SpecializableModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: GroupOfSpecializable$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ConsoleModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaRunTimeModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SymbolModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Symbol_apply$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StringAddClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ArrowAssocClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StringAdd_$plus$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NotNullClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaNumberClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TraitSetterAnnotationClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DelayedInitClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TypeConstraintClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SingletonClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SerializableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaSerializableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ComparableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: CloneableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaCloneableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaNumberClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RemoteInterfaceClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RemoteExceptionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ByNameParamClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: EqualsPatternClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaRepeatedParamClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RepeatedParamClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MatchingStrategyClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ConsClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: IterableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: IteratorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ListClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SeqClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StringBuilderClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TraversableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ListModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: List_apply$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NilModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SeqModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: IteratorModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Iterator_apply$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ArrayModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ArrayModule_overloadedApply$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ArrayClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Array_apply$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Array_update$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Array_length$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Array_clone$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SoftReferenceClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: WeakReferenceClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MethodClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: EmptyMethodCacheClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MethodCacheClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ReflectPackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ReflectApiPackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ReflectRuntimePackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: PartialManifestClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: PartialManifestModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: FullManifestClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: FullManifestModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: OptManifestClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NoManifest$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ExprsClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ExprClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ExprModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ClassTagModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ClassTagClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TypeTagsClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: WeakTypeTagClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: WeakTypeTagModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TypeTagClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TypeTagModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ApiUniverseClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaUniverseClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MirrorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TypeCreatorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TreeCreatorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MacroContextClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MacroImplAnnotation$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StringContextClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaSignatureAnnotation$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaLongSignatureAnnotation$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: OptionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: OptionModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Option_apply$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SomeClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NoneModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SomeModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ProductClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TupleClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: FunctionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AbstractFunctionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ProductRootClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ObjectArray$lzycompute in internal/Definitions$DefinitionsClass.class - // NOFORCE: ComparatorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // NOFORCE: ValueTypeClass$lzycompute in internal/Definitions$DefinitionsClass.class - // NOFORCE: DelegateClass$lzycompute in internal/Definitions$DefinitionsClass.class - // NOFORCE: Delegate_scalaCallerTargets$lzycompute in internal/Definitions$DefinitionsClass.class - // MSIL has been eol'd. probably we shouldn't care anymore - // runtime reflection doesn't support MSIL anyways - // FORCE: Any_$eq$eq$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_$bang$eq$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_equals$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_hashCode$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_toString$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_$hash$hash$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_getClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_isInstanceOf$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_asInstanceOf$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_$hash$hash$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_$eq$eq$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_$bang$eq$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_eq$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_ne$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_isInstanceOf$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_asInstanceOf$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_synchronized$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: String_$plus$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ObjectRefClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: VolatileObjectRefClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RuntimeStaticsModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxesRunTimeModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxesRunTimeClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedNumberClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedCharacterClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedBooleanClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedByteClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedShortClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedIntClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedLongClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedFloatClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedDoubleClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Boxes_isNumberOrBool$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Boxes_isNumber$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedUnitClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedUnitModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnnotationClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ClassfileAnnotationClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StaticAnnotationClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BridgeClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ElidableMethodClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ImplicitNotFoundClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MigrationAnnotationClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaStrictFPAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SerializableAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SwitchClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TailrecClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: VarargsClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: uncheckedStableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: uncheckedVarianceClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BeanPropertyAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BooleanBeanPropertyAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: CloneableAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: CompileTimeOnlyAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DeprecatedAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DeprecatedNameAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: $DeprecatedInheritanceAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DeprecatedOverridingAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NativeAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RemoteAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaInlineClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaNoInlineClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SerialVersionUIDAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SpecializedClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ThrowsClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TransientAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UncheckedClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UnspecializedClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: VolatileAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BeanGetterTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BeanSetterTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: FieldTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: GetterTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ParamTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SetterTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ClassTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ObjectTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MethodTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: LanguageFeatureAnnot$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: languageFeatureModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: experimentalModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MacrosFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DynamicsFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: PostfixOpsFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ReflectiveCallsFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ImplicitConversionsFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: HigherKindsFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ExistentialsFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: metaAnnotations$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnnotationDefaultAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: boxedClassValues$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: isUnbox$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: isBox$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: isPhantomClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: syntheticCoreClasses$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: syntheticCoreMethods$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: hijackedCoreClasses$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: symbolsNotPresentInBytecode$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: $isPossibleSyntheticParent$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: boxedValueClassesSet$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: abbrvTag$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: numericWeight$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: boxedModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: boxedClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: refClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: volatileRefClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: boxMethod$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: unboxMethod$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UnitClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ByteClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ShortClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: CharClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: IntClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: LongClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: FloatClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DoubleClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BooleanClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Boolean_and$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Boolean_or$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Boolean_not$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UnitTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ByteTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ShortTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: CharTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: IntTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: LongTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: FloatTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DoubleTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BooleanTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaNumericValueClasses$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaValueClassesNoUnit$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaValueClasses$lzycompute in internal/Definitions$DefinitionsClass.class - definitions.JavaLangPackage - definitions.JavaLangPackageClass - definitions.ScalaPackage - definitions.ScalaPackageClass - definitions.RuntimePackage - definitions.RuntimePackageClass - definitions.JavaLangEnumClass - definitions.anyparam - definitions.anyvalparam - definitions.anyrefparam - definitions.AnyClass - definitions.AnyRefClass - definitions.ObjectClass - definitions.AnyTpe - definitions.AnyRefTpe - definitions.ObjectTpe - // FIXME: definitions.AnyRefModule - definitions.AnyValClass - definitions.AnyValTpe - definitions.RuntimeNothingClass - definitions.RuntimeNullClass - definitions.NothingClass - definitions.NullClass - definitions.NothingTpe - definitions.NullTpe - definitions.ClassCastExceptionClass - definitions.IndexOutOfBoundsExceptionClass - definitions.InvocationTargetExceptionClass - definitions.MatchErrorClass - definitions.NonLocalReturnControlClass - definitions.NullPointerExceptionClass - definitions.ThrowableClass - definitions.UninitializedErrorClass - definitions.PartialFunctionClass - definitions.AbstractPartialFunctionClass - definitions.SymbolClass - definitions.StringClass - definitions.StringModule - definitions.ClassClass - definitions.DynamicClass - definitions.SysPackage - definitions.UnqualifiedModules - definitions.UnqualifiedOwners - definitions.PredefModule - definitions.PredefModuleClass - definitions.SpecializableModule - definitions.GroupOfSpecializable - definitions.ConsoleModule - definitions.ScalaRunTimeModule - definitions.SymbolModule - definitions.Symbol_apply - definitions.StringAddClass - definitions.ArrowAssocClass - definitions.StringAdd_$plus - definitions.NotNullClass - definitions.ScalaNumberClass - definitions.TraitSetterAnnotationClass - definitions.DelayedInitClass - definitions.TypeConstraintClass - definitions.SingletonClass - definitions.SerializableClass - definitions.JavaSerializableClass - definitions.ComparableClass - definitions.CloneableClass - definitions.JavaCloneableClass - definitions.JavaNumberClass - definitions.RemoteInterfaceClass - definitions.RemoteExceptionClass - definitions.ByNameParamClass - definitions.EqualsPatternClass - definitions.JavaRepeatedParamClass - definitions.RepeatedParamClass - // FIXME: definitions.MatchingStrategyClass - definitions.ConsClass - definitions.IterableClass - definitions.IteratorClass - definitions.ListClass - definitions.SeqClass - definitions.StringBuilderClass - definitions.TraversableClass - definitions.ListModule - definitions.List_apply - definitions.NilModule - definitions.SeqModule - definitions.IteratorModule - definitions.Iterator_apply - definitions.ArrayModule - definitions.ArrayModule_overloadedApply - definitions.ArrayClass - definitions.Array_apply - definitions.Array_update - definitions.Array_length - definitions.Array_clone - definitions.SoftReferenceClass - definitions.WeakReferenceClass - definitions.MethodClass - definitions.EmptyMethodCacheClass - definitions.MethodCacheClass - definitions.ReflectPackage - definitions.ReflectApiPackage - definitions.ReflectRuntimePackage - definitions.PartialManifestClass - definitions.PartialManifestModule - definitions.FullManifestClass - definitions.FullManifestModule - definitions.OptManifestClass - definitions.NoManifest - definitions.ExprsClass - definitions.ExprClass - definitions.ExprModule - definitions.ClassTagModule - definitions.ClassTagClass - definitions.TypeTagsClass - definitions.WeakTypeTagClass - definitions.WeakTypeTagModule - definitions.TypeTagClass - definitions.TypeTagModule - definitions.ApiUniverseClass - definitions.JavaUniverseClass - definitions.MirrorClass - definitions.TypeCreatorClass - definitions.TreeCreatorClass - definitions.MacroContextClass - definitions.MacroImplAnnotation - definitions.StringContextClass - definitions.ScalaSignatureAnnotation - definitions.ScalaLongSignatureAnnotation - definitions.OptionClass - definitions.OptionModule - definitions.Option_apply - definitions.SomeClass - definitions.NoneModule - definitions.SomeModule - definitions.ProductClass - definitions.TupleClass - definitions.FunctionClass - definitions.AbstractFunctionClass - definitions.ProductRootClass - definitions.ObjectArray - definitions.Any_$eq$eq - definitions.Any_$bang$eq - definitions.Any_equals - definitions.Any_hashCode - definitions.Any_toString - definitions.Any_$hash$hash - definitions.Any_getClass - definitions.Any_isInstanceOf - definitions.Any_asInstanceOf - definitions.Object_$hash$hash - definitions.Object_$eq$eq - definitions.Object_$bang$eq - definitions.Object_eq - definitions.Object_ne - definitions.Object_isInstanceOf - definitions.Object_asInstanceOf - definitions.Object_synchronized - definitions.String_$plus - definitions.ObjectRefClass - definitions.VolatileObjectRefClass - definitions.RuntimeStaticsModule - definitions.BoxesRunTimeModule - definitions.BoxesRunTimeClass - definitions.BoxedNumberClass - definitions.BoxedCharacterClass - definitions.BoxedBooleanClass - definitions.BoxedByteClass - definitions.BoxedShortClass - definitions.BoxedIntClass - definitions.BoxedLongClass - definitions.BoxedFloatClass - definitions.BoxedDoubleClass - definitions.Boxes_isNumberOrBool - definitions.Boxes_isNumber - definitions.BoxedUnitClass - definitions.BoxedUnitModule - definitions.AnnotationClass - definitions.ClassfileAnnotationClass - definitions.StaticAnnotationClass - definitions.BridgeClass - definitions.ElidableMethodClass - definitions.ImplicitNotFoundClass - definitions.MigrationAnnotationClass - definitions.ScalaStrictFPAttr - definitions.SerializableAttr - definitions.SwitchClass - definitions.TailrecClass - definitions.VarargsClass - definitions.uncheckedStableClass - definitions.uncheckedVarianceClass - definitions.BeanPropertyAttr - definitions.BooleanBeanPropertyAttr - definitions.CloneableAttr - definitions.CompileTimeOnlyAttr - definitions.DeprecatedAttr - definitions.DeprecatedNameAttr - definitions.DeprecatedInheritanceAttr - definitions.DeprecatedOverridingAttr - definitions.NativeAttr - definitions.RemoteAttr - definitions.ScalaInlineClass - definitions.ScalaNoInlineClass - definitions.SerialVersionUIDAttr - definitions.SpecializedClass - definitions.ThrowsClass - definitions.TransientAttr - definitions.UncheckedClass - definitions.UnspecializedClass - definitions.VolatileAttr - definitions.BeanGetterTargetClass - definitions.BeanSetterTargetClass - definitions.FieldTargetClass - definitions.GetterTargetClass - definitions.ParamTargetClass - definitions.SetterTargetClass - definitions.ClassTargetClass - definitions.ObjectTargetClass - definitions.MethodTargetClass - definitions.LanguageFeatureAnnot - definitions.languageFeatureModule - definitions.experimentalModule - definitions.MacrosFeature - definitions.DynamicsFeature - definitions.PostfixOpsFeature - definitions.ReflectiveCallsFeature - definitions.ImplicitConversionsFeature - definitions.HigherKindsFeature - definitions.ExistentialsFeature - definitions.metaAnnotations - definitions.AnnotationDefaultAttr - definitions.boxedClassValues - definitions.isUnbox - definitions.isBox - definitions.isPhantomClass - definitions.syntheticCoreClasses - definitions.syntheticCoreMethods - definitions.hijackedCoreClasses - definitions.symbolsNotPresentInBytecode - definitions.isPossibleSyntheticParent - definitions.boxedValueClassesSet - definitions.abbrvTag - definitions.numericWeight - definitions.boxedModule - definitions.boxedClass - definitions.refClass - definitions.volatileRefClass - definitions.boxMethod - definitions.unboxMethod - definitions.UnitClass - definitions.ByteClass - definitions.ShortClass - definitions.CharClass - definitions.IntClass - definitions.LongClass - definitions.FloatClass - definitions.DoubleClass - definitions.BooleanClass - definitions.Boolean_and - definitions.Boolean_or - definitions.Boolean_not - definitions.UnitTpe - definitions.ByteTpe - definitions.ShortTpe - definitions.CharTpe - definitions.IntTpe - definitions.LongTpe - definitions.FloatTpe - definitions.DoubleTpe - definitions.BooleanTpe - definitions.ScalaNumericValueClasses - definitions.ScalaValueClassesNoUnit - definitions.ScalaValueClasses - } } diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala index a4bc920d33..61663f6181 100644 --- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala +++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala @@ -15,13 +15,37 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => * is found, a package is created instead. */ class TopClassCompleter(clazz: Symbol, module: Symbol) extends SymLoader with FlagAssigningCompleter { +// def makePackage() { +// println("wrong guess; making package "+clazz) +// val ptpe = newPackageType(module.moduleClass) +// for (sym <- List(clazz, module, module.moduleClass)) { +// sym setFlag Flags.PACKAGE +// sym setInfo ptpe +// } +// } + override def complete(sym: Symbol) = { debugInfo("completing "+sym+"/"+clazz.fullName) assert(sym == clazz || sym == module || sym == module.moduleClass) - slowButSafeAtPhaseNotLaterThan(picklerPhase) { +// try { + atPhaseNotLaterThan(picklerPhase) { val loadingMirror = mirrorThatLoaded(sym) val javaClass = loadingMirror.javaClass(clazz.javaClassName) loadingMirror.unpickleClass(clazz, module, javaClass) +// } catch { +// case ex: ClassNotFoundException => makePackage() +// case ex: NoClassDefFoundError => makePackage() + // Note: We catch NoClassDefFoundError because there are situations + // where a package and a class have the same name except for capitalization. + // It seems in this case the class is loaded even if capitalization differs + // but then a NoClassDefFound error is issued with a ("wrong name: ...") + // reason. (I guess this is a concession to Windows). + // The present behavior is a bit too forgiving, in that it masks + // all class load errors, not just wrong name errors. We should try + // to be more discriminating. To get on the right track simply delete + // the clause above and load a collection class such as collection.Iterable. + // You'll see an error that class `parallel` has the wrong name. +// } } } override def load(sym: Symbol) = complete(sym) @@ -73,51 +97,18 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => 0 < dp && dp < (name.length - 1) } - // Since runtime reflection doesn't have a luxury of enumerating all classes - // on the classpath, it has to materialize symbols for top-level definitions - // (packages, classes, objects) on demand. - // - // Someone asks us for a class named `foo.Bar`? Easy. Let's speculatively create - // a package named `foo` and then look up `newTypeName("bar")` in its decls. - // This lookup, implemented in `SymbolLoaders.PackageScope` tests the waters by - // trying to to `Class.forName("foo.Bar")` and then creates a ClassSymbol upon - // success (the whole story is a bit longer, but the rest is irrelevant here). - // - // That's all neat, but these non-deterministic mutations of the global symbol - // table give a lot of trouble in multi-threaded setting. One of the popular - // reflection crashes happens when multiple threads happen to trigger symbol - // materialization multiple times for the same symbol, making subsequent - // reflective operations stumble upon outrageous stuff like overloaded packages. - // - // Short of significantly changing SymbolLoaders I see no other way than just - // to slap a global lock on materialization in runtime reflection. class PackageScope(pkgClass: Symbol) extends Scope(initFingerPrints = -1L) // disable fingerprinting as we do not know entries beforehand with SynchronizedScope { assert(pkgClass.isType) - - // materializing multiple copies of the same symbol in PackageScope is a very popular bug - // this override does its best to guard against it - override def enter[T <: Symbol](sym: T): T = { - val existing = super.lookupEntry(sym.name) - assert(existing == null || existing.sym.isMethod, s"pkgClass = $pkgClass, sym = $sym, existing = $existing") - super.enter(sym) - } - - // package scopes need to synchronize on the GIL - // because lookupEntry might cause changes to the global symbol table - override def syncLockSynchronized[T](body: => T): T = gilSynchronized(body) - private val negatives = new mutable.HashSet[Name] - override def lookupEntry(name: Name): ScopeEntry = syncLockSynchronized { - def lookupExisting: Option[ScopeEntry] = { - val e = super.lookupEntry(name) - if (e != null) - Some(e) - else if (isInvalidClassName(name) || (negatives contains name)) - Some(null) // TODO: omg - else - None - } - def materialize: ScopeEntry = { + // disable fingerprinting as we do not know entries beforehand + private val negatives = mutable.Set[Name]() // Syncnote: Performance only, so need not be protected. + override def lookupEntry(name: Name): ScopeEntry = { + val e = super.lookupEntry(name) + if (e != null) + e + else if (isInvalidClassName(name) || (negatives contains name)) + null + else { val path = if (pkgClass.isEmptyPackageClass) name.toString else pkgClass.fullName + "." + name @@ -146,7 +137,6 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => null } } - lookupExisting getOrElse materialize } } diff --git a/src/reflect/scala/reflect/runtime/SymbolTable.scala b/src/reflect/scala/reflect/runtime/SymbolTable.scala index d317d6a12b..5c08e9a508 100644 --- a/src/reflect/scala/reflect/runtime/SymbolTable.scala +++ b/src/reflect/scala/reflect/runtime/SymbolTable.scala @@ -8,7 +8,7 @@ import scala.reflect.internal.Flags._ * It can be used either from a reflexive universe (class scala.reflect.runtime.JavaUniverse), or else from * a runtime compiler that uses reflection to get a class information (class scala.tools.reflect.ReflectGlobal) */ -private[scala] trait SymbolTable extends internal.SymbolTable with JavaMirrors with SymbolLoaders with SynchronizedOps with Gil { +private[scala] trait SymbolTable extends internal.SymbolTable with JavaMirrors with SymbolLoaders with SynchronizedOps { def info(msg: => String) = if (settings.verbose.value) println("[reflect-compiler] "+msg) diff --git a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala index f9f4a26b42..7b280e59b9 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala @@ -8,40 +8,28 @@ private[reflect] trait SynchronizedOps extends internal.SymbolTable // Names - // this lock isn't subsumed by the reflection GIL - // because there's no way newXXXName methods are going to call anything reflective - // therefore we don't have a danger of a deadlock from having a fine-grained lock for name creation private lazy val nameLock = new Object - // these three methods are the only gateways into name hashtable manipulations - // we need to protected them with a lock, because they are by far not atomic - override protected def newTermName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TermName = - nameLock.synchronized { super.newTermName(cs, offset, len, cachedString) } - override protected def toTypeName(termName: TermName): TypeName = nameLock.synchronized { super.toTypeName(termName) } - override protected def toTermName(typeName: TypeName): TermName = nameLock.synchronized { super.toTermName(typeName) } + override def newTermName(s: String): TermName = nameLock.synchronized { super.newTermName(s) } + override def newTypeName(s: String): TypeName = nameLock.synchronized { super.newTypeName(s) } // BaseTypeSeqs override protected def newBaseTypeSeq(parents: List[Type], elems: Array[Type]) = - // only need to synchronize BaseTypeSeqs if they contain refined types - if (elems.filter(_.isInstanceOf[RefinedType]).nonEmpty) new BaseTypeSeq(parents, elems) with SynchronizedBaseTypeSeq - else new BaseTypeSeq(parents, elems) + new BaseTypeSeq(parents, elems) with SynchronizedBaseTypeSeq trait SynchronizedBaseTypeSeq extends BaseTypeSeq { - override def apply(i: Int): Type = gilSynchronized { super.apply(i) } - override def rawElem(i: Int) = gilSynchronized { super.rawElem(i) } - override def typeSymbol(i: Int): Symbol = gilSynchronized { super.typeSymbol(i) } - override def toList: List[Type] = gilSynchronized { super.toList } - override def copy(head: Type, offset: Int): BaseTypeSeq = gilSynchronized { super.copy(head, offset) } - override def map(f: Type => Type): BaseTypeSeq = gilSynchronized { super.map(f) } - override def exists(p: Type => Boolean): Boolean = gilSynchronized { super.exists(p) } - override lazy val maxDepth = gilSynchronized { maxDepthOfElems } - override def toString = gilSynchronized { super.toString } - - override def lateMap(f: Type => Type): BaseTypeSeq = - // only need to synchronize BaseTypeSeqs if they contain refined types - if (map(f).toList.filter(_.isInstanceOf[RefinedType]).nonEmpty) new MappedBaseTypeSeq(this, f) with SynchronizedBaseTypeSeq - else new MappedBaseTypeSeq(this, f) + override def apply(i: Int): Type = synchronized { super.apply(i) } + override def rawElem(i: Int) = synchronized { super.rawElem(i) } + override def typeSymbol(i: Int): Symbol = synchronized { super.typeSymbol(i) } + override def toList: List[Type] = synchronized { super.toList } + override def copy(head: Type, offset: Int): BaseTypeSeq = synchronized { super.copy(head, offset) } + override def map(f: Type => Type): BaseTypeSeq = synchronized { super.map(f) } + override def exists(p: Type => Boolean): Boolean = synchronized { super.exists(p) } + override lazy val maxDepth = synchronized { maxDepthOfElems } + override def toString = synchronized { super.toString } + + override def lateMap(f: Type => Type): BaseTypeSeq = new MappedBaseTypeSeq(this, f) with SynchronizedBaseTypeSeq } // Scopes @@ -50,19 +38,15 @@ private[reflect] trait SynchronizedOps extends internal.SymbolTable override def newNestedScope(outer: Scope): Scope = new Scope(outer) with SynchronizedScope trait SynchronizedScope extends Scope { - // we can keep this lock fine-grained, because methods of Scope don't do anything extraordinary, which makes deadlocks impossible - // fancy subclasses of internal.Scopes#Scope should do synchronization themselves (e.g. see PackageScope for an example) - private lazy val syncLock = new Object - def syncLockSynchronized[T](body: => T): T = if (isCompilerUniverse) body else syncLock.synchronized { body } - override def isEmpty: Boolean = syncLockSynchronized { super.isEmpty } - override def size: Int = syncLockSynchronized { super.size } - override def enter[T <: Symbol](sym: T): T = syncLockSynchronized { super.enter(sym) } - override def rehash(sym: Symbol, newname: Name) = syncLockSynchronized { super.rehash(sym, newname) } - override def unlink(e: ScopeEntry) = syncLockSynchronized { super.unlink(e) } - override def unlink(sym: Symbol) = syncLockSynchronized { super.unlink(sym) } - override def lookupAll(name: Name) = syncLockSynchronized { super.lookupAll(name) } - override def lookupEntry(name: Name) = syncLockSynchronized { super.lookupEntry(name) } - override def lookupNextEntry(entry: ScopeEntry) = syncLockSynchronized { super.lookupNextEntry(entry) } - override def toList: List[Symbol] = syncLockSynchronized { super.toList } + override def isEmpty: Boolean = synchronized { super.isEmpty } + override def size: Int = synchronized { super.size } + override def enter[T <: Symbol](sym: T): T = synchronized { super.enter(sym) } + override def rehash(sym: Symbol, newname: Name) = synchronized { super.rehash(sym, newname) } + override def unlink(e: ScopeEntry) = synchronized { super.unlink(e) } + override def unlink(sym: Symbol) = synchronized { super.unlink(sym) } + override def lookupAll(name: Name) = synchronized { super.lookupAll(name) } + override def lookupEntry(name: Name) = synchronized { super.lookupEntry(name) } + override def lookupNextEntry(entry: ScopeEntry) = synchronized { super.lookupNextEntry(entry) } + override def toList: List[Symbol] = synchronized { super.toList } } } diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala index 5a0ac01ac4..00f6952dc1 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala @@ -5,18 +5,14 @@ import scala.reflect.io.AbstractFile private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => - // we can keep this lock fine-grained, because nextId is just a simple increment, which makes deadlocks impossible - private lazy val nextIdLock = new Object - override protected def nextId() = nextIdLock.synchronized { super.nextId() } + override protected def nextId() = synchronized { super.nextId() } - // we can keep this lock fine-grained, because freshExistentialName is just a simple increment, which makes deadlocks impossible - private lazy val freshExistentialNameLock = new Object override protected def freshExistentialName(suffix: String) = - freshExistentialNameLock.synchronized { super.freshExistentialName(suffix) } + synchronized { super.freshExistentialName(suffix) } // Set the fields which point companions at one another. Returns the module. override def connectModuleToClass(m: ModuleSymbol, moduleClass: ClassSymbol): ModuleSymbol = - gilSynchronized { super.connectModuleToClass(m, moduleClass) } + synchronized { super.connectModuleToClass(m, moduleClass) } override def newFreeTermSymbol(name: TermName, value: => Any, flags: Long = 0L, origin: String = null): FreeTermSymbol = new FreeTermSymbol(name, value, origin) with SynchronizedTermSymbol initFlags flags @@ -28,40 +24,35 @@ private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: Symb trait SynchronizedSymbol extends Symbol { - def gilSynchronizedIfNotInited[T](body: => T): T = { - if (isFullyInitialized) body - else gilSynchronized { body } - } - - override def validTo = gilSynchronizedIfNotInited { super.validTo } - override def info = gilSynchronizedIfNotInited { super.info } - override def rawInfo: Type = gilSynchronizedIfNotInited { super.rawInfo } - - override def typeParams: List[Symbol] = gilSynchronizedIfNotInited { - if (isCompilerUniverse) super.typeParams - else { - if (isMonomorphicType) Nil - else { - // analogously to the "info" getter, here we allow for two completions: - // one: sourceCompleter to LazyType, two: LazyType to completed type - if (validTo == NoPeriod) - rawInfo load this - if (validTo == NoPeriod) - rawInfo load this - - rawInfo.typeParams - } - } - } - override def unsafeTypeParams: List[Symbol] = gilSynchronizedIfNotInited { - if (isCompilerUniverse) super.unsafeTypeParams - else { - if (isMonomorphicType) Nil - else rawInfo.typeParams - } - } - - override def isStable: Boolean = gilSynchronized { super.isStable } + override def rawflags = synchronized { super.rawflags } + override def rawflags_=(x: Long) = synchronized { super.rawflags_=(x) } + + override def rawowner = synchronized { super.rawowner } + override def owner_=(owner: Symbol) = synchronized { super.owner_=(owner) } + + override def validTo = synchronized { super.validTo } + override def validTo_=(x: Period) = synchronized { super.validTo_=(x) } + + override def pos = synchronized { super.pos } + override def setPos(pos: Position): this.type = { synchronized { super.setPos(pos) }; this } + + override def privateWithin = synchronized { super.privateWithin } + override def privateWithin_=(sym: Symbol) = synchronized { super.privateWithin_=(sym) } + + override def info = synchronized { super.info } + override def info_=(info: Type) = synchronized { super.info_=(info) } + override def updateInfo(info: Type): Symbol = synchronized { super.updateInfo(info) } + override def rawInfo: Type = synchronized { super.rawInfo } + + override def typeParams: List[Symbol] = synchronized { super.typeParams } + + override def reset(completer: Type): this.type = synchronized { super.reset(completer) } + + override def infosString: String = synchronized { super.infosString } + + override def annotations: List[AnnotationInfo] = synchronized { super.annotations } + override def setAnnotations(annots: List[AnnotationInfo]): this.type = { synchronized { super.setAnnotations(annots) }; this } + // ------ creators ------------------------------------------------------------------- @@ -101,38 +92,49 @@ private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: Symb override protected def createModuleSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol = new ModuleSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags - override protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol = - createModuleSymbol(name, pos, newFlags) - - override protected def createValueParameterSymbol(name: TermName, pos: Position, newFlags: Long) = - new TermSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags + override protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol = createModuleSymbol(name, pos, newFlags) - override protected def createValueMemberSymbol(name: TermName, pos: Position, newFlags: Long) = - new TermSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags + // TODO + // override protected def createValueParameterSymbol(name: TermName, pos: Position, newFlags: Long) + // override protected def createValueMemberSymbol(name: TermName, pos: Position, newFlags: Long) } // ------- subclasses --------------------------------------------------------------------- - trait SynchronizedTermSymbol extends SynchronizedSymbol + trait SynchronizedTermSymbol extends TermSymbol with SynchronizedSymbol { + override def name_=(x: Name) = synchronized { super.name_=(x) } + override def rawname = synchronized { super.rawname } + override def referenced: Symbol = synchronized { super.referenced } + override def referenced_=(x: Symbol) = synchronized { super.referenced_=(x) } + } trait SynchronizedMethodSymbol extends MethodSymbol with SynchronizedTermSymbol { - // we can keep this lock fine-grained, because it's just a cache over asSeenFrom, which makes deadlocks impossible - // unfortunately we cannot elide this lock, because the cache depends on `pre` - private lazy val typeAsMemberOfLock = new Object - override def typeAsMemberOf(pre: Type): Type = gilSynchronizedIfNotInited { typeAsMemberOfLock.synchronized { super.typeAsMemberOf(pre) } } + override def typeAsMemberOf(pre: Type): Type = synchronized { super.typeAsMemberOf(pre) } + override def paramss: List[List[Symbol]] = synchronized { super.paramss } + override def returnType: Type = synchronized { super.returnType } } - trait SynchronizedModuleSymbol extends ModuleSymbol with SynchronizedTermSymbol - trait SynchronizedTypeSymbol extends TypeSymbol with SynchronizedSymbol { - // unlike with typeConstructor, a lock is necessary here, because tpe calculation relies on - // temporarily assigning NoType to tpeCache to detect cyclic reference errors - private lazy val tpeLock = new Object - override def tpe: Type = gilSynchronizedIfNotInited { tpeLock.synchronized { super.tpe } } + override def name_=(x: Name) = synchronized { super.name_=(x) } + override def rawname = synchronized { super.rawname } + override def typeConstructor: Type = synchronized { super.typeConstructor } + override def tpe: Type = synchronized { super.tpe } } - trait SynchronizedClassSymbol extends ClassSymbol with SynchronizedTypeSymbol + trait SynchronizedClassSymbol extends ClassSymbol with SynchronizedTypeSymbol { + override def associatedFile = synchronized { super.associatedFile } + override def associatedFile_=(f: AbstractFile) = synchronized { super.associatedFile_=(f) } + override def thisSym: Symbol = synchronized { super.thisSym } + override def thisType: Type = synchronized { super.thisType } + override def typeOfThis: Type = synchronized { super.typeOfThis } + override def typeOfThis_=(tp: Type) = synchronized { super.typeOfThis_=(tp) } + override def children = synchronized { super.children } + override def addChild(sym: Symbol) = synchronized { super.addChild(sym) } + } - trait SynchronizedModuleClassSymbol extends ModuleClassSymbol with SynchronizedClassSymbol + trait SynchronizedModuleClassSymbol extends ModuleClassSymbol with SynchronizedClassSymbol { + override def sourceModule = synchronized { super.sourceModule } + override def implicitMembers: Scope = synchronized { super.implicitMembers } + } } diff --git a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala index 939363f8b4..a3e7c28ca4 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala @@ -12,9 +12,8 @@ private[reflect] trait SynchronizedTypes extends internal.Types { self: SymbolTa // No sharing of map objects: override protected def commonOwnerMap = new CommonOwnerMap - // we can keep this lock fine-grained, because super.unique just updates the cache - // and, in particular, doesn't call any reflection APIs which makes deadlocks impossible - private lazy val uniqueLock = new Object + private object uniqueLock + private val uniques = WeakHashMap[Type, WeakReference[Type]]() override def unique[T <: Type](tp: T): T = uniqueLock.synchronized { // we need to have weak uniques for runtime reflection @@ -38,35 +37,46 @@ private[reflect] trait SynchronizedTypes extends internal.Types { self: SymbolTa } class SynchronizedUndoLog extends UndoLog { - final override def lock(): Unit = gil.lock() - final override def unlock(): Unit = gil.unlock() + private val actualLock = new java.util.concurrent.locks.ReentrantLock + + final override def lock(): Unit = actualLock.lock() + final override def unlock(): Unit = actualLock.unlock() } override protected def newUndoLog = new SynchronizedUndoLog override protected def baseTypeOfNonClassTypeRef(tpe: NonClassTypeRef, clazz: Symbol) = - gilSynchronized { super.baseTypeOfNonClassTypeRef(tpe, clazz) } + synchronized { super.baseTypeOfNonClassTypeRef(tpe, clazz) } + + private object subsametypeLock override def isSameType(tp1: Type, tp2: Type): Boolean = - gilSynchronized { super.isSameType(tp1, tp2) } + subsametypeLock.synchronized { super.isSameType(tp1, tp2) } override def isDifferentType(tp1: Type, tp2: Type): Boolean = - gilSynchronized { super.isDifferentType(tp1, tp2) } + subsametypeLock.synchronized { super.isDifferentType(tp1, tp2) } override def isSubType(tp1: Type, tp2: Type, depth: Int): Boolean = - gilSynchronized { super.isSubType(tp1, tp2, depth) } + subsametypeLock.synchronized { super.isSubType(tp1, tp2, depth) } + + private object lubglbLock override def glb(ts: List[Type]): Type = - gilSynchronized { super.glb(ts) } + lubglbLock.synchronized { super.glb(ts) } override def lub(ts: List[Type]): Type = - gilSynchronized { super.lub(ts) } + lubglbLock.synchronized { super.lub(ts) } + + private object indentLock + + override protected def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = { + indentLock.synchronized { super.explain(op, p, tp1, arg2) } + } - override protected def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = - gilSynchronized { super.explain(op, p, tp1, arg2) } + private object toStringLock override protected def typeToString(tpe: Type): String = - gilSynchronized(super.typeToString(tpe)) + toStringLock.synchronized(super.typeToString(tpe)) /* The idea of caches is as follows. * When in reflexive mode, a cache is either null, or one sentinal @@ -79,18 +89,18 @@ private[reflect] trait SynchronizedTypes extends internal.Types { self: SymbolTa */ override protected def defineUnderlyingOfSingleType(tpe: SingleType) = - gilSynchronized { super.defineUnderlyingOfSingleType(tpe) } + tpe.synchronized { super.defineUnderlyingOfSingleType(tpe) } override protected def defineBaseTypeSeqOfCompoundType(tpe: CompoundType) = - gilSynchronized { super.defineBaseTypeSeqOfCompoundType(tpe) } + tpe.synchronized { super.defineBaseTypeSeqOfCompoundType(tpe) } override protected def defineBaseClassesOfCompoundType(tpe: CompoundType) = - gilSynchronized { super.defineBaseClassesOfCompoundType(tpe) } + tpe.synchronized { super.defineBaseClassesOfCompoundType(tpe) } override protected def defineParentsOfTypeRef(tpe: TypeRef) = - gilSynchronized { super.defineParentsOfTypeRef(tpe) } + tpe.synchronized { super.defineParentsOfTypeRef(tpe) } override protected def defineBaseTypeSeqOfTypeRef(tpe: TypeRef) = - gilSynchronized { super.defineBaseTypeSeqOfTypeRef(tpe) } + tpe.synchronized { super.defineBaseTypeSeqOfTypeRef(tpe) } } diff --git a/src/reflect/scala/reflect/runtime/TwoWayCache.scala b/src/reflect/scala/reflect/runtime/TwoWayCache.scala new file mode 100644 index 0000000000..05debcba65 --- /dev/null +++ b/src/reflect/scala/reflect/runtime/TwoWayCache.scala @@ -0,0 +1,66 @@ +package scala.reflect +package runtime + +import scala.collection.mutable.WeakHashMap +import java.lang.ref.WeakReference + +/** A cache that maintains a bijection between Java reflection type `J` + * and Scala reflection type `S`. + * + * The cache is two-way weak (i.e. is powered by weak references), + * so that neither Java artifacts prevent Scala artifacts from being garbage collected, + * nor the other way around. + */ +private[runtime] class TwoWayCache[J, S] { + + private val toScalaMap = new WeakHashMap[J, WeakReference[S]] + private val toJavaMap = new WeakHashMap[S, WeakReference[J]] + + def enter(j: J, s: S) = synchronized { + // debugInfo("cached: "+j+"/"+s) + toScalaMap(j) = new WeakReference(s) + toJavaMap(s) = new WeakReference(j) + } + + private object SomeRef { + def unapply[T](optRef: Option[WeakReference[T]]): Option[T] = + if (optRef.nonEmpty) { + val result = optRef.get.get + if (result != null) Some(result) else None + } else None + } + + def toScala(key: J)(body: => S): S = synchronized { + toScalaMap get key match { + case SomeRef(v) => + v + case _ => + val result = body + enter(key, result) + result + } + } + + def toJava(key: S)(body: => J): J = synchronized { + toJavaMap get key match { + case SomeRef(v) => + v + case _ => + val result = body + enter(result, key) + result + } + } + + def toJavaOption(key: S)(body: => Option[J]): Option[J] = synchronized { + toJavaMap get key match { + case SomeRef(v) => + Some(v) + case _ => + val result = body + for (value <- result) enter(value, key) + result + } + } +} + diff --git a/src/reflect/scala/reflect/runtime/TwoWayCaches.scala b/src/reflect/scala/reflect/runtime/TwoWayCaches.scala deleted file mode 100644 index 6e2890e536..0000000000 --- a/src/reflect/scala/reflect/runtime/TwoWayCaches.scala +++ /dev/null @@ -1,68 +0,0 @@ -package scala.reflect -package runtime - -import scala.collection.mutable.WeakHashMap -import java.lang.ref.WeakReference - -/** A cache that maintains a bijection between Java reflection type `J` - * and Scala reflection type `S`. - * - * The cache is two-way weak (i.e. is powered by weak references), - * so that neither Java artifacts prevent Scala artifacts from being garbage collected, - * nor the other way around. - */ -private[runtime] trait TwoWayCaches { self: SymbolTable => - class TwoWayCache[J, S] { - - private val toScalaMap = new WeakHashMap[J, WeakReference[S]] - private val toJavaMap = new WeakHashMap[S, WeakReference[J]] - - def enter(j: J, s: S) = gilSynchronized { - // debugInfo("cached: "+j+"/"+s) - toScalaMap(j) = new WeakReference(s) - toJavaMap(s) = new WeakReference(j) - } - - private object SomeRef { - def unapply[T](optRef: Option[WeakReference[T]]): Option[T] = - if (optRef.nonEmpty) { - val result = optRef.get.get - if (result != null) Some(result) else None - } else None - } - - def toScala(key: J)(body: => S): S = gilSynchronized { - toScalaMap get key match { - case SomeRef(v) => - v - case _ => - val result = body - enter(key, result) - result - } - } - - def toJava(key: S)(body: => J): J = gilSynchronized { - toJavaMap get key match { - case SomeRef(v) => - v - case _ => - val result = body - enter(result, key) - result - } - } - - def toJavaOption(key: S)(body: => Option[J]): Option[J] = gilSynchronized { - toJavaMap get key match { - case SomeRef(v) => - Some(v) - case _ => - val result = body - for (value <- result) enter(value, key) - result - } - } - } -} - |