Skip to content

Allow MiniPhase to be DenotTransformer & LazyVals #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 20, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions src/dotty/runtime/LazyHolders.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package dotty.runtime

/**
* Classes used as holders for local lazy vals
*/
class LazyInt(init: => Int) {
lazy val value = init
}

class LazyLong(init: => Long) {
lazy val value = init
}

class LazyBoolean(init: => Boolean) {
lazy val value = init
}

class LazyDouble(init: => Double) {
lazy val value = init
}

class LazyFloat(init: => Float) {
lazy val value = init
}

class LazyByte(init: => Byte) {
lazy val value = init
}

class LazyRef(init: => AnyRef) {
lazy val value = init
}

class LazyShort(init: => Short) {
lazy val value = init
}

class LazyChar(init: => Char) {
lazy val value = init
}
79 changes: 79 additions & 0 deletions src/dotty/runtime/LazyVals.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package dotty.runtime

import scala.annotation.tailrec

/**
* Helper methods used in thread-safe lazy vals.
*/
object LazyVals {
private val unsafe = scala.concurrent.util.Unsafe.instance

final val BITS_PER_LAZY_VAL = 2
final val LAZY_VAL_MASK = 3

@inline def STATE(cur: Long, ord: Long) = (cur >> (ord * BITS_PER_LAZY_VAL)) & LAZY_VAL_MASK
@inline def CAS(t: Object, offset: Long, e: Long, v: Long, ord: Int) = {
val mask = ~(LAZY_VAL_MASK << ord * BITS_PER_LAZY_VAL)
val n = (e & mask) | (v << (ord * BITS_PER_LAZY_VAL))
compareAndSet(t, offset, e, n)
}
@inline def setFlag(t: Object, offset: Long, v: Int, ord: Int) = {
var retry = true
while (retry) {
val cur = get(t, offset)
if (STATE(cur, ord) == 1) retry = CAS(t, offset, cur, v, ord)
else {
// cur == 2, somebody is waiting on monitor
if (CAS(t, offset, cur, v, ord)) {
val monitor = getMonitor(t, ord)
monitor.synchronized {
monitor.notifyAll()
}
retry = false
}
}
}
}
@inline def wait4Notification(t: Object, offset: Long, cur: Long, ord: Int) = {
var retry = true
while (retry) {
val cur = get(t, offset)
val state = STATE(cur, ord)
if (state == 1) CAS(t, offset, cur, 2, ord)
else if (state == 2) {
val monitor = getMonitor(t, ord)
monitor.synchronized {
monitor.wait()
}
}
else retry = false
}
}

@inline def compareAndSet(t: Object, off: Long, e: Long, v: Long) = unsafe.compareAndSwapLong(t, off, e, v)
@inline def get(t: Object, off: Long) = unsafe.getLongVolatile(t, off)

val processors: Int = java.lang.Runtime.getRuntime.availableProcessors()
val base: Int = 8 * processors * processors
val monitors: Array[Object] = (0 to base).map {
x => new Object()
}.toArray

@inline def getMonitor(obj: Object, fieldId: Int = 0) = {
var id = (java.lang.System.identityHashCode(obj) + fieldId) % base
if (id < 0) id += base
monitors(id)
}

@inline def getOffset(obj: Object, name: String) = unsafe.objectFieldOffset(obj.getClass.getDeclaredField(name))

object Names {
final val state = "STATE"
final val cas = "CAS"
final val setFlag = "setFlag"
final val wait4Notification = "wait4Notification"
final val compareAndSet = "compareAndSet"
final val get = "get"
final val getOffset = "getOffset"
}
}
16 changes: 14 additions & 2 deletions src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,25 @@ import Symbols._
import typer.{FrontEnd, Typer, Mode, ImportInfo}
import reporting.ConsoleReporter
import dotty.tools.dotc.core.Phases.Phase
import dotty.tools.dotc.transform.{UncurryTreeTransform, LazyValsCreateCompanionObjects, LazyValTranformContext}
import dotty.tools.dotc.transform.TreeTransforms.{TreeTransform, TreeTransformer}
import dotty.tools.dotc.transform.PostTyperTransformers.PostTyperTransformer
import dotty.tools.dotc.core.DenotTransformers.DenotTransformer
import dotty.tools.dotc.core.Denotations.SingleDenotation
import dotty.tools.dotc.transform.TreeTransforms.Separator

class Compiler {

def phases: List[Phase] = List(new FrontEnd)
def phases: List[List[Phase]] = List(
List(new FrontEnd), List(new LazyValsCreateCompanionObjects),
//force separataion between lazyVals and LVCreateCO
List(new LazyValTranformContext().transformer, new UncurryTreeTransform)
)

var runId = 1
def nextRunId = { runId += 1; runId }
def nextRunId = {
runId += 1; runId
}

def rootContext(implicit ctx: Context): Context = {
ctx.definitions.init(ctx)
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/Run.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Run(comp: Compiler)(implicit ctx: Context) {
def compileSources(sources: List[SourceFile]) = Stats.monitorHeartBeat {
if (sources forall (_.exists)) {
units = sources map (new CompilationUnit(_))
for (phase <- ctx.allPhases) {
for (phase <- ctx.allPhases.init) {
if (!ctx.reporter.hasErrors)
phase.runOn(units)
}
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,7 @@ object Trees {
}
}

abstract class TreeTransformer(val cpy: TreeCopier = inst.cpy) {
abstract class TreeMap(val cpy: TreeCopier = inst.cpy) {

def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
case Ident(name) =>
Expand Down
8 changes: 4 additions & 4 deletions src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -334,10 +334,10 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
shallowFold[Option[tpd.Tree]](None)((accum, tree) => if (pred(tree)) Some(tree) else accum)

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

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

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

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

/** The current tree map composed with a substitution [from -> to] */
def withSubstitution(from: List[Symbol], to: List[Symbol]) =
new TreeMapper(
new TreeTypeMap(
typeMap andThen ((tp: Type) => tp.substSym(from, to)),
ownerMap andThen (from zip to).toMap)
}
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
}
}

abstract class UntypedTreeTransformer(cpy: UntypedTreeCopier = untpd.cpy) extends TreeTransformer(cpy) {
abstract class UntypedTreeMap(cpy: UntypedTreeCopier = untpd.cpy) extends TreeMap(cpy) {
override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
case ModuleDef(mods, name, impl) =>
cpy.ModuleDef(tree, mods, name, transformSub(impl))
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/config/Printers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ object Printers {
val completions = noPrinter
val gadts = noPrinter
val incremental = noPrinter

val config = noPrinter
}
14 changes: 11 additions & 3 deletions src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import collection.immutable.BitSet
import printing._
import config.{Settings, ScalaSettings, Platform, JavaPlatform}
import language.implicitConversions

import DenotTransformers.DenotTransformer
object Contexts {

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

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

def withSetting[T](setting: Setting[T], value: T): this.type =
withSettings(setting.updateIn(sstate, value))
Expand Down Expand Up @@ -361,7 +362,6 @@ object Contexts {
* compiler run.
*/
class ContextBase extends ContextState
with Transformers.TransformerBase
with Denotations.DenotationsBase
with Phases.PhasesBase {

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

// Set up some phases to get started */
usePhases(SomePhase :: Nil)
usePhases(List(List(SomePhase)))

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

/** Phases with consecutive Transforms groupped into a single phase */
private [core] var squashedPhases: Array[Phase] = _

/** Next denotation transformer id */
private[core] var nextDenotTransformerId: Array[Int] = _

private[core] var denotTransformers: Array[DenotTransformer] = _

// Printers state
/** Number of recursive invocations of a show method on cuyrrent stack */
private[dotc] var toTextRecursions = 0
Expand Down
2 changes: 2 additions & 0 deletions src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ class Definitions {
lazy val AnnotationDefaultAnnot = ctx.requiredClass("dotty.annotation.internal.AnnotationDefault")
lazy val ThrowsAnnot = ctx.requiredClass("scala.throws")
lazy val UncheckedAnnot = ctx.requiredClass("scala.unchecked")
lazy val VolatileAnnot = ctx.requiredClass("scala.volatile")

// convenient one-parameter method types
def methOfAny(tp: Type) = MethodType(List(AnyType), tp)
Expand Down Expand Up @@ -266,6 +267,7 @@ class Definitions {
def JavaRepeatedParamType = JavaRepeatedParamClass.typeRef
def ThrowableType = ThrowableClass.typeRef
def OptionType = OptionClass.typeRef
def VolatileAnnotType = VolatileAnnot.typeRef

def ClassType(arg: Type)(implicit ctx: Context) = {
val ctype = ClassClass.typeRef
Expand Down
33 changes: 33 additions & 0 deletions src/dotty/tools/dotc/core/DenotTransformers.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package dotty.tools.dotc
package core

import Periods._
import SymDenotations._
import Contexts._
import Types._
import Denotations._
import Phases._
import java.lang.AssertionError
import dotty.tools.dotc.util.DotClass

object DenotTransformers {

/** A transformer group contains a sequence of transformers,
* ordered by the phase where they apply. Transformers are added
* to a group via `install`.
*/

/** A transformer transforms denotations at a given phase */
trait DenotTransformer extends Phase {

/** The last phase during which the transformed denotations are valid */
def lastPhaseId(implicit ctx: Context) = ctx.nextDenotTransformerId(id + 1)

/** The validity period of the transformer in the given context */
def validFor(implicit ctx: Context): Period =
Period(ctx.runId, id, lastPhaseId)

/** The transformation method */
def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation
}
}
Loading