Skip to content

Don't retain picklers until backend. #1725

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 22, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/dotty/tools/backend/jvm/GenBCode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
val plainC = pcb.cnode

if (claszSymbol.isClass) // @DarkDimius is this test needed here?
for (pickler <- ctx.compilationUnit.picklers.get(claszSymbol.asClass)) {
val binary = pickler.assembleParts()
for (binary <- ctx.compilationUnit.pickled.get(claszSymbol.asClass)) {
val dataAttr = new CustomAttr(nme.TASTYATTR.toString, binary)
(if (mirrorC ne null) mirrorC else plainC).visitAttribute(dataAttr)
}
Expand Down
8 changes: 2 additions & 6 deletions src/dotty/tools/dotc/CompilationUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,8 @@ class CompilationUnit(val source: SourceFile) {

def isJava = source.file.name.endsWith(".java")

/**
* Picklers used to create TASTY sections, indexed by toplevel class to which they belong.
* Sections: Header, ASTs and Positions are populated by `pickler` phase.
* Subsequent phases can add new sections.
*/
var picklers: Map[ClassSymbol, TastyPickler] = Map()
/** Pickled TASTY binaries, indexed by class. */
var pickled: Map[ClassSymbol, Array[Byte]] = Map()

var unpicklers: Map[ClassSymbol, TastyUnpickler] = Map()
}
20 changes: 14 additions & 6 deletions src/dotty/tools/dotc/transform/Pickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ class Pickler extends Phase {
s.close
}

// Maps that keep a record if -Ytest-pickler is set.
private val beforePickling = new mutable.HashMap[ClassSymbol, String]
private val picklers = new mutable.HashMap[ClassSymbol, TastyPickler]

/** Drop any elements of this list that are linked module classes of other elements in the list */
private def dropCompanionModuleClasses(clss: List[ClassSymbol])(implicit ctx: Context): List[ClassSymbol] = {
Expand All @@ -40,9 +42,11 @@ class Pickler extends Phase {

for { cls <- dropCompanionModuleClasses(topLevelClasses(unit.tpdTree))
tree <- sliceTopLevel(unit.tpdTree, cls) } {
if (ctx.settings.YtestPickler.value) beforePickling(cls) = tree.show
val pickler = new TastyPickler()
unit.picklers += (cls -> pickler)
if (ctx.settings.YtestPickler.value) {
beforePickling(cls) = tree.show
picklers(cls) = pickler
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this goes in the right direction, but in my heap dump I noticed that a massive amount of memory was taken by beforePickling so that may not be enough to get the tests to run smoothly. It may be helpful to do beforePickling(cls) = null and picklers(cls) = null in testUnpickler to free up these resources.

}
val treePkl = pickler.treePkl
treePkl.pickle(tree :: Nil)
treePkl.compactify()
Expand All @@ -51,8 +55,12 @@ class Pickler extends Phase {
if (tree.pos.exists)
new PositionPickler(pickler, treePkl.buf.addrsOfTree).picklePositions(tree :: Nil)

// other pickle sections go here.
val pickled = pickler.assembleParts()
unit.pickled += (cls -> pickled)

def rawBytes = // not needed right now, but useful to print raw format.
pickler.assembleParts().iterator.grouped(10).toList.zipWithIndex.map {
pickled.iterator.grouped(10).toList.zipWithIndex.map {
case (row, i) => s"${i}0: ${row.mkString(" ")}"
}
// println(i"rawBytes = \n$rawBytes%\n%") // DEBUG
Expand All @@ -66,18 +74,18 @@ class Pickler extends Phase {
override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = {
val result = super.runOn(units)
if (ctx.settings.YtestPickler.value)
testUnpickler(units)(
testUnpickler(
ctx.fresh
.setPeriod(Period(ctx.runId + 1, FirstPhaseId))
.addMode(Mode.ReadPositions))
result
}

private def testUnpickler(units: List[CompilationUnit])(implicit ctx: Context): Unit = {
private def testUnpickler(implicit ctx: Context): Unit = {
pickling.println(i"testing unpickler at run ${ctx.runId}")
ctx.initialize()
val unpicklers =
for (unit <- units; (cls, pickler) <- unit.picklers) yield {
for ((cls, pickler) <- picklers) yield {
val unpickler = new DottyUnpickler(pickler.assembleParts())
unpickler.enter(roots = Set())
cls -> unpickler
Expand Down