summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@typesafe.com>2014-05-13 21:17:50 +0200
committerLukas Rytz <lukas.rytz@typesafe.com>2014-05-13 21:17:50 +0200
commitc763d8413b8e1ef5129378952b2327e8a7c2de7d (patch)
tree5bacd568c182fae72d5a6dddbc6c7fe0f0d4e96d /src/compiler
parentea166087ce3fe2731a8b0d767cbbd4c5e5e648c1 (diff)
parentfa2204e1749b21aa838350f321d5d85644be4ecf (diff)
downloadscala-c763d8413b8e1ef5129378952b2327e8a7c2de7d.tar.gz
scala-c763d8413b8e1ef5129378952b2327e8a7c2de7d.tar.bz2
scala-c763d8413b8e1ef5129378952b2327e8a7c2de7d.zip
Merge pull request #3745 from lrytz/t8582
SI-8582 emit InnerClasses attribute 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/BCodeHelpers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala11
6 files changed, 78 insertions, 4 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/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
index f800dbf9cd..1ede914288 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
@@ -1108,7 +1108,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
constructor.visitVarInsn(asm.Opcodes.ALOAD, 0)
// push the class
- constructor.visitLdcInsn(exemplar(cls).c)
+ constructor.visitLdcInsn(exemplar(cls).c.toASMType)
// push the string array of field information
constructor.visitLdcInsn(new java.lang.Integer(fieldList.length))
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
index 360ce58ecc..ee9be5b11c 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
/*
*
@@ -114,9 +116,13 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
addClassFields()
innerClassBufferASM ++= trackMemberClasses(claszSymbol, Nil)
-
gen(cd.impl)
+ addInnerClassesASM(cnode, innerClassBufferASM.toList)
+
+ if (AsmUtils.traceClassEnabled && cnode.name.contains(AsmUtils.traceClassPattern))
+ AsmUtils.traceClass(cnode)
+ cnode.innerClasses
assert(cd.symbol == claszSymbol, "Someone messed up BCodePhase.claszSymbol during genPlainClass().")
} // end of method genPlainClass()
@@ -639,6 +645,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)
}