Skip to content

Commit 989aaf9

Browse files
committed
Fast specialization
We avoid going through InfoTransformer, which will cause all symbols to be checked. The reason why it works is that the specialized base classes, i.e. Function0-2 already have all the relevant definitions.
1 parent 51f0a3e commit 989aaf9

File tree

1 file changed

+12
-59
lines changed

1 file changed

+12
-59
lines changed

compiler/src/dotty/tools/dotc/transform/SpecializeFunctions.scala

Lines changed: 12 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -11,88 +11,41 @@ import scala.collection.mutable
1111
/** Specializes classes that inherit from `FunctionN` where there exists a
1212
* specialized form.
1313
*/
14-
class SpecializeFunctions extends MiniPhase with InfoTransformer {
14+
class SpecializeFunctions extends MiniPhase {
1515
import ast.tpd._
1616
val phaseName = "specializeFunctions"
1717
override def runsAfter = Set(ElimByName.name)
1818

1919
override def isEnabled(using Context): Boolean =
2020
!ctx.settings.scalajs.value
2121

22-
override def infoMayChange(sym: Symbol)(using Context): Boolean =
23-
!sym.is(Flags.Package) && sym.isClass && sym.isDefinedInCurrentRun
24-
25-
/** Transforms the type to include decls for specialized applys */
26-
override def transformInfo(tp: Type, sym: Symbol)(using Context) = tp match {
27-
case tp: ClassInfo =>
28-
val apply = tp.decls.lookup(nme.apply)
29-
if (!apply.exists) return tp
30-
31-
var newApplys: List[Symbol] = Nil
32-
33-
var arity = 0
34-
while (arity < 3) {
35-
val func = defn.SpecializableFunctions(arity)
36-
if (sym != func && sym.derivesFrom(func)) {
37-
val baseType = tp.cls.typeRef.baseType(func)
38-
val paramTypes = baseType.argInfos
39-
val argTypes = paramTypes.init
40-
val retType = paramTypes.last
41-
42-
val isSpecializable = defn.isSpecializableFunction(sym.asClass, argTypes, retType)
43-
if (!isSpecializable) return tp
44-
45-
val apply = baseType.member(nme.apply)
46-
val overrideApply = tp.decls.find { sym =>
47-
sym.is(Flags.Method, butNot = Flags.Deferred) && sym.name == nme.apply && sym.info.matches(apply.info)
48-
}
49-
50-
if (overrideApply.exists) {
51-
val specializedMethodName: Name = nme.apply.specializedFunction(retType, argTypes)
52-
val applySpecialized = newSymbol(
53-
sym,
54-
specializedMethodName,
55-
overrideApply.flags | Flags.Synthetic,
56-
overrideApply.info
57-
)
58-
59-
newApplys ::= applySpecialized
60-
}
61-
}
62-
arity += 1
63-
}
64-
65-
if (newApplys.isEmpty) tp
66-
else {
67-
val scope = tp.decls.cloneScope
68-
newApplys.toList.foreach { sym => scope.enter(sym) }
69-
tp.derivedClassInfo(decls = scope)
70-
}
71-
72-
case _ => tp
73-
}
74-
7522
/** Create forwarders from the generic applys to the specialized ones.
7623
*/
7724
override def transformDefDef(ddef: DefDef)(using Context) = {
7825
val sym = ddef.symbol
7926

8027
if ddef.name != nme.apply
28+
|| sym.is(Flags.Deferred)
8129
|| ddef.vparamss.length != 1
8230
|| ddef.vparamss.head.length > 2
8331
|| !sym.owner.isClass
84-
|| !derivesFromFn012(sym.owner.asClass)
8532
then
8633
return ddef
8734

8835
val cls = sym.owner.asClass
8936
val paramTypes = ddef.vparamss.head.map(_.symbol.info)
90-
val retType = ddef.tpe.widen.finalResultType
91-
37+
val retType = sym.info.finalResultType
9238
val specName = nme.apply.specializedFunction(retType, paramTypes)
93-
val specializedApply = cls.asClass.info.decls.lookup(specName)
9439

95-
if (!specializedApply.exists) return ddef
40+
val isSpecializable = defn.isSpecializableFunction(cls, paramTypes, retType)
41+
if (!isSpecializable || cls.info.decls.lookup(specName).exists) return ddef
42+
43+
val specializedApply = newSymbol(
44+
cls,
45+
specName,
46+
sym.flags | Flags.Synthetic,
47+
sym.info
48+
).entered
9649

9750
val specializedDecl =
9851
DefDef(specializedApply.asTerm, vparamss => {

0 commit comments

Comments
 (0)