Skip to content

Commit a2477ea

Browse files
committed
Optimize encoding of TastyString
Most pickled quotes fit in a single string. We avoid the creation of the list for single string by typing as `String | List[String]`.
1 parent 0e621d2 commit a2477ea

File tree

5 files changed

+20
-9
lines changed

5 files changed

+20
-9
lines changed

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ object PickledQuotes {
5151
}
5252

5353
/** Unpickle the tree contained in the TastyExpr */
54-
def unpickleTerm(pickled: List[String], fillHole: Int => Seq[Any] => Any)(using Context): Tree = {
54+
def unpickleTerm(pickled: String | List[String], fillHole: Int => Seq[Any] => Any)(using Context): Tree = {
5555
val unpickled = withMode(Mode.ReadPositions)(unpickle(pickled, isType = false))
5656
val Inlined(call, Nil, expnasion) = unpickled
5757
val inlineCtx = inlineContext(call)
@@ -61,7 +61,7 @@ object PickledQuotes {
6161
}
6262

6363
/** Unpickle the tree contained in the TastyType */
64-
def unpickleTypeTree(pickled: List[String], fillHole: Int => Seq[Any] => Any)(using Context): Tree = {
64+
def unpickleTypeTree(pickled: String | List[String], fillHole: Int => Seq[Any] => Any)(using Context): Tree = {
6565
val unpickled = withMode(Mode.ReadPositions)(unpickle(pickled, isType = true))
6666
spliceTypes(unpickled, fillHole)
6767
}
@@ -175,8 +175,11 @@ object PickledQuotes {
175175
}
176176

177177
/** Unpickle TASTY bytes into it's tree */
178-
private def unpickle(pickled: List[String], isType: Boolean)(using Context): Tree = {
179-
val bytes = TastyString.unpickle(pickled)
178+
private def unpickle(pickled: String | List[String], isType: Boolean)(using Context): Tree = {
179+
val bytes = pickled match
180+
case pickled: String => TastyString.unpickle(pickled)
181+
case pickled: List[String] => TastyString.unpickle(pickled)
182+
180183
quotePickling.println(s"**** unpickling quote from TASTY\n${TastyPrinter.show(bytes)}")
181184

182185
val mode = if (isType) UnpickleMode.TypeTree else UnpickleMode.Term

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2630,11 +2630,11 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, scala.intern
26302630

26312631
end reflect
26322632

2633-
def unpickleExpr[T](pickled: List[String], fillHole: Int => Seq[Any] => Any): scala.quoted.Expr[T] =
2633+
def unpickleExpr[T](pickled: String | List[String], fillHole: Int => Seq[Any] => Any): scala.quoted.Expr[T] =
26342634
val tree = PickledQuotes.unpickleTerm(pickled, fillHole)(using reflect.rootContext)
26352635
new scala.internal.quoted.Expr(tree, hash).asInstanceOf[scala.quoted.Expr[T]]
26362636

2637-
def unpickleType[T <: AnyKind](pickled: List[String], fillHole: Int => Seq[Any] => Any): scala.quoted.Type[T] =
2637+
def unpickleType[T <: AnyKind](pickled: String | List[String], fillHole: Int => Seq[Any] => Any): scala.quoted.Type[T] =
26382638
val tree = PickledQuotes.unpickleTypeTree(pickled, fillHole)(using reflect.rootContext)
26392639
new scala.internal.quoted.Type(tree, hash).asInstanceOf[scala.quoted.Type[T]]
26402640

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,9 @@ object TastyString {
2222
strings.foreach(string.append)
2323
Base64.getDecoder().decode(string.result().getBytes(UTF_8))
2424
}
25+
26+
/** Decode the Strings into TASTY bytes */
27+
def unpickle(string: String): Array[Byte] =
28+
Base64.getDecoder().decode(string.getBytes(UTF_8))
29+
2530
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,10 @@ class ReifyQuotes extends MacroTransform {
200200
* this closure is always applied directly to the actual context and the BetaReduce phase removes it.
201201
*/
202202
def pickleAsTasty() = {
203-
val pickledQuoteStrings = liftList(PickledQuotes.pickleQuote(body).map(x => Literal(Constant(x))), defn.StringType)
203+
val pickleQuote = PickledQuotes.pickleQuote(body)
204+
val pickledQuoteStrings = pickleQuote match
205+
case x :: Nil => Literal(Constant(x))
206+
case xs => liftList(xs.map(x => Literal(Constant(x))), defn.StringType)
204207
val splicesList = liftList(splices, defn.FunctionType(1).appliedTo(defn.SeqType.appliedTo(defn.AnyType), defn.AnyType))
205208
val quoteClass = if isType then defn.QuotedTypeClass else defn.QuotedExprClass
206209
val quotedType = quoteClass.typeRef.appliedTo(originalTp)

library/src/scala/internal/quoted/QuoteContextInternal.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ trait QuoteContextInternal { self: QuoteContext =>
99
/** Unpickle `repr` which represents a pickled `Expr` tree,
1010
* replacing splice nodes with `holes`
1111
*/
12-
def unpickleExpr[T](pickled: List[String], fillHole: Int => Seq[Any] => Any): scala.quoted.Expr[T]
12+
def unpickleExpr[T](pickled: String | List[String], fillHole: Int => Seq[Any] => Any): scala.quoted.Expr[T]
1313

1414
/** Unpickle `repr` which represents a pickled `Type` tree,
1515
* replacing splice nodes with `holes`
1616
*/
17-
def unpickleType[T <: AnyKind](pickled: List[String], fillHole: Int => Seq[Any] => Any): scala.quoted.Type[T]
17+
def unpickleType[T <: AnyKind](pickled: String | List[String], fillHole: Int => Seq[Any] => Any): scala.quoted.Type[T]
1818

1919
val ExprMatch: ExprMatchModule
2020

0 commit comments

Comments
 (0)