@@ -29,6 +29,10 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
29
29
30
30
val phaseName = " jvm"
31
31
32
+ case class WorkUnit (label : String , jclassName : String , jclass : asm.ClassWriter , outF : AbstractFile )
33
+
34
+ type WorkUnitQueue = _root_.java.util.concurrent.LinkedBlockingQueue [WorkUnit ]
35
+
32
36
/** Create a new phase */
33
37
override def newPhase (p : Phase ): Phase = new AsmPhase (p)
34
38
@@ -148,6 +152,44 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
148
152
}
149
153
}
150
154
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
+
151
193
override def run () {
152
194
153
195
if (settings.debug.value)
@@ -161,10 +203,14 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
161
203
var sortedClasses = classes.values.toList sortBy (" " + _.symbol.fullName)
162
204
163
205
debuglog(" Created new bytecode generator for " + classes.size + " classes." )
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)
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()
168
214
169
215
while (! sortedClasses.isEmpty) {
170
216
val c = sortedClasses.head
@@ -187,6 +233,10 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
187
233
classes -= c.symbol // GC opportunity
188
234
}
189
235
236
+ q put WorkUnit (null , null , null , null )
237
+
238
+ while (! q.isEmpty) { _root_.java.lang.Thread .sleep(10 ) }
239
+
190
240
bytecodeWriter.close()
191
241
classes.clear()
192
242
reverseJavaName.clear()
@@ -448,7 +498,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
448
498
val JAVA_LANG_STRING = asm.Type .getObjectType(" java/lang/String" )
449
499
450
500
/** basic functionality for class file building */
451
- abstract class JBuilder (bytecodeWriter : BytecodeWriter ) {
501
+ abstract class JBuilder (wuQ : WorkUnitQueue , needsOutfileForSymbol : Boolean ) {
452
502
453
503
val EMPTY_JTYPE_ARRAY = Array .empty[asm.Type ]
454
504
val EMPTY_STRING_ARRAY = Array .empty[String ]
@@ -504,17 +554,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
504
554
// utitilies useful when emitting plain, mirror, and beaninfo classes.
505
555
// -----------------------------------------------------------------------------------------
506
556
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
-
518
557
/** Specialized array conversion to prevent calling
519
558
* java.lang.reflect.Array.newInstance via TraversableOnce.toArray
520
559
*/
@@ -728,11 +767,18 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
728
767
}
729
768
}
730
769
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
+
731
777
} // end of class JBuilder
732
778
733
779
734
780
/** functionality for building plain and mirror classes */
735
- abstract class JCommonBuilder (bytecodeWriter : BytecodeWriter ) extends JBuilder (bytecodeWriter ) {
781
+ abstract class JCommonBuilder (wuQ : WorkUnitQueue , needsOutfileForSymbol : Boolean ) extends JBuilder (wuQ, needsOutfileForSymbol ) {
736
782
737
783
// -----------------------------------------------------------------------------------------
738
784
// more constants
@@ -1290,8 +1336,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
1290
1336
case class BlockInteval (start : BasicBlock , end : BasicBlock )
1291
1337
1292
1338
/** builder of plain classes */
1293
- class JPlainBuilder (bytecodeWriter : BytecodeWriter )
1294
- extends JCommonBuilder (bytecodeWriter )
1339
+ class JPlainBuilder (wuQ : WorkUnitQueue , needsOutfileForSymbol : Boolean )
1340
+ extends JCommonBuilder (wuQ, needsOutfileForSymbol )
1295
1341
with JAndroidBuilder {
1296
1342
1297
1343
val MIN_SWITCH_DENSITY = 0.7
@@ -1445,7 +1491,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
1445
1491
1446
1492
addInnerClasses(clasz.symbol, jclass)
1447
1493
jclass.visitEnd()
1448
- writeIfNotTooBig (" " + c.symbol.name, thisName, jclass, c.symbol)
1494
+ enqueue (" " + c.symbol.name, thisName, jclass, c.symbol)
1449
1495
1450
1496
}
1451
1497
@@ -2863,7 +2909,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
2863
2909
2864
2910
2865
2911
/** builder of mirror classes */
2866
- class JMirrorBuilder (bytecodeWriter : BytecodeWriter ) extends JCommonBuilder (bytecodeWriter ) {
2912
+ class JMirrorBuilder (wuQ : WorkUnitQueue , needsOutfileForSymbol : Boolean ) extends JCommonBuilder (wuQ, needsOutfileForSymbol ) {
2867
2913
2868
2914
private var cunit : CompilationUnit = _
2869
2915
def getCurrentCUnit (): CompilationUnit = cunit;
@@ -2907,15 +2953,15 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
2907
2953
2908
2954
addInnerClasses(modsym, mirrorClass)
2909
2955
mirrorClass.visitEnd()
2910
- writeIfNotTooBig (" " + modsym.name, mirrorName, mirrorClass, modsym)
2956
+ enqueue (" " + modsym.name, mirrorName, mirrorClass, modsym)
2911
2957
}
2912
2958
2913
2959
2914
2960
} // end of class JMirrorBuilder
2915
2961
2916
2962
2917
2963
/** builder of bean info classes */
2918
- class JBeanInfoBuilder (bytecodeWriter : BytecodeWriter ) extends JBuilder (bytecodeWriter ) {
2964
+ class JBeanInfoBuilder (wuQ : WorkUnitQueue , needsOutfileForSymbol : Boolean ) extends JBuilder (wuQ, needsOutfileForSymbol ) {
2919
2965
2920
2966
/**
2921
2967
* Generate a bean info class that describes the given class.
@@ -3036,7 +3082,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
3036
3082
addInnerClasses(clasz.symbol, beanInfoClass)
3037
3083
beanInfoClass.visitEnd()
3038
3084
3039
- writeIfNotTooBig (" BeanInfo " , beanInfoName, beanInfoClass, clasz.symbol)
3085
+ enqueue (" BeanInfo " , beanInfoName, beanInfoClass, clasz.symbol)
3040
3086
}
3041
3087
3042
3088
} // end of class JBeanInfoBuilder
0 commit comments