summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
diff options
context:
space:
mode:
authorMiguel Garcia <miguelalfredo.garcia@epfl.ch>2013-03-24 18:03:44 +0100
committerMiguel Garcia <miguelalfredo.garcia@epfl.ch>2013-04-27 10:56:27 +0200
commit38f426d2ae2058b44ac96d5b6618d7552a23c359 (patch)
tree6dfd08860b3e7f2fb6aa225c736dea90feddd2e3 /src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
parent0c5e2e8f577165ac622a93e0b407f272130f0f37 (diff)
downloadscala-38f426d2ae2058b44ac96d5b6618d7552a23c359.tar.gz
scala-38f426d2ae2058b44ac96d5b6618d7552a23c359.tar.bz2
scala-38f426d2ae2058b44ac96d5b6618d7552a23c359.zip
compiler flag -Ygen-asmp to emit .asmp textual files for bytecode
This commit adds the -Ygen-asmp compiler flag, similar in purpose to what -Ygen-javap used to be. The ASM-based counterpart to javap is useful even in those cases where javap is available, as it produces for example readable (textual) output for pickles. Additionally, javap displays quite differently two constant pools that have identical contents (javap shows their physical layout, not just the information the entries hold). Finally, stack maps (classfile version 50 and up) are displayed in encoded form by javap, their expansion by ASM is more readable.
Diffstat (limited to 'src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
index 66aed14d1c..e20b75ed13 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
@@ -41,6 +41,17 @@ trait BytecodeWriters {
private def getFile(sym: Symbol, clsName: String, suffix: String): AbstractFile =
getFile(outputDirectory(sym), clsName, suffix)
+ def factoryNonJarBytecodeWriter(): BytecodeWriter = {
+ val emitAsmp = settings.Ygenasmp.isSetByUser
+ val doDump = settings.Ydumpclasses.isSetByUser
+ (emitAsmp, doDump) match {
+ case (false, false) => new ClassBytecodeWriter { }
+ case (false, true ) => new ClassBytecodeWriter with DumpBytecodeWriter { }
+ case (true, false) => new ClassBytecodeWriter with AsmpBytecodeWriter
+ case (true, true ) => new ClassBytecodeWriter with AsmpBytecodeWriter with DumpBytecodeWriter { }
+ }
+ }
+
trait BytecodeWriter {
def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol): Unit
def close(): Unit = ()
@@ -65,6 +76,43 @@ trait BytecodeWriters {
override def close() = writer.close()
}
+ /*
+ * The ASM textual representation for bytecode overcomes disadvantages of javap ouput in three areas:
+ * (a) pickle dingbats undecipherable to the naked eye;
+ * (b) two constant pools, while having identical contents, are displayed differently due to physical layout.
+ * (c) stack maps (classfile version 50 and up) are displayed in encoded form by javap,
+ * their expansion by ASM is more readable.
+ *
+ * */
+ trait AsmpBytecodeWriter extends BytecodeWriter {
+ import scala.tools.asm
+
+ private val baseDir = Directory(settings.Ygenasmp.value).createDirectory()
+
+ private def emitAsmp(jclassBytes: Array[Byte], asmpFile: io.File) {
+ val pw = asmpFile.printWriter()
+ try {
+ val cnode = new asm.tree.ClassNode()
+ val cr = new asm.ClassReader(jclassBytes)
+ cr.accept(cnode, 0)
+ val trace = new scala.tools.asm.util.TraceClassVisitor(new java.io.PrintWriter(new java.io.StringWriter()))
+ cnode.accept(trace)
+ trace.p.print(pw)
+ }
+ finally pw.close()
+ }
+
+ abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
+ super.writeClass(label, jclassName, jclassBytes, sym)
+
+ val segments = jclassName.split("[./]")
+ val asmpFile = segments.foldLeft(baseDir: Path)(_ / _) changeExtension "asmp" toFile;
+
+ asmpFile.parent.createDirectory()
+ emitAsmp(jclassBytes, asmpFile)
+ }
+ }
+
trait ClassBytecodeWriter extends BytecodeWriter {
def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
val outfile = getFile(sym, jclassName, ".class")