Skip to content

Commit 7334e94

Browse files
committed
Inline emitAnnotations
1 parent ef05863 commit 7334e94

File tree

2 files changed

+126
-135
lines changed

2 files changed

+126
-135
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala

Lines changed: 126 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,18 @@ package backend
33
package jvm
44

55
import scala.tools.asm
6+
import scala.tools.asm.AnnotationVisitor
67
import scala.tools.asm.ClassWriter
78
import scala.collection.mutable
89
import dotty.tools.io.AbstractFile
910

1011
import dotty.tools.dotc.CompilationUnit
12+
import dotty.tools.dotc.ast.tpd
13+
import dotty.tools.dotc.ast.Trees
1114
import dotty.tools.dotc.core.Annotations.Annotation
15+
import dotty.tools.dotc.core.Constants._
1216
import dotty.tools.dotc.core.Symbols._
13-
import dotty.tools.dotc.core.StdNames.str
17+
import dotty.tools.dotc.core.StdNames._
1418
import dotty.tools.dotc.core.Decorators._
1519
import dotty.tools.dotc.core.Flags
1620
import dotty.tools.dotc.core.Names.Name
@@ -30,6 +34,7 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
3034
//import bTypes._
3135
//import coreBTypes._
3236
import bTypes._
37+
import tpd._
3338
import coreBTypes._
3439
import int._
3540

@@ -273,26 +278,138 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
273278
/*
274279
* must-single-thread
275280
*/
276-
def emitAnnotations(cw: asm.ClassVisitor, annotations: List[Annotation]) =
277-
int.emitAnnotations(cw, annotations, BCodeHelpers.this)(this)
281+
def emitAnnotations(cw: asm.ClassVisitor, annotations: List[Annotation]): Unit =
282+
for(annot <- annotations; if shouldEmitAnnotation(annot)) {
283+
val typ = annot.tree.tpe
284+
val assocs = assocsFromApply(annot.tree)
285+
val av = cw.visitAnnotation(typeDescriptor(typ.asInstanceOf[Type]), isRuntimeVisible(annot))
286+
emitAssocs(av, assocs, BCodeHelpers.this)(this)
287+
}
278288

279289
/*
280290
* must-single-thread
281291
*/
282-
def emitAnnotations(mw: asm.MethodVisitor, annotations: List[Annotation]) =
283-
int.emitAnnotations(mw, annotations, BCodeHelpers.this)(this)
292+
def emitAnnotations(mw: asm.MethodVisitor, annotations: List[Annotation]): Unit =
293+
for(annot <- annotations; if shouldEmitAnnotation(annot)) {
294+
val typ = annot.tree.tpe
295+
val assocs = assocsFromApply(annot.tree)
296+
val av = mw.visitAnnotation(typeDescriptor(typ.asInstanceOf[Type]), isRuntimeVisible(annot))
297+
emitAssocs(av, assocs, BCodeHelpers.this)(this)
298+
}
284299

285300
/*
286301
* must-single-thread
287302
*/
288-
def emitAnnotations(fw: asm.FieldVisitor, annotations: List[Annotation]) =
289-
int.emitAnnotations(fw, annotations, BCodeHelpers.this)(this)
303+
def emitAnnotations(fw: asm.FieldVisitor, annotations: List[Annotation]): Unit =
304+
for(annot <- annotations; if shouldEmitAnnotation(annot)) {
305+
val typ = annot.tree.tpe
306+
val assocs = assocsFromApply(annot.tree)
307+
val av = fw.visitAnnotation(typeDescriptor(typ.asInstanceOf[Type]), isRuntimeVisible(annot))
308+
emitAssocs(av, assocs, BCodeHelpers.this)(this)
309+
}
290310

291311
/*
292312
* must-single-thread
293313
*/
294-
def emitParamAnnotations(jmethod: asm.MethodVisitor, pannotss: List[List[Annotation]]) =
295-
int.emitParamAnnotations(jmethod, pannotss, BCodeHelpers.this)(this)
314+
def emitParamAnnotations(jmethod: asm.MethodVisitor, pannotss: List[List[Annotation]]): Unit =
315+
val annotationss = pannotss map (_ filter shouldEmitAnnotation)
316+
if (annotationss forall (_.isEmpty)) return
317+
for ((annots, idx) <- annotationss.zipWithIndex;
318+
annot <- annots) {
319+
val typ = annot.tree.tpe
320+
val assocs = assocsFromApply(annot.tree)
321+
val pannVisitor: asm.AnnotationVisitor = jmethod.visitParameterAnnotation(idx, typeDescriptor(typ.asInstanceOf[Type]), isRuntimeVisible(annot))
322+
emitAssocs(pannVisitor, assocs, BCodeHelpers.this)(this)
323+
}
324+
325+
private def emitAssocs(av: asm.AnnotationVisitor, assocs: List[(Name, Object)], bcodeStore: BCodeHelpers)
326+
(innerClasesStore: bcodeStore.BCInnerClassGen) = {
327+
for ((name, value) <- assocs)
328+
emitArgument(av, name.mangledString, value.asInstanceOf[Tree], bcodeStore)(innerClasesStore)
329+
av.visitEnd()
330+
}
331+
332+
private def emitArgument(av: AnnotationVisitor,
333+
name: String,
334+
arg: Tree, bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen): Unit = {
335+
val narg = normalizeArgument(arg)
336+
// Transformation phases are not run on annotation trees, so we need to run
337+
// `constToLiteral` at this point.
338+
val t = constToLiteral(narg)(ctx.withPhase(ctx.erasurePhase))
339+
t match {
340+
case Literal(const @ Constant(_)) =>
341+
const.tag match {
342+
case BooleanTag | ByteTag | ShortTag | CharTag | IntTag | LongTag | FloatTag | DoubleTag => av.visit(name, const.value)
343+
case StringTag =>
344+
assert(const.value != null, const) // TODO this invariant isn't documented in `case class Constant`
345+
av.visit(name, const.stringValue) // `stringValue` special-cases null, but that execution path isn't exercised for a const with StringTag
346+
case ClazzTag => av.visit(name, typeToTypeKind(const.typeValue)(bcodeStore)(innerClasesStore).toASMType)
347+
case EnumTag =>
348+
val edesc = innerClasesStore.typeDescriptor(const.tpe.asInstanceOf[bcodeStore.int.Type]) // the class descriptor of the enumeration class.
349+
val evalue = const.symbolValue.name.mangledString // value the actual enumeration value.
350+
av.visitEnum(name, edesc, evalue)
351+
}
352+
case t: TypeApply if (t.fun.symbol == defn.Predef_classOf) =>
353+
av.visit(name, typeToTypeKind(t.args.head.tpe.classSymbol.denot.info)(bcodeStore)(innerClasesStore).toASMType)
354+
case Ident(nme.WILDCARD) =>
355+
// An underscore argument indicates that we want to use the default value for this parameter, so do not emit anything
356+
case t: tpd.RefTree if t.symbol.denot.owner.isAllOf(Flags.JavaEnumTrait) =>
357+
val edesc = innerClasesStore.typeDescriptor(t.tpe.asInstanceOf[bcodeStore.int.Type]) // the class descriptor of the enumeration class.
358+
val evalue = t.symbol.name.mangledString // value the actual enumeration value.
359+
av.visitEnum(name, edesc, evalue)
360+
case t: SeqLiteral =>
361+
val arrAnnotV: AnnotationVisitor = av.visitArray(name)
362+
for (arg <- t.elems) { emitArgument(arrAnnotV, null, arg, bcodeStore)(innerClasesStore) }
363+
arrAnnotV.visitEnd()
364+
365+
case Apply(fun, args) if fun.symbol == defn.ArrayClass.primaryConstructor ||
366+
toDenot(fun.symbol).owner == defn.ArrayClass.linkedClass && fun.symbol.name == nme.apply =>
367+
val arrAnnotV: AnnotationVisitor = av.visitArray(name)
368+
369+
var actualArgs = if (fun.tpe.isImplicitMethod) {
370+
// generic array method, need to get implicit argument out of the way
371+
fun.asInstanceOf[Apply].args
372+
} else args
373+
374+
val flatArgs = actualArgs.flatMap { arg =>
375+
normalizeArgument(arg) match {
376+
case t: tpd.SeqLiteral => t.elems
377+
case e => List(e)
378+
}
379+
}
380+
for(arg <- flatArgs) {
381+
emitArgument(arrAnnotV, null, arg, bcodeStore)(innerClasesStore)
382+
}
383+
arrAnnotV.visitEnd()
384+
/*
385+
case sb @ ScalaSigBytes(bytes) =>
386+
// see http://www.scala-lang.org/sid/10 (Storage of pickled Scala signatures in class files)
387+
// also JVMS Sec. 4.7.16.1 The element_value structure and JVMS Sec. 4.4.7 The CONSTANT_Utf8_info Structure.
388+
if (sb.fitsInOneString) {
389+
av.visit(name, BCodeAsmCommon.strEncode(sb))
390+
} else {
391+
val arrAnnotV: asm.AnnotationVisitor = av.visitArray(name)
392+
for(arg <- BCodeAsmCommon.arrEncode(sb)) { arrAnnotV.visit(name, arg) }
393+
arrAnnotV.visitEnd()
394+
} // for the lazy val in ScalaSigBytes to be GC'ed, the invoker of emitAnnotations() should hold the ScalaSigBytes in a method-local var that doesn't escape.
395+
*/
396+
case t @ Apply(constr, args) if t.tpe.derivesFrom(JavaAnnotationClass) =>
397+
val typ = t.tpe.classSymbol.denot.info
398+
val assocs = assocsFromApply(t)
399+
val desc = innerClasesStore.typeDescriptor(typ.asInstanceOf[bcodeStore.int.Type]) // the class descriptor of the nested annotation class
400+
val nestedVisitor = av.visitAnnotation(name, desc)
401+
emitAssocs(nestedVisitor, assocs, bcodeStore)(innerClasesStore)
402+
403+
case t =>
404+
ctx.error(ex"Annotation argument is not a constant", t.sourcePos)
405+
}
406+
}
407+
408+
private def normalizeArgument(arg: Tree): Tree = arg match {
409+
case Trees.NamedArg(_, arg1) => normalizeArgument(arg1)
410+
case Trees.Typed(arg1, _) => normalizeArgument(arg1)
411+
case _ => arg
412+
}
296413

297414
} // end of trait BCAnnotGen
298415

compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala

Lines changed: 0 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -82,132 +82,6 @@ class DottyBackendInterface(val outputDirectory: AbstractFile, val superCallsMap
8282
case _ => arg
8383
}
8484

85-
private def emitArgument(av: AnnotationVisitor,
86-
name: String,
87-
arg: Tree, bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen): Unit = {
88-
val narg = normalizeArgument(arg)
89-
// Transformation phases are not run on annotation trees, so we need to run
90-
// `constToLiteral` at this point.
91-
val t = constToLiteral(narg)(ctx.withPhase(ctx.erasurePhase))
92-
t match {
93-
case Literal(const @ Constant(_)) =>
94-
const.tag match {
95-
case BooleanTag | ByteTag | ShortTag | CharTag | IntTag | LongTag | FloatTag | DoubleTag => av.visit(name, const.value)
96-
case StringTag =>
97-
assert(const.value != null, const) // TODO this invariant isn't documented in `case class Constant`
98-
av.visit(name, const.stringValue) // `stringValue` special-cases null, but that execution path isn't exercised for a const with StringTag
99-
case ClazzTag => av.visit(name, typeToTypeKind(const.typeValue)(bcodeStore)(innerClasesStore).toASMType)
100-
case EnumTag =>
101-
val edesc = innerClasesStore.typeDescriptor(const.tpe.asInstanceOf[bcodeStore.int.Type]) // the class descriptor of the enumeration class.
102-
val evalue = const.symbolValue.name.mangledString // value the actual enumeration value.
103-
av.visitEnum(name, edesc, evalue)
104-
}
105-
case t: TypeApply if (t.fun.symbol == defn.Predef_classOf) =>
106-
av.visit(name, typeToTypeKind(t.args.head.tpe.classSymbol.denot.info)(bcodeStore)(innerClasesStore).toASMType)
107-
case Ident(nme.WILDCARD) =>
108-
// An underscore argument indicates that we want to use the default value for this parameter, so do not emit anything
109-
case t: tpd.RefTree if t.symbol.denot.owner.isAllOf(Flags.JavaEnumTrait) =>
110-
val edesc = innerClasesStore.typeDescriptor(t.tpe.asInstanceOf[bcodeStore.int.Type]) // the class descriptor of the enumeration class.
111-
val evalue = t.symbol.name.mangledString // value the actual enumeration value.
112-
av.visitEnum(name, edesc, evalue)
113-
case t: SeqLiteral =>
114-
val arrAnnotV: AnnotationVisitor = av.visitArray(name)
115-
for (arg <- t.elems) { emitArgument(arrAnnotV, null, arg, bcodeStore)(innerClasesStore) }
116-
arrAnnotV.visitEnd()
117-
118-
case Apply(fun, args) if fun.symbol == defn.ArrayClass.primaryConstructor ||
119-
toDenot(fun.symbol).owner == defn.ArrayClass.linkedClass && fun.symbol.name == nme.apply =>
120-
val arrAnnotV: AnnotationVisitor = av.visitArray(name)
121-
122-
var actualArgs = if (fun.tpe.isImplicitMethod) {
123-
// generic array method, need to get implicit argument out of the way
124-
fun.asInstanceOf[Apply].args
125-
} else args
126-
127-
val flatArgs = actualArgs.flatMap { arg =>
128-
normalizeArgument(arg) match {
129-
case t: tpd.SeqLiteral => t.elems
130-
case e => List(e)
131-
}
132-
}
133-
for(arg <- flatArgs) {
134-
emitArgument(arrAnnotV, null, arg, bcodeStore)(innerClasesStore)
135-
}
136-
arrAnnotV.visitEnd()
137-
/*
138-
case sb @ ScalaSigBytes(bytes) =>
139-
// see http://www.scala-lang.org/sid/10 (Storage of pickled Scala signatures in class files)
140-
// also JVMS Sec. 4.7.16.1 The element_value structure and JVMS Sec. 4.4.7 The CONSTANT_Utf8_info Structure.
141-
if (sb.fitsInOneString) {
142-
av.visit(name, BCodeAsmCommon.strEncode(sb))
143-
} else {
144-
val arrAnnotV: asm.AnnotationVisitor = av.visitArray(name)
145-
for(arg <- BCodeAsmCommon.arrEncode(sb)) { arrAnnotV.visit(name, arg) }
146-
arrAnnotV.visitEnd()
147-
} // for the lazy val in ScalaSigBytes to be GC'ed, the invoker of emitAnnotations() should hold the ScalaSigBytes in a method-local var that doesn't escape.
148-
*/
149-
case t @ Apply(constr, args) if t.tpe.derivesFrom(JavaAnnotationClass) =>
150-
val typ = t.tpe.classSymbol.denot.info
151-
val assocs = assocsFromApply(t)
152-
val desc = innerClasesStore.typeDescriptor(typ.asInstanceOf[bcodeStore.int.Type]) // the class descriptor of the nested annotation class
153-
val nestedVisitor = av.visitAnnotation(name, desc)
154-
emitAssocs(nestedVisitor, assocs, bcodeStore)(innerClasesStore)
155-
156-
case t =>
157-
ctx.error(ex"Annotation argument is not a constant", t.sourcePos)
158-
}
159-
}
160-
161-
def emitAnnotations(cw: asm.ClassVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers)
162-
(innerClasesStore: bcodeStore.BCInnerClassGen): Unit = {
163-
for(annot <- annotations; if shouldEmitAnnotation(annot)) {
164-
val typ = annot.tree.tpe
165-
val assocs = assocsFromApply(annot.tree)
166-
val av = cw.visitAnnotation(innerClasesStore.typeDescriptor(typ.asInstanceOf[bcodeStore.int.Type]), isRuntimeVisible(annot))
167-
emitAssocs(av, assocs, bcodeStore)(innerClasesStore)
168-
}
169-
}
170-
171-
private def emitAssocs(av: asm.AnnotationVisitor, assocs: List[(Name, Object)], bcodeStore: BCodeHelpers)
172-
(innerClasesStore: bcodeStore.BCInnerClassGen) = {
173-
for ((name, value) <- assocs)
174-
emitArgument(av, name.mangledString, value.asInstanceOf[Tree], bcodeStore)(innerClasesStore)
175-
av.visitEnd()
176-
}
177-
178-
def emitAnnotations(mw: asm.MethodVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers)
179-
(innerClasesStore: bcodeStore.BCInnerClassGen): Unit = {
180-
for(annot <- annotations; if shouldEmitAnnotation(annot)) {
181-
val typ = annot.tree.tpe
182-
val assocs = assocsFromApply(annot.tree)
183-
val av = mw.visitAnnotation(innerClasesStore.typeDescriptor(typ.asInstanceOf[bcodeStore.int.Type]), isRuntimeVisible(annot))
184-
emitAssocs(av, assocs, bcodeStore)(innerClasesStore)
185-
}
186-
}
187-
188-
def emitAnnotations(fw: asm.FieldVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers)
189-
(innerClasesStore: bcodeStore.BCInnerClassGen): Unit = {
190-
for(annot <- annotations; if shouldEmitAnnotation(annot)) {
191-
val typ = annot.tree.tpe
192-
val assocs = assocsFromApply(annot.tree)
193-
val av = fw.visitAnnotation(innerClasesStore.typeDescriptor(typ.asInstanceOf[bcodeStore.int.Type]), isRuntimeVisible(annot))
194-
emitAssocs(av, assocs, bcodeStore)(innerClasesStore)
195-
}
196-
}
197-
198-
def emitParamAnnotations(jmethod: asm.MethodVisitor, pannotss: List[List[Annotation]], bcodeStore: BCodeHelpers)
199-
(innerClasesStore: bcodeStore.BCInnerClassGen): Unit = {
200-
val annotationss = pannotss map (_ filter shouldEmitAnnotation)
201-
if (annotationss forall (_.isEmpty)) return
202-
for ((annots, idx) <- annotationss.zipWithIndex;
203-
annot <- annots) {
204-
val typ = annot.tree.tpe
205-
val assocs = assocsFromApply(annot.tree)
206-
val pannVisitor: asm.AnnotationVisitor = jmethod.visitParameterAnnotation(idx, innerClasesStore.typeDescriptor(typ.asInstanceOf[bcodeStore.int.Type]), isRuntimeVisible(annot))
207-
emitAssocs(pannVisitor, assocs, bcodeStore)(innerClasesStore)
208-
}
209-
}
210-
21185
def getAnnotPickle(jclassName: String, sym: Symbol): Option[Annotation] = None
21286

21387

0 commit comments

Comments
 (0)