From 34ce72f3633e151c8b4f44b0ca84c9f4c38ac0ee Mon Sep 17 00:00:00 2001 From: Iulian Dragos Date: Tue, 10 Jul 2012 17:27:51 +0200 Subject: Revert "GenASM: pipeline disk-write with building of classfiles" This reverts commit 5d12fa4b791e73d5c99a0e145d28cbaba12823d2. --- .../tools/nsc/backend/jvm/BytecodeWriters.scala | 22 +++-- .../scala/tools/nsc/backend/jvm/GenASM.scala | 94 ++++++---------------- .../scala/tools/nsc/backend/jvm/GenJVM.scala | 10 +-- 3 files changed, 35 insertions(+), 91 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala index 42921e733d..ff68aba845 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala @@ -37,7 +37,7 @@ trait BytecodeWriters { getFile(outputDirectory(sym), clsName, suffix) trait BytecodeWriter { - def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], outfile: AbstractFile): Unit + def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol): Unit def close(): Unit = () } @@ -48,9 +48,7 @@ trait BytecodeWriters { ) val writer = new Jar(jfile).jarWriter(jarMainAttrs: _*) - def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], outfile: AbstractFile) { - assert(outfile == null, - "The outfile formal param is there just because ClassBytecodeWriter overrides this method and uses it.") + def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) { val path = jclassName + ".class" val out = writer.newOutputStream(path) @@ -74,21 +72,21 @@ trait BytecodeWriters { try javap(Seq("-verbose", "dummy")) foreach (_.show()) finally pw.close() } - abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], outfile: AbstractFile) { - super.writeClass(label, jclassName, jclassBytes, outfile) + abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) { + super.writeClass(label, jclassName, jclassBytes, sym) + val bytes = getFile(sym, jclassName, ".class").toByteArray val segments = jclassName.split("[./]") val javapFile = segments.foldLeft(baseDir: Path)(_ / _) changeExtension "javap" toFile; javapFile.parent.createDirectory() - emitJavap(jclassBytes, javapFile) + emitJavap(bytes, javapFile) } } trait ClassBytecodeWriter extends BytecodeWriter { - def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], outfile: AbstractFile) { - assert(outfile != null, - "Precisely this override requires its invoker to hand out a non-null AbstractFile.") + def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) { + val outfile = getFile(sym, jclassName, ".class") val outstream = new DataOutputStream(outfile.bufferedOutput) try outstream.write(jclassBytes, 0, jclassBytes.length) @@ -100,8 +98,8 @@ trait BytecodeWriters { trait DumpBytecodeWriter extends BytecodeWriter { val baseDir = Directory(settings.Ydumpclasses.value).createDirectory() - abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], outfile: AbstractFile) { - super.writeClass(label, jclassName, jclassBytes, outfile) + abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) { + super.writeClass(label, jclassName, jclassBytes, sym) val pathName = jclassName var dumpFile = pathName.split("[./]").foldLeft(baseDir: Path) (_ / _) changeExtension "class" toFile; diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 32c100b026..ac2780f53e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -29,10 +29,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { val phaseName = "jvm" - case class WorkUnit(label: String, jclassName: String, jclass: asm.ClassWriter, outF: AbstractFile) - - type WorkUnitQueue = _root_.java.util.concurrent.LinkedBlockingQueue[WorkUnit] - /** Create a new phase */ override def newPhase(p: Phase): Phase = new AsmPhase(p) @@ -152,44 +148,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { } } - // ----------------------------------------------------------------------------------------- - // Allow overlapping disk write of classfiles with building of the next classfiles. - // ----------------------------------------------------------------------------------------- - - val q = new WorkUnitQueue(500) - - class WriteTask(bytecodeWriter: BytecodeWriter) extends _root_.java.lang.Runnable { - - def run() { - var stop = false - try { - while (!stop) { - val WorkUnit(label, jclassName, jclass, outF) = q.take - if(jclass eq null) { stop = true } - else { writeIfNotTooBig(label, jclassName, jclass, outF) } - } - } catch { - case ex: InterruptedException => throw ex - } - } - - private def writeIfNotTooBig(label: String, jclassName: String, jclass: asm.ClassWriter, outF: AbstractFile) { - try { - val arr = jclass.toByteArray() - bytecodeWriter.writeClass(label, jclassName, arr, outF) - } catch { - case e: java.lang.RuntimeException if(e.getMessage() == "Class file too large!") => - // TODO check where ASM throws the equivalent of CodeSizeTooBigException - log("Skipped class "+jclassName+" because it exceeds JVM limits (it's too big or has methods that are too long).") - } - } - - } - - // ----------------------------------------------------------------------------------------- - // what AsmPhase does. - // ----------------------------------------------------------------------------------------- - override def run() { if (settings.debug.value) @@ -203,14 +161,10 @@ abstract class GenASM extends SubComponent with BytecodeWriters { var sortedClasses = classes.values.toList sortBy ("" + _.symbol.fullName) debuglog("Created new bytecode generator for " + classes.size + " classes.") - val bytecodeWriter = initBytecodeWriter(sortedClasses filter isJavaEntryPoint) - val needsOutfileForSymbol = bytecodeWriter.isInstanceOf[ClassBytecodeWriter] - - val plainCodeGen = new JPlainBuilder(q, needsOutfileForSymbol) - val mirrorCodeGen = new JMirrorBuilder(q, needsOutfileForSymbol) - val beanInfoCodeGen = new JBeanInfoBuilder(q, needsOutfileForSymbol) - - new _root_.java.lang.Thread(new WriteTask(bytecodeWriter)).start() + val bytecodeWriter = initBytecodeWriter(sortedClasses filter isJavaEntryPoint) + val plainCodeGen = new JPlainBuilder(bytecodeWriter) + val mirrorCodeGen = new JMirrorBuilder(bytecodeWriter) + val beanInfoCodeGen = new JBeanInfoBuilder(bytecodeWriter) while(!sortedClasses.isEmpty) { val c = sortedClasses.head @@ -233,10 +187,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { classes -= c.symbol // GC opportunity } - q put WorkUnit(null, null, null, null) - - while(!q.isEmpty) { _root_.java.lang.Thread.sleep(10) } - bytecodeWriter.close() classes.clear() reverseJavaName.clear() @@ -498,7 +448,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { val JAVA_LANG_STRING = asm.Type.getObjectType("java/lang/String") /** basic functionality for class file building */ - abstract class JBuilder(wuQ: WorkUnitQueue, needsOutfileForSymbol: Boolean) { + abstract class JBuilder(bytecodeWriter: BytecodeWriter) { val EMPTY_JTYPE_ARRAY = Array.empty[asm.Type] val EMPTY_STRING_ARRAY = Array.empty[String] @@ -554,6 +504,17 @@ abstract class GenASM extends SubComponent with BytecodeWriters { // utitilies useful when emitting plain, mirror, and beaninfo classes. // ----------------------------------------------------------------------------------------- + def writeIfNotTooBig(label: String, jclassName: String, jclass: asm.ClassWriter, sym: Symbol) { + try { + val arr = jclass.toByteArray() + bytecodeWriter.writeClass(label, jclassName, arr, sym) + } catch { + case e: java.lang.RuntimeException if(e.getMessage() == "Class file too large!") => + // TODO check where ASM throws the equivalent of CodeSizeTooBigException + log("Skipped class "+jclassName+" because it exceeds JVM limits (it's too big or has methods that are too long).") + } + } + /** Specialized array conversion to prevent calling * java.lang.reflect.Array.newInstance via TraversableOnce.toArray */ @@ -767,18 +728,11 @@ abstract class GenASM extends SubComponent with BytecodeWriters { } } - def enqueue(label: String, jclassName: String, jclass: asm.ClassWriter, sym: Symbol) { - val outF: scala.tools.nsc.io.AbstractFile = { - if(needsOutfileForSymbol) getFile(sym, jclassName, ".class") else null - } - wuQ put WorkUnit(label, jclassName, jclass, outF) - } - } // end of class JBuilder /** functionality for building plain and mirror classes */ - abstract class JCommonBuilder(wuQ: WorkUnitQueue, needsOutfileForSymbol: Boolean) extends JBuilder(wuQ, needsOutfileForSymbol) { + abstract class JCommonBuilder(bytecodeWriter: BytecodeWriter) extends JBuilder(bytecodeWriter) { def debugLevel = settings.debuginfo.indexOfChoice @@ -1342,8 +1296,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters { case class BlockInteval(start: BasicBlock, end: BasicBlock) /** builder of plain classes */ - class JPlainBuilder(wuQ: WorkUnitQueue, needsOutfileForSymbol: Boolean) - extends JCommonBuilder(wuQ, needsOutfileForSymbol) + class JPlainBuilder(bytecodeWriter: BytecodeWriter) + extends JCommonBuilder(bytecodeWriter) with JAndroidBuilder { val MIN_SWITCH_DENSITY = 0.7 @@ -1499,7 +1453,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { addInnerClasses(clasz.symbol, jclass) jclass.visitEnd() - enqueue("" + c.symbol.name, thisName, jclass, c.symbol) + writeIfNotTooBig("" + c.symbol.name, thisName, jclass, c.symbol) } @@ -2938,7 +2892,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { /** builder of mirror classes */ - class JMirrorBuilder(wuQ: WorkUnitQueue, needsOutfileForSymbol: Boolean) extends JCommonBuilder(wuQ, needsOutfileForSymbol) { + class JMirrorBuilder(bytecodeWriter: BytecodeWriter) extends JCommonBuilder(bytecodeWriter) { private var cunit: CompilationUnit = _ def getCurrentCUnit(): CompilationUnit = cunit; @@ -2984,7 +2938,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { addInnerClasses(modsym, mirrorClass) mirrorClass.visitEnd() - enqueue("" + modsym.name, mirrorName, mirrorClass, modsym) + writeIfNotTooBig("" + modsym.name, mirrorName, mirrorClass, modsym) } @@ -2992,7 +2946,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { /** builder of bean info classes */ - class JBeanInfoBuilder(wuQ: WorkUnitQueue, needsOutfileForSymbol: Boolean) extends JBuilder(wuQ, needsOutfileForSymbol) { + class JBeanInfoBuilder(bytecodeWriter: BytecodeWriter) extends JBuilder(bytecodeWriter) { /** * Generate a bean info class that describes the given class. @@ -3113,7 +3067,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { addInnerClasses(clasz.symbol, beanInfoClass) beanInfoClass.visitEnd() - enqueue("BeanInfo ", beanInfoName, beanInfoClass, clasz.symbol) + writeIfNotTooBig("BeanInfo ", beanInfoName, beanInfoClass, clasz.symbol) } } // end of class JBeanInfoBuilder diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index ad054015ef..21260d399c 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -183,6 +183,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with class BytecodeGenerator(bytecodeWriter: BytecodeWriter) extends BytecodeUtil { def this() = this(new ClassBytecodeWriter { }) def debugLevel = settings.debuginfo.indexOfChoice + import bytecodeWriter.writeClass val MIN_SWITCH_DENSITY = 0.7 val INNER_CLASSES_FLAGS = @@ -343,15 +344,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with writeClass("" + sym.name, jclass.getName(), toByteArray(jclass), sym) } - val needsOutfileForSymbol = bytecodeWriter.isInstanceOf[ClassBytecodeWriter] - - def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) { - val outF: scala.tools.nsc.io.AbstractFile = { - if(needsOutfileForSymbol) getFile(sym, jclassName, ".class") else null - } - bytecodeWriter.writeClass(label, jclassName, jclassBytes, outF) - } - /** Returns the ScalaSignature annotation if it must be added to this class, * none otherwise; furthermore, it adds to `jclass` the ScalaSig marker * attribute (marking that a scala signature annotation is present) or the -- cgit v1.2.3