Skip to content

Commit 65de258

Browse files
committed
Add synthetic bridge when compiling FunctionN
1 parent ad386fc commit 65de258

File tree

1 file changed

+150
-107
lines changed

1 file changed

+150
-107
lines changed

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

Lines changed: 150 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import ast.Trees._, ast.tpd, core._
66
import Contexts.Context, Types._, Decorators._, Symbols._, DenotTransformers._
77
import SymDenotations._, Scopes._, StdNames._, NameOps._, Names._
88

9+
import scala.reflect.internal.util.Collections
10+
911
/** This phase synthesizes specialized methods for FunctionN, this is done
1012
* since there are no scala signatures in the bytecode for the specialized
1113
* methods.
@@ -19,122 +21,163 @@ class SpecializedApplyMethods extends MiniPhaseTransform with InfoTransformer {
1921

2022
val phaseName = "specializedApplyMethods"
2123

24+
private[this] var func0Applys: List[Symbol] = _
25+
private[this] var func1Applys: List[Symbol] = _
26+
private[this] var func2Applys: List[Symbol] = _
27+
private[this] var func0: Symbol = _
28+
private[this] var func1: Symbol = _
29+
private[this] var func2: Symbol = _
30+
31+
private def init()(implicit ctx: Context): Unit = if (func0Applys eq null) {
32+
def specApply(sym: Symbol, ret: Type, args: List[Type])(implicit ctx: Context) = {
33+
val all = args :+ ret
34+
val name = nme.apply.specializedFor(all, all.map(_.typeSymbol.name), Nil, Nil)
35+
ctx.newSymbol(sym, name, Flags.Method, MethodType(args, ret))
36+
}
37+
38+
func0 = defn.FunctionClass(0)
39+
func0Applys = List(
40+
specApply(func0, defn.UnitType, Nil),
41+
specApply(func0, defn.ByteType, Nil),
42+
specApply(func0, defn.ShortType, Nil),
43+
specApply(func0, defn.IntType, Nil),
44+
specApply(func0, defn.LongType, Nil),
45+
specApply(func0, defn.CharType, Nil),
46+
specApply(func0, defn.FloatType, Nil),
47+
specApply(func0, defn.DoubleType, Nil),
48+
specApply(func0, defn.BooleanType, Nil)
49+
)
50+
func1 = defn.FunctionClass(1)
51+
func1Applys = List(
52+
specApply(func1, defn.UnitType, List(defn.IntType)),
53+
specApply(func1, defn.IntType, List(defn.IntType)),
54+
specApply(func1, defn.FloatType, List(defn.IntType)),
55+
specApply(func1, defn.LongType, List(defn.IntType)),
56+
specApply(func1, defn.DoubleType, List(defn.IntType)),
57+
specApply(func1, defn.UnitType, List(defn.LongType)),
58+
specApply(func1, defn.BooleanType, List(defn.LongType)),
59+
specApply(func1, defn.IntType, List(defn.LongType)),
60+
specApply(func1, defn.FloatType, List(defn.LongType)),
61+
specApply(func1, defn.LongType, List(defn.LongType)),
62+
specApply(func1, defn.DoubleType, List(defn.LongType)),
63+
specApply(func1, defn.UnitType, List(defn.FloatType)),
64+
specApply(func1, defn.BooleanType, List(defn.FloatType)),
65+
specApply(func1, defn.IntType, List(defn.FloatType)),
66+
specApply(func1, defn.FloatType, List(defn.FloatType)),
67+
specApply(func1, defn.LongType, List(defn.FloatType)),
68+
specApply(func1, defn.DoubleType, List(defn.FloatType)),
69+
specApply(func1, defn.UnitType, List(defn.DoubleType)),
70+
specApply(func1, defn.BooleanType, List(defn.DoubleType)),
71+
specApply(func1, defn.IntType, List(defn.DoubleType)),
72+
specApply(func1, defn.FloatType, List(defn.DoubleType)),
73+
specApply(func1, defn.LongType, List(defn.DoubleType)),
74+
specApply(func1, defn.DoubleType, List(defn.DoubleType))
75+
)
76+
func2 = defn.FunctionClass(2)
77+
func2Applys = List(
78+
specApply(func2, defn.UnitType, List(defn.IntType, defn.IntType)),
79+
specApply(func2, defn.BooleanType, List(defn.IntType, defn.IntType)),
80+
specApply(func2, defn.IntType, List(defn.IntType, defn.IntType)),
81+
specApply(func2, defn.FloatType, List(defn.IntType, defn.IntType)),
82+
specApply(func2, defn.LongType, List(defn.IntType, defn.IntType)),
83+
specApply(func2, defn.DoubleType, List(defn.IntType, defn.IntType)),
84+
specApply(func2, defn.UnitType, List(defn.IntType, defn.LongType)),
85+
specApply(func2, defn.BooleanType, List(defn.IntType, defn.LongType)),
86+
specApply(func2, defn.IntType, List(defn.IntType, defn.LongType)),
87+
specApply(func2, defn.FloatType, List(defn.IntType, defn.LongType)),
88+
specApply(func2, defn.LongType, List(defn.IntType, defn.LongType)),
89+
specApply(func2, defn.DoubleType, List(defn.IntType, defn.LongType)),
90+
specApply(func2, defn.UnitType, List(defn.IntType, defn.DoubleType)),
91+
specApply(func2, defn.BooleanType, List(defn.IntType, defn.DoubleType)),
92+
specApply(func2, defn.IntType, List(defn.IntType, defn.DoubleType)),
93+
specApply(func2, defn.FloatType, List(defn.IntType, defn.DoubleType)),
94+
specApply(func2, defn.LongType, List(defn.IntType, defn.DoubleType)),
95+
specApply(func2, defn.DoubleType, List(defn.IntType, defn.DoubleType)),
96+
specApply(func2, defn.UnitType, List(defn.LongType, defn.IntType)),
97+
specApply(func2, defn.BooleanType, List(defn.LongType, defn.IntType)),
98+
specApply(func2, defn.IntType, List(defn.LongType, defn.IntType)),
99+
specApply(func2, defn.FloatType, List(defn.LongType, defn.IntType)),
100+
specApply(func2, defn.LongType, List(defn.LongType, defn.IntType)),
101+
specApply(func2, defn.DoubleType, List(defn.LongType, defn.IntType)),
102+
specApply(func2, defn.UnitType, List(defn.LongType, defn.LongType)),
103+
specApply(func2, defn.BooleanType, List(defn.LongType, defn.LongType)),
104+
specApply(func2, defn.IntType, List(defn.LongType, defn.LongType)),
105+
specApply(func2, defn.FloatType, List(defn.LongType, defn.LongType)),
106+
specApply(func2, defn.LongType, List(defn.LongType, defn.LongType)),
107+
specApply(func2, defn.DoubleType, List(defn.LongType, defn.LongType)),
108+
specApply(func2, defn.UnitType, List(defn.LongType, defn.DoubleType)),
109+
specApply(func2, defn.BooleanType, List(defn.LongType, defn.DoubleType)),
110+
specApply(func2, defn.IntType, List(defn.LongType, defn.DoubleType)),
111+
specApply(func2, defn.FloatType, List(defn.LongType, defn.DoubleType)),
112+
specApply(func2, defn.LongType, List(defn.LongType, defn.DoubleType)),
113+
specApply(func2, defn.DoubleType, List(defn.LongType, defn.DoubleType)),
114+
specApply(func2, defn.UnitType, List(defn.DoubleType, defn.IntType)),
115+
specApply(func2, defn.BooleanType, List(defn.DoubleType, defn.IntType)),
116+
specApply(func2, defn.IntType, List(defn.DoubleType, defn.IntType)),
117+
specApply(func2, defn.FloatType, List(defn.DoubleType, defn.IntType)),
118+
specApply(func2, defn.LongType, List(defn.DoubleType, defn.IntType)),
119+
specApply(func2, defn.DoubleType, List(defn.DoubleType, defn.IntType)),
120+
specApply(func2, defn.UnitType, List(defn.DoubleType, defn.LongType)),
121+
specApply(func2, defn.BooleanType, List(defn.DoubleType, defn.LongType)),
122+
specApply(func2, defn.IntType, List(defn.DoubleType, defn.LongType)),
123+
specApply(func2, defn.FloatType, List(defn.DoubleType, defn.LongType)),
124+
specApply(func2, defn.LongType, List(defn.DoubleType, defn.LongType)),
125+
specApply(func2, defn.DoubleType, List(defn.DoubleType, defn.LongType)),
126+
specApply(func2, defn.UnitType, List(defn.DoubleType, defn.DoubleType)),
127+
specApply(func2, defn.BooleanType, List(defn.DoubleType, defn.DoubleType)),
128+
specApply(func2, defn.IntType, List(defn.DoubleType, defn.DoubleType)),
129+
specApply(func2, defn.FloatType, List(defn.DoubleType, defn.DoubleType)),
130+
specApply(func2, defn.LongType, List(defn.DoubleType, defn.DoubleType)),
131+
specApply(func2, defn.DoubleType, List(defn.DoubleType, defn.DoubleType))
132+
)
133+
}
134+
135+
/** Add symbols for specialized methods to FunctionN */
22136
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context) = tp match {
23137
case tp: ClassInfo if defn.isFunctionClass(sym) => {
24-
def specApply(ret: Type, args: List[Type])(implicit ctx: Context) = {
25-
val all = args :+ ret
26-
val name = nme.apply.specializedFor(all, all.map(_.typeSymbol.name), Nil, Nil)
27-
ctx.newSymbol(sym, name, Flags.Method, MethodType(args, ret))
138+
init()
139+
val newDecls = sym.name.functionArity match {
140+
case 0 => func0Applys.foldLeft(tp.decls.cloneScope) {
141+
(decls, sym) => decls.enter(sym); decls
142+
}
143+
case 1 => func1Applys.foldLeft(tp.decls.cloneScope) {
144+
(decls, sym) => decls.enter(sym); decls
145+
}
146+
case 2 => func2Applys.foldLeft(tp.decls.cloneScope) {
147+
(decls, sym) => decls.enter(sym); decls
148+
}
149+
case _ => tp.decls
28150
}
29151

30-
val newDecls = sym.name.functionArity match {
31-
case 0 =>
32-
List(
33-
specApply(defn.UnitType, Nil),
34-
specApply(defn.ByteType, Nil),
35-
specApply(defn.ShortType, Nil),
36-
specApply(defn.IntType, Nil),
37-
specApply(defn.LongType, Nil),
38-
specApply(defn.CharType, Nil),
39-
specApply(defn.FloatType, Nil),
40-
specApply(defn.DoubleType, Nil),
41-
specApply(defn.BooleanType, Nil)
42-
)
43-
.foldLeft(tp.decls.cloneScope){ (decls, sym) => decls.enter(sym); decls }
152+
tp.derivedClassInfo(decls = newDecls)
153+
}
154+
case _ => tp
155+
}
44156

45-
case 1 =>
46-
List(
47-
specApply(defn.UnitType, List(defn.IntType)),
48-
specApply(defn.IntType, List(defn.IntType)),
49-
specApply(defn.FloatType, List(defn.IntType)),
50-
specApply(defn.LongType, List(defn.IntType)),
51-
specApply(defn.DoubleType, List(defn.IntType)),
52-
specApply(defn.UnitType, List(defn.LongType)),
53-
specApply(defn.BooleanType, List(defn.LongType)),
54-
specApply(defn.IntType, List(defn.LongType)),
55-
specApply(defn.FloatType, List(defn.LongType)),
56-
specApply(defn.LongType, List(defn.LongType)),
57-
specApply(defn.DoubleType, List(defn.LongType)),
58-
specApply(defn.UnitType, List(defn.FloatType)),
59-
specApply(defn.BooleanType, List(defn.FloatType)),
60-
specApply(defn.IntType, List(defn.FloatType)),
61-
specApply(defn.FloatType, List(defn.FloatType)),
62-
specApply(defn.LongType, List(defn.FloatType)),
63-
specApply(defn.DoubleType, List(defn.FloatType)),
64-
specApply(defn.UnitType, List(defn.DoubleType)),
65-
specApply(defn.BooleanType, List(defn.DoubleType)),
66-
specApply(defn.IntType, List(defn.DoubleType)),
67-
specApply(defn.FloatType, List(defn.DoubleType)),
68-
specApply(defn.LongType, List(defn.DoubleType)),
69-
specApply(defn.DoubleType, List(defn.DoubleType))
70-
)
71-
.foldLeft(tp.decls.cloneScope){ (decls, sym) => decls.enter(sym); decls }
157+
/** Create bridge methods for FunctionN with specialized applys */
158+
override def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo) = {
159+
val owner = tree.symbol.owner
160+
val additionalSymbols =
161+
if (owner eq func0) func0Applys
162+
else if (owner eq func1) func1Applys
163+
else if (owner eq func2) func2Applys
164+
else Nil
72165

73-
case 2 =>
74-
List(
75-
specApply(defn.UnitType, List(defn.IntType, defn.IntType)),
76-
specApply(defn.BooleanType, List(defn.IntType, defn.IntType)),
77-
specApply(defn.IntType, List(defn.IntType, defn.IntType)),
78-
specApply(defn.FloatType, List(defn.IntType, defn.IntType)),
79-
specApply(defn.LongType, List(defn.IntType, defn.IntType)),
80-
specApply(defn.DoubleType, List(defn.IntType, defn.IntType)),
81-
specApply(defn.UnitType, List(defn.IntType, defn.LongType)),
82-
specApply(defn.BooleanType, List(defn.IntType, defn.LongType)),
83-
specApply(defn.IntType, List(defn.IntType, defn.LongType)),
84-
specApply(defn.FloatType, List(defn.IntType, defn.LongType)),
85-
specApply(defn.LongType, List(defn.IntType, defn.LongType)),
86-
specApply(defn.DoubleType, List(defn.IntType, defn.LongType)),
87-
specApply(defn.UnitType, List(defn.IntType, defn.DoubleType)),
88-
specApply(defn.BooleanType, List(defn.IntType, defn.DoubleType)),
89-
specApply(defn.IntType, List(defn.IntType, defn.DoubleType)),
90-
specApply(defn.FloatType, List(defn.IntType, defn.DoubleType)),
91-
specApply(defn.LongType, List(defn.IntType, defn.DoubleType)),
92-
specApply(defn.DoubleType, List(defn.IntType, defn.DoubleType)),
93-
specApply(defn.UnitType, List(defn.LongType, defn.IntType)),
94-
specApply(defn.BooleanType, List(defn.LongType, defn.IntType)),
95-
specApply(defn.IntType, List(defn.LongType, defn.IntType)),
96-
specApply(defn.FloatType, List(defn.LongType, defn.IntType)),
97-
specApply(defn.LongType, List(defn.LongType, defn.IntType)),
98-
specApply(defn.DoubleType, List(defn.LongType, defn.IntType)),
99-
specApply(defn.UnitType, List(defn.LongType, defn.LongType)),
100-
specApply(defn.BooleanType, List(defn.LongType, defn.LongType)),
101-
specApply(defn.IntType, List(defn.LongType, defn.LongType)),
102-
specApply(defn.FloatType, List(defn.LongType, defn.LongType)),
103-
specApply(defn.LongType, List(defn.LongType, defn.LongType)),
104-
specApply(defn.DoubleType, List(defn.LongType, defn.LongType)),
105-
specApply(defn.UnitType, List(defn.LongType, defn.DoubleType)),
106-
specApply(defn.BooleanType, List(defn.LongType, defn.DoubleType)),
107-
specApply(defn.IntType, List(defn.LongType, defn.DoubleType)),
108-
specApply(defn.FloatType, List(defn.LongType, defn.DoubleType)),
109-
specApply(defn.LongType, List(defn.LongType, defn.DoubleType)),
110-
specApply(defn.DoubleType, List(defn.LongType, defn.DoubleType)),
111-
specApply(defn.UnitType, List(defn.DoubleType, defn.IntType)),
112-
specApply(defn.BooleanType, List(defn.DoubleType, defn.IntType)),
113-
specApply(defn.IntType, List(defn.DoubleType, defn.IntType)),
114-
specApply(defn.FloatType, List(defn.DoubleType, defn.IntType)),
115-
specApply(defn.LongType, List(defn.DoubleType, defn.IntType)),
116-
specApply(defn.DoubleType, List(defn.DoubleType, defn.IntType)),
117-
specApply(defn.UnitType, List(defn.DoubleType, defn.LongType)),
118-
specApply(defn.BooleanType, List(defn.DoubleType, defn.LongType)),
119-
specApply(defn.IntType, List(defn.DoubleType, defn.LongType)),
120-
specApply(defn.FloatType, List(defn.DoubleType, defn.LongType)),
121-
specApply(defn.LongType, List(defn.DoubleType, defn.LongType)),
122-
specApply(defn.DoubleType, List(defn.DoubleType, defn.LongType)),
123-
specApply(defn.UnitType, List(defn.DoubleType, defn.DoubleType)),
124-
specApply(defn.BooleanType, List(defn.DoubleType, defn.DoubleType)),
125-
specApply(defn.IntType, List(defn.DoubleType, defn.DoubleType)),
126-
specApply(defn.FloatType, List(defn.DoubleType, defn.DoubleType)),
127-
specApply(defn.LongType, List(defn.DoubleType, defn.DoubleType)),
128-
specApply(defn.DoubleType, List(defn.DoubleType, defn.DoubleType))
129-
)
130-
.foldLeft(tp.decls.cloneScope){ (decls, sym) => decls.enter(sym); decls }
166+
if (additionalSymbols eq Nil) tree
167+
else {
168+
val newBody: List[Tree] = tree.body ++ additionalSymbols.map { applySym =>
169+
polyDefDef(applySym.asTerm, tparams => vparamss => {
170+
val prefix = This(owner.asClass).select(nme.apply).appliedToTypes(vparamss.head.map(_.tpe))
171+
val argTypess = prefix.tpe.widen.paramTypess
131172

132-
case _ =>
133-
tp.decls
173+
val argss = Collections.map2(vparamss, argTypess) { (vparams, argTypes) =>
174+
Collections.map2(vparams, argTypes) { (vparam, argType) => vparam.ensureConforms(argType) }
175+
}
176+
prefix.appliedToArgss(argss).ensureConforms(applySym.info.finalResultType)
177+
})
134178
}
135179

136-
tp.derivedClassInfo(decls = newDecls)
180+
cpy.Template(tree)(body = newBody)
137181
}
138-
case _ => tp
139182
}
140183
}

0 commit comments

Comments
 (0)