From 84ad34ad7a50a7f9d39d6958a7b8840e16c37a3c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 1 Jul 2015 15:59:33 +0200 Subject: Add @sharable annotation Add @sharable annotation for classes and vals that are presumed to be safely sharable between threads. Also: Document CtxLazy. --- src/dotty/tools/dotc/Bench.scala | 2 +- src/dotty/tools/dotc/ast/Desugar.scala | 2 +- src/dotty/tools/dotc/ast/Trees.scala | 19 ++++++++++--------- src/dotty/tools/dotc/config/Properties.scala | 4 ++-- src/dotty/tools/dotc/config/ScalaVersion.scala | 5 +++-- src/dotty/tools/dotc/core/Contexts.scala | 5 +++-- src/dotty/tools/dotc/core/SymDenotations.scala | 9 +++++---- src/dotty/tools/dotc/core/TypeOps.scala | 5 +++-- src/dotty/tools/dotc/core/Types.scala | 16 +++++++++------- src/dotty/tools/dotc/parsing/Parsers.scala | 4 ++-- src/dotty/tools/dotc/transform/CheckReentrant.scala | 1 - src/dotty/tools/dotc/transform/CtxLazy.scala | 10 +++++++++- src/dotty/tools/dotc/transform/TreeTransform.scala | 5 +++-- src/dotty/tools/dotc/typer/Implicits.scala | 2 +- src/dotty/tools/dotc/typer/Inferencing.scala | 2 +- src/dotty/tools/dotc/typer/ProtoTypes.scala | 4 ++-- src/dotty/tools/dotc/util/SourceFile.scala | 2 +- src/dotty/tools/dotc/util/Stats.scala | 5 +++-- 18 files changed, 59 insertions(+), 43 deletions(-) diff --git a/src/dotty/tools/dotc/Bench.scala b/src/dotty/tools/dotc/Bench.scala index 417054dce..47b5fd6dd 100644 --- a/src/dotty/tools/dotc/Bench.scala +++ b/src/dotty/tools/dotc/Bench.scala @@ -10,7 +10,7 @@ import reporting.Reporter object Bench extends Driver { - private var numRuns = 1 + @sharable private var numRuns = 1 def newCompiler(): Compiler = new Compiler diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala index 660a8dbcb..30467f185 100644 --- a/src/dotty/tools/dotc/ast/Desugar.scala +++ b/src/dotty/tools/dotc/ast/Desugar.scala @@ -209,7 +209,7 @@ object desugar { else tdef } - private val synthetic = Modifiers(Synthetic) + @sharable private val synthetic = Modifiers(Synthetic) private def toDefParam(tparam: TypeDef): TypeDef = tparam.withFlags(Param) diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index 97facaa5d..f63d32b14 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -1,4 +1,5 @@ -package dotty.tools.dotc +package dotty.tools +package dotc package ast import core._ @@ -26,7 +27,7 @@ object Trees { type Untyped = Null /** The total number of created tree nodes, maintained if Stats.enabled */ - var ntrees = 0 + @sharable var ntrees = 0 /** Modifiers and annotations for definitions * @param flags The set flags @@ -68,7 +69,7 @@ object Trees { def tokenPos: Seq[(Token, Position)] = ??? } - private var nextId = 0 // for debugging + @sharable private var nextId = 0 // for debugging type LazyTree = AnyRef /* really: Tree | Lazy[Tree] */ type LazyTreeList = AnyRef /* really: List[Tree] | Lazy[List[Tree]] */ @@ -723,9 +724,9 @@ object Trees { setMods(Modifiers[T](PrivateLocal)) } - val theEmptyTree: Thicket[Type] = Thicket(Nil) - val theEmptyValDef = new EmptyValDef[Type] - val theEmptyModifiers = new Modifiers() + @sharable val theEmptyTree: Thicket[Type] = Thicket(Nil) + @sharable val theEmptyValDef = new EmptyValDef[Type] + @sharable val theEmptyModifiers = new Modifiers() def genericEmptyValDef[T >: Untyped]: ValDef[T] = theEmptyValDef.asInstanceOf[ValDef[T]] def genericEmptyTree[T >: Untyped]: Thicket[T] = theEmptyTree.asInstanceOf[Thicket[T]] @@ -845,9 +846,9 @@ object Trees { type Annotated = Trees.Annotated[T] type Thicket = Trees.Thicket[T] - val EmptyTree: Thicket = genericEmptyTree - val EmptyValDef: ValDef = genericEmptyValDef - val EmptyModifiers: Modifiers = genericEmptyModifiers + @sharable val EmptyTree: Thicket = genericEmptyTree + @sharable val EmptyValDef: ValDef = genericEmptyValDef + @sharable val EmptyModifiers: Modifiers = genericEmptyModifiers // ----- Auxiliary creation methods ------------------ diff --git a/src/dotty/tools/dotc/config/Properties.scala b/src/dotty/tools/dotc/config/Properties.scala index d592a7bb1..ec1f24d06 100644 --- a/src/dotty/tools/dotc/config/Properties.scala +++ b/src/dotty/tools/dotc/config/Properties.scala @@ -12,7 +12,7 @@ object Properties extends PropertiesTrait { /** Scala manifest attributes. */ - val ScalaCompilerVersion = new AttributeName("Scala-Compiler-Version") + @sharable val ScalaCompilerVersion = new AttributeName("Scala-Compiler-Version") } trait PropertiesTrait { @@ -23,7 +23,7 @@ trait PropertiesTrait { protected val propFilename = "/" + propCategory + ".properties" /** The loaded properties */ - protected lazy val scalaProps: java.util.Properties = { + @sharable protected lazy val scalaProps: java.util.Properties = { val props = new java.util.Properties val stream = pickJarBasedOn getResourceAsStream propFilename if (stream ne null) diff --git a/src/dotty/tools/dotc/config/ScalaVersion.scala b/src/dotty/tools/dotc/config/ScalaVersion.scala index 7d4585441..721768d6b 100644 --- a/src/dotty/tools/dotc/config/ScalaVersion.scala +++ b/src/dotty/tools/dotc/config/ScalaVersion.scala @@ -1,6 +1,7 @@ /* @author James Iry */ -package dotty.tools.dotc.config +package dotty.tools +package dotc.config import scala.util.{Try, Success, Failure} @@ -15,7 +16,7 @@ sealed abstract class ScalaVersion extends Ordered[ScalaVersion] { /** * A scala version that sorts higher than all actual versions */ -case object NoScalaVersion extends ScalaVersion { +@sharable case object NoScalaVersion extends ScalaVersion { def unparse = "none" def compare(that: ScalaVersion): Int = that match { diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index c9deaab10..206ef9d8b 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -28,6 +28,7 @@ import printing._ import config.{Settings, ScalaSettings, Platform, JavaPlatform} import language.implicitConversions import DenotTransformers.DenotTransformer + object Contexts { /** A context is passed basically everywhere in dotc. @@ -473,7 +474,7 @@ object Contexts { gadt = new GADTMap(SimpleMap.Empty) } - object NoContext extends Context { + @sharable object NoContext extends Context { lazy val base = unsupported("base") override val implicits: ContextualImplicits = new ContextualImplicits(Nil, null)(this) } @@ -620,7 +621,7 @@ object Contexts { /** implicit conversion that injects all ContextBase members into a context */ implicit def toBase(ctx: Context): ContextBase = ctx.base - val theBase = new ContextBase // !!! DEBUG, so that we can use a minimal context for reporting even in code that normally cannot access a context + // @sharable val theBase = new ContextBase // !!! DEBUG, so that we can use a minimal context for reporting even in code that normally cannot access a context } /** Info that changes on each compiler run */ diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 164b0b8f3..53973b587 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1,4 +1,5 @@ -package dotty.tools.dotc +package dotty.tools +package dotc package core import Periods._, Contexts._, Symbols._, Denotations._, Names._, NameOps._, Annotations._ @@ -1713,8 +1714,8 @@ object SymDenotations { validFor = Period.allInRun(NoRunId) // will be brought forward automatically } - val NoDenotation = new NoDenotation - val NotDefinedHereDenotation = new NoDenotation + @sharable val NoDenotation = new NoDenotation + @sharable val NotDefinedHereDenotation = new NoDenotation // ---- Completion -------------------------------------------------------- @@ -1757,7 +1758,7 @@ object SymDenotations { val NoSymbolFn = (ctx: Context) => NoSymbol /** A missing completer */ - class NoCompleter extends LazyType { + @sharable class NoCompleter extends LazyType { def complete(denot: SymDenotation)(implicit ctx: Context): Unit = unsupported("complete") } diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 2b2ef83a2..b61d39749 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -1,4 +1,5 @@ -package dotty.tools.dotc +package dotty.tools +package dotc package core import Contexts._, Types._, Symbols._, Names._, Flags._, Scopes._ @@ -572,5 +573,5 @@ trait TypeOps { this: Context => // TODO: Make standalone object. object TypeOps { val emptyDNF = (Nil, Set[Name]()) :: Nil - var track = false // !!!DEBUG + @sharable var track = false // !!!DEBUG } diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index d6bb9c3c5..85e2634d4 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -1,4 +1,5 @@ -package dotty.tools.dotc +package dotty.tools +package dotc package core import util.common._ @@ -35,7 +36,7 @@ import language.implicitConversions object Types { - private var nextId = 0 + @sharable private var nextId = 0 /** The class of types. * The principal subclasses and sub-objects are as follows: @@ -73,6 +74,7 @@ object Types { // ----- Tests ----------------------------------------------------- + // debug only: a unique identifier for a type val uniqId = { nextId = nextId + 1 // if (nextId == 19555) @@ -2752,13 +2754,13 @@ object Types { case class ImportType(expr: Tree) extends UncachedGroundType /** Sentinel for "missing type" */ - case object NoType extends CachedGroundType { + @sharable case object NoType extends CachedGroundType { override def exists = false override def computeHash = hashSeed } /** Missing prefix */ - case object NoPrefix extends CachedGroundType { + @sharable case object NoPrefix extends CachedGroundType { override def computeHash = hashSeed } @@ -2775,7 +2777,7 @@ object Types { final class CachedWildcardType(optBounds: Type) extends WildcardType(optBounds) - object WildcardType extends WildcardType(NoType) { + @sharable object WildcardType extends WildcardType(NoType) { def apply(bounds: TypeBounds)(implicit ctx: Context) = unique(new CachedWildcardType(bounds)) } @@ -2983,7 +2985,7 @@ object Types { } } - object IdentityTypeMap extends TypeMap()(NoContext) { + @sharable object IdentityTypeMap extends TypeMap()(NoContext) { override def stopAtStatic = true def apply(tp: Type) = tp } @@ -3208,7 +3210,7 @@ object Types { // ----- Debug --------------------------------------------------------- - var debugTrace = false + @sharable var debugTrace = false val watchList = List[String]( ) map (_.toTypeName) diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index 2a42a7fa9..d6125f236 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -36,11 +36,11 @@ object Parsers { def nonePositive: Boolean = parCounts forall (_ <= 0) } - object Location extends Enumeration { + @sharable object Location extends Enumeration { val InParens, InBlock, InPattern, ElseWhere = Value } - object ParamOwner extends Enumeration { + @sharable object ParamOwner extends Enumeration { val Class, Type, TypeParam, Def = Value } diff --git a/src/dotty/tools/dotc/transform/CheckReentrant.scala b/src/dotty/tools/dotc/transform/CheckReentrant.scala index aff8a1e7b..9fe569581 100644 --- a/src/dotty/tools/dotc/transform/CheckReentrant.scala +++ b/src/dotty/tools/dotc/transform/CheckReentrant.scala @@ -20,7 +20,6 @@ import typer.Checking import Names.Name import NameOps._ import StdNames._ -import util.CtxLazy /** The first tree transform diff --git a/src/dotty/tools/dotc/transform/CtxLazy.scala b/src/dotty/tools/dotc/transform/CtxLazy.scala index c0bac4e11..2b83a95a2 100644 --- a/src/dotty/tools/dotc/transform/CtxLazy.scala +++ b/src/dotty/tools/dotc/transform/CtxLazy.scala @@ -1,7 +1,15 @@ package dotty.tools.dotc -package util +package transform import core.Contexts.Context +/** Utility class for lazy values whose evaluation depends on a context. + * This should be used whenever the evaluation of a lazy expression + * depends on some context, but the value can be re-used afterwards + * with a different context. + * + * A typical use case is a lazy val in a phase object which exists once per root context where + * the expression intiializing the lazy val depends only on the root context, but not any changes afterwards. + */ class CtxLazy[T](expr: Context => T) { private var myValue: T = _ private var forced = false diff --git a/src/dotty/tools/dotc/transform/TreeTransform.scala b/src/dotty/tools/dotc/transform/TreeTransform.scala index 43d77d766..62cd5dbe9 100644 --- a/src/dotty/tools/dotc/transform/TreeTransform.scala +++ b/src/dotty/tools/dotc/transform/TreeTransform.scala @@ -1,4 +1,5 @@ -package dotty.tools.dotc +package dotty.tools +package dotc package transform import dotty.tools.dotc.ast.tpd @@ -194,7 +195,7 @@ object TreeTransforms { } } - val NoTransform = new TreeTransform { + @sharable val NoTransform = new TreeTransform { def phase = unsupported("phase") idx = -1 } diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index f79288e74..5444dddb0 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -681,4 +681,4 @@ class TermRefSet(implicit ctx: Context) extends mutable.Traversable[TermRef] { f(TermRef(pre, sym)) } -object EmptyTermRefSet extends TermRefSet()(NoContext) +@sharable object EmptyTermRefSet extends TermRefSet()(NoContext) diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala index 79e00db6b..8df544dd6 100644 --- a/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/src/dotty/tools/dotc/typer/Inferencing.scala @@ -257,7 +257,7 @@ trait Inferencing { this: Checking => } /** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */ -object ForceDegree extends Enumeration { +@sharable object ForceDegree extends Enumeration { val none, // don't force type variables noBottom, // force type variables, fail if forced to Nothing or Null all = Value // force type variables, don't fail diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala index 13011cb85..cd33fce30 100644 --- a/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -151,7 +151,7 @@ object ProtoTypes { * operation is further selection. In this case, the expression need not be a value. * @see checkValue */ - object AnySelectionProto extends SelectionProto(nme.WILDCARD, WildcardType, NoViewsAllowed) + @sharable object AnySelectionProto extends SelectionProto(nme.WILDCARD, WildcardType, NoViewsAllowed) /** A prototype for selections in pattern constructors */ class UnapplySelectionProto(name: Name) extends SelectionProto(name, WildcardType, NoViewsAllowed) @@ -308,7 +308,7 @@ object ProtoTypes { * * [] _ */ - object AnyFunctionProto extends UncachedGroundType with MatchAlways + @sharable object AnyFunctionProto extends UncachedGroundType with MatchAlways /** Add all parameters in given polytype `pt` to the constraint's domain. * If the constraint contains already some of these parameters in its domain, diff --git a/src/dotty/tools/dotc/util/SourceFile.scala b/src/dotty/tools/dotc/util/SourceFile.scala index 5e8f85e28..20933976e 100644 --- a/src/dotty/tools/dotc/util/SourceFile.scala +++ b/src/dotty/tools/dotc/util/SourceFile.scala @@ -131,7 +131,7 @@ case class SourceFile(file: AbstractFile, content: Array[Char]) { override def toString = file.toString } -object NoSource extends SourceFile("", Nil) { +@sharable object NoSource extends SourceFile("", Nil) { override def exists = false } diff --git a/src/dotty/tools/dotc/util/Stats.scala b/src/dotty/tools/dotc/util/Stats.scala index d899e9546..fdd3602c9 100644 --- a/src/dotty/tools/dotc/util/Stats.scala +++ b/src/dotty/tools/dotc/util/Stats.scala @@ -1,10 +1,11 @@ -package dotty.tools.dotc +package dotty.tools +package dotc package util import core.Contexts._ import collection.mutable -object Stats { +@sharable object Stats { final val enabled = true -- cgit v1.2.3