Skip to content

Commit 31f095d

Browse files
committed
Do not store tasty bytes when not placed the classfile
To allow the bytes to be GCed after pickler
1 parent eb54aef commit 31f095d

File tree

5 files changed

+44
-28
lines changed

5 files changed

+44
-28
lines changed

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

+23-18
Original file line numberDiff line numberDiff line change
@@ -213,31 +213,36 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
213213
val outF = if (needsOutFolder) getOutFolder(claszSymbol, pcb.thisName) else null;
214214
val plainC = pcb.cnode
215215

216-
if (claszSymbol.isClass) // @DarkDimius is this test needed here?
217-
for (binary <- ctx.compilationUnit.pickled.get(claszSymbol.asClass)) {
216+
if (claszSymbol.isClass) { // @DarkDimius is this test needed here?
217+
def storeTastyTagBytes(getBytes: String => Array[Byte]): Unit = {
218218
val store = if (mirrorC ne null) mirrorC else plainC
219-
val tasty =
220-
if (!ctx.settings.YemitTastyInClass.value) {
221-
val uuid = new TastyHeaderUnpickler(binary).readHeader()
222-
val lo = uuid.getMostSignificantBits
223-
val hi = uuid.getLeastSignificantBits
224-
219+
val bytes = getBytes(store.name)
220+
val dataAttr = new CustomAttr(nme.TASTYATTR.mangledString, bytes)
221+
store.visitAttribute(dataAttr)
222+
}
223+
if (ctx.settings.YemitTastyInClass.value) {
224+
for (binary <- ctx.compilationUnit.pickled.get(claszSymbol.asClass)) {
225+
storeTastyTagBytes { name =>
226+
// Create an empty file to signal that a tasty section exist in the corresponding .class
227+
// This is much cheaper and simpler to check than doing classfile parsing
228+
getFileForClassfile(outF, name, ".hasTasty")
229+
binary
230+
}
231+
}
232+
} else {
233+
for (uuid <- ctx.compilationUnit.tastyUUID.get(claszSymbol.asClass)) {
234+
assert(!ctx.settings.YemitTastyInClass.value)
235+
storeTastyTagBytes { name =>
225236
// TASTY attribute is created but only the UUID bytes are stored in it.
226237
// A TASTY attribute has length 16 if and only if the .tasty file exists.
227238
val buffer = new TastyBuffer(16)
228-
buffer.writeUncompressedLong(lo)
229-
buffer.writeUncompressedLong(hi)
239+
buffer.writeUncompressedLong(uuid.getLeastSignificantBits)
240+
buffer.writeUncompressedLong(uuid.getMostSignificantBits)
230241
buffer.bytes
231-
} else {
232-
// Create an empty file to signal that a tasty section exist in the corresponding .class
233-
// This is much cheaper and simpler to check than doing classfile parsing
234-
getFileForClassfile(outF, store.name, ".hasTasty")
235-
binary
236242
}
237-
val dataAttr = new CustomAttr(nme.TASTYATTR.mangledString, tasty)
238-
store.visitAttribute(dataAttr)
243+
}
239244
}
240-
245+
}
241246

242247
// ----------- create files
243248

compiler/src/dotty/tools/dotc/CompilationUnit.scala

+7-2
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ package dotc
44
import core.Types.Type // Do not remove me #3383
55
import util.SourceFile
66
import ast.{tpd, untpd}
7-
import tpd.{ Tree, TreeTraverser }
7+
import tpd.{Tree, TreeTraverser}
88
import typer.PrepareTransparent.InlineAccessors
99
import dotty.tools.dotc.core.Contexts.Context
1010
import dotty.tools.dotc.core.SymDenotations.ClassDenotation
1111
import dotty.tools.dotc.core.Symbols._
1212
import dotty.tools.dotc.transform.SymUtils._
1313

14+
import java.util.UUID
15+
1416
class CompilationUnit(val source: SourceFile) {
1517

1618
override def toString = source.toString
@@ -19,11 +21,14 @@ class CompilationUnit(val source: SourceFile) {
1921

2022
var tpdTree: tpd.Tree = tpd.EmptyTree
2123

22-
def isJava = source.file.name.endsWith(".java")
24+
def isJava: Boolean = source.file.name.endsWith(".java")
2325

2426
/** Pickled TASTY binaries, indexed by class. */
2527
var pickled: Map[ClassSymbol, Array[Byte]] = Map()
2628

29+
/** UUID of the pickled TASTY, indexed by class. */
30+
var tastyUUID: Map[ClassSymbol, UUID] = Map()
31+
2732
/** Will be reset to `true` if `untpdTree` contains `Quote` trees. The information
2833
* is used in phase ReifyQuotes in order to avoid traversing a quote-less tree.
2934
*/

compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ object PickledQuotes {
9292
if (pickling ne noPrinter)
9393
println(i"**** pickling quote of \n${tree.show}")
9494

95-
val pickled = pickler.assembleParts()
95+
val pickled = pickler.assembleParts()._2
9696

9797
if (pickling ne noPrinter)
9898
new TastyPrinter(pickled).printContents()

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

+6-3
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ package tasty
66
import TastyFormat._
77
import collection.mutable
88
import TastyBuffer._
9-
import core.Symbols.{Symbol, ClassSymbol}
9+
import core.Symbols.{ClassSymbol, Symbol}
1010
import ast.tpd
1111
import Decorators._
1212

13+
import java.util.UUID
14+
1315
class TastyPickler(val rootCls: ClassSymbol) {
1416

1517
private val sections = new mutable.ArrayBuffer[(NameRef, TastyBuffer)]
@@ -19,7 +21,8 @@ class TastyPickler(val rootCls: ClassSymbol) {
1921
def newSection(name: String, buf: TastyBuffer) =
2022
sections += ((nameBuffer.nameIndex(name.toTermName), buf))
2123

22-
def assembleParts(): Array[Byte] = {
24+
/** Returns the UUID and bytes of the tasty file */
25+
def assembleParts(): (UUID, Array[Byte]) = {
2326
def lengthWithLength(buf: TastyBuffer) =
2427
buf.length + natSize(buf.length)
2528

@@ -60,7 +63,7 @@ class TastyPickler(val rootCls: ClassSymbol) {
6063
all.writeBytes(buf.bytes, buf.length)
6164
}
6265
assert(all.length == totalSize && all.bytes.length == totalSize, s"totalSize = $totalSize, all.length = ${all.length}, all.bytes.length = ${all.bytes.length}")
63-
all.bytes
66+
(new UUID(uuidHi, uuidLow), all.bytes)
6467
}
6568

6669
/** The address in the TASTY file of a given tree, or None if unknown.

compiler/src/dotty/tools/dotc/transform/Pickler.scala

+7-4
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,12 @@ class Pickler extends Phase {
6565
new CommentPickler(pickler, treePkl.buf.addrOfTree).pickleComment(tree)
6666

6767
// other pickle sections go here.
68-
val pickled = pickler.assembleParts()
69-
unit.pickled += (cls -> pickled)
68+
val (uuid, pickled) = pickler.assembleParts()
7069

71-
if (!ctx.settings.YemitTastyInClass.value) {
70+
if (ctx.settings.YemitTastyInClass.value) {
71+
unit.pickled += (cls -> pickled)
72+
} else {
73+
unit.tastyUUID += (cls -> uuid)
7274
val parts = cls.fullName.stripModuleClassSuffix.mangledString.split('.')
7375
val name = parts.last
7476
val tastyDirectory = parts.init.foldLeft(ctx.settings.outputDir.value)((dir, part) => dir.subdirectoryNamed(part))
@@ -108,7 +110,8 @@ class Pickler extends Phase {
108110
ctx.initialize()
109111
val unpicklers =
110112
for ((cls, pickler) <- picklers) yield {
111-
val unpickler = new DottyUnpickler(pickler.assembleParts())
113+
val bytes = pickler.assembleParts()._2
114+
val unpickler = new DottyUnpickler(bytes)
112115
unpickler.enter(roots = Set.empty)
113116
cls -> unpickler
114117
}

0 commit comments

Comments
 (0)