Skip to content

Commit

Permalink
Read TASTy header eagerly to avoid var in CompilationUnitInfo
Browse files Browse the repository at this point in the history
Also avoid reading header twice to check the UUID.
  • Loading branch information
nicolasstucki committed Nov 21, 2023
1 parent 4acf82a commit 2bfc55c
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 35 deletions.
12 changes: 2 additions & 10 deletions compiler/src/dotty/tools/dotc/core/CompilationUnitInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,14 @@ import dotty.tools.tasty.TastyVersion
*/
class CompilationUnitInfo(
val associatedFile: AbstractFile,
private var tastyVersionOpt: Option[TastyVersion],
val tastyVersion: Option[TastyVersion],
) {

def tastyVersion: Option[TastyVersion] = tastyVersionOpt

/** Sets the TASTy version. Used to initialize the TASTy version when
* Loading a TASTy file in TastyLoader.
*/
def initTastyVersion(version: TastyVersion): Unit =
tastyVersionOpt = Some(version)

override def toString(): String =
s"CompilationUnitInfo($associatedFile, $tastyVersion)"
}

object CompilationUnitInfo:
def apply(assocFile: AbstractFile | Null): CompilationUnitInfo | Null =
if assocFile == null then null
else new CompilationUnitInfo(assocFile, tastyVersionOpt = None) // TODO use current TASTy version
else new CompilationUnitInfo(assocFile, tastyVersion = None) // TODO use current TASTy version
45 changes: 27 additions & 18 deletions compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ import ast.desugar

import parsing.JavaParsers.OutlineJavaParser
import parsing.Parsers.OutlineParser
import dotty.tools.tasty.{TastyHeaderUnpickler, UnpickleException, UnpicklerConfig}
import dotty.tools.tasty.{TastyHeaderUnpickler, UnpickleException, UnpicklerConfig, TastyVersion}
import dotty.tools.dotc.core.tasty.TastyUnpickler


object SymbolLoaders {
import ast.untpd.*

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

class TastyLoader(val tastyFile: AbstractFile) extends SymbolLoader {

private val compUnitInfo = new CompilationUnitInfo(
tastyFile,
tastyVersionOpt = None // set on doComplete
private val unpickler: tasty.DottyUnpickler =
handleUnpicklingExceptions:
val tastyBytes = tastyFile.toByteArray
new tasty.DottyUnpickler(tastyBytes) // reads header and name table

def compilationUnitInfo: CompilationUnitInfo | Null =
val tastyHeader = unpickler.unpickler.header
new CompilationUnitInfo(
tastyFile,
tastyVersion = Some(
TastyVersion(
tastyHeader.majorVersion,
tastyHeader.minorVersion,
tastyHeader.experimentalVersion,
)
)
)

def compilationUnitInfo: CompilationUnitInfo | Null = compUnitInfo

def description(using Context): String = "TASTy file " + tastyFile.toString

override def doComplete(root: SymDenotation)(using Context): Unit =
try
handleUnpicklingExceptions:
checkTastyUUID()
val (classRoot, moduleRoot) = rootDenots(root.asClass)
val tastyBytes = tastyFile.toByteArray
val unpickler = new tasty.DottyUnpickler(tastyBytes)
compUnitInfo.initTastyVersion(unpickler.tastyVersion)
unpickler.enter(roots = Set(classRoot, moduleRoot, moduleRoot.sourceModule))(using ctx.withSource(util.NoSource))
if mayLoadTreesFromTasty then
classRoot.classSymbol.rootTreeOrProvider = unpickler
moduleRoot.classSymbol.rootTreeOrProvider = unpickler
checkTastyUUID(tastyFile, tastyBytes)

private def handleUnpicklingExceptions[T](thunk: =>T): T =
try thunk
catch case e: RuntimeException =>
val message = e match
case e: UnpickleException =>
i"""TASTy file ${tastyFile.canonicalPath} could not be read, failing with:
s"""TASTy file ${tastyFile.canonicalPath} could not be read, failing with:
| ${Option(e.getMessage).getOrElse("")}"""
case _ =>
i"""TASTy file ${tastyFile.canonicalPath} is broken, reading aborted with ${e.getClass}
s"""TASTy file ${tastyFile.canonicalPath} is broken, reading aborted with ${e.getClass}
| ${Option(e.getMessage).getOrElse("")}"""
if (ctx.debug) e.printStackTrace()
throw IOException(message)
throw IOException(message, e)


private def checkTastyUUID(tastyFile: AbstractFile, tastyBytes: Array[Byte])(using Context): Unit =
private def checkTastyUUID()(using Context): Unit =
val classfile =
val className = tastyFile.name.stripSuffix(".tasty")
tastyFile.resolveSibling(className + ".class")
if classfile != null then
val tastyUUID = new TastyHeaderUnpickler(TastyUnpickler.scala3CompilerConfig, tastyBytes).readHeader()
val tastyUUID = unpickler.unpickler.header.uuid
new ClassfileTastyUUIDParser(classfile)(ctx).checkTastyUUID(tastyUUID)
else
// This will be the case in any of our tests that compile with `-Youtput-only-tasty`
Expand Down
7 changes: 0 additions & 7 deletions compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,6 @@ class DottyUnpickler(bytes: Array[Byte], mode: UnpickleMode = UnpickleMode.TopLe
private val attributeUnpicklerOpt = unpickler.unpickle(new AttributesSectionUnpickler)
private val treeUnpickler = unpickler.unpickle(treeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt, attributeUnpicklerOpt)).get

def tastyVersion: TastyVersion =
TastyVersion(
unpickler.header.majorVersion,
unpickler.header.minorVersion,
unpickler.header.experimentalVersion,
)

/** Enter all toplevel classes and objects into their scopes
* @param roots a set of SymDenotations that should be overwritten by unpickling
*/
Expand Down

0 comments on commit 2bfc55c

Please sign in to comment.