Skip to content

Commit 7cc6dcb

Browse files
authored
Merge pull request scala#7844 from retronym/topic/uncurry-fast-path
Reduce allocations in Uncurry.transformArgs
2 parents 3e59216 + 8bd0ca1 commit 7cc6dcb

File tree

1 file changed

+19
-14
lines changed

1 file changed

+19
-14
lines changed

src/compiler/scala/tools/nsc/transform/UnCurry.scala

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ package tools.nsc
1515
package transform
1616

1717
import scala.annotation.tailrec
18-
1918
import symtab.Flags._
2019
import scala.collection.mutable
20+
import scala.collection.mutable.ListBuffer
2121
import scala.reflect.internal.util.ListOfNil
2222

2323
/*<export> */
@@ -247,14 +247,15 @@ abstract class UnCurry extends InfoTransform
247247
}
248248
}
249249

250-
def transformArgs(pos: Position, fun: Symbol, args: List[Tree], formals: List[Type]): List[Tree] = {
250+
def transformArgs(pos: Position, fun: Symbol, args: List[Tree], params: List[Symbol]): List[Tree] = {
251251
val isJava = fun.isJavaDefined
252-
def transformVarargs(varargsElemType: Type) = {
252+
253+
def transformVarargs(varargsElemType: Type): List[Tree] = {
253254
def mkArrayValue(ts: List[Tree], elemtp: Type) =
254255
ArrayValue(TypeTree(elemtp), ts) setType arrayType(elemtp)
255256

256257
// when calling into scala varargs, make sure it's a sequence.
257-
def arrayToSequence(tree: Tree, elemtp: Type, copy: Boolean) = {
258+
def arrayToSequence(tree: Tree, elemtp: Type, copy: Boolean): Tree = {
258259
exitingUncurry {
259260
localTyper.typedPos(pos) {
260261
val pt = arrayType(elemtp)
@@ -273,7 +274,7 @@ abstract class UnCurry extends InfoTransform
273274
}
274275

275276
// when calling into java varargs, make sure it's an array - see bug #1360
276-
def sequenceToArray(tree: Tree) = {
277+
def sequenceToArray(tree: Tree): Tree = {
277278
val toArraySym = tree.tpe member nme.toArray
278279
assert(toArraySym != NoSymbol)
279280
def getClassTag(tp: Type): Tree = {
@@ -314,7 +315,7 @@ abstract class UnCurry extends InfoTransform
314315
else arrayToSequence(tree, varargsElemType, copy = isNewCollections) // existing array, make a defensive copy
315316
}
316317
else {
317-
def mkArray = mkArrayValue(args drop (formals.length - 1), varargsElemType)
318+
def mkArray = mkArrayValue(args drop (params.length - 1), varargsElemType)
318319
if (javaStyleVarArgs) mkArray
319320
else if (args.isEmpty) gen.mkNil // avoid needlessly double-wrapping an empty argument list
320321
else arrayToSequence(mkArray, varargsElemType, copy = false) // fresh array, no need to copy
@@ -328,18 +329,22 @@ abstract class UnCurry extends InfoTransform
328329
}
329330
}
330331
}
331-
args.take(formals.length - 1) :+ (suffix setType formals.last)
332+
val args1 = ListBuffer[Tree]()
333+
args1 ++= args.iterator.take(params.length - 1)
334+
args1 += suffix setType params.last.info
335+
args1.toList
332336
}
333337

334-
val args1 = if (isVarArgTypes(formals)) transformVarargs(formals.last.typeArgs.head.widen) else args
338+
val isVarargs = isVarArgsList(params)
339+
val args1 = if (isVarargs) transformVarargs(params.last.info.typeArgs.head.widen) else args
335340

336-
map2(formals, args1) { (formal, arg) =>
337-
if (!isByNameParamType(formal)) arg
341+
map2Conserve(args1, params) { (arg, param) =>
342+
if (!isByNameParamType(param.info)) arg
338343
else if (isByNameRef(arg)) { // thunk does not need to be forced because it's a reference to a by-name arg passed to a by-name param
339344
byNameArgs += arg
340345
arg setType functionType(Nil, arg.tpe)
341346
} else {
342-
log(s"Argument '$arg' at line ${arg.pos.line} is $formal from ${fun.fullName}")
347+
log(s"Argument '$arg' at line ${arg.pos.line} is ${param.info} from ${fun.fullName}")
343348
def canUseDirectly(qual: Tree) = qual.tpe.typeSymbol.isSubClass(FunctionClass(0)) && treeInfo.isExprSafeToInline(qual)
344349
arg match {
345350
// don't add a thunk for by-name argument if argument already is an application of
@@ -482,16 +487,16 @@ abstract class UnCurry extends InfoTransform
482487
super.transform(tree)
483488

484489
case Apply(fn, args) =>
485-
// Read formals before `transform(fn)`, because UnCurry replaces T* by Seq[T] (see DesugaredParameterType).
490+
// Read the param symbols before `transform(fn)`, because UnCurry replaces T* by Seq[T] (see DesugaredParameterType).
486491
// The call to `transformArgs` below needs `formals` that still have varargs.
487-
val formals = fn.tpe.paramTypes
492+
val fnParams = fn.tpe.params
488493
val transformedFn = transform(fn)
489494
// scala/bug#6479: no need to lift in args to label jumps
490495
// scala/bug#11127: boolean && / || are emitted using jumps, the lhs stack value is consumed by the conditional jump
491496
val noReceiverOnStack = fn.symbol.isLabel || fn.symbol == currentRun.runDefinitions.Boolean_and || fn.symbol == currentRun.runDefinitions.Boolean_or
492497
val needLift = needTryLift || !noReceiverOnStack
493498
withNeedLift(needLift) {
494-
treeCopy.Apply(tree, transformedFn, transformTrees(transformArgs(tree.pos, fn.symbol, args, formals)))
499+
treeCopy.Apply(tree, transformedFn, transformTrees(transformArgs(tree.pos, fn.symbol, args, fnParams)))
495500
}
496501

497502
case Assign(_: RefTree, _) =>

0 commit comments

Comments
 (0)