summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-12-30 11:14:38 -0800
committerPaul Phillips <paulp@improving.org>2011-12-30 11:19:05 -0800
commit9ae096330d07c1a865b934bb2bc978464824bd7e (patch)
tree04b3fa68538f7774e0e9e9e96983d7aee46a3791 /src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
parent66cc6ee5736facc0cb7670d0f334aba2274630ee (diff)
downloadscala-9ae096330d07c1a865b934bb2bc978464824bd7e.tar.gz
scala-9ae096330d07c1a865b934bb2bc978464824bd7e.tar.bz2
scala-9ae096330d07c1a865b934bb2bc978464824bd7e.zip
Optimization in refchecks.
addVarargBridges is extremely expensive to cover such a corner case (scala classes inheriting and overriding java varargs methods.) Added a fast path excluding every class which doesn't have a java varargs method somewhere amidst its ancestors.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/RefChecks.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala86
1 files changed, 50 insertions, 36 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index f920f3c135..59a1a254c6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -150,49 +150,64 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
// Override checking ------------------------------------------------------------
+
+ def isJavaVarargsAncestor(clazz: Symbol) = (
+ clazz.isClass
+ && clazz.isJavaDefined
+ && (clazz.info.nonPrivateMembers exists isJavaVarArgsMethod)
+ )
/** Add bridges for vararg methods that extend Java vararg methods
*/
def addVarargBridges(clazz: Symbol): List[Tree] = {
- val self = clazz.thisType
- val bridges = new ListBuffer[Tree]
-
- def varargBridge(member: Symbol, bridgetpe: Type): Tree = {
- val bridge = member.cloneSymbolImpl(clazz)
- .setPos(clazz.pos).setFlag(member.flags | VBRIDGE)
- bridge.setInfo(bridgetpe.cloneInfo(bridge))
- clazz.info.decls enter bridge
- val List(params) = bridge.paramss
- val TypeRef(_, JavaRepeatedParamClass, List(elemtp)) = params.last.tpe
- val (initargs, List(lastarg0)) = (params map Ident) splitAt (params.length - 1)
- val lastarg = gen.wildcardStar(gen.mkWrapArray(lastarg0, elemtp))
- val body = Apply(Select(This(clazz), member), initargs ::: List(lastarg))
- localTyper.typed {
- /*util.trace("generating varargs bridge")*/(DefDef(bridge, body))
+ // This is quite expensive, so attempt to skip it completely.
+ // Insist there at least be a java-defined ancestor which
+ // defines a varargs method. TODO: Find a cheaper way to exclude.
+ if (clazz.thisType.baseClasses exists isJavaVarargsAncestor) {
+ log("Found java varargs ancestor in " + clazz.fullLocationString + ".")
+ val self = clazz.thisType
+ val bridges = new ListBuffer[Tree]
+
+ def varargBridge(member: Symbol, bridgetpe: Type): Tree = {
+ log("Generating varargs bridge for " + member.fullLocationString + " of type " + bridgetpe)
+
+ val bridge = member.cloneSymbolImpl(clazz)
+ .setPos(clazz.pos).setFlag(member.flags | VBRIDGE)
+ bridge.setInfo(bridgetpe.cloneInfo(bridge))
+ clazz.info.decls enter bridge
+
+ val params = bridge.paramss.head
+ val elemtp = params.last.tpe.typeArgs.head
+ val idents = params map Ident
+ val lastarg = gen.wildcardStar(gen.mkWrapArray(idents.last, elemtp))
+ val body = Apply(Select(This(clazz), member), idents.init :+ lastarg)
+
+ localTyper typed DefDef(bridge, body)
}
- }
-
- // For all concrete non-private members that have a (Scala) repeated parameter:
- // compute the corresponding method type `jtpe` with a Java repeated parameter
- // if a method with type `jtpe` exists and that method is not a varargs bridge
- // then create a varargs bridge of type `jtpe` that forwards to the
- // member method with the Scala vararg type.
- for (member <- clazz.info.nonPrivateMembers) {
- if (!(member hasFlag DEFERRED) && hasRepeatedParam(member.info)) {
- val jtpe = toJavaRepeatedParam(self.memberType(member))
- val inherited = clazz.info.nonPrivateMemberAdmitting(member.name, VBRIDGE) filter (
- sym => (self.memberType(sym) matches jtpe) && !(sym hasFlag VBRIDGE)
- // this is a bit tortuous: we look for non-private members or bridges
- // if we find a bridge everything is OK. If we find another member,
- // we need to create a bridge
- )
- if (inherited.exists) {
- bridges += varargBridge(member, jtpe)
+
+ // For all concrete non-private members that have a (Scala) repeated parameter:
+ // compute the corresponding method type `jtpe` with a Java repeated parameter
+ // if a method with type `jtpe` exists and that method is not a varargs bridge
+ // then create a varargs bridge of type `jtpe` that forwards to the
+ // member method with the Scala vararg type.
+ for (member <- clazz.info.nonPrivateMembers) {
+ if (!member.isDeferred && member.isMethod && hasRepeatedParam(member.info)) {
+ val inherited = clazz.info.nonPrivateMemberAdmitting(member.name, VBRIDGE)
+ // Delaying calling memberType as long as possible
+ if (inherited ne NoSymbol) {
+ val jtpe = toJavaRepeatedParam(self.memberType(member))
+ // this is a bit tortuous: we look for non-private members or bridges
+ // if we find a bridge everything is OK. If we find another member,
+ // we need to create a bridge
+ if (inherited filter (sym => (self.memberType(sym) matches jtpe) && !(sym hasFlag VBRIDGE)) exists)
+ bridges += varargBridge(member, jtpe)
+ }
}
}
+
+ bridges.toList
}
-
- bridges.toList
+ else Nil
}
/** 1. Check all members of class `clazz` for overriding conditions.
@@ -1549,7 +1564,6 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
checkOverloadedRestrictions(currentOwner)
val bridges = addVarargBridges(currentOwner)
checkAllOverrides(currentOwner)
-
if (bridges.nonEmpty) treeCopy.Template(tree, parents, self, body ::: bridges)
else tree