Skip to content

Commit 783c5cc

Browse files
committed
Merge pull request scala#4210 from lrytz/opt/classBTypeFromClassfile
Construct ClassBTypes from parsed classfiles
2 parents d395e52 + f3f9eb4 commit 783c5cc

File tree

16 files changed

+536
-184
lines changed

16 files changed

+536
-184
lines changed

src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55

66
package scala.tools.nsc.backend.jvm
77

8-
import scala.tools.asm.tree.{AbstractInsnNode, ClassNode, MethodNode}
9-
import java.io.PrintWriter
8+
import scala.tools.asm.tree.{InsnList, AbstractInsnNode, ClassNode, MethodNode}
9+
import java.io.{StringWriter, PrintWriter}
1010
import scala.tools.asm.util.{TraceClassVisitor, TraceMethodVisitor, Textifier}
1111
import scala.tools.asm.ClassReader
12+
import scala.collection.convert.decorateAsScala._
1213

1314
object AsmUtils {
1415

@@ -36,19 +37,12 @@ object AsmUtils {
3637

3738
def traceMethod(mnode: MethodNode): Unit = {
3839
println(s"Bytecode for method ${mnode.name}")
39-
val p = new Textifier
40-
val tracer = new TraceMethodVisitor(p)
41-
mnode.accept(tracer)
42-
val w = new PrintWriter(System.out)
43-
p.print(w)
44-
w.flush()
40+
println(textify(mnode))
4541
}
4642

4743
def traceClass(cnode: ClassNode): Unit = {
4844
println(s"Bytecode for class ${cnode.name}")
49-
val w = new PrintWriter(System.out)
50-
cnode.accept(new TraceClassVisitor(w))
51-
w.flush()
45+
println(textify(cnode))
5246
}
5347

5448
def traceClass(bytes: Array[Byte]): Unit = traceClass(readClass(bytes))
@@ -59,8 +53,56 @@ object AsmUtils {
5953
node
6054
}
6155

62-
def instructionString(instruction: AbstractInsnNode): String = instruction.getOpcode match {
63-
case -1 => instruction.toString
64-
case op => scala.tools.asm.util.Printer.OPCODES(op)
56+
/**
57+
* Returns a human-readable representation of the cnode ClassNode.
58+
*/
59+
def textify(cnode: ClassNode): String = {
60+
val trace = new TraceClassVisitor(new PrintWriter(new StringWriter))
61+
cnode.accept(trace)
62+
val sw = new StringWriter
63+
val pw = new PrintWriter(sw)
64+
trace.p.print(pw)
65+
sw.toString
6566
}
67+
68+
/**
69+
* Returns a human-readable representation of the code in the mnode MethodNode.
70+
*/
71+
def textify(mnode: MethodNode): String = {
72+
val trace = new TraceClassVisitor(new PrintWriter(new StringWriter))
73+
mnode.accept(trace)
74+
val sw = new StringWriter
75+
val pw = new PrintWriter(sw)
76+
trace.p.print(pw)
77+
sw.toString
78+
}
79+
80+
/**
81+
* Returns a human-readable representation of the given instruction.
82+
*/
83+
def textify(insn: AbstractInsnNode): String = {
84+
val trace = new TraceMethodVisitor(new Textifier)
85+
insn.accept(trace)
86+
val sw = new StringWriter
87+
val pw = new PrintWriter(sw)
88+
trace.p.print(pw)
89+
sw.toString.trim
90+
}
91+
92+
/**
93+
* Returns a human-readable representation of the given instruction sequence.
94+
*/
95+
def textify(insns: Iterator[AbstractInsnNode]): String = {
96+
val trace = new TraceMethodVisitor(new Textifier)
97+
insns.foreach(_.accept(trace))
98+
val sw: StringWriter = new StringWriter
99+
val pw: PrintWriter = new PrintWriter(sw)
100+
trace.p.print(pw)
101+
sw.toString.trim
102+
}
103+
104+
/**
105+
* Returns a human-readable representation of the given instruction sequence.
106+
*/
107+
def textify(insns: InsnList): String = textify(insns.iterator().asScala)
66108
}

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

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -791,32 +791,28 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
791791
assert(moduleClass.companionClass == NoSymbol, moduleClass)
792792
innerClassBufferASM.clear()
793793
this.cunit = cunit
794-
val moduleName = internalName(moduleClass) // + "$"
795-
val mirrorName = moduleName.substring(0, moduleName.length() - 1)
796794

797-
val flags = (asm.Opcodes.ACC_SUPER | asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_FINAL)
795+
val bType = mirrorClassClassBType(moduleClass)
798796
val mirrorClass = new asm.tree.ClassNode
799797
mirrorClass.visit(
800798
classfileVersion,
801-
flags,
802-
mirrorName,
799+
bType.info.flags,
800+
bType.internalName,
803801
null /* no java-generic-signature */,
804802
ObjectReference.internalName,
805803
EMPTY_STRING_ARRAY
806804
)
807805

808-
if (emitSource) {
809-
mirrorClass.visitSource("" + cunit.source,
810-
null /* SourceDebugExtension */)
811-
}
806+
if (emitSource)
807+
mirrorClass.visitSource("" + cunit.source, null /* SourceDebugExtension */)
812808

813-
val ssa = getAnnotPickle(mirrorName, moduleClass.companionSymbol)
809+
val ssa = getAnnotPickle(bType.internalName, moduleClass.companionSymbol)
814810
mirrorClass.visitAttribute(if (ssa.isDefined) pickleMarkerLocal else pickleMarkerForeign)
815811
emitAnnotations(mirrorClass, moduleClass.annotations ++ ssa)
816812

817-
addForwarders(isRemote(moduleClass), mirrorClass, mirrorName, moduleClass)
813+
addForwarders(isRemote(moduleClass), mirrorClass, bType.internalName, moduleClass)
818814

819-
innerClassBufferASM ++= classBTypeFromSymbol(moduleClass).info.memberClasses
815+
innerClassBufferASM ++= bType.info.nestedClasses
820816
addInnerClassesASM(mirrorClass, innerClassBufferASM.toList)
821817

822818
mirrorClass.visitEnd()
@@ -932,7 +928,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
932928
constructor.visitMaxs(0, 0) // just to follow protocol, dummy arguments
933929
constructor.visitEnd()
934930

935-
innerClassBufferASM ++= classBTypeFromSymbol(cls).info.memberClasses
931+
innerClassBufferASM ++= classBTypeFromSymbol(cls).info.nestedClasses
936932
addInnerClassesASM(beanInfoClass, innerClassBufferASM.toList)
937933

938934
beanInfoClass.visitEnd()

src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ abstract class BCodeIdiomatic extends SubComponent {
271271
assert(from != BOOL && to != BOOL, s"inconvertible types : $from -> $to")
272272

273273
// We're done with BOOL already
274-
from match {
274+
(from: @unchecked) match {
275275

276276
// using `asm.Type.SHORT` instead of `BType.SHORT` because otherwise "warning: could not emit switch for @switch annotated match"
277277

@@ -361,7 +361,7 @@ abstract class BCodeIdiomatic extends SubComponent {
361361
assert(elem.isNonVoidPrimitiveType)
362362
val rand = {
363363
// using `asm.Type.SHORT` instead of `BType.SHORT` because otherwise "warning: could not emit switch for @switch annotated match"
364-
elem match {
364+
(elem: @unchecked) match {
365365
case BOOL => Opcodes.T_BOOLEAN
366366
case BYTE => Opcodes.T_BYTE
367367
case SHORT => Opcodes.T_SHORT

src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
118118

119119
addClassFields()
120120

121-
innerClassBufferASM ++= classBTypeFromSymbol(claszSymbol).info.memberClasses
121+
innerClassBufferASM ++= classBTypeFromSymbol(claszSymbol).info.nestedClasses
122122
gen(cd.impl)
123123
addInnerClassesASM(cnode, innerClassBufferASM.toList)
124124

0 commit comments

Comments
 (0)