Skip to content

Commit

Permalink
Specialization landed in trunk.
Browse files Browse the repository at this point in the history
  • Loading branch information
dragos committed Jun 18, 2009
1 parent be8e3c6 commit 3ee6b36
Show file tree
Hide file tree
Showing 58 changed files with 3,088 additions and 55 deletions.
16 changes: 16 additions & 0 deletions TODO
@@ -0,0 +1,16 @@
Ideas and things to be done, in random order
============================================

* Private members that are specialized should be name-mangled. The are
now turned to 'protected'. Probably 'expandName' is enough (keep the old
symbols).

* specialize methods only when representation changes (basically when
value parameters have naked type parameters or arrays of naked type
params).

* handle specialized type members (whatever that may mean)

* Could we have better runtime types for specialized instances?

* Could we have user provided specializations?
10 changes: 9 additions & 1 deletion src/compiler/scala/tools/nsc/Global.scala
Expand Up @@ -390,7 +390,13 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
val runsRightAfter = None
} with ExplicitOuter

// phaseName = "erasure"
// phaseName = "specialize"
object specializeTypes extends {
val global: Global.this.type = Global.this
val runsAfter = List[String]("")
val runsRightAfter = Some("tailcalls")
} with SpecializeTypes

object erasure extends {
val global: Global.this.type = Global.this
val runsAfter = List[String]("explicitouter")
Expand Down Expand Up @@ -557,6 +563,8 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable

phasesSet += uncurry // uncurry, translate function values to anonymous classes
phasesSet += tailCalls // replace tail calls by jumps
if (settings.specialize.value)
phasesSet += specializeTypes
phasesSet += explicitOuter // replace C.this by explicit outer pointers, eliminate pattern matching
phasesSet += erasure // erase generic types to Java 1.4 types, add interfaces for traits
phasesSet += lazyVals //
Expand Down
1 change: 1 addition & 0 deletions src/compiler/scala/tools/nsc/Settings.scala
Expand Up @@ -792,6 +792,7 @@ trait ScalacSettings {
List("no-cache", "mono-cache", "poly-cache", "invoke-dynamic"), "poly-cache") .
withHelpSyntax("-Ystruct-dispatch:<method>")
val Xwarndeadcode = BooleanSetting ("-Ywarn-dead-code", "Emit warnings for dead code")
val specialize = BooleanSetting ("-Yspecialize", "Specialize generic code on types.")

/**
* -P "Plugin" settings
Expand Down
29 changes: 18 additions & 11 deletions src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
Expand Up @@ -48,7 +48,7 @@ abstract class TreeBrowsers {
*/
class SwingBrowser {

def browse(t: Tree): Unit = {
def browse(t: Tree): Tree = {
val tm = new ASTTreeModel(t)

val frame = new BrowserFrame()
Expand All @@ -59,6 +59,7 @@ abstract class TreeBrowsers {

// wait for the frame to be closed
lock.acquire
t
}

def browse(units: Iterator[CompilationUnit]): Unit =
Expand Down Expand Up @@ -138,7 +139,7 @@ abstract class TreeBrowsers {
var splitPane: JSplitPane = _
var treeModel: TreeModel = _

val textArea: JTextArea = new JTextArea(20, 150)
val textArea: JTextArea = new JTextArea(30, 120)
val infoPanel = new TextInfoPanel()

/** Create a frame that displays the AST.
Expand Down Expand Up @@ -201,7 +202,7 @@ abstract class TreeBrowsers {
/**
* Present detailed information about the selected tree node.
*/
class TextInfoPanel extends JTextArea(30, 40) {
class TextInfoPanel extends JTextArea(20, 50) {

setFont(new Font("monospaced", Font.PLAIN, 12))

Expand All @@ -216,17 +217,24 @@ abstract class TreeBrowsers {
case _ =>
str.append("tree.pos: ").append(t.pos)
str.append("\nSymbol: ").append(TreeInfo.symbolText(t))
str.append("\nSymbol info: \n")
TreeInfo.symbolTypeDoc(t).format(getWidth() / getColumnWidth(), buf)
str.append(buf.toString())
str.append("\nSymbol owner: ").append(
if ((t.symbol ne null) && t.symbol != NoSymbol)
t.symbol.owner.toString
else
"NoSymbol has no owner")
if ((t.symbol ne null) && t.symbol.isType)
str.append("\ntermSymbol: " + t.symbol.tpe.termSymbol + "\ntypeSymbol: " + t.symbol.tpe.typeSymbol)
str.append("\nSymbol tpe: ")
if (t.symbol ne null) {
str.append(t.symbol.tpe).append("\n")
buf = new StringWriter()
TypePrinter.toDocument(t.symbol.tpe).format(getWidth() / getColumnWidth(), buf)
str.append(buf.toString())
}
str.append("\nSymbol Attributes: \n").append(TreeInfo.symbolAttributes(t))
str.append("\n\nSymbol info: \n")
TreeInfo.symbolTypeDoc(t).format(getWidth() / getColumnWidth(), buf)
str.append(buf.toString())
str.append("\n\nSymbol Attributes: \n").append(TreeInfo.symbolAttributes(t))
str.append("\ntree.tpe: ")
if (t.tpe ne null) {
str.append(t.tpe.toString()).append("\n")
Expand All @@ -239,7 +247,6 @@ abstract class TreeBrowsers {
}
}


/** Computes different information about a tree node. It
* is used as central place to do all pattern matching against
* Tree.
Expand Down Expand Up @@ -567,7 +574,7 @@ abstract class TreeBrowsers {
if ((s ne null) && (s != NoSymbol)) {
var str = flagsToString(s.flags)
if (s.isStaticMember) str = str + " isStatic ";
str
str + " annotations: " + s.annotations.mkString("", " ", "")
}
else ""
}
Expand Down Expand Up @@ -620,7 +627,7 @@ abstract class TreeBrowsers {
Document.group(
Document.nest(4, "TypeRef(" :/:
toDocument(pre) :: ", " :/:
sym.name.toString() :: ", " :/:
sym.name.toString() + sym.idString :: ", " :/:
"[ " :: toDocument(args) ::"]" :: ")")
)

Expand All @@ -641,7 +648,7 @@ abstract class TreeBrowsers {
Document.group(
Document.nest(4,"ClassInfoType(" :/:
toDocument(parents) :: ", " :/:
clazz.name.toString() :: ")")
clazz.name.toString() + clazz.idString :: ")")
)

case MethodType(params, result) =>
Expand Down
53 changes: 28 additions & 25 deletions src/compiler/scala/tools/nsc/ast/TreePrinters.scala
Expand Up @@ -57,7 +57,10 @@ abstract class TreePrinters {

def printTypeParams(ts: List[TypeDef]) {
if (!ts.isEmpty) {
print("["); printSeq(ts){printParam}{print(", ")}; print("]")
print("["); printSeq(ts){ t =>
printAnnotations(t)
printParam(t)
}{print(", ")}; print("]")
}
}

Expand Down Expand Up @@ -87,7 +90,6 @@ abstract class TreePrinters {
printColumn(List(tree), "{", ";", "}")
}
}

def symName(tree: Tree, name: Name): String =
if (tree.symbol != null && tree.symbol != NoSymbol) {
((if (tree.symbol.isMixinConstructor) "/*"+tree.symbol.owner.name+"*/" else "") +
Expand Down Expand Up @@ -177,6 +179,7 @@ abstract class TreePrinters {

case TypeDef(mods, name, tparams, rhs) =>
if (mods hasFlag (PARAM | DEFERRED)) {
printAnnotations(tree)
printModifiers(tree, mods); print("type "); printParam(tree)
} else {
printAnnotations(tree)
Expand All @@ -194,19 +197,19 @@ abstract class TreePrinters {
if (isNotRemap(s)) s._1.toString else s._1.toString + "=>" + s._2.toString

print("import "); print(expr)
print(".")
print(".")
selectors match {
case List(s) =>
// If there is just one selector and it is not remapping a name, no braces are needed
if (isNotRemap(s)) {
print(selectorToString(s))
} else {
print("{"); print(selectorToString(s)); print("}")
}
if (isNotRemap(s)) {
print(selectorToString(s))
} else {
print("{"); print(selectorToString(s)); print("}")
}
// If there is more than one selector braces are always needed
case many =>
case many =>
print(many.map(selectorToString).mkString("{", ", ", "}"))
}
}

case DocDef(comment, definition) =>
print(comment); println; print(definition)
Expand Down Expand Up @@ -410,21 +413,21 @@ abstract class TreePrinters {
def create(writer: PrintWriter): TreePrinter = new TreePrinter(writer)
def create(stream: OutputStream): TreePrinter = create(new PrintWriter(stream))
def create(): TreePrinter = {
/** A writer that writes to the current Console and
* is sensitive to replacement of the Console's
* output stream.
*/
object ConsoleWriter extends Writer {
override def write(str: String) { Console.print(str) }

def write(cbuf: Array[Char], off: Int, len: Int) {
val str = new String(cbuf, off, len)
write(str)
}

def close = { /* do nothing */ }
def flush = { /* do nothing */ }
}
create(new PrintWriter(ConsoleWriter))
}
/** A writer that writes to the current Console and
* is sensitive to replacement of the Console's
* output stream.
*/
object ConsoleWriter extends Writer {
override def write(str: String) { Console.print(str) }

def write(cbuf: Array[Char], off: Int, len: Int) {
val str = new String(cbuf, off, len)
write(str)
}

def close = { /* do nothing */ }
def flush = { /* do nothing */ }
}
}
4 changes: 4 additions & 0 deletions src/compiler/scala/tools/nsc/ast/Trees.scala
Expand Up @@ -477,6 +477,10 @@ trait Trees {
def DefDef(sym: Symbol, rhs: Tree): DefDef =
DefDef(sym, Modifiers(sym.flags), rhs)

def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef = {
DefDef(sym, rhs(sym.info.paramss))
}

/** Abstract type, type parameter, or type alias */
case class TypeDef(mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree)
extends MemberDef {
Expand Down
10 changes: 5 additions & 5 deletions src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Expand Up @@ -1725,15 +1725,15 @@ self =>

/** TypeParamClauseOpt ::= [TypeParamClause]
* TypeParamClause ::= `[' VariantTypeParam {`,' VariantTypeParam} `]']
* VariantTypeParam ::= [`+' | `-'] TypeParam
* VariantTypeParam ::= {Annotation} [`+' | `-'] TypeParam
* FunTypeParamClauseOpt ::= [FunTypeParamClause]
* FunTypeParamClause ::= `[' TypeParam {`,' TypeParam} `]']
* TypeParam ::= Id TypeParamClauseOpt TypeBounds [<% Type]
*/
def typeParamClauseOpt(owner: Name, implicitViewBuf: ListBuffer[Tree]): List[TypeDef] = {
def typeParam(): TypeDef = {
def typeParam(ms: Modifiers): TypeDef = {
var mods = ms | Flags.PARAM
val start = in.offset
var mods = Modifiers(Flags.PARAM)
if (owner.isTypeName && isIdent) {
if (in.name == PLUS) {
in.nextToken()
Expand Down Expand Up @@ -1763,10 +1763,10 @@ self =>
newLineOptWhenFollowedBy(LBRACKET)
if (in.token == LBRACKET) {
in.nextToken()
params += typeParam()
params += typeParam(NoMods.withAnnotations(annotations(true, false)))
while (in.token == COMMA) {
in.nextToken()
params += typeParam()
params += typeParam(NoMods.withAnnotations(annotations(true, false)))
}
accept(RBRACKET)
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/symtab/Definitions.scala
Expand Up @@ -500,7 +500,7 @@ trait Definitions {
}

val refClass = new HashMap[Symbol, Symbol]
private val abbrvTag = new HashMap[Symbol, Char]
val abbrvTag = new HashMap[Symbol, Char]

private def newValueClass(name: Name, tag: Char): Symbol = {
val boxedName = sn.Boxed(name)
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/scala/tools/nsc/symtab/Flags.scala
Expand Up @@ -38,7 +38,6 @@ object Flags {
final val BYNAMEPARAM = 0x00010000 // parameter is by name
final val CONTRAVARIANT = 0x00020000 // symbol is a contravariant type variable
final val LABEL = 0x00020000 // method symbol is a label. Set by TailCall
final val DEFAULTINIT = 0x00020000 // field is initialized to the default value (used by checkinit)
final val INCONSTRUCTOR = 0x00020000 // class symbol is defined in this/superclass
// constructor.
final val ABSOVERRIDE = 0x00040000 // combination of abstract & override
Expand Down Expand Up @@ -81,6 +80,8 @@ object Flags {
// after each phase.

final val LOCKED = 0x8000000000L // temporary flag to catch cyclic dependencies
final val SPECIALIZED = 0x10000000000L// symbol is a generated specialized member
final val DEFAULTINIT = 0x20000000000L// symbol is a generated specialized member

final val InitialFlags = 0x0001FFFFFFFFFFFFL // flags that are enabled from phase 1.
final val LateFlags = 0x00FE000000000000L // flags that override flags in 0x1FC.
Expand Down
14 changes: 10 additions & 4 deletions src/compiler/scala/tools/nsc/symtab/Symbols.scala
Expand Up @@ -124,6 +124,10 @@ trait Symbols {
/** Does this symbol have an annotation of the given class? */
def hasAnnotation(cls: Symbol) = annotations exists { _.atp.typeSymbol == cls }

/** Remove all annotations matching the given class. */
def removeAnnotation(cls: Symbol): Unit =
setAnnotations(annotations.remove(_.atp.typeSymbol == cls))

/** set when symbol has a modifier of the form private[X], NoSymbol otherwise.
* Here's some explanation how privateWithin gets combined with access flags:
*
Expand Down Expand Up @@ -988,9 +992,11 @@ trait Symbols {
cloneSymbol(owner)

/** A clone of this symbol, but with given owner */
final def cloneSymbol(owner: Symbol): Symbol =
cloneSymbolImpl(owner).setInfo(info.cloneInfo(this))
final def cloneSymbol(owner: Symbol): Symbol = {
val newSym = cloneSymbolImpl(owner)
newSym.setInfo(info.cloneInfo(newSym))
.setFlag(this.rawflags).setAnnotations(this.annotations)
}

/** Internal method to clone a symbol's implementation without flags or type
*/
Expand Down Expand Up @@ -1537,14 +1543,14 @@ trait Symbols {
}

override def alias: Symbol =
if (hasFlag(SUPERACCESSOR | PARAMACCESSOR | MIXEDIN)) initialize.referenced
if (hasFlag(SUPERACCESSOR | PARAMACCESSOR | MIXEDIN | SPECIALIZED)) initialize.referenced
else NoSymbol

def setAlias(alias: Symbol): TermSymbol = {
assert(alias != NoSymbol, this)
assert(!(alias hasFlag OVERLOADED), alias)

assert(hasFlag(SUPERACCESSOR | PARAMACCESSOR | MIXEDIN), this)
assert(hasFlag(SUPERACCESSOR | PARAMACCESSOR | MIXEDIN | SPECIALIZED), this)
referenced = alias
this
}
Expand Down
11 changes: 7 additions & 4 deletions src/compiler/scala/tools/nsc/transform/Erasure.scala
Expand Up @@ -102,8 +102,8 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
case RefinedType(parents, decls) =>
if (parents.isEmpty) erasedTypeRef(ObjectClass)
else apply(parents.head)
case AnnotatedType(_, atp, _) =>
apply(atp)
case AnnotatedType(_, atp, _) =>
apply(atp)
case ClassInfoType(parents, decls, clazz) =>
ClassInfoType(
if ((clazz == ObjectClass) || (isValueType(clazz))) List()
Expand Down Expand Up @@ -781,7 +781,10 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {

val opc = new overridingPairs.Cursor(root) {
override def exclude(sym: Symbol): Boolean =
!sym.isTerm || sym.hasFlag(PRIVATE) || super.exclude(sym)
(!sym.isTerm || sym.hasFlag(PRIVATE) || super.exclude(sym)
// specialized members have no type history before 'specialize', causing duble def errors for curried defs
|| !sym.hasTypeAt(currentRun.refchecksPhase.id))

override def matches(sym1: Symbol, sym2: Symbol): Boolean =
atPhase(phase.next)(sym1.tpe =:= sym2.tpe)
}
Expand All @@ -794,7 +797,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
opc.overriding.infosString +
opc.overridden.locationString + " " +
opc.overridden.infosString)
doubleDefError(opc.overriding, opc.overridden)
doubleDefError(opc.overriding, opc.overridden)
}
opc.next
}
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/scala/tools/nsc/transform/InfoTransform.scala
Expand Up @@ -22,8 +22,11 @@ trait InfoTransform extends Transform {
new Phase(prev)

protected def changesBaseClasses = true
protected def keepsTypeParams = false

class Phase(prev: scala.tools.nsc.Phase) extends super.Phase(prev) {
override val keepsTypeParams = InfoTransform.this.keepsTypeParams

if (infoTransformers.nextFrom(id).pid != id) {
// this phase is not yet in the infoTransformers
val infoTransformer = new InfoTransformer {
Expand Down

0 comments on commit 3ee6b36

Please sign in to comment.