Skip to content

Commit 026a70d

Browse files
author
Adriaan Moors
committed
Merge pull request scala#861 from dragos/revert-genasm-bg-thread
Revert "GenASM: pipeline disk-write with building of classfiles"
2 parents f86a50d + 34ce72f commit 026a70d

File tree

3 files changed

+35
-91
lines changed

3 files changed

+35
-91
lines changed

src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ trait BytecodeWriters {
3737
getFile(outputDirectory(sym), clsName, suffix)
3838

3939
trait BytecodeWriter {
40-
def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], outfile: AbstractFile): Unit
40+
def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol): Unit
4141
def close(): Unit = ()
4242
}
4343

@@ -48,9 +48,7 @@ trait BytecodeWriters {
4848
)
4949
val writer = new Jar(jfile).jarWriter(jarMainAttrs: _*)
5050

51-
def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], outfile: AbstractFile) {
52-
assert(outfile == null,
53-
"The outfile formal param is there just because ClassBytecodeWriter overrides this method and uses it.")
51+
def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
5452
val path = jclassName + ".class"
5553
val out = writer.newOutputStream(path)
5654

@@ -74,21 +72,21 @@ trait BytecodeWriters {
7472
try javap(Seq("-verbose", "dummy")) foreach (_.show())
7573
finally pw.close()
7674
}
77-
abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], outfile: AbstractFile) {
78-
super.writeClass(label, jclassName, jclassBytes, outfile)
75+
abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
76+
super.writeClass(label, jclassName, jclassBytes, sym)
7977

78+
val bytes = getFile(sym, jclassName, ".class").toByteArray
8079
val segments = jclassName.split("[./]")
8180
val javapFile = segments.foldLeft(baseDir: Path)(_ / _) changeExtension "javap" toFile;
8281

8382
javapFile.parent.createDirectory()
84-
emitJavap(jclassBytes, javapFile)
83+
emitJavap(bytes, javapFile)
8584
}
8685
}
8786

8887
trait ClassBytecodeWriter extends BytecodeWriter {
89-
def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], outfile: AbstractFile) {
90-
assert(outfile != null,
91-
"Precisely this override requires its invoker to hand out a non-null AbstractFile.")
88+
def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
89+
val outfile = getFile(sym, jclassName, ".class")
9290
val outstream = new DataOutputStream(outfile.bufferedOutput)
9391

9492
try outstream.write(jclassBytes, 0, jclassBytes.length)
@@ -100,8 +98,8 @@ trait BytecodeWriters {
10098
trait DumpBytecodeWriter extends BytecodeWriter {
10199
val baseDir = Directory(settings.Ydumpclasses.value).createDirectory()
102100

103-
abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], outfile: AbstractFile) {
104-
super.writeClass(label, jclassName, jclassBytes, outfile)
101+
abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
102+
super.writeClass(label, jclassName, jclassBytes, sym)
105103

106104
val pathName = jclassName
107105
var dumpFile = pathName.split("[./]").foldLeft(baseDir: Path) (_ / _) changeExtension "class" toFile;

src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala

Lines changed: 24 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
2929

3030
val phaseName = "jvm"
3131

32-
case class WorkUnit(label: String, jclassName: String, jclass: asm.ClassWriter, outF: AbstractFile)
33-
34-
type WorkUnitQueue = _root_.java.util.concurrent.LinkedBlockingQueue[WorkUnit]
35-
3632
/** Create a new phase */
3733
override def newPhase(p: Phase): Phase = new AsmPhase(p)
3834

@@ -152,44 +148,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
152148
}
153149
}
154150

155-
// -----------------------------------------------------------------------------------------
156-
// Allow overlapping disk write of classfiles with building of the next classfiles.
157-
// -----------------------------------------------------------------------------------------
158-
159-
val q = new WorkUnitQueue(500)
160-
161-
class WriteTask(bytecodeWriter: BytecodeWriter) extends _root_.java.lang.Runnable {
162-
163-
def run() {
164-
var stop = false
165-
try {
166-
while (!stop) {
167-
val WorkUnit(label, jclassName, jclass, outF) = q.take
168-
if(jclass eq null) { stop = true }
169-
else { writeIfNotTooBig(label, jclassName, jclass, outF) }
170-
}
171-
} catch {
172-
case ex: InterruptedException => throw ex
173-
}
174-
}
175-
176-
private def writeIfNotTooBig(label: String, jclassName: String, jclass: asm.ClassWriter, outF: AbstractFile) {
177-
try {
178-
val arr = jclass.toByteArray()
179-
bytecodeWriter.writeClass(label, jclassName, arr, outF)
180-
} catch {
181-
case e: java.lang.RuntimeException if(e.getMessage() == "Class file too large!") =>
182-
// TODO check where ASM throws the equivalent of CodeSizeTooBigException
183-
log("Skipped class "+jclassName+" because it exceeds JVM limits (it's too big or has methods that are too long).")
184-
}
185-
}
186-
187-
}
188-
189-
// -----------------------------------------------------------------------------------------
190-
// what AsmPhase does.
191-
// -----------------------------------------------------------------------------------------
192-
193151
override def run() {
194152

195153
if (settings.debug.value)
@@ -203,14 +161,10 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
203161
var sortedClasses = classes.values.toList sortBy ("" + _.symbol.fullName)
204162

205163
debuglog("Created new bytecode generator for " + classes.size + " classes.")
206-
val bytecodeWriter = initBytecodeWriter(sortedClasses filter isJavaEntryPoint)
207-
val needsOutfileForSymbol = bytecodeWriter.isInstanceOf[ClassBytecodeWriter]
208-
209-
val plainCodeGen = new JPlainBuilder(q, needsOutfileForSymbol)
210-
val mirrorCodeGen = new JMirrorBuilder(q, needsOutfileForSymbol)
211-
val beanInfoCodeGen = new JBeanInfoBuilder(q, needsOutfileForSymbol)
212-
213-
new _root_.java.lang.Thread(new WriteTask(bytecodeWriter)).start()
164+
val bytecodeWriter = initBytecodeWriter(sortedClasses filter isJavaEntryPoint)
165+
val plainCodeGen = new JPlainBuilder(bytecodeWriter)
166+
val mirrorCodeGen = new JMirrorBuilder(bytecodeWriter)
167+
val beanInfoCodeGen = new JBeanInfoBuilder(bytecodeWriter)
214168

215169
while(!sortedClasses.isEmpty) {
216170
val c = sortedClasses.head
@@ -233,10 +187,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
233187
classes -= c.symbol // GC opportunity
234188
}
235189

236-
q put WorkUnit(null, null, null, null)
237-
238-
while(!q.isEmpty) { _root_.java.lang.Thread.sleep(10) }
239-
240190
bytecodeWriter.close()
241191
classes.clear()
242192
reverseJavaName.clear()
@@ -498,7 +448,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
498448
val JAVA_LANG_STRING = asm.Type.getObjectType("java/lang/String")
499449

500450
/** basic functionality for class file building */
501-
abstract class JBuilder(wuQ: WorkUnitQueue, needsOutfileForSymbol: Boolean) {
451+
abstract class JBuilder(bytecodeWriter: BytecodeWriter) {
502452

503453
val EMPTY_JTYPE_ARRAY = Array.empty[asm.Type]
504454
val EMPTY_STRING_ARRAY = Array.empty[String]
@@ -554,6 +504,17 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
554504
// utitilies useful when emitting plain, mirror, and beaninfo classes.
555505
// -----------------------------------------------------------------------------------------
556506

507+
def writeIfNotTooBig(label: String, jclassName: String, jclass: asm.ClassWriter, sym: Symbol) {
508+
try {
509+
val arr = jclass.toByteArray()
510+
bytecodeWriter.writeClass(label, jclassName, arr, sym)
511+
} catch {
512+
case e: java.lang.RuntimeException if(e.getMessage() == "Class file too large!") =>
513+
// TODO check where ASM throws the equivalent of CodeSizeTooBigException
514+
log("Skipped class "+jclassName+" because it exceeds JVM limits (it's too big or has methods that are too long).")
515+
}
516+
}
517+
557518
/** Specialized array conversion to prevent calling
558519
* java.lang.reflect.Array.newInstance via TraversableOnce.toArray
559520
*/
@@ -767,18 +728,11 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
767728
}
768729
}
769730

770-
def enqueue(label: String, jclassName: String, jclass: asm.ClassWriter, sym: Symbol) {
771-
val outF: scala.tools.nsc.io.AbstractFile = {
772-
if(needsOutfileForSymbol) getFile(sym, jclassName, ".class") else null
773-
}
774-
wuQ put WorkUnit(label, jclassName, jclass, outF)
775-
}
776-
777731
} // end of class JBuilder
778732

779733

780734
/** functionality for building plain and mirror classes */
781-
abstract class JCommonBuilder(wuQ: WorkUnitQueue, needsOutfileForSymbol: Boolean) extends JBuilder(wuQ, needsOutfileForSymbol) {
735+
abstract class JCommonBuilder(bytecodeWriter: BytecodeWriter) extends JBuilder(bytecodeWriter) {
782736

783737
def debugLevel = settings.debuginfo.indexOfChoice
784738

@@ -1342,8 +1296,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
13421296
case class BlockInteval(start: BasicBlock, end: BasicBlock)
13431297

13441298
/** builder of plain classes */
1345-
class JPlainBuilder(wuQ: WorkUnitQueue, needsOutfileForSymbol: Boolean)
1346-
extends JCommonBuilder(wuQ, needsOutfileForSymbol)
1299+
class JPlainBuilder(bytecodeWriter: BytecodeWriter)
1300+
extends JCommonBuilder(bytecodeWriter)
13471301
with JAndroidBuilder {
13481302

13491303
val MIN_SWITCH_DENSITY = 0.7
@@ -1499,7 +1453,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
14991453

15001454
addInnerClasses(clasz.symbol, jclass)
15011455
jclass.visitEnd()
1502-
enqueue("" + c.symbol.name, thisName, jclass, c.symbol)
1456+
writeIfNotTooBig("" + c.symbol.name, thisName, jclass, c.symbol)
15031457

15041458
}
15051459

@@ -2938,7 +2892,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
29382892

29392893

29402894
/** builder of mirror classes */
2941-
class JMirrorBuilder(wuQ: WorkUnitQueue, needsOutfileForSymbol: Boolean) extends JCommonBuilder(wuQ, needsOutfileForSymbol) {
2895+
class JMirrorBuilder(bytecodeWriter: BytecodeWriter) extends JCommonBuilder(bytecodeWriter) {
29422896

29432897
private var cunit: CompilationUnit = _
29442898
def getCurrentCUnit(): CompilationUnit = cunit;
@@ -2984,15 +2938,15 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
29842938

29852939
addInnerClasses(modsym, mirrorClass)
29862940
mirrorClass.visitEnd()
2987-
enqueue("" + modsym.name, mirrorName, mirrorClass, modsym)
2941+
writeIfNotTooBig("" + modsym.name, mirrorName, mirrorClass, modsym)
29882942
}
29892943

29902944

29912945
} // end of class JMirrorBuilder
29922946

29932947

29942948
/** builder of bean info classes */
2995-
class JBeanInfoBuilder(wuQ: WorkUnitQueue, needsOutfileForSymbol: Boolean) extends JBuilder(wuQ, needsOutfileForSymbol) {
2949+
class JBeanInfoBuilder(bytecodeWriter: BytecodeWriter) extends JBuilder(bytecodeWriter) {
29962950

29972951
/**
29982952
* Generate a bean info class that describes the given class.
@@ -3113,7 +3067,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
31133067
addInnerClasses(clasz.symbol, beanInfoClass)
31143068
beanInfoClass.visitEnd()
31153069

3116-
enqueue("BeanInfo ", beanInfoName, beanInfoClass, clasz.symbol)
3070+
writeIfNotTooBig("BeanInfo ", beanInfoName, beanInfoClass, clasz.symbol)
31173071
}
31183072

31193073
} // end of class JBeanInfoBuilder

src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
183183
class BytecodeGenerator(bytecodeWriter: BytecodeWriter) extends BytecodeUtil {
184184
def this() = this(new ClassBytecodeWriter { })
185185
def debugLevel = settings.debuginfo.indexOfChoice
186+
import bytecodeWriter.writeClass
186187

187188
val MIN_SWITCH_DENSITY = 0.7
188189
val INNER_CLASSES_FLAGS =
@@ -343,15 +344,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
343344
writeClass("" + sym.name, jclass.getName(), toByteArray(jclass), sym)
344345
}
345346

346-
val needsOutfileForSymbol = bytecodeWriter.isInstanceOf[ClassBytecodeWriter]
347-
348-
def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
349-
val outF: scala.tools.nsc.io.AbstractFile = {
350-
if(needsOutfileForSymbol) getFile(sym, jclassName, ".class") else null
351-
}
352-
bytecodeWriter.writeClass(label, jclassName, jclassBytes, outF)
353-
}
354-
355347
/** Returns the ScalaSignature annotation if it must be added to this class,
356348
* none otherwise; furthermore, it adds to `jclass` the ScalaSig marker
357349
* attribute (marking that a scala signature annotation is present) or the

0 commit comments

Comments
 (0)