Limit unnecessary Array allocations from ClassToAPI.

+----------------------------------------------------------------------------+----------------+
|                                    Name                                    |  Shallow Size  |
+----------------------------------------------------------------------------+----------------+
|  +---1571683 zero length arrays xsbti.api.Annotation[]                     |    25,146,928  |
|  |                                                                         |                |
|  +---1373273 zero length arrays xsbti.api.TypeParameter[]                  |    21,972,368  |
|  |                                                                         |                |
|  +---305126 zero length arrays xsbti.api.ParameterList[]                   |     4,882,016  |
|  |                                                                         |                |
|  +---295294 zero length arrays xsbti.api.MethodParameter[]                 |     4,724,704  |
|  |                                                                         |                |
This commit is contained in:
Paul Phillips 2011-09-07 11:24:40 -07:00
parent fae7c3b429
commit 528b4ed342
1 changed files with 37 additions and 14 deletions

View File

@ -16,7 +16,19 @@ object ClassToAPI
new api.SourceAPI(pkgs.toArray, defs.toArray)
}
def packages(c: Seq[Class[_]]): Set[String] =
// Avoiding implicit allocation.
private def arrayMap[T <: AnyRef, U <: AnyRef : ClassManifest](xs: Array[T])(f: T => U): Array[U] = {
val len = xs.length
var i = 0
val res = new Array[U](len)
while (i < len) {
res(i) = f(xs(i))
i += 1
}
res
}
def packages(c: Seq[Class[_]]): Set[String] =
c.flatMap(packageName).toSet
def isTopLevel(c: Class[_]): Boolean =
@ -36,7 +48,7 @@ object ClassToAPI
val tpe = if(Modifier.isInterface(c.getModifiers)) Trait else ClassDef
lazy val (static, instance) = structure(c, enclPkg, cmap)
val cls = new api.ClassLike(tpe, strict(Empty), lzy(instance), typeParameters(c.getTypeParameters), name, acc, mods, annots)
val stat = new api.ClassLike(Module, strict(Empty), lzy(static), Array(), name, acc, mods, annots)
val stat = new api.ClassLike(Module, strict(Empty), lzy(static), emptyTypeParameterArray, name, acc, mods, annots)
val defs = cls :: stat :: Nil
cmap(c.getName) = defs
defs
@ -51,18 +63,23 @@ object ClassToAPI
val all = (methods ++ fields ++ constructors ++ classes)
val parentTypes = parents(c)
val instanceStructure = new api.Structure(lzy(parentTypes.toArray), lzy(all.declared.toArray), lzy(all.inherited.toArray))
val staticStructure = new api.Structure(emptyTpeArray, lzy(all.staticDeclared.toArray), lzy(all.staticInherited.toArray))
val staticStructure = new api.Structure(lzyEmptyTpeArray, lzy(all.staticDeclared.toArray), lzy(all.staticInherited.toArray))
(staticStructure, instanceStructure)
}
def lzy[T <: AnyRef](t: => T): xsbti.api.Lazy[T] = xsbti.SafeLazy(t)
private val emptyTpeArray = lzy(Array[xsbti.api.Type]())
private val emptyDefArray = lzy(Array[xsbti.api.Definition]())
private val emptyTypeArray = new Array[xsbti.api.Type](0)
private val emptyAnnotationArray = new Array[xsbti.api.Annotation](0)
private val emptyTypeParameterArray = new Array[xsbti.api.TypeParameter](0)
private val emptySimpleTypeArray = new Array[xsbti.api.SimpleType](0)
private val lzyEmptyTpeArray = lzy(emptyTypeArray)
private val lzyEmptyDefArray = lzy(new Array[xsbti.api.Definition](0))
def parents(c: Class[_]): Seq[api.Type] =
types(c.getGenericSuperclass +: c.getGenericInterfaces)
def types(ts: Seq[Type]): Array[api.Type] = ts filter (_ ne null) map reference toArray;
def upperBounds(ts: Array[Type]): api.Type =
new api.Structure(lzy(types(ts)), emptyDefArray, emptyDefArray)
new api.Structure(lzy(types(ts)), lzyEmptyDefArray, lzyEmptyDefArray)
def fieldToDef(enclPkg: Option[String])(f: Field): api.FieldLike =
{
@ -91,13 +108,16 @@ object ClassToAPI
}
def exceptionAnnotations(exceptions: Array[Type]): Array[api.Annotation] =
exceptions map { t => new api.Annotation(Throws, Array(new api.AnnotationArgument("value", t.toString))) }
if (exceptions.length == 0) emptyAnnotationArray
else arrayMap(exceptions)(t => new api.Annotation(Throws, Array(new api.AnnotationArgument("value", t.toString))))
def parameter(annots: Array[Annotation], parameter: Type, varArgs: Boolean): api.MethodParameter =
new api.MethodParameter("", annotated(reference(parameter),annots), false, if(varArgs) api.ParameterModifier.Repeated else api.ParameterModifier.Plain)
def annotated(t: api.SimpleType, annots: Array[Annotation]): api.Type =
if(annots.isEmpty) t else new api.Annotated(t, annotations(annots))
def annotated(t: api.SimpleType, annots: Array[Annotation]): api.Type = (
if (annots.length == 0) t
else new api.Annotated(t, annotations(annots))
)
case class Defs(declared: Seq[api.Definition], inherited: Seq[api.Definition], staticDeclared: Seq[api.Definition], staticInherited: Seq[api.Definition])
{
@ -120,9 +140,11 @@ object ClassToAPI
def isStatic(a: Member): Boolean = Modifier.isStatic(a.getModifiers)
def typeParameters[T <: GenericDeclaration](tps: Array[TypeVariable[T]]): Array[api.TypeParameter] =
tps map typeParameter
if (tps.length == 0) emptyTypeParameterArray
else arrayMap(tps)(typeParameter)
def typeParameter[T <: GenericDeclaration](tp: TypeVariable[T]): api.TypeParameter =
new api.TypeParameter(typeVariable(tp), Array(), Array(), api.Variance.Invariant, NothingRef, upperBounds(tp.getBounds))
new api.TypeParameter(typeVariable(tp), emptyAnnotationArray, emptyTypeParameterArray, api.Variance.Invariant, NothingRef, upperBounds(tp.getBounds))
// needs to be stable across compilations
// preferably, it would be a proper unique id based on de Bruijn index
@ -151,7 +173,7 @@ object ClassToAPI
if(isPublic(i)) Public else if(isPrivate(i)) Private else if(isProtected(i)) Protected else packagePrivate(pkg)
}
def annotations(a: Array[Annotation]): Array[api.Annotation] = a map annotation
def annotations(a: Array[Annotation]): Array[api.Annotation] = if (a.length == 0) emptyAnnotationArray else arrayMap(a)(annotation)
def annotation(a: Annotation): api.Annotation =
new api.Annotation( reference(a.annotationType), Array(javaAnnotation(a.toString)))
@ -177,8 +199,9 @@ object ClassToAPI
}
def referenceP(t: ParameterizedType): api.Parameterized =
{
val args = t.getActualTypeArguments.map(reference)
val base = reference(t.getRawType)
val targs = t.getActualTypeArguments
val args = if (targs.length == 0) emptyTypeArray else arrayMap(targs)(t => reference(t): api.Type)
val base = reference(t.getRawType)
new api.Parameterized(base, args.toArray[api.Type])
}
def reference(t: Type): api.SimpleType =