Skip to content

Commit 2e46f3d

Browse files
committed
Port Scala#6057 - Pipeline code gen and post-processing
1 parent b4deeff commit 2e46f3d

File tree

3 files changed

+45
-38
lines changed

3 files changed

+45
-38
lines changed

compiler/src/dotty/tools/backend/jvm/CodeGen.scala

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ class CodeGen(val int: DottyBackendInterface, val primitives: DottyPrimitives)(
4040

4141
private lazy val mirrorCodeGen = Impl.JMirrorBuilder()
4242

43-
def gen(unit: CompilationUnit): Unit = {
43+
def genUnit(unit: CompilationUnit): GeneratedDefs = {
44+
val generatedClasses = mutable.ListBuffer.empty[GeneratedClass]
45+
val generatedTasty = mutable.ListBuffer.empty[GeneratedTasty]
46+
4447
val postProcessor = Phases.genBCodePhase match {
4548
case genBCode: GenBCode => genBCode.postProcessor
4649
case _ => null
@@ -52,7 +55,7 @@ class CodeGen(val int: DottyBackendInterface, val primitives: DottyPrimitives)(
5255
val sourceFile = unit.source.file
5356

5457
def registerGeneratedClass(classNode: ClassNode, isArtifact: Boolean) = if (classNode != null){
55-
postProcessor.generatedClasses += GeneratedClass(classNode, sourceFile, isArtifact, onFileCreated(classNode, sym, unit.source))
58+
generatedClasses += GeneratedClass(classNode, sourceFile, isArtifact, onFileCreated(classNode, sym, unit.source))
5659
}
5760

5861
val plainC = genClass(cd, unit)
@@ -68,12 +71,33 @@ class CodeGen(val int: DottyBackendInterface, val primitives: DottyPrimitives)(
6871

6972
if sym.isClass then
7073
val attrNode = if (mirrorC ne null) mirrorC else plainC
71-
setTastyAttributes(sym, attrNode, postProcessor, unit)
74+
genTastyAndSetAttributes(sym, attrNode)
7275
catch
7376
case ex: Throwable =>
7477
ex.printStackTrace()
7578
report.error(s"Error while emitting ${unit.source}\n${ex.getMessage}", NoSourcePosition)
7679

80+
81+
def genTastyAndSetAttributes(claszSymbol: Symbol, store: ClassNode): Unit =
82+
import Impl.createJAttribute
83+
for (binary <- unit.pickled.get(claszSymbol.asClass)) {
84+
generatedTasty += GeneratedTasty(store, binary)
85+
val tasty =
86+
val uuid = new TastyHeaderUnpickler(binary()).readHeader()
87+
val lo = uuid.getMostSignificantBits
88+
val hi = uuid.getLeastSignificantBits
89+
90+
// TASTY attribute is created but only the UUID bytes are stored in it.
91+
// A TASTY attribute has length 16 if and only if the .tasty file exists.
92+
val buffer = new TastyBuffer(16)
93+
buffer.writeUncompressedLong(lo)
94+
buffer.writeUncompressedLong(hi)
95+
buffer.bytes
96+
97+
val dataAttr = createJAttribute(nme.TASTYATTR.mangledString, tasty, 0, tasty.length)
98+
store.visitAttribute(dataAttr)
99+
}
100+
77101
def genClassDefs(tree: Tree): Unit =
78102
tree match {
79103
case EmptyTree => ()
@@ -83,8 +107,10 @@ class CodeGen(val int: DottyBackendInterface, val primitives: DottyPrimitives)(
83107
}
84108

85109
genClassDefs(unit.tpdTree)
110+
GeneratedDefs(generatedClasses.toList, generatedTasty.toList)
86111
}
87112

113+
// Creates a callback that would be evaluated in PostProcessor after creating a file
88114
private def onFileCreated(cls: ClassNode, claszSymbol: Symbol, sourceFile: interfaces.SourceFile): AbstractFile => Unit = clsFile => {
89115
val (fullClassName, isLocal) = atPhase(sbtExtractDependenciesPhase) {
90116
(ExtractDependencies.classNameAsString(claszSymbol), claszSymbol.isLocal)
@@ -112,25 +138,6 @@ class CodeGen(val int: DottyBackendInterface, val primitives: DottyPrimitives)(
112138
override def jfile = Optional.ofNullable(absfile.file)
113139
}
114140

115-
private def setTastyAttributes(claszSymbol: Symbol, store: ClassNode, postProcessor: PostProcessor, unit: CompilationUnit): Unit =
116-
import Impl.createJAttribute
117-
for (binary <- unit.pickled.get(claszSymbol.asClass)) {
118-
postProcessor.generatedTasty += GeneratedTasty(store, binary)
119-
val tasty =
120-
val uuid = new TastyHeaderUnpickler(binary()).readHeader()
121-
val lo = uuid.getMostSignificantBits
122-
val hi = uuid.getLeastSignificantBits
123-
124-
// TASTY attribute is created but only the UUID bytes are stored in it.
125-
// A TASTY attribute has length 16 if and only if the .tasty file exists.
126-
val buffer = new TastyBuffer(16)
127-
buffer.writeUncompressedLong(lo)
128-
buffer.writeUncompressedLong(hi)
129-
buffer.bytes
130-
131-
val dataAttr = createJAttribute(nme.TASTYATTR.mangledString, tasty, 0, tasty.length)
132-
store.visitAttribute(dataAttr)
133-
}
134141

135142
private def genClass(cd: TypeDef, unit: CompilationUnit): ClassNode = {
136143
val b = new Impl.SyncAndTryBuilder(unit) {}
@@ -175,4 +182,4 @@ class CodeGen(val int: DottyBackendInterface, val primitives: DottyPrimitives)(
175182
protected val primitives: DottyPrimitives = self.primitives
176183
}
177184
object Impl extends ImplEarlyInit with BCodeSyncAndTry
178-
}
185+
}

compiler/src/dotty/tools/backend/jvm/GenBCode.scala

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,16 @@ class GenBCode extends Phase { self =>
6464

6565
override def run(using Context): Unit =
6666
backendInterface.ctx = summon[Context]
67-
codeGen.gen(ctx.compilationUnit)
67+
val generated = codeGen.genUnit(ctx.compilationUnit)
68+
// In Scala 2 backend depening on either global optimizations are enabled
69+
// post processing might be delayed to build the call graph, or run imiedietlly if opts are disabled
70+
// In Scala 3 we don't perform backend optimizations and though always post process without the delay
71+
// https://github.com/scala/scala/pull/6057
72+
postProcessor.postProcessAndSendToDisk(generated)
6873

6974
override def runOn(units: List[CompilationUnit])(using ctx:Context): List[CompilationUnit] = {
70-
try
71-
val result = super.runOn(units)
72-
postProcessor.postProcessAndSendToDisk()
73-
result
74-
finally
75+
try super.runOn(units)
76+
finally
7577
frontendAccess.compilerSettings.outputDirectory match {
7678
case jar: JarArchive =>
7779
if (ctx.run.nn.suspendedUnits.nonEmpty)
@@ -81,7 +83,8 @@ class GenBCode extends Phase { self =>
8183

8284
jar.close()
8385
case _ =>
84-
}
86+
}
87+
postProcessor.classfileWriter.close()
8588
}
8689
}
8790

compiler/src/dotty/tools/backend/jvm/PostProcessor.scala

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@ class PostProcessor(val frontendAccess: PostProcessorFrontendAccess, val bTypes:
1919

2020
val backendUtils = new BackendUtils(this)
2121
lazy val classfileWriter = ClassfileWriter(frontendAccess)
22-
lazy val generatedClasses = ListBuffer.empty[GeneratedClass]
23-
lazy val generatedTasty = ListBuffer.empty[GeneratedTasty]
2422

25-
def postProcessAndSendToDisk(): Unit = {
26-
for (GeneratedClass(classNode, sourceFile, isArtifact, onFileCreated) <- generatedClasses) {
23+
def postProcessAndSendToDisk(generatedDefs: GeneratedDefs): Unit = {
24+
val GeneratedDefs(classes, tasty) = generatedDefs
25+
for (GeneratedClass(classNode, sourceFile, isArtifact, onFileCreated) <- classes) {
2726
val bytes =
2827
try
2928
if !isArtifact then setSerializableLambdas(classNode)
@@ -50,11 +49,9 @@ class PostProcessor(val frontendAccess: PostProcessorFrontendAccess, val bTypes:
5049
}
5150
}
5251

53-
for (GeneratedTasty(classNode, binaryGen) <- generatedTasty){
52+
for (GeneratedTasty(classNode, binaryGen) <- tasty){
5453
classfileWriter.writeTasty(classNode.name.nn, binaryGen())
5554
}
56-
57-
classfileWriter.close()
5855
}
5956

6057
private def setSerializableLambdas(classNode: ClassNode): Unit = {
@@ -113,7 +110,7 @@ class PostProcessor(val frontendAccess: PostProcessorFrontendAccess, val bTypes:
113110
*/
114111
case class GeneratedClass(classNode: ClassNode, sourceFile: AbstractFile, isArtifact: Boolean, onFileCreated: AbstractFile => Unit)
115112
case class GeneratedTasty(classNode: ClassNode, tastyGen: () => Array[Byte])
116-
113+
case class GeneratedDefs(classes: List[GeneratedClass], tasty: List[GeneratedTasty])
117114

118115
// Temporary class, will be refactored in a future commit
119116
trait ClassWriterForPostProcessor {

0 commit comments

Comments
 (0)