Skip to content

Commit 48d0999

Browse files
Merge pull request #12242 from dotty-staging/add-cache-to-quote-unpickling
Cache quote unpickling
2 parents aadc10f + 00115c6 commit 48d0999

File tree

4 files changed

+62
-17
lines changed

4 files changed

+62
-17
lines changed

compiler/src/dotty/tools/dotc/quoted/MacroExpansion.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ object MacroExpansion {
1414
ctx.property(MacroExpansionPosition)
1515

1616
def context(inlinedFrom: tpd.Tree)(using Context): Context =
17-
ctx.fresh.setProperty(MacroExpansionPosition, SourcePosition(inlinedFrom.source, inlinedFrom.span)).setTypeAssigner(new Typer).withSource(inlinedFrom.source)
17+
QuotesCache.init(ctx.fresh).setProperty(MacroExpansionPosition, SourcePosition(inlinedFrom.source, inlinedFrom.span)).setTypeAssigner(new Typer).withSource(inlinedFrom.source)
1818
}
1919

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

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -181,25 +181,38 @@ object PickledQuotes {
181181

182182
/** Unpickle TASTY bytes into it's tree */
183183
private def unpickle(pickled: String | List[String], isType: Boolean)(using Context): Tree = {
184-
val bytes = pickled match
185-
case pickled: String => TastyString.unpickle(pickled)
186-
case pickled: List[String] => TastyString.unpickle(pickled)
184+
QuotesCache.getTree(pickled) match
185+
case Some(tree) =>
186+
quotePickling.println(s"**** Using cached quote for TASTY\n$tree")
187+
treeOwner(tree) match
188+
case Some(owner) =>
189+
// Copy the cached tree to make sure the all definitions are unique.
190+
TreeTypeMap(oldOwners = List(owner), newOwners = List(owner)).apply(tree)
191+
case _ =>
192+
tree
187193

188-
quotePickling.println(s"**** unpickling quote from TASTY\n${TastyPrinter.show(bytes)}")
194+
case _ =>
195+
val bytes = pickled match
196+
case pickled: String => TastyString.unpickle(pickled)
197+
case pickled: List[String] => TastyString.unpickle(pickled)
198+
199+
quotePickling.println(s"**** unpickling quote from TASTY\n${TastyPrinter.show(bytes)}")
189200

190-
val mode = if (isType) UnpickleMode.TypeTree else UnpickleMode.Term
191-
val unpickler = new DottyUnpickler(bytes, mode)
192-
unpickler.enter(Set.empty)
201+
val mode = if (isType) UnpickleMode.TypeTree else UnpickleMode.Term
202+
val unpickler = new DottyUnpickler(bytes, mode)
203+
unpickler.enter(Set.empty)
193204

194-
val tree = unpickler.tree
205+
val tree = unpickler.tree
206+
QuotesCache(pickled) = tree
195207

196-
// Make sure trees and positions are fully loaded
197-
new TreeTraverser {
198-
def traverse(tree: Tree)(using Context): Unit = traverseChildren(tree)
199-
}.traverse(tree)
208+
// Make sure trees and positions are fully loaded
209+
new TreeTraverser {
210+
def traverse(tree: Tree)(using Context): Unit = traverseChildren(tree)
211+
}.traverse(tree)
200212

201-
quotePickling.println(i"**** unpickled quote\n$tree")
202-
tree
213+
quotePickling.println(i"**** unpickled quote\n$tree")
214+
215+
tree
203216
}
204217

205218
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package dotty.tools.dotc.quoted
2+
3+
import dotty.tools.dotc.core.Contexts._
4+
import dotty.tools.dotc.util.Property
5+
import dotty.tools.dotc.reporting.trace
6+
import dotty.tools.dotc.ast.tpd
7+
8+
import scala.collection.mutable
9+
10+
object QuotesCache {
11+
import tpd._
12+
13+
/** A key to be used in a context property that caches the unpickled trees */
14+
private val QuotesCacheKey = new Property.Key[collection.mutable.Map[String | List[String], Tree]]
15+
16+
17+
/** Get the cached tree of the quote */
18+
def getTree(pickled: String | List[String])(using Context): Option[Tree] =
19+
ctx.property(QuotesCacheKey).get.get(pickled)
20+
21+
/** Update the cached tree of the quote */
22+
def update(pickled: String | List[String], tree: Tree)(using Context): Unit =
23+
ctx.property(QuotesCacheKey).get.update(pickled, tree)
24+
25+
/** Context with a cache for quote trees and tasty bytes */
26+
def init(ctx: FreshContext): ctx.type =
27+
ctx.setProperty(QuotesCacheKey, collection.mutable.Map.empty)
28+
}

staging/src/scala/quoted/staging/QuoteDriver.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package staging
44
import dotty.tools.dotc.ast.tpd
55
import dotty.tools.dotc.Driver
66
import dotty.tools.dotc.core.Contexts.{Context, ContextBase, FreshContext}
7+
import dotty.tools.dotc.quoted.QuotesCache
78
import dotty.tools.io.{AbstractFile, Directory, PlainDirectory, VirtualDirectory}
89
import dotty.tools.repl.AbstractFileClassLoader
910
import dotty.tools.dotc.reporting._
@@ -33,8 +34,11 @@ private class QuoteDriver(appClassloader: ClassLoader) extends Driver:
3334
new VirtualDirectory("<quote compilation output>")
3435
end outDir
3536

36-
val ctx0 = setup(settings.compilerArgs.toArray :+ "dummy.scala", initCtx.fresh).get._2
37-
val ctx = setCompilerSettings(ctx0.fresh.setSetting(ctx0.settings.outputDir, outDir), settings)
37+
val ctx = {
38+
val ctx0 = QuotesCache.init(initCtx.fresh)
39+
val ctx1 = setup(settings.compilerArgs.toArray :+ "dummy.scala", ctx0).get._2
40+
setCompilerSettings(ctx1.fresh.setSetting(ctx1.settings.outputDir, outDir), settings)
41+
}
3842

3943
new QuoteCompiler().newRun(ctx).compileExpr(exprBuilder) match
4044
case Right(value) =>

0 commit comments

Comments
 (0)