Skip to content

Commit 1817f58

Browse files
committed
Move TypeSpecializer before ElimByName and implement check for @specialized
1 parent 83bf74b commit 1817f58

File tree

5 files changed

+43
-73
lines changed

5 files changed

+43
-73
lines changed

src/dotty/tools/dotc/Compiler.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,16 @@ class Compiler {
5050
List(new PatternMatcher,
5151
new ExplicitOuter,
5252
new Splitter),
53-
List(new SeqLiterals,
53+
List(new TypeSpecializer),
54+
List(new LazyVals,
55+
new ElimByName,
56+
new SeqLiterals,
5457
new InterceptedMethods,
5558
new Literalize,
5659
new Getters,
5760
new ClassTags,
5861
new ElimByName,
5962
new ResolveSuper),
60-
List(new TypeSpecializer),
6163
List(new Erasure),
6264
List(new ElimErasedValueType,
6365
new VCInline,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ class ScalaSettings extends Settings.SettingGroup {
152152
val YnoDeepSubtypes = BooleanSetting("-Yno-deep-subtypes", "throw an exception on deep subtyping call stacks.")
153153
val YprintSyms = BooleanSetting("-Yprint-syms", "when printing trees print info in symbols instead of corresponding info in trees.")
154154
val YtestPickler = BooleanSetting("-Ytest-pickler", "self-test for pickling functionality; should be used with -Ystop-after:pickler")
155+
val Yspecialize = StringSetting("-Yspecialize","","Specialize all methods.","") // How should the second and fourth paramerters be initialised ?
155156
def stop = YstopAfter
156157

157158
/** Area-specific debug output.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ class Definitions {
326326
lazy val TransientAnnot = ctx.requiredClass("scala.transient")
327327
lazy val NativeAnnot = ctx.requiredClass("scala.native")
328328
lazy val ScalaStrictFPAnnot = ctx.requiredClass("scala.annotation.strictfp")
329+
lazy val specializedAnnot = ctx.requiredClass("scala.specialized")
329330

330331
// Annotation classes
331332
lazy val AliasAnnot = ctx.requiredClass("dotty.annotation.internal.Alias")

src/dotty/tools/dotc/transform/TypeSpecializer.scala

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,26 @@ package dotty.tools.dotc.transform
33
import dotty.tools.dotc.ast.TreeTypeMap
44
import dotty.tools.dotc.ast.tpd._
55
import dotty.tools.dotc.core.Contexts.Context
6-
import dotty.tools.dotc.core.Flags
6+
import dotty.tools.dotc.core.{Symbols, Flags}
77
import dotty.tools.dotc.core.Types._
88
import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, MiniPhaseTransform}
99
import dotty.tools.dotc.core.Decorators._
10-
import scala.collection.mutable.{ListBuffer, ArrayBuffer}
10+
import scala.collection.mutable
1111

1212
class TypeSpecializer extends MiniPhaseTransform {
1313

14-
override def phaseName = "Type Specializer"
14+
override def phaseName = "specialize"
1515

1616
final val maxTparamsToSpecialize = 2
17-
17+
18+
private val specializationRequests: mutable.HashMap[Symbol, List[List[Type]]] = mutable.HashMap.empty
19+
20+
def registerSpecializationRequest(method: Symbol)(arguments: List[Type])(implicit ctx: Context) = {
21+
assert(ctx.phaseId <= this.period.phaseId)
22+
val prev = specializationRequests.getOrElse(method, List.empty)
23+
specializationRequests.put(method, arguments :: prev)
24+
}
25+
1826
private final def specialisedTypes(implicit ctx: Context) =
1927
Map(ctx.definitions.ByteType -> "$mcB$sp",
2028
ctx.definitions.BooleanType -> "$mcZ$sp",
@@ -25,24 +33,30 @@ class TypeSpecializer extends MiniPhaseTransform {
2533
ctx.definitions.DoubleType -> "$mcD$sp",
2634
ctx.definitions.CharType -> "$mcC$sp",
2735
ctx.definitions.UnitType -> "$mcV$sp")
28-
36+
37+
def shouldSpecializeForAll(sym: Symbols.Symbol)(implicit ctx: Context): Boolean = {
38+
// either -Yspecialize:all is given, or sym has @specialize annotation
39+
sym.denot.hasAnnotation(ctx.definitions.specializedAnnot) || (ctx.settings.Yspecialize.value == "all")
40+
}
41+
42+
def shouldSpecializeForSome(sym: Symbol)(implicit ctx: Context): List[List[Type]] = {
43+
specializationRequests.getOrElse(sym, Nil)
44+
}
45+
46+
47+
48+
2949
override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
3050

31-
def rewireType(tpe: Type) = tpe match {
32-
case tpe: TermRef => tpe.widen
33-
case _ => tpe
34-
}
35-
3651
tree.tpe.widen match {
3752

3853
case poly: PolyType if !(tree.symbol.isPrimaryConstructor
39-
|| (tree.symbol is Flags.Label)
40-
|| (tree.tparams.length > maxTparamsToSpecialize)) => {
54+
|| (tree.symbol is Flags.Label)) => {
4155
val origTParams = tree.tparams.map(_.symbol)
4256
val origVParams = tree.vparamss.flatten.map(_.symbol)
4357
println(s"specializing ${tree.symbol} for Tparams: ${origTParams.length}")
4458

45-
def specialize(instatiations: collection.mutable.ListBuffer[Type], names: collection.mutable.ArrayBuffer[String]): Tree = {
59+
def specialize(instatiations: List[Type], names: List[String]): Tree = {
4660

4761
val newSym = ctx.newSymbol(tree.symbol.owner, (tree.name + names.mkString).toTermName, tree.symbol.flags | Flags.Synthetic, poly.instantiate(instatiations.toList))
4862
polyDefDef(newSym, { tparams => vparams => {
@@ -58,29 +72,25 @@ class TypeSpecializer extends MiniPhaseTransform {
5872
})
5973
}
6074

61-
def generateSpecializations(remainingTParams: List[TypeDef])
62-
(instatiated: ArrayBuffer[TypeDef], instatiations: ListBuffer[Type],
63-
names: ArrayBuffer[String]): Iterable[Tree] = {
75+
def generateSpecializations(remainingTParams: List[TypeDef], remainingBounds: List[TypeBounds])
76+
(instatiations: List[Type],
77+
names: List[String]): Iterable[Tree] = {
6478
if (remainingTParams.nonEmpty) {
6579
val typeToSpecialize = remainingTParams.head
66-
specialisedTypes.flatMap { tpnme =>
80+
val bounds = remainingBounds.head
81+
specialisedTypes.filter{ tpnme =>
82+
bounds.contains(tpnme._1)
83+
}.flatMap { tpnme =>
6784
val tpe = tpnme._1
6885
val nme = tpnme._2
69-
instatiated.+=(typeToSpecialize)
70-
instatiations.+=(tpe)
71-
names.+=(nme)
72-
val r = generateSpecializations(remainingTParams.tail)(instatiated, instatiations, names)
73-
instatiated.drop(1)
74-
instatiations.drop(1)
75-
names.drop(1)
76-
r
86+
generateSpecializations(remainingTParams.tail, remainingBounds.tail)(tpe :: instatiations, nme :: names)
7787
}
7888
} else
79-
List(specialize(instatiations, names))
89+
List(specialize(instatiations.reverse, names.reverse))
8090
}
8191

8292

83-
Thicket(tree :: generateSpecializations(tree.tparams)(ArrayBuffer.empty, ListBuffer.empty, ArrayBuffer.empty).toList)
93+
Thicket(tree :: generateSpecializations(tree.tparams, poly.paramBounds)(List.empty, List.empty).toList)
8494
}
8595
case _ => tree
8696
}

test/dotc/tests.scala

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -143,48 +143,4 @@ class tests extends CompilerTest {
143143

144144

145145
@Test def dotty = compileDir(dottyDir, "tools", "-deep" :: allowDeepSubtypes ++ twice) // note the -deep argument
146-
147-
148-
@Test def dotc_ast = compileDir(dotcDir, "ast")
149-
@Test def dotc_config = compileDir(dotcDir, "config")
150-
@Test def dotc_core = compileDir(dotcDir, "core")("-Yno-double-bindings" :: allowDeepSubtypes)// twice omitted to make tests run faster
151-
152-
// This directory doesn't exist anymore
153-
// @Test def dotc_core_pickling = compileDir(coreDir, "pickling")(allowDeepSubtypes)// twice omitted to make tests run faster
154-
155-
@Test def dotc_transform = compileDir(dotcDir, "transform")// twice omitted to make tests run faster
156-
157-
@Test def dotc_parsing = compileDir(dotcDir, "parsing") // twice omitted to make tests run faster
158-
159-
@Test def dotc_printing = compileDir(dotcDir, "printing") // twice omitted to make tests run faster
160-
161-
@Test def dotc_reporting = compileDir(dotcDir, "reporting") // twice omitted to make tests run faster
162-
163-
@Test def dotc_typer = compileDir(dotcDir, "typer")// twice omitted to make tests run faster
164-
// error: error while loading Checking$$anon$2$,
165-
// class file 'target/scala-2.11/dotty_2.11-0.1-SNAPSHOT.jar(dotty/tools/dotc/typer/Checking$$anon$2.class)'
166-
// has location not matching its contents: contains class $anon
167-
168-
@Test def dotc_util = compileDir(dotcDir, "util") // twice omitted to make tests run faster
169-
170-
@Test def tools_io = compileDir(toolsDir, "io") // inner class has symbol <none>
171-
172-
@Test def helloWorld = compileFile(posDir, "HelloWorld")
173-
@Test def labels = compileFile(posDir, "Labels", twice)
174-
//@Test def tools = compileDir(dottyDir, "tools", "-deep" :: Nil)(allowDeepSubtypes)
175-
176-
@Test def testNonCyclic = compileList("testNonCyclic", List(
177-
dotcDir + "CompilationUnit.scala",
178-
coreDir + "Types.scala",
179-
dotcDir + "ast/Trees.scala"
180-
), List("-Xprompt") ++ staleSymbolError ++ twice)
181-
182-
@Test def testIssue_34 = compileList("testIssue_34", List(
183-
dotcDir + "config/Properties.scala",
184-
dotcDir + "config/PathResolver.scala"
185-
), List(/* "-Ylog:frontend", */ "-Xprompt") ++ staleSymbolError ++ twice)
186-
187-
val javaDir = "./tests/pos/java-interop/"
188-
@Test def java_all = compileFiles(javaDir, twice)
189-
//@Test def dotc_compilercommand = compileFile(dotcDir + "config/", "CompilerCommand")
190146
}

0 commit comments

Comments
 (0)