Skip to content

Commit 9b153c2

Browse files
Duhemmliufengyun
authored andcommitted
Optimize phase SpecializeFunctions
- Stop immediately if the type doesn't derive from `Function{0,1,2}` - We don't need to check if any of the parents derives from `Function{0,1,2}`, we can just check if the type derives from it.
1 parent 0d42bf0 commit 9b153c2

File tree

1 file changed

+55
-48
lines changed

1 file changed

+55
-48
lines changed

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

Lines changed: 55 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,28 @@ class SpecializeFunctions extends MiniPhase with InfoTransformer {
2020

2121
/** Transforms the type to include decls for specialized applys */
2222
override def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context) = tp match {
23-
case tp: ClassInfo if !sym.is(Flags.Package) && (tp.decls ne EmptyScope) =>
23+
case tp: ClassInfo if !sym.is(Flags.Package) && (tp.decls ne EmptyScope) && derivesFromFn012(sym) =>
2424
var newApplys = Map.empty[Name, Symbol]
2525

26-
tp.parents.foreach { parent =>
27-
List(0, 1, 2).foreach { arity =>
28-
val func = defn.FunctionClass(arity)
29-
if (parent.derivesFrom(func)) {
30-
val typeParams = tp.cls.typeRef.baseType(func).argInfos
31-
val isSpecializable =
32-
defn.isSpecializableFunction(
33-
parent.classSymbol.asClass,
34-
typeParams.init,
35-
typeParams.last
36-
)
37-
38-
if (isSpecializable && tp.decls.lookup(nme.apply).exists) {
39-
val interface = specInterface(typeParams)
40-
val specializedMethodName = nme.apply.specializedFunction(typeParams.last, typeParams.init)
41-
newApplys += (specializedMethodName -> interface)
42-
}
26+
var arity = 0
27+
while (arity < 3) {
28+
val func = defn.FunctionClass(arity)
29+
if (tp.derivesFrom(func)) {
30+
val typeParams = tp.cls.typeRef.baseType(func).argInfos
31+
val isSpecializable =
32+
defn.isSpecializableFunction(
33+
sym.asClass,
34+
typeParams.init,
35+
typeParams.last
36+
)
37+
38+
if (isSpecializable && tp.decls.lookup(nme.apply).exists) {
39+
val interface = specInterface(typeParams)
40+
val specializedMethodName = nme.apply.specializedFunction(typeParams.last, typeParams.init)
41+
newApplys += (specializedMethodName -> interface)
4342
}
4443
}
44+
arity += 1
4545
}
4646

4747
def newDecls =
@@ -68,39 +68,41 @@ class SpecializeFunctions extends MiniPhase with InfoTransformer {
6868
* in the template body.
6969
*/
7070
override def transformTemplate(tree: Template)(implicit ctx: Context) = {
71-
val applyBuf = new mutable.ListBuffer[Tree]
72-
val newBody = tree.body.mapConserve {
73-
case dt: DefDef if dt.name == nme.apply && dt.vparamss.length == 1 =>
74-
val cls = tree.symbol.enclosingClass.asClass
75-
val typeParams = dt.vparamss.head.map(_.symbol.info)
76-
val retType = dt.tpe.widen.finalResultType
77-
78-
val specName = specializedName(nme.apply, typeParams :+ retType)
79-
val specializedApply = cls.info.decls.lookup(specName)
80-
if (specializedApply.exists) {
81-
val apply = specializedApply.asTerm
82-
val specializedDecl =
83-
polyDefDef(apply, trefs => vrefss => {
84-
dt.rhs
85-
.changeOwner(dt.symbol, apply)
86-
.subst(dt.vparamss.flatten.map(_.symbol), vrefss.flatten.map(_.symbol))
71+
val cls = tree.symbol.enclosingClass.asClass
72+
if (derivesFromFn012(cls)) {
73+
val applyBuf = new mutable.ListBuffer[Tree]
74+
val newBody = tree.body.mapConserve {
75+
case dt: DefDef if dt.name == nme.apply && dt.vparamss.length == 1 =>
76+
val typeParams = dt.vparamss.head.map(_.symbol.info)
77+
val retType = dt.tpe.widen.finalResultType
78+
79+
val specName = specializedName(nme.apply, typeParams :+ retType)
80+
val specializedApply = cls.info.decls.lookup(specName)
81+
if (specializedApply.exists) {
82+
val apply = specializedApply.asTerm
83+
val specializedDecl =
84+
polyDefDef(apply, trefs => vrefss => {
85+
dt.rhs
86+
.changeOwner(dt.symbol, apply)
87+
.subst(dt.vparamss.flatten.map(_.symbol), vrefss.flatten.map(_.symbol))
88+
})
89+
applyBuf += specializedDecl
90+
91+
// create a forwarding to the specialized apply
92+
cpy.DefDef(dt)(rhs = {
93+
tpd
94+
.ref(apply)
95+
.appliedToArgs(dt.vparamss.head.map(vparam => ref(vparam.symbol)))
8796
})
88-
applyBuf += specializedDecl
97+
} else dt
8998

90-
// create a forwarding to the specialized apply
91-
cpy.DefDef(dt)(rhs = {
92-
tpd
93-
.ref(apply)
94-
.appliedToArgs(dt.vparamss.head.map(vparam => ref(vparam.symbol)))
95-
})
96-
} else dt
97-
98-
case x => x
99-
}
99+
case x => x
100+
}
100101

101-
cpy.Template(tree)(
102-
body = applyBuf.toList ++ newBody
103-
)
102+
cpy.Template(tree)(
103+
body = applyBuf.toList ::: newBody
104+
)
105+
} else tree
104106
}
105107

106108
/** Dispatch to specialized `apply`s in user code when available */
@@ -146,4 +148,9 @@ class SpecializeFunctions extends MiniPhase with InfoTransformer {
146148

147149
private def specInterface(typeParams: List[Type])(implicit ctx: Context) =
148150
ctx.getClassIfDefined(functionName(typeParams).specializedFunction(typeParams.last, typeParams.init))
151+
152+
private def derivesFromFn012(sym: Symbol)(implicit ctx: Context): Boolean =
153+
sym.derivesFrom(defn.FunctionClass(0)) ||
154+
sym.derivesFrom(defn.FunctionClass(1)) ||
155+
sym.derivesFrom(defn.FunctionClass(2))
149156
}

0 commit comments

Comments
 (0)