Skip to content

Commit 2df29a2

Browse files
committed
Merge pull request #81 from DarkDimius/integration/lazy
Allow MiniPhase to be DenotTransformer & LazyVals
2 parents e23b5a2 + 09d02bd commit 2df29a2

32 files changed

+1267
-219
lines changed

src/dotty/runtime/LazyHolders.scala

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package dotty.runtime
2+
3+
/**
4+
* Classes used as holders for local lazy vals
5+
*/
6+
class LazyInt(init: => Int) {
7+
lazy val value = init
8+
}
9+
10+
class LazyLong(init: => Long) {
11+
lazy val value = init
12+
}
13+
14+
class LazyBoolean(init: => Boolean) {
15+
lazy val value = init
16+
}
17+
18+
class LazyDouble(init: => Double) {
19+
lazy val value = init
20+
}
21+
22+
class LazyFloat(init: => Float) {
23+
lazy val value = init
24+
}
25+
26+
class LazyByte(init: => Byte) {
27+
lazy val value = init
28+
}
29+
30+
class LazyRef(init: => AnyRef) {
31+
lazy val value = init
32+
}
33+
34+
class LazyShort(init: => Short) {
35+
lazy val value = init
36+
}
37+
38+
class LazyChar(init: => Char) {
39+
lazy val value = init
40+
}

src/dotty/runtime/LazyVals.scala

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package dotty.runtime
2+
3+
import scala.annotation.tailrec
4+
5+
/**
6+
* Helper methods used in thread-safe lazy vals.
7+
*/
8+
object LazyVals {
9+
private val unsafe = scala.concurrent.util.Unsafe.instance
10+
11+
final val BITS_PER_LAZY_VAL = 2
12+
final val LAZY_VAL_MASK = 3
13+
14+
@inline def STATE(cur: Long, ord: Long) = (cur >> (ord * BITS_PER_LAZY_VAL)) & LAZY_VAL_MASK
15+
@inline def CAS(t: Object, offset: Long, e: Long, v: Long, ord: Int) = {
16+
val mask = ~(LAZY_VAL_MASK << ord * BITS_PER_LAZY_VAL)
17+
val n = (e & mask) | (v << (ord * BITS_PER_LAZY_VAL))
18+
compareAndSet(t, offset, e, n)
19+
}
20+
@inline def setFlag(t: Object, offset: Long, v: Int, ord: Int) = {
21+
var retry = true
22+
while (retry) {
23+
val cur = get(t, offset)
24+
if (STATE(cur, ord) == 1) retry = CAS(t, offset, cur, v, ord)
25+
else {
26+
// cur == 2, somebody is waiting on monitor
27+
if (CAS(t, offset, cur, v, ord)) {
28+
val monitor = getMonitor(t, ord)
29+
monitor.synchronized {
30+
monitor.notifyAll()
31+
}
32+
retry = false
33+
}
34+
}
35+
}
36+
}
37+
@inline def wait4Notification(t: Object, offset: Long, cur: Long, ord: Int) = {
38+
var retry = true
39+
while (retry) {
40+
val cur = get(t, offset)
41+
val state = STATE(cur, ord)
42+
if (state == 1) CAS(t, offset, cur, 2, ord)
43+
else if (state == 2) {
44+
val monitor = getMonitor(t, ord)
45+
monitor.synchronized {
46+
monitor.wait()
47+
}
48+
}
49+
else retry = false
50+
}
51+
}
52+
53+
@inline def compareAndSet(t: Object, off: Long, e: Long, v: Long) = unsafe.compareAndSwapLong(t, off, e, v)
54+
@inline def get(t: Object, off: Long) = unsafe.getLongVolatile(t, off)
55+
56+
val processors: Int = java.lang.Runtime.getRuntime.availableProcessors()
57+
val base: Int = 8 * processors * processors
58+
val monitors: Array[Object] = (0 to base).map {
59+
x => new Object()
60+
}.toArray
61+
62+
@inline def getMonitor(obj: Object, fieldId: Int = 0) = {
63+
var id = (java.lang.System.identityHashCode(obj) + fieldId) % base
64+
if (id < 0) id += base
65+
monitors(id)
66+
}
67+
68+
@inline def getOffset(obj: Object, name: String) = unsafe.objectFieldOffset(obj.getClass.getDeclaredField(name))
69+
70+
object Names {
71+
final val state = "STATE"
72+
final val cas = "CAS"
73+
final val setFlag = "setFlag"
74+
final val wait4Notification = "wait4Notification"
75+
final val compareAndSet = "compareAndSet"
76+
final val get = "get"
77+
final val getOffset = "getOffset"
78+
}
79+
}

src/dotty/tools/dotc/Compiler.scala

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,25 @@ import Symbols._
88
import typer.{FrontEnd, Typer, Mode, ImportInfo}
99
import reporting.ConsoleReporter
1010
import dotty.tools.dotc.core.Phases.Phase
11+
import dotty.tools.dotc.transform.{UncurryTreeTransform, LazyValsCreateCompanionObjects, LazyValTranformContext}
12+
import dotty.tools.dotc.transform.TreeTransforms.{TreeTransform, TreeTransformer}
13+
import dotty.tools.dotc.transform.PostTyperTransformers.PostTyperTransformer
14+
import dotty.tools.dotc.core.DenotTransformers.DenotTransformer
15+
import dotty.tools.dotc.core.Denotations.SingleDenotation
16+
import dotty.tools.dotc.transform.TreeTransforms.Separator
1117

1218
class Compiler {
1319

14-
def phases: List[Phase] = List(new FrontEnd)
20+
def phases: List[List[Phase]] = List(
21+
List(new FrontEnd), List(new LazyValsCreateCompanionObjects),
22+
//force separataion between lazyVals and LVCreateCO
23+
List(new LazyValTranformContext().transformer, new UncurryTreeTransform)
24+
)
1525

1626
var runId = 1
17-
def nextRunId = { runId += 1; runId }
27+
def nextRunId = {
28+
runId += 1; runId
29+
}
1830

1931
def rootContext(implicit ctx: Context): Context = {
2032
ctx.definitions.init(ctx)

src/dotty/tools/dotc/Run.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class Run(comp: Compiler)(implicit ctx: Context) {
3030
def compileSources(sources: List[SourceFile]) = Stats.monitorHeartBeat {
3131
if (sources forall (_.exists)) {
3232
units = sources map (new CompilationUnit(_))
33-
for (phase <- ctx.allPhases) {
33+
for (phase <- ctx.allPhases.init) {
3434
if (!ctx.reporter.hasErrors)
3535
phase.runOn(units)
3636
}

src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@ object Trees {
10771077
}
10781078
}
10791079

1080-
abstract class TreeTransformer(val cpy: TreeCopier = inst.cpy) {
1080+
abstract class TreeMap(val cpy: TreeCopier = inst.cpy) {
10811081

10821082
def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
10831083
case Ident(name) =>

src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -334,10 +334,10 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
334334
shallowFold[Option[tpd.Tree]](None)((accum, tree) => if (pred(tree)) Some(tree) else accum)
335335

336336
def subst(from: List[Symbol], to: List[Symbol])(implicit ctx: Context): ThisTree =
337-
new TreeMapper(typeMap = new ctx.SubstSymMap(from, to)).apply(tree)
337+
new TreeTypeMap(typeMap = new ctx.SubstSymMap(from, to)).apply(tree)
338338

339339
def changeOwner(from: Symbol, to: Symbol)(implicit ctx: Context): ThisTree =
340-
new TreeMapper(ownerMap = (sym => if (sym == from) to else sym)).apply(tree)
340+
new TreeTypeMap(ownerMap = (sym => if (sym == from) to else sym)).apply(tree)
341341

342342
def appliedToTypes(targs: List[Type])(implicit ctx: Context): Tree =
343343
if (targs.isEmpty) tree else TypeApply(tree, targs map (TypeTree(_)))
@@ -347,7 +347,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
347347
def tpes: List[Type] = xs map (_.tpe)
348348
}
349349

350-
class TreeMapper(val typeMap: TypeMap = IdentityTypeMap, val ownerMap: Symbol => Symbol = identity _)(implicit ctx: Context) extends TreeTransformer {
350+
class TreeTypeMap(val typeMap: TypeMap = IdentityTypeMap, val ownerMap: Symbol => Symbol = identity _)(implicit ctx: Context) extends TreeMap {
351351
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = super.transform {
352352
tree.withType(typeMap(tree.tpe)) match {
353353
case bind: tpd.Bind =>
@@ -378,7 +378,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
378378

379379
/** The current tree map composed with a substitution [from -> to] */
380380
def withSubstitution(from: List[Symbol], to: List[Symbol]) =
381-
new TreeMapper(
381+
new TreeTypeMap(
382382
typeMap andThen ((tp: Type) => tp.substSym(from, to)),
383383
ownerMap andThen (from zip to).toMap)
384384
}

src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
285285
}
286286
}
287287

288-
abstract class UntypedTreeTransformer(cpy: UntypedTreeCopier = untpd.cpy) extends TreeTransformer(cpy) {
288+
abstract class UntypedTreeMap(cpy: UntypedTreeCopier = untpd.cpy) extends TreeMap(cpy) {
289289
override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
290290
case ModuleDef(mods, name, impl) =>
291291
cpy.ModuleDef(tree, mods, name, transformSub(impl))

src/dotty/tools/dotc/config/Printers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ object Printers {
2323
val completions = noPrinter
2424
val gadts = noPrinter
2525
val incremental = noPrinter
26-
26+
val config = noPrinter
2727
}

src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import collection.immutable.BitSet
2525
import printing._
2626
import config.{Settings, ScalaSettings, Platform, JavaPlatform}
2727
import language.implicitConversions
28-
28+
import DenotTransformers.DenotTransformer
2929
object Contexts {
3030

3131
/** A context is passed basically everywhere in dotc.
@@ -325,6 +325,7 @@ object Contexts {
325325
def withProperty(prop: (String, Any)): this.type = withMoreProperties(moreProperties + prop)
326326

327327
def withPhase(pid: PhaseId): this.type = withPeriod(Period(runId, pid))
328+
def withPhase(phase: Phase): this.type = withPhase(phase.id)
328329

329330
def withSetting[T](setting: Setting[T], value: T): this.type =
330331
withSettings(setting.updateIn(sstate, value))
@@ -361,7 +362,6 @@ object Contexts {
361362
* compiler run.
362363
*/
363364
class ContextBase extends ContextState
364-
with Transformers.TransformerBase
365365
with Denotations.DenotationsBase
366366
with Phases.PhasesBase {
367367

@@ -387,7 +387,7 @@ object Contexts {
387387
def rootLoader(root: TermSymbol)(implicit ctx: Context): SymbolLoader = platform.rootLoader(root)
388388

389389
// Set up some phases to get started */
390-
usePhases(SomePhase :: Nil)
390+
usePhases(List(List(SomePhase)))
391391

392392
/** The standard definitions */
393393
val definitions = new Definitions
@@ -460,6 +460,14 @@ object Contexts {
460460
/** Phases by id */
461461
private[core] var phases: Array[Phase] = _
462462

463+
/** Phases with consecutive Transforms groupped into a single phase */
464+
private [core] var squashedPhases: Array[Phase] = _
465+
466+
/** Next denotation transformer id */
467+
private[core] var nextDenotTransformerId: Array[Int] = _
468+
469+
private[core] var denotTransformers: Array[DenotTransformer] = _
470+
463471
// Printers state
464472
/** Number of recursive invocations of a show method on cuyrrent stack */
465473
private[dotc] var toTextRecursions = 0

src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ class Definitions {
233233
lazy val AnnotationDefaultAnnot = ctx.requiredClass("dotty.annotation.internal.AnnotationDefault")
234234
lazy val ThrowsAnnot = ctx.requiredClass("scala.throws")
235235
lazy val UncheckedAnnot = ctx.requiredClass("scala.unchecked")
236+
lazy val VolatileAnnot = ctx.requiredClass("scala.volatile")
236237

237238
// convenient one-parameter method types
238239
def methOfAny(tp: Type) = MethodType(List(AnyType), tp)
@@ -266,6 +267,7 @@ class Definitions {
266267
def JavaRepeatedParamType = JavaRepeatedParamClass.typeRef
267268
def ThrowableType = ThrowableClass.typeRef
268269
def OptionType = OptionClass.typeRef
270+
def VolatileAnnotType = VolatileAnnot.typeRef
269271

270272
def ClassType(arg: Type)(implicit ctx: Context) = {
271273
val ctype = ClassClass.typeRef
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package dotty.tools.dotc
2+
package core
3+
4+
import Periods._
5+
import SymDenotations._
6+
import Contexts._
7+
import Types._
8+
import Denotations._
9+
import Phases._
10+
import java.lang.AssertionError
11+
import dotty.tools.dotc.util.DotClass
12+
13+
object DenotTransformers {
14+
15+
/** A transformer group contains a sequence of transformers,
16+
* ordered by the phase where they apply. Transformers are added
17+
* to a group via `install`.
18+
*/
19+
20+
/** A transformer transforms denotations at a given phase */
21+
trait DenotTransformer extends Phase {
22+
23+
/** The last phase during which the transformed denotations are valid */
24+
def lastPhaseId(implicit ctx: Context) = ctx.nextDenotTransformerId(id + 1)
25+
26+
/** The validity period of the transformer in the given context */
27+
def validFor(implicit ctx: Context): Period =
28+
Period(ctx.runId, id, lastPhaseId)
29+
30+
/** The transformation method */
31+
def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation
32+
}
33+
}

0 commit comments

Comments
 (0)