Skip to content

Commit 2bfc55c

Browse files
committed
Read TASTy header eagerly to avoid var in CompilationUnitInfo
Also avoid reading header twice to check the UUID.
1 parent 4acf82a commit 2bfc55c

File tree

3 files changed

+29
-35
lines changed

3 files changed

+29
-35
lines changed

compiler/src/dotty/tools/dotc/core/CompilationUnitInfo.scala

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,14 @@ import dotty.tools.tasty.TastyVersion
1212
*/
1313
class CompilationUnitInfo(
1414
val associatedFile: AbstractFile,
15-
private var tastyVersionOpt: Option[TastyVersion],
15+
val tastyVersion: Option[TastyVersion],
1616
) {
1717

18-
def tastyVersion: Option[TastyVersion] = tastyVersionOpt
19-
20-
/** Sets the TASTy version. Used to initialize the TASTy version when
21-
* Loading a TASTy file in TastyLoader.
22-
*/
23-
def initTastyVersion(version: TastyVersion): Unit =
24-
tastyVersionOpt = Some(version)
25-
2618
override def toString(): String =
2719
s"CompilationUnitInfo($associatedFile, $tastyVersion)"
2820
}
2921

3022
object CompilationUnitInfo:
3123
def apply(assocFile: AbstractFile | Null): CompilationUnitInfo | Null =
3224
if assocFile == null then null
33-
else new CompilationUnitInfo(assocFile, tastyVersionOpt = None) // TODO use current TASTy version
25+
else new CompilationUnitInfo(assocFile, tastyVersion = None) // TODO use current TASTy version

compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@ import ast.desugar
2424

2525
import parsing.JavaParsers.OutlineJavaParser
2626
import parsing.Parsers.OutlineParser
27-
import dotty.tools.tasty.{TastyHeaderUnpickler, UnpickleException, UnpicklerConfig}
27+
import dotty.tools.tasty.{TastyHeaderUnpickler, UnpickleException, UnpicklerConfig, TastyVersion}
2828
import dotty.tools.dotc.core.tasty.TastyUnpickler
2929

30-
3130
object SymbolLoaders {
3231
import ast.untpd.*
3332

@@ -418,44 +417,54 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
418417

419418
class TastyLoader(val tastyFile: AbstractFile) extends SymbolLoader {
420419

421-
private val compUnitInfo = new CompilationUnitInfo(
422-
tastyFile,
423-
tastyVersionOpt = None // set on doComplete
420+
private val unpickler: tasty.DottyUnpickler =
421+
handleUnpicklingExceptions:
422+
val tastyBytes = tastyFile.toByteArray
423+
new tasty.DottyUnpickler(tastyBytes) // reads header and name table
424+
425+
def compilationUnitInfo: CompilationUnitInfo | Null =
426+
val tastyHeader = unpickler.unpickler.header
427+
new CompilationUnitInfo(
428+
tastyFile,
429+
tastyVersion = Some(
430+
TastyVersion(
431+
tastyHeader.majorVersion,
432+
tastyHeader.minorVersion,
433+
tastyHeader.experimentalVersion,
434+
)
435+
)
424436
)
425437

426-
def compilationUnitInfo: CompilationUnitInfo | Null = compUnitInfo
427-
428438
def description(using Context): String = "TASTy file " + tastyFile.toString
429439

430440
override def doComplete(root: SymDenotation)(using Context): Unit =
431-
try
441+
handleUnpicklingExceptions:
442+
checkTastyUUID()
432443
val (classRoot, moduleRoot) = rootDenots(root.asClass)
433-
val tastyBytes = tastyFile.toByteArray
434-
val unpickler = new tasty.DottyUnpickler(tastyBytes)
435-
compUnitInfo.initTastyVersion(unpickler.tastyVersion)
436444
unpickler.enter(roots = Set(classRoot, moduleRoot, moduleRoot.sourceModule))(using ctx.withSource(util.NoSource))
437445
if mayLoadTreesFromTasty then
438446
classRoot.classSymbol.rootTreeOrProvider = unpickler
439447
moduleRoot.classSymbol.rootTreeOrProvider = unpickler
440-
checkTastyUUID(tastyFile, tastyBytes)
448+
449+
private def handleUnpicklingExceptions[T](thunk: =>T): T =
450+
try thunk
441451
catch case e: RuntimeException =>
442452
val message = e match
443453
case e: UnpickleException =>
444-
i"""TASTy file ${tastyFile.canonicalPath} could not be read, failing with:
454+
s"""TASTy file ${tastyFile.canonicalPath} could not be read, failing with:
445455
| ${Option(e.getMessage).getOrElse("")}"""
446456
case _ =>
447-
i"""TASTy file ${tastyFile.canonicalPath} is broken, reading aborted with ${e.getClass}
457+
s"""TASTy file ${tastyFile.canonicalPath} is broken, reading aborted with ${e.getClass}
448458
| ${Option(e.getMessage).getOrElse("")}"""
449-
if (ctx.debug) e.printStackTrace()
450-
throw IOException(message)
459+
throw IOException(message, e)
451460

452461

453-
private def checkTastyUUID(tastyFile: AbstractFile, tastyBytes: Array[Byte])(using Context): Unit =
462+
private def checkTastyUUID()(using Context): Unit =
454463
val classfile =
455464
val className = tastyFile.name.stripSuffix(".tasty")
456465
tastyFile.resolveSibling(className + ".class")
457466
if classfile != null then
458-
val tastyUUID = new TastyHeaderUnpickler(TastyUnpickler.scala3CompilerConfig, tastyBytes).readHeader()
467+
val tastyUUID = unpickler.unpickler.header.uuid
459468
new ClassfileTastyUUIDParser(classfile)(ctx).checkTastyUUID(tastyUUID)
460469
else
461470
// This will be the case in any of our tests that compile with `-Youtput-only-tasty`

compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,6 @@ class DottyUnpickler(bytes: Array[Byte], mode: UnpickleMode = UnpickleMode.TopLe
5656
private val attributeUnpicklerOpt = unpickler.unpickle(new AttributesSectionUnpickler)
5757
private val treeUnpickler = unpickler.unpickle(treeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt, attributeUnpicklerOpt)).get
5858

59-
def tastyVersion: TastyVersion =
60-
TastyVersion(
61-
unpickler.header.majorVersion,
62-
unpickler.header.minorVersion,
63-
unpickler.header.experimentalVersion,
64-
)
65-
6659
/** Enter all toplevel classes and objects into their scopes
6760
* @param roots a set of SymDenotations that should be overwritten by unpickling
6861
*/

0 commit comments

Comments
 (0)