From 6fd03ba60065c2fdec8658a8745f05a593b330be Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 16 Nov 2017 17:42:49 +0100 Subject: [PATCH 1/3] Add missing pickler in TASTYCompiler --- compiler/src/dotty/tools/dotc/fromtasty/TASTYCompiler.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompiler.scala b/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompiler.scala index 80184d05317b..34fd6e7d2ec5 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompiler.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompiler.scala @@ -14,7 +14,10 @@ class TASTYCompiler extends Compiler { case List(_: Pickler) => false case _ => true }.tail - List(new ReadTastyTreesFromClasses) :: backendPhases + + List(new ReadTastyTreesFromClasses) :: + List(new Pickler) :: + backendPhases } override def newRun(implicit ctx: Context): Run = { From a9baef29b1878d9c4469869d3ac23f44a0c5c3ce Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sun, 19 Nov 2017 16:19:16 +0100 Subject: [PATCH 2/3] Keep loaded pickled tasty when compiling from tasty --- .../src/dotty/tools/dotc/core/Symbols.scala | 20 +++++++++++++++++-- .../dotc/core/tasty/TastyUnpickler.scala | 2 ++ .../fromtasty/ReadTastyTreesFromClasses.scala | 13 ++++++++---- .../tools/dotc/fromtasty/TASTYCompiler.scala | 5 +---- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 2e3661a52039..cbd36685a8ed 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -604,22 +604,38 @@ object Symbols { /** If this is either: * - a top-level class and `-Yretain-trees` is set - * - a top-level class loaded from TASTY and `-Xlink-optimise` is set + * - a top-level class loaded from TASTY and `-tasty` or `-Xlink` is set * then return the TypeDef tree (possibly wrapped inside PackageDefs) for this class, otherwise EmptyTree. * This will force the info of the class. */ def tree(implicit ctx: Context): tpd.Tree /* tpd.PackageDef | tpd.TypeDef | tpd.EmptyTree */ = { + load() + myTree + } + + /** If this is either: + * - a top-level class loaded from TASTY with `-tasty` + * then return the bytes of the tasty. + */ + def pickled(implicit ctx: Context): Array[Byte] = { + load() + myTasty + } + + private def load()(implicit ctx: Context): Unit = { denot.info // TODO: Consider storing this tree like we store lazy trees for inline functions if (unpickler != null && !denot.isAbsent) { assert(myTree.isEmpty) val body = unpickler.body(ctx.addMode(Mode.ReadPositions)) myTree = body.headOption.getOrElse(tpd.EmptyTree) + if (ctx.settings.tasty.value) + myTasty = unpickler.unpickler.bytes unpickler = null } - myTree } private[this] var myTree: tpd.Tree /* tpd.PackageDef | tpd.TypeDef | tpd.EmptyTree */ = tpd.EmptyTree + private[this] var myTasty: Array[Byte] = _ private[dotc] var unpickler: tasty.DottyUnpickler = _ private[dotc] def registerTree(tree: tpd.TypeDef)(implicit ctx: Context): Unit = { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala index c062e3fbae8e..394399d6bf60 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala @@ -99,4 +99,6 @@ class TastyUnpickler(reader: TastyReader) { def unpickle[R](sec: SectionUnpickler[R]): Option[R] = for (reader <- sectionReader.get(sec.name)) yield sec.unpickle(reader, nameAtRef) + + private[dotc] def bytes: Array[Byte] = reader.bytes } diff --git a/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala b/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala index 9ba0a19ca311..c072ec7f09d9 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala @@ -25,8 +25,12 @@ class ReadTastyTreesFromClasses extends FrontEnd { tree(className).flatMap { case (clsd, unpickled) => if (unpickled.isEmpty) None - else Some(CompilationUnit.mkCompilationUnit(clsd, unpickled, forceTrees = true)) - + else { + val unit = CompilationUnit.mkCompilationUnit(clsd, unpickled, forceTrees = true) + val cls = clsd.symbol.asClass + unit.pickled += (cls -> cls.pickled) + Some(unit) + } } } // The TASTY section in a/b/C.class may either contain a class a.b.C, an object a.b.C, or both. @@ -41,12 +45,13 @@ class ReadTastyTreesFromClasses extends FrontEnd { val clsd = ctx.base.staticRef(className) ctx.base.staticRef(className) match { case clsd: ClassDenotation => + val cls = clsd.symbol.asClass def cannotUnpickle(reason: String) = ctx.error(s"class $className cannot be unpickled because $reason") def tryToLoad = clsd.infoOrCompleter match { case info: ClassfileLoader => info.load(clsd) - Option(clsd.symbol.asClass.tree).orElse { + Option(cls.tree).orElse { cannotUnpickle(s"its class file ${info.classfile} does not have a TASTY attribute") None } @@ -55,7 +60,7 @@ class ReadTastyTreesFromClasses extends FrontEnd { cannotUnpickle(s"its info of type ${info.getClass} is not a ClassfileLoader") None } - Option(clsd.symbol.asClass.tree).orElse(tryToLoad).map(tree => (clsd, tree)) + Option(cls.tree).orElse(tryToLoad).map(tree => (clsd, tree)) case _ => ctx.error(s"class not found: $className") diff --git a/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompiler.scala b/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompiler.scala index 34fd6e7d2ec5..80184d05317b 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompiler.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/TASTYCompiler.scala @@ -14,10 +14,7 @@ class TASTYCompiler extends Compiler { case List(_: Pickler) => false case _ => true }.tail - - List(new ReadTastyTreesFromClasses) :: - List(new Pickler) :: - backendPhases + List(new ReadTastyTreesFromClasses) :: backendPhases } override def newRun(implicit ctx: Context): Run = { From 88200a8ff32bccb8c5ecb3c014ad6cdf35e7d1cc Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Sun, 19 Nov 2017 17:31:51 +0100 Subject: [PATCH 3/3] Use unpickler to get pickled tasty directly --- .../src/dotty/tools/dotc/core/Symbols.scala | 21 +++---------------- .../fromtasty/ReadTastyTreesFromClasses.scala | 3 ++- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index cbd36685a8ed..fb2b45268927 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -609,33 +609,18 @@ object Symbols { * This will force the info of the class. */ def tree(implicit ctx: Context): tpd.Tree /* tpd.PackageDef | tpd.TypeDef | tpd.EmptyTree */ = { - load() - myTree - } - - /** If this is either: - * - a top-level class loaded from TASTY with `-tasty` - * then return the bytes of the tasty. - */ - def pickled(implicit ctx: Context): Array[Byte] = { - load() - myTasty - } - - private def load()(implicit ctx: Context): Unit = { denot.info // TODO: Consider storing this tree like we store lazy trees for inline functions if (unpickler != null && !denot.isAbsent) { assert(myTree.isEmpty) val body = unpickler.body(ctx.addMode(Mode.ReadPositions)) myTree = body.headOption.getOrElse(tpd.EmptyTree) - if (ctx.settings.tasty.value) - myTasty = unpickler.unpickler.bytes - unpickler = null + if (!ctx.settings.tasty.value) + unpickler = null } + myTree } private[this] var myTree: tpd.Tree /* tpd.PackageDef | tpd.TypeDef | tpd.EmptyTree */ = tpd.EmptyTree - private[this] var myTasty: Array[Byte] = _ private[dotc] var unpickler: tasty.DottyUnpickler = _ private[dotc] def registerTree(tree: tpd.TypeDef)(implicit ctx: Context): Unit = { diff --git a/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala b/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala index c072ec7f09d9..b7345f49e1c0 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/ReadTastyTreesFromClasses.scala @@ -28,7 +28,8 @@ class ReadTastyTreesFromClasses extends FrontEnd { else { val unit = CompilationUnit.mkCompilationUnit(clsd, unpickled, forceTrees = true) val cls = clsd.symbol.asClass - unit.pickled += (cls -> cls.pickled) + unit.pickled += (cls -> cls.unpickler.unpickler.bytes) + cls.unpickler = null Some(unit) } }