@@ -21,28 +21,30 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
21
21
final val maxTparamsToSpecialize = 2
22
22
23
23
private final def specialisedTypeToSuffix (implicit ctx : Context ) =
24
- Map (ctx.definitions .ByteType -> " $mcB$sp" ,
25
- ctx.definitions .BooleanType -> " $mcZ$sp" ,
26
- ctx.definitions .ShortType -> " $mcS$sp" ,
27
- ctx.definitions .IntType -> " $mcI$sp" ,
28
- ctx.definitions .LongType -> " $mcJ$sp" ,
29
- ctx.definitions .FloatType -> " $mcF$sp" ,
30
- ctx.definitions .DoubleType -> " $mcD$sp" ,
31
- ctx.definitions .CharType -> " $mcC$sp" ,
32
- ctx.definitions .UnitType -> " $mcV$sp" )
24
+ Map (defn .ByteType -> " $mcB$sp" ,
25
+ defn .BooleanType -> " $mcZ$sp" ,
26
+ defn .ShortType -> " $mcS$sp" ,
27
+ defn .IntType -> " $mcI$sp" ,
28
+ defn .LongType -> " $mcJ$sp" ,
29
+ defn .FloatType -> " $mcF$sp" ,
30
+ defn .DoubleType -> " $mcD$sp" ,
31
+ defn .CharType -> " $mcC$sp" ,
32
+ defn .UnitType -> " $mcV$sp" )
33
33
34
34
private def primitiveTypes (implicit ctx : Context ) =
35
- List (ctx.definitions .ByteType ,
36
- ctx.definitions .BooleanType ,
37
- ctx.definitions .ShortType ,
38
- ctx.definitions .IntType ,
39
- ctx.definitions .LongType ,
40
- ctx.definitions .FloatType ,
41
- ctx.definitions .DoubleType ,
42
- ctx.definitions .CharType ,
43
- ctx.definitions .UnitType
35
+ List (defn .ByteType ,
36
+ defn .BooleanType ,
37
+ defn .ShortType ,
38
+ defn .IntType ,
39
+ defn .LongType ,
40
+ defn .FloatType ,
41
+ defn .DoubleType ,
42
+ defn .CharType ,
43
+ defn .UnitType
44
44
)
45
45
46
+ private def defn (implicit ctx: Context ) = ctx.definitions
47
+
46
48
private val specializationRequests : mutable.HashMap [Symbols .Symbol , List [Type ]] = mutable.HashMap .empty
47
49
48
50
/**
@@ -51,15 +53,45 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
51
53
*/
52
54
private val newSymbolMap : mutable.HashMap [Symbol , mutable.HashMap [List [Type ], Symbols .Symbol ]] = mutable.HashMap .empty
53
55
56
+ def allowedToSpecialize (sym : Symbol , numOfTypes : Int )(implicit ctx : Context ): Boolean = {
57
+ numOfTypes <= maxTparamsToSpecialize &&
58
+ numOfTypes > 0 &&
59
+ sym.name != nme.asInstanceOf_ &&
60
+ sym.name != nme.isInstanceOf_ &&
61
+ ! (sym is Flags .JavaDefined ) &&
62
+ ! sym.isConstructor &&
63
+ ! sym.name.toString.contains(" Function2" )
64
+ }
65
+
66
+ def getSpecTypes (sym : Symbol , poly : PolyType )(implicit ctx : Context ): List [Type ] = {
67
+ val requested = specializationRequests.getOrElse(sym, List ())
68
+ if (requested.nonEmpty) requested.toList
69
+ else {
70
+ if (ctx.settings.Yspecialize .value == " all" ) primitiveTypes
71
+ else Nil
72
+ }.filter(tpe => poly.paramBounds.forall(_.contains(tpe)))
73
+ }
74
+
75
+ def requestedSpecialization (decl : Symbol )(implicit ctx : Context ): Boolean =
76
+ specializationRequests.contains(decl) ||
77
+ (ctx.settings.Yspecialize .value != " " && decl.name.contains(ctx.settings.Yspecialize .value)) ||
78
+ ctx.settings.Yspecialize .value == " all"
79
+
80
+ def registerSpecializationRequest (method : Symbols .Symbol )(arguments : List [Type ])(implicit ctx : Context ) = {
81
+ if (ctx.phaseId > this .treeTransformPhase.id)
82
+ assert(ctx.phaseId <= this .treeTransformPhase.id)
83
+ val prev = specializationRequests.getOrElse(method, List .empty)
84
+ specializationRequests.put(method, (arguments ::: prev).toSet.toList)
85
+ }
86
+
54
87
override def transformInfo (tp : Type , sym : Symbol )(implicit ctx : Context ): Type = {
55
88
def generateSpecializations (remainingTParams : List [Name ], specTypes : List [Type ])
56
89
(instantiations : List [Type ], names : List [String ], poly : PolyType , decl : Symbol )
57
90
(implicit ctx : Context ): List [Symbol ] = {
58
91
if (remainingTParams.nonEmpty) {
59
- val specializations = (for (tpe <- specTypes) yield {
92
+ (for (tpe <- specTypes) yield {
60
93
generateSpecializations(remainingTParams.tail, specTypes)(tpe :: instantiations, specialisedTypeToSuffix(ctx)(tpe) :: names, poly, decl)
61
94
}).flatten
62
- specializations
63
95
}
64
96
else {
65
97
generateSpecializedSymbols(instantiations.reverse, names.reverse, poly, decl)
@@ -76,65 +108,39 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
76
108
map.values.toList
77
109
}
78
110
79
- if ((sym ne ctx.definitions .ScalaPredefModule .moduleClass) &&
111
+ if ((sym ne defn .ScalaPredefModule .moduleClass) &&
80
112
! (sym is Flags .Package ) &&
81
- ! sym.isAnonymousClass &&
82
- ! (sym.name == nme.asInstanceOf_)) {
113
+ ! sym.isAnonymousClass) {
83
114
sym.info match {
84
115
case classInfo : ClassInfo =>
85
- val newDecls = classInfo.decls.filterNot(_.isConstructor/* isPrimaryConstructor*/ ).flatMap(decl => {
86
- if (decl.name.toString.contains(" foobar" )) {
87
- println(" hello" )
88
- }
89
- if (shouldSpecialize(decl)) {
116
+ val newDecls = classInfo.decls
117
+ .filterNot(_.isConstructor)
118
+ .filter(requestedSpecialization)
119
+ .flatMap(decl => {
90
120
decl.info.widen match {
91
- case poly : PolyType =>
92
- if (poly.paramNames.length <= maxTparamsToSpecialize && poly.paramNames.length > 0 ) {
93
- val specTypes = getSpecTypes(decl).filter(tpe => poly.paramBounds.forall(_.contains(tpe)))
94
- generateSpecializations(poly.paramNames, specTypes)(List .empty, List .empty, poly, decl)
95
- }
96
- else Nil
121
+ case poly : PolyType if allowedToSpecialize(decl.symbol, poly.paramNames.length) =>
122
+ generateSpecializations(poly.paramNames, getSpecTypes(decl, poly))(List .empty, List .empty, poly, decl)
97
123
case nil => Nil
98
124
}
99
- } else Nil
100
125
})
101
- if (newDecls.nonEmpty) {
102
126
val decls = classInfo.decls.cloneScope
103
127
newDecls.foreach(decls.enter)
104
128
classInfo.derivedClassInfo(decls = decls)
105
- }
129
+ case poly : PolyType if ! newSymbolMap.contains(sym) &&
130
+ requestedSpecialization(sym) &&
131
+ allowedToSpecialize(sym, poly.paramNames.length)=>
132
+ generateSpecializations(poly.paramNames, getSpecTypes(sym, poly))(List .empty, List .empty, poly, sym)
106
133
case nil =>
107
134
}
108
135
tp
109
136
} else tp
110
137
}
111
138
112
- def getSpecTypes (sym : Symbol )(implicit ctx : Context ): List [Type ] = {
113
- val requested = specializationRequests.getOrElse(sym, List ())
114
- if (requested.nonEmpty) requested.toList
115
- else {
116
- if (ctx.settings.Yspecialize .value == " all" ) primitiveTypes
117
- else Nil
118
- }
119
- }
120
-
121
- def shouldSpecialize (decl : Symbol )(implicit ctx : Context ): Boolean =
122
- specializationRequests.contains(decl) ||
123
- (ctx.settings.Yspecialize .value != " " && decl.name.contains(ctx.settings.Yspecialize .value)) ||
124
- ctx.settings.Yspecialize .value == " all"
125
-
126
- def registerSpecializationRequest (method : Symbols .Symbol )(arguments : List [Type ])(implicit ctx : Context ) = {
127
- if (ctx.phaseId > this .treeTransformPhase.id)
128
- assert(ctx.phaseId <= this .treeTransformPhase.id)
129
- val prev = specializationRequests.getOrElse(method, List .empty)
130
- specializationRequests.put(method, arguments ::: prev)
131
- }
132
-
133
139
override def transformDefDef (tree : DefDef )(implicit ctx : Context , info : TransformerInfo ): Tree = {
134
140
135
141
tree.tpe.widen match {
136
142
137
- case poly : PolyType if ! (tree.symbol.isConstructor// isPrimaryConstructor
143
+ case poly : PolyType if ! (tree.symbol.isConstructor
138
144
|| (tree.symbol is Flags .Label ))
139
145
|| (tree.symbol.name == nme.asInstanceOf_) =>
140
146
val origTParams = tree.tparams.map(_.symbol)
@@ -162,31 +168,35 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
162
168
}
163
169
} else Nil
164
170
}
165
- val specializedMethods = specialize(tree.symbol)
166
- Thicket (tree :: specializedMethods)
171
+ Thicket (tree :: specialize(tree.symbol))
167
172
case _ => tree
168
173
}
169
174
}
170
175
171
176
override def transformTypeApply (tree : tpd.TypeApply )(implicit ctx : Context , info : TransformerInfo ): Tree = {
172
177
178
+
173
179
def allowedToSpecialize (sym : Symbol ): Boolean = {
174
180
sym.name != nme.asInstanceOf_ &&
175
181
! (sym is Flags .JavaDefined ) &&
176
182
! sym.isConstructor// isPrimaryConstructor
177
183
}
184
+
178
185
val TypeApply (fun,args) = tree
179
- if (newSymbolMap.contains(fun.symbol) && allowedToSpecialize(fun.symbol)) {
186
+ if (newSymbolMap.contains(fun.symbol)) {
180
187
val newSymInfos = newSymbolMap(fun.symbol)
181
188
val betterDefs = newSymInfos.filter(x => (x._1 zip args).forall{a =>
182
189
val specializedType = a._1
183
190
val argType = a._2
184
191
argType.tpe <:< specializedType
185
192
}).toList
186
- assert(betterDefs.length < 2 ) // TODO: How to select the best if there are several ?
193
+
194
+ if (betterDefs.length > 1 ) ctx.debuglog(" Several specialized variants fit." )
195
+ // assert(betterDefs.length < 2) // TODO: How to select the best if there are several ?
187
196
188
197
if (betterDefs.nonEmpty) {
189
- println(s " method $fun rewired to specialized variant with type ( ${betterDefs.head._1}) " )
198
+ val best = betterDefs.head
199
+ println(s " method ${fun.symbol.name} of ${fun.symbol.owner} rewired to specialized variant with type ( ${best._1}) " )
190
200
val prefix = fun match {
191
201
case Select (pre, name) =>
192
202
pre
@@ -197,9 +207,10 @@ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
197
207
else EmptyTree
198
208
}
199
209
if (prefix ne EmptyTree )
200
- prefix.select(betterDefs.head ._2)
201
- else ref(betterDefs.head ._2)
210
+ prefix.select(best ._2)
211
+ else ref(best ._2)
202
212
} else tree
203
213
} else tree
204
214
}
205
215
}
216
+
0 commit comments