summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-06-11 20:32:55 +0000
committerPaul Phillips <paulp@improving.org>2011-06-11 20:32:55 +0000
commitf0ca26ab84172034f3ac41639d1a5dce242f9a5a (patch)
tree257e78624f3d6c485dcfe40f1f77be5c9a8749d1
parent581a8c6ffe558c6fb2fc44239c13db6eec8be968 (diff)
downloadscala-f0ca26ab84172034f3ac41639d1a5dce242f9a5a.tar.gz
scala-f0ca26ab84172034f3ac41639d1a5dce242f9a5a.tar.bz2
scala-f0ca26ab84172034f3ac41639d1a5dce242f9a5a.zip
A third round of optimizations from Tiark, no r...
A third round of optimizations from Tiark, no review.
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala52
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala15
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala10
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala2
5 files changed, 57 insertions, 23 deletions
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 1459371349..cb3ec1bfeb 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -877,11 +877,12 @@ trait Types /*extends reflect.generic.Types*/ { self: SymbolTable =>
// For now I modified it as below, which achieves the same without error.
//
// make each type var in this type use its original type for comparisons instead of collecting constraints
- suspension = new mutable.HashSet
+ val susp = new mutable.HashSet[TypeVar] // use a local val so it remains unboxed
this foreach {
- case tv: TypeVar => tv.suspended = true; suspension += tv
+ case tv: TypeVar => tv.suspended = true; susp += tv
case _ =>
}
+ suspension = susp
}
incCounter(findMemberCount)
@@ -930,12 +931,14 @@ trait Types /*extends reflect.generic.Types*/ { self: SymbolTable =>
}
} else {
var prevEntry = members.lookupEntry(sym.name)
+ var symtpe: Type = null
while ((prevEntry ne null) &&
!(prevEntry.sym == sym ||
prevEntry.sym.owner != sym.owner &&
!sym.hasFlag(PRIVATE) && {
if (self eq null) self = this.narrow
- self.memberType(prevEntry.sym) matches self.memberType(sym)
+ if (symtpe eq null) symtpe = self.memberType(sym)
+ self.memberType(prevEntry.sym) matches symtpe
})) {
prevEntry = members lookupNextEntry prevEntry
}
@@ -1844,9 +1847,9 @@ A type's typeSymbol should never be inspected directly.
val substTps = formals.intersect(typeParams)
if (sameLength(substTps, typeParams))
- typeRef(pre, sym, actuals)
+ copyTypeRef(this, pre, sym, actuals)
else if (sameLength(formals, actuals)) // partial application (needed in infer when bunching type arguments from classes and methods together)
- typeRef(pre, sym, dummyArgs).subst(formals, actuals)
+ copyTypeRef(this, pre, sym, dummyArgs).subst(formals, actuals)
else ErrorType
}
else
@@ -1864,7 +1867,7 @@ A type's typeSymbol should never be inspected directly.
// @M: initialize (by sym.info call) needed (see test/files/pos/ticket0137.scala)
@inline private def etaExpand: Type = {
val tpars = sym.info.typeParams // must go through sym.info for typeParams to initialise symbol
- typeFunAnon(tpars, typeRef(pre, sym, tpars map (_.tpeHK))) // todo: also beta-reduce?
+ typeFunAnon(tpars, copyTypeRef(this, pre, sym, tpars map (_.tpeHK))) // todo: also beta-reduce?
}
override def dealias: Type =
@@ -2748,6 +2751,27 @@ A type's typeSymbol should never be inspected directly.
}
}
+ def copyTypeRef(tp: Type, pre: Type, sym: Symbol, args: List[Type]): Type = tp match {
+ case TypeRef(pre0, sym0, args0) =>
+ if ((pre == pre0) && (sym.name == sym0.name)) {
+
+ val sym1 = sym
+ // we require that object is initialized, thus info.typeParams instead of typeParams.
+ if (sym1.isAliasType && sameLength(sym1.info.typeParams, args)) {
+ if (sym1.lockOK) TypeRef(pre, sym1, args) // don't expand type alias (cycles checked by lockOK)
+ else throw new TypeError("illegal cyclic reference involving " + sym1)
+ }
+ else {
+ TypeRef(pre, sym1, args)
+ }
+
+ } else
+ typeRef(pre, sym, args)
+ }
+
+
+
+
/** The canonical creator for implicit method types */
def JavaMethodType(params: List[Symbol], resultType: Type): JavaMethodType =
new JavaMethodType(params, resultType) // don't unique this!
@@ -2794,8 +2818,8 @@ A type's typeSymbol should never be inspected directly.
def appliedType(tycon: Type, args: List[Type]): Type =
if (args.isEmpty) tycon //@M! `if (args.isEmpty) tycon' is crucial (otherwise we create new types in phases after typer and then they don't get adapted (??))
else tycon match {
- case TypeRef(pre, sym @ (NothingClass|AnyClass), _) => typeRef(pre, sym, Nil) //@M drop type args to Any/Nothing
- case TypeRef(pre, sym, _) => typeRef(pre, sym, args)
+ case TypeRef(pre, sym @ (NothingClass|AnyClass), _) => copyTypeRef(tycon, pre, sym, Nil) //@M drop type args to Any/Nothing
+ case TypeRef(pre, sym, _) => copyTypeRef(tycon, pre, sym, args)
case PolyType(tparams, restpe) => restpe.instantiateTypeParams(tparams, args)
case ExistentialType(tparams, restpe) => ExistentialType(tparams, appliedType(restpe, args))
case st: SingletonType => appliedType(st.widen, args) // @M TODO: what to do? see bug1
@@ -3079,7 +3103,7 @@ A type's typeSymbol should never be inspected directly.
else mapOverArgs(args, tparams)
}
if ((pre1 eq pre) && (args1 eq args)) tp
- else typeRef(pre1, coevolveSym(pre, pre1, sym), args1)
+ else copyTypeRef(tp, pre1, coevolveSym(pre, pre1, sym), args1)
case ThisType(_) => tp
case SingleType(pre, sym) =>
if (sym.isPackageClass) tp // short path
@@ -3548,7 +3572,7 @@ A type's typeSymbol should never be inspected directly.
/** A map to implement the `substSym' method. */
class SubstSymMap(from: List[Symbol], to: List[Symbol]) extends SubstMap(from, to) {
protected def toType(fromtp: Type, sym: Symbol) = fromtp match {
- case TypeRef(pre, _, args) => typeRef(pre, sym, args)
+ case TypeRef(pre, _, args) => copyTypeRef(fromtp, pre, sym, args)
case SingleType(pre, _) => singleType(pre, sym)
}
override def apply(tp: Type): Type = if (from.isEmpty) tp else {
@@ -3561,7 +3585,7 @@ A type's typeSymbol should never be inspected directly.
case TypeRef(pre, sym, args) if pre ne NoPrefix =>
val newSym = subst(sym, from, to)
// assert(newSym.typeParams.length == sym.typeParams.length, "typars mismatch in SubstSymMap: "+(sym, sym.typeParams, newSym, newSym.typeParams))
- mapOver(typeRef(pre, newSym, args)) // mapOver takes care of subst'ing in args
+ mapOver(copyTypeRef(tp, pre, newSym, args)) // mapOver takes care of subst'ing in args
case SingleType(pre, sym) if pre ne NoPrefix =>
mapOver(singleType(pre, subst(sym, from, to)))
case _ =>
@@ -3945,7 +3969,7 @@ A type's typeSymbol should never be inspected directly.
try {
val sym1 = adaptToNewRun(pre1, sym)
if ((pre1 eq pre) && (sym1 eq sym) && (args1 eq args)/* && sym.isExternal*/) tp
- else typeRef(pre1, sym1, args1)
+ else copyTypeRef(tp, pre1, sym1, args1)
} catch {
case ex: MissingAliasControl =>
apply(tp.dealias)
@@ -4087,7 +4111,7 @@ A type's typeSymbol should never be inspected directly.
patType match {
case TypeRef(pre, sym, args) =>
val pre1 = maybeCreateDummyClone(pre, sym)
- (pre1 ne NoType) && isPopulated(typeRef(pre1, sym, args), selType)
+ (pre1 ne NoType) && isPopulated(copyTypeRef(patType, pre1, sym, args), selType)
case _ =>
false
}
@@ -4512,7 +4536,7 @@ A type's typeSymbol should never be inspected directly.
def instTypeVar(tp: Type): Type = tp match {
case TypeRef(pre, sym, args) =>
- typeRef(instTypeVar(pre), sym, args)
+ copyTypeRef(tp, instTypeVar(pre), sym, args)
case SingleType(pre, sym) =>
singleType(instTypeVar(pre), sym)
case TypeVar(_, constr) =>
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 3ab1a637fa..5b4e783db0 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -255,7 +255,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
parents = parents.distinct
if (parents.tail.nonEmpty)
- ifaces = parents drop 1 map (x => javaName(x.typeSymbol)) toArray;
+ ifaces = mkArray(parents drop 1 map (x => javaName(x.typeSymbol)))
jclass = fjbgContext.JClass(javaFlags(c.symbol),
name,
@@ -573,7 +573,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
* in which case we treat every signature as valid. Medium term we
* should certainly write independent signature validation.
*/
- if (SigParser.isParserAvailable && !isValidSignature(sym, sig)) {
+ if (settings.Xverify.value && SigParser.isParserAvailable && !isValidSignature(sym, sig)) {
clasz.cunit.warning(sym.pos,
"""|compiler bug: created invalid generic signature for %s in %s
|signature: %s
@@ -750,8 +750,8 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
jmethod = jclass.addNewMethod(flags,
javaName(m.symbol),
resTpe,
- m.params map (p => javaType(p.kind)) toArray,
- m.params map (p => javaName(p.sym)) toArray)
+ mkArray(m.params map (p => javaType(p.kind))),
+ mkArray(m.params map (p => javaName(p.sym))))
addRemoteException(jmethod, m.symbol)
@@ -953,8 +953,8 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
accessFlags,
javaName(m),
javaType(methodInfo.resultType),
- paramJavaTypes.toArray,
- paramNames.toArray)
+ mkArray(paramJavaTypes),
+ mkArray(paramNames))
val mirrorCode = mirrorMethod.getCode().asInstanceOf[JExtendedCode]
mirrorCode.emitGETSTATIC(moduleName,
nme.MODULE_INSTANCE_FIELD.toString,
@@ -1497,8 +1497,9 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
// assert(instr.pos.source.isEmpty || instr.pos.source.get == (clasz.cunit.source), "sources don't match")
// val crtLine = instr.pos.line.get(lastLineNr);
+
val crtLine = try {
- (instr.pos).line
+ if (instr.pos == NoPosition) lastLineNr else (instr.pos).line // check NoPosition to avoid costly exception
} catch {
case _: UnsupportedOperationException =>
log("Warning: wrong position in: " + method)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala
index 6ff5d42e55..418dbea9e1 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala
@@ -68,6 +68,14 @@ trait GenJVMUtil {
GE -> LT
)
+ /** Specialized array conversion to prevent calling
+ * java.lang.reflect.Array.newInstance via TraversableOnce.toArray
+ */
+
+ def mkArray(xs: Traversable[JType]): Array[JType] = { val a = new Array[JType](xs.size); xs.copyToArray(a); a }
+ def mkArray(xs: Traversable[String]): Array[String] = { val a = new Array[String](xs.size); xs.copyToArray(a); a }
+
+
/** Return the a name of this symbol that can be used on the Java
* platform. It removes spaces from names.
*
@@ -109,7 +117,7 @@ trait GenJVMUtil {
if (s.isMethod)
new JMethodType(
if (s.isClassConstructor) JType.VOID else javaType(s.tpe.resultType),
- s.tpe.paramTypes map javaType toArray
+ mkArray(s.tpe.paramTypes map javaType)
)
else
javaType(s.tpe)
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 2ab933f5ba..3dab85f77c 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -61,6 +61,7 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings {
val Xmigration28 = BooleanSetting ("-Xmigration", "Warn about constructs whose behavior may have changed between 2.7 and 2.8.")
val nouescape = BooleanSetting ("-Xno-uescape", "Disable handling of \\u unicode escapes.")
val Xnojline = BooleanSetting ("-Xnojline", "Do not use JLine for editing.")
+ val Xverify = BooleanSetting ("-Xverify", "Verify generic signatures in generated bytecode.")
val plugin = MultiStringSetting("-Xplugin", "file", "Load one or more plugins from files.")
val disable = MultiStringSetting("-Xplugin-disable", "plugin", "Disable the given plugin(s).")
val showPlugins = BooleanSetting ("-Xplugin-list", "Print a synopsis of loaded plugins.")
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 2cf3d06866..c5c03b9181 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -230,7 +230,7 @@ abstract class Erasure extends AddInterfaces
}
}
// for debugging signatures: traces logic given system property
- private val traceProp = sys.BooleanProp keyExists "scalac.sigs.trace"
+ private val traceProp = (sys.BooleanProp keyExists "scalac.sigs.trace").value // performance: get the value here
private val traceSig = util.Tracer(traceProp)
/** This object is only used for sanity testing when -check:genjvm is set.