summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2012-07-10 14:49:14 -0700
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-07-10 14:49:14 -0700
commit026a70d55591c3b5ee157e22998b62168afee686 (patch)
treeb2c04650891e10b3fbe5a38bcc8b39c2e4cb4e0d
parentf86a50d51f0a34ce8aa0ad18813983022e9f5487 (diff)
parent34ce72f3633e151c8b4f44b0ca84c9f4c38ac0ee (diff)
downloadscala-026a70d55591c3b5ee157e22998b62168afee686.tar.gz
scala-026a70d55591c3b5ee157e22998b62168afee686.tar.bz2
scala-026a70d55591c3b5ee157e22998b62168afee686.zip
Merge pull request #861 from dragos/revert-genasm-bg-threadv2.10.0-M5
Revert "GenASM: pipeline disk-write with building of classfiles"
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala22
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala94
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala10
3 files changed, 35 insertions, 91 deletions
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