summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2014-05-10 09:07:36 +0200
committerLukas Rytz <lukas.rytz@gmail.com>2014-05-13 15:17:17 +0200
commit9e1b464d44d2402211b905d6d89cf4004090fe43 (patch)
tree2f140ce75390ba3e5c7fd519d15b76438110cf5a /src/compiler
parentea166087ce3fe2731a8b0d767cbbd4c5e5e648c1 (diff)
downloadscala-9e1b464d44d2402211b905d6d89cf4004090fe43.tar.gz
scala-9e1b464d44d2402211b905d6d89cf4004090fe43.tar.bz2
scala-9e1b464d44d2402211b905d6d89cf4004090fe43.zip
Allow tracing methods and classes in GenBCode
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala53
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala9
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala11
5 files changed, 75 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala
new file mode 100644
index 0000000000..856f85d9e3
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala
@@ -0,0 +1,53 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2014 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.tools.nsc.backend.jvm
+
+import scala.tools.asm.tree.{ClassNode, MethodNode}
+import java.io.PrintWriter
+import scala.tools.asm.util.{TraceClassVisitor, TraceMethodVisitor, Textifier}
+
+object AsmUtils {
+
+ /**
+ * Print the bytecode of methods generated by GenBCode to the standard output. Only methods
+ * whose name contains `traceMethodPattern` are traced.
+ */
+ final val traceMethodEnabled = false
+ final val traceMethodPattern = ""
+
+ /**
+ * Print the bytecode of classes generated by GenBCode to the standard output.
+ */
+ final val traceClassEnabled = false
+ final val traceClassPattern = ""
+
+ /**
+ * Print the bytedcode of classes as they are serialized by the ASM library. The serialization
+ * performed by `asm.ClassWriter` can change the code generated by GenBCode. For example, it
+ * introduces stack map frames, it computes the maximal stack sizes, and it replaces dead
+ * code by NOPs (see also https://github.com/scala/scala/pull/3726#issuecomment-42861780).
+ */
+ final val traceSerializedClassEnabled = false
+ final val traceSerializedClassPattern = ""
+
+ def traceMethod(mnode: MethodNode): Unit = {
+ println(s"Bytecode for method ${mnode.name}")
+ val p = new Textifier
+ val tracer = new TraceMethodVisitor(p)
+ mnode.accept(tracer)
+ val w = new PrintWriter(System.out)
+ p.print(w)
+ w.flush()
+ }
+
+ def traceClass(cnode: ClassNode): Unit = {
+ println(s"Bytecode for class ${cnode.name}")
+ val w = new PrintWriter(System.out)
+ cnode.accept(new TraceClassVisitor(w))
+ w.flush()
+ }
+
+}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
index 92ebe5027a..3d1b646069 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
@@ -808,7 +808,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
emit(asm.Opcodes.ATHROW) // ICode enters here into enterIgnoreMode, we'll rely instead on DCE at ClassNode level.
} else if (from.isNullType) {
bc drop from
- mnode.visitInsn(asm.Opcodes.ACONST_NULL)
+ emit(asm.Opcodes.ACONST_NULL)
}
else (from, to) match {
case (BYTE, LONG) | (SHORT, LONG) | (CHAR, LONG) | (INT, LONG) => bc.emitT2T(INT, LONG)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
index 360ce58ecc..dae53bc0e5 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
@@ -14,6 +14,8 @@ import scala.tools.nsc.symtab._
import scala.annotation.switch
import scala.tools.asm
+import scala.tools.asm.util.{TraceMethodVisitor, ASMifier}
+import java.io.PrintWriter
/*
*
@@ -117,6 +119,9 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
gen(cd.impl)
+ if (AsmUtils.traceClassEnabled && cnode.name.contains(AsmUtils.traceClassPattern))
+ AsmUtils.traceClass(cnode)
+
assert(cd.symbol == claszSymbol, "Someone messed up BCodePhase.claszSymbol during genPlainClass().")
} // end of method genPlainClass()
@@ -639,6 +644,10 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
// Note we don't invoke visitMax, thus there are no FrameNode among mnode.instructions.
// The only non-instruction nodes to be found are LabelNode and LineNumberNode.
}
+
+ if (AsmUtils.traceMethodEnabled && mnode.name.contains(AsmUtils.traceMethodPattern))
+ AsmUtils.traceMethod(mnode)
+
mnode = null
} // end of method genDefDef()
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
index 8e6c09213f..1d29fdee10 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
@@ -1,6 +1,6 @@
/* NSC -- new Scala compiler
* Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
+ * @author Martin Odersky
*/
package scala.tools.nsc
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
index 193100474c..61cf76f524 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
@@ -243,6 +243,17 @@ abstract class GenBCode extends BCodeSyncAndTry {
val plainC = SubItem3(plain.name, getByteArray(plain))
val beanC = if (bean == null) null else SubItem3(bean.name, getByteArray(bean))
+ if (AsmUtils.traceSerializedClassEnabled && plain.name.contains(AsmUtils.traceSerializedClassPattern)) {
+ def readClass(bytes: Array[Byte]): asm.tree.ClassNode = {
+ val node = new asm.tree.ClassNode()
+ new asm.ClassReader(bytes).accept(node, 0)
+ node
+ }
+ if (mirrorC != null) AsmUtils.traceClass(readClass(mirrorC.jclassBytes))
+ AsmUtils.traceClass(readClass(plainC.jclassBytes))
+ if (beanC != null) AsmUtils.traceClass(readClass(beanC.jclassBytes))
+ }
+
q3 add Item3(arrivalPos, mirrorC, plainC, beanC, outFolder)
}