diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala | 62 |
1 files changed, 54 insertions, 8 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala index cd7e0b83e8..402dc66a7f 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala @@ -5,11 +5,15 @@ package scala.tools.nsc.backend.jvm -import scala.tools.asm.tree.{InsnList, AbstractInsnNode, ClassNode, MethodNode} -import java.io.{StringWriter, PrintWriter} -import scala.tools.asm.util.{CheckClassAdapter, TraceClassVisitor, TraceMethodVisitor, Textifier} -import scala.tools.asm.{ClassWriter, Attribute, ClassReader} -import scala.collection.convert.decorateAsScala._ +import scala.tools.asm.tree.{AbstractInsnNode, ClassNode, FieldNode, InsnList, MethodNode} +import java.io.{PrintWriter, StringWriter} +import java.util + +import scala.tools.asm.util.{CheckClassAdapter, Textifier, TraceClassVisitor, TraceMethodVisitor} +import scala.tools.asm.{Attribute, ClassReader, ClassWriter} +import scala.collection.JavaConverters._ +import scala.concurrent.duration.Duration +import scala.concurrent.{Await, Future} import scala.tools.nsc.backend.jvm.analysis.InitialProducer import scala.tools.nsc.backend.jvm.opt.InlineInfoAttributePrototype @@ -29,7 +33,7 @@ object AsmUtils { final val traceClassPattern = "" /** - * Print the bytedcode of classes as they are serialized by the ASM library. The serialization + * Print the bytecode 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). @@ -55,6 +59,48 @@ object AsmUtils { node } + def readClass(filename: String): ClassNode = readClass(classBytes(filename)) + + def classBytes(file: String): Array[Byte] = { + val f = new java.io.RandomAccessFile(file, "r") + val bytes = new Array[Byte](f.length.toInt) + f.read(bytes) + bytes + } + + def classFromBytes(bytes: Array[Byte]): ClassNode = { + val node = new ClassNode() + new ClassReader(bytes).accept(node, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES) + + node + } + +// def main(args: Array[String]): Unit = println(textify(sortedClassRead(classBytes(args.head)))) + + def sortClassMembers(node: ClassNode): node.type = { + node.fields.sort(_.name compareTo _.name) + node.methods.sort(_.name compareTo _.name) + node + } + + // drop ScalaSig annotation and class attributes + def zapScalaClassAttrs(node: ClassNode): node.type = { + if (node.visibleAnnotations != null) + node.visibleAnnotations = node.visibleAnnotations.asScala.filterNot(a => a == null || a.desc.contains("Lscala/reflect/ScalaSignature")).asJava + + node.attrs = null + node + } + + def main(args: Array[String]): Unit = args.par.foreach { classFileName => + val node = zapScalaClassAttrs(sortClassMembers(classFromBytes(classBytes(classFileName)))) + + val pw = new PrintWriter(classFileName + ".asm") + val trace = new TraceClassVisitor(pw) + node.accept(trace) + pw.close() + } + /** * Returns a human-readable representation of the cnode ClassNode. */ @@ -115,12 +161,12 @@ object AsmUtils { * Run ASM's CheckClassAdapter over a class. Returns None if no problem is found, otherwise * Some(msg) with the verifier's error message. */ - def checkClass(classNode: ClassNode): Option[String] = { + def checkClass(classNode: ClassNode, dumpNonErroneous: Boolean = false): Option[String] = { val cw = new ClassWriter(ClassWriter.COMPUTE_MAXS) classNode.accept(cw) val sw = new StringWriter() val pw = new PrintWriter(sw) - CheckClassAdapter.verify(new ClassReader(cw.toByteArray), false, pw) + CheckClassAdapter.verify(new ClassReader(cw.toByteArray), dumpNonErroneous, pw) val res = sw.toString if (res.isEmpty) None else Some(res) } |