summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-11-15 11:14:57 +0000
committerMartin Odersky <odersky@gmail.com>2009-11-15 11:14:57 +0000
commitc43f01c39d029be1a82c78bb2f49da5eb6833ab5 (patch)
tree65b9ac40a15157547ee7959c3a9e29c58825447a
parent1cd31e2edd031c0d32266de54ef63ddb9233c047 (diff)
downloadscala-c43f01c39d029be1a82c78bb2f49da5eb6833ab5.tar.gz
scala-c43f01c39d029be1a82c78bb2f49da5eb6833ab5.tar.bz2
scala-c43f01c39d029be1a82c78bb2f49da5eb6833ab5.zip
Fixed #2848 and #2630; Improvements in equality...
Fixed #2848 and #2630; Improvements in equality speed
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala47
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala18
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala14
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala10
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala12
-rw-r--r--src/library/scala/runtime/BoxesRunTime.java82
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala5
-rwxr-xr-xtest/files/pos/t2484.scala17
8 files changed, 115 insertions, 90 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index bff4bd51c3..e4dfb14833 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -131,6 +131,8 @@ trait Trees {
this
}
+ /** Set tpe to give `tp` and return this.
+ */
def setType(tp: Type): this.type = {
/*assert(kindingIrrelevant(tp) || !kindStar || !tp.isHigherKinded,
tp+" should not be higher-kinded");*/
@@ -138,6 +140,15 @@ trait Trees {
this
}
+ /** Like `setType`, but if this is a previously empty TypeTree
+ * that fact is remembered so that resetType will snap back.
+ */
+ def defineType(tp: Type): this.type = setType(tp)
+
+ /** Reset type to `null`, with special handling of TypeTrees and the EmptyType
+ */
+ def resetType() { tpe = null }
+
def symbol: Symbol = null
def symbol_=(sym: Symbol) {
throw new Error("symbol_= inapplicable for " + this)
@@ -323,6 +334,7 @@ trait Trees {
super.tpe_=(NoType)
override def tpe_=(t: Type) =
if (t != NoType) throw new Error("tpe_=("+t+") inapplicable for <empty>")
+ override def resetType() {}
override def isEmpty = true
}
@@ -868,12 +880,25 @@ trait Trees {
case class TypeTree() extends TypTree {
override def symbol = if (tpe == null) null else tpe.typeSymbol
- private var orig: Tree = null // should be EmptyTree?
+ private var orig: Tree = null
+ private var wasEmpty: Boolean = false
def original: Tree = orig
def setOriginal(tree: Tree): this.type = { orig = tree; setPos(tree.pos); this }
+ override def defineType(tp: Type): this.type = {
+ wasEmpty = isEmpty
+ setType(tp)
+ }
+
+ /** Reset type to null, unless type original was empty and then
+ * got its type via a defineType
+ */
+ override def resetType() {
+ if (wasEmpty) tpe = null
+ }
+
override def isEmpty = (tpe eq null) || tpe == NoType
}
@@ -1817,18 +1842,16 @@ trait Trees {
protected def isLocal(sym: Symbol): Boolean = true
protected def resetDef(tree: Tree) {
tree.symbol = NoSymbol
- tree.tpe = null
- super.traverse(tree)
}
- override def traverse(tree: Tree): Unit = tree match {
- case EmptyTree | TypeTree() =>
- ;
- case _: DefTree | Function(_, _) | Template(_, _, _) =>
- resetDef(tree)
- case _ =>
- if (tree.hasSymbol && isLocal(tree.symbol)) tree.symbol = NoSymbol
- tree.tpe = null
- super.traverse(tree)
+ override def traverse(tree: Tree): Unit = {
+ tree match {
+ case _: DefTree | Function(_, _) | Template(_, _, _) =>
+ resetDef(tree)
+ case _ =>
+ if (tree.hasSymbol && isLocal(tree.symbol)) tree.symbol = NoSymbol
+ }
+ tree.resetType()
+ super.traverse(tree)
}
}
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index be3af86d53..4d2aa9f5da 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -443,24 +443,6 @@ self =>
}
}
- /** A traverser that resets all type and symbol attributes in a tree
- object ResetAttrs extends Transformer {
- override def transform(t: Tree): Tree = {
- if (t.hasSymbol) t.symbol = NoSymbol
- t match {
- case EmptyTree =>
- t
- case tt: TypeTree =>
- if (tt.original != null) tt.original
- else t
- case _ =>
- t.tpe = null
- super.transform(t)
- }
- }
- }
- */
-
/** The typer run */
class TyperRun extends Run {
// units is always empty
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 35afe7cf5f..942890e2f1 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -4700,15 +4700,9 @@ A type's typeSymbol should never be inspected directly.
else NothingClass.tpe
}
}
- if (settings.debug.value) {
- println(indent + "glb of " + ts + " at depth "+depth)//debug
- indent = indent + " "
- }
+ // if (settings.debug.value) { println(indent + "glb of " + ts + " at depth "+depth); indent = indent + " " } //DEBUG
val res = if (depth < 0) NothingClass.tpe else glb0(ts)
- if (settings.debug.value) {
- indent = indent.substring(0, indent.length() - 2)
- log(indent + "glb of " + ts + " is " + res)//debug
- }
+ // if (settings.debug.value) { indent = indent.substring(0, indent.length() - 2); log(indent + "glb of " + ts + " is " + res) }//DEBUG
if (ts exists (_.isNotNull)) res.notNull else res
}
@@ -4726,7 +4720,7 @@ A type's typeSymbol should never be inspected directly.
* of types.
*/
private def commonOwner(tps: List[Type]): Symbol = {
- if (settings.debug.value) log("computing common owner of types " + tps)//debug
+ // if (settings.debug.value) log("computing common owner of types " + tps)//DEBUG
commonOwnerMap.init
tps foreach { tp => commonOwnerMap.apply(tp); () }
commonOwnerMap.result
@@ -4793,7 +4787,7 @@ A type's typeSymbol should never be inspected directly.
*/
def addMember(thistp: Type, tp: Type, sym: Symbol) {
assert(sym != NoSymbol)
- if (settings.debug.value) log("add member " + sym+":"+sym.info+" to "+thistp)
+ // if (settings.debug.value) log("add member " + sym+":"+sym.info+" to "+thistp) //DEBUG
if (!(thistp specializes sym)) {
if (sym.isTerm)
for (alt <- tp.nonPrivateDecl(sym.name).alternatives)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index b3e4666f35..596c11bcac 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -481,8 +481,7 @@ trait Contexts { self: Analyzer =>
}
impls
}
- if (settings.debug.value)
- log("collect implicit imports " + imp + "=" + collect(imp.tree.selectors))//debug
+ //if (settings.debug.value) log("collect implicit imports " + imp + "=" + collect(imp.tree.selectors))//DEBUG
collect(imp.tree.selectors)
}
@@ -499,17 +498,14 @@ trait Contexts { self: Analyzer =>
val newImplicits: List[ImplicitInfo] =
if (owner != nextOuter.owner && owner.isClass && !owner.isPackageClass && !inSelfSuperCall) {
if (!owner.isInitialized) return nextOuter.implicitss
- if (settings.debug.value)
- log("collect member implicits " + owner + ", implicit members = " +
- owner.thisType.implicitMembers)//debug
+ // if (settings.debug.value) log("collect member implicits " + owner + ", implicit members = " + owner.thisType.implicitMembers)//DEBUG
val savedEnclClass = enclClass
this.enclClass = this
val res = collectImplicits(owner.thisType.implicitMembers, owner.thisType)
this.enclClass = savedEnclClass
res
} else if (scope != nextOuter.scope && !owner.isPackageClass) {
- if (settings.debug.value)
- log("collect local implicits " + scope.toList)//debug
+ if (settings.debug.value) log("collect local implicits " + scope.toList)//DEBUG
collectImplicits(scope.toList, NoPrefix)
} else if (imports != nextOuter.imports) {
assert(imports.tail == nextOuter.imports)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index d4a7b9e1e7..e36e8ffb02 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -615,7 +615,7 @@ trait Namers { self: Analyzer =>
clazz.typeOfThis = selfTypeCompleter(self.tpt)
self.symbol = clazz.thisSym.setPos(self.pos)
} else {
- self.tpt.tpe = NoType
+ self.tpt defineType NoType
if (self.name != nme.WILDCARD) {
clazz.typeOfThis = clazz.tpe
self.symbol = clazz.thisSym
@@ -747,7 +747,7 @@ trait Namers { self: Analyzer =>
var vparamSymss = enterValueParams(meth, vparamss)
if (tpt.isEmpty && meth.name == nme.CONSTRUCTOR) {
- tpt.tpe = context.enclClass.owner.tpe
+ tpt defineType context.enclClass.owner.tpe
tpt setPos meth.pos.focus
}
@@ -873,7 +873,7 @@ trait Namers { self: Analyzer =>
var pfs = resultPt.paramTypes
for (vparam <- vparams) {
if (vparam.tpt.isEmpty) {
- vparam.tpt.tpe = pfs.head
+ vparam.tpt defineType pfs.head
vparam.tpt setPos vparam.pos.focus
vparam.symbol setInfo pfs.head
}
@@ -900,7 +900,7 @@ trait Namers { self: Analyzer =>
}
for (vparams <- vparamss; vparam <- vparams if vparam.tpt.isEmpty) {
context.error(vparam.pos, "missing parameter type")
- vparam.tpt.tpe = ErrorType
+ vparam.tpt defineType ErrorType
}
addDefaultGetters(meth, vparamss, tparams, overriddenSymbol)
@@ -910,7 +910,7 @@ trait Namers { self: Analyzer =>
// replace deSkolemized symbols with skolemized ones (for resultPt computed by looking at overridden symbol, right?)
val pt = resultPt.substSym(tparamSyms, tparams map (_.symbol))
// compute result type from rhs
- tpt.tpe = widenIfNotFinal(meth, typer.computeType(rhs, pt), pt)
+ tpt defineType widenIfNotFinal(meth, typer.computeType(rhs, pt), pt)
tpt setPos meth.pos.focus
tpt.tpe
} else typer.typedType(tpt).tpe
@@ -1148,7 +1148,7 @@ trait Namers { self: Analyzer =>
context.error(tpt.pos, "missing parameter type");
ErrorType
} else {
- tpt.tpe = widenIfNotFinal(
+ tpt defineType widenIfNotFinal(
sym,
newTyper(typer1.context.make(vdef, sym)).computeType(rhs, WildcardType),
WildcardType)
diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java
index b1cc464513..bd38e37503 100644
--- a/src/library/scala/runtime/BoxesRunTime.java
+++ b/src/library/scala/runtime/BoxesRunTime.java
@@ -117,59 +117,71 @@ public class BoxesRunTime
/* COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON */
+ private static int eqTypeCode(Number a) {
+ if ((a instanceof Integer) || (a instanceof Byte)) return INT;
+ if (a instanceof Long) return LONG;
+ if (a instanceof Double) return DOUBLE;
+ if (a instanceof Short) return INT;
+ if (a instanceof Float) return FLOAT;
+ return OTHER;
+ }
+
+ public static boolean equals(Object x, Object y) {
+ if (x == y) return true;
+ if (x == null) return false;
+ return equals2(x, y);
+ }
+
/** Since all applicable logic has to be present in the equals method of a ScalaNumber
* in any case, we dispatch to it as soon as we spot one on either side.
*/
- public static boolean equals(Object x, Object y) {
+ public static boolean equals2(Object x, Object y) {
if (x instanceof Number) {
- if (x instanceof ScalaNumber)
- return x.equals(y);
-
Number xn = (Number)x;
- if (y instanceof Number) {
- if (y instanceof ScalaNumber)
- return y.equals(x);
+ if (y instanceof Number) {
Number yn = (Number)y;
- if ((xn instanceof Double) || (yn instanceof Double))
- return xn.doubleValue() == yn.doubleValue();
- if ((xn instanceof Float) || (yn instanceof Float))
- return xn.floatValue() == yn.floatValue();
- if ((xn instanceof Long) || (yn instanceof Long))
- return xn.longValue() == yn.longValue();
- if (typeCode(x) <= INT && typeCode(y) <= INT)
+ int xcode = eqTypeCode(xn);
+ int ycode = eqTypeCode(yn);
+ switch (ycode > xcode ? ycode : xcode) {
+ case INT:
return xn.intValue() == yn.intValue();
-
- return x.equals(y);
- }
- if (y instanceof Character)
+ case LONG:
+ return xn.longValue() == yn.longValue();
+ case FLOAT:
+ return xn.floatValue() == yn.floatValue();
+ case DOUBLE:
+ return xn.doubleValue() == yn.doubleValue();
+ default:
+ if ((yn instanceof ScalaNumber) && !(xn instanceof ScalaNumber))
+ return y.equals(x);
+ }
+ } else if (y instanceof Character)
return equalsNumChar(xn, (Character)y);
} else if (x instanceof Character) {
Character xc = (Character)x;
if (y instanceof Character)
- return xc.equals(y);
+ return xc.charValue() == ((Character)y).charValue();
if (y instanceof Number)
return equalsNumChar((Number)y, xc);
- } else if (x == null) {
- return y == null;
}
return x.equals(y);
}
- private static boolean equalsNumChar(Number x, Character y) {
- char ch = y.charValue();
- if (x instanceof Double)
- return x.doubleValue() == ch;
- if (x instanceof Float)
- return x.floatValue() == ch;
- if (x instanceof Long)
- return x.longValue() == ch;
- if (x instanceof ScalaNumber)
- return x.equals(y);
- if (typeCode(x) <= INT)
- return x.intValue() == ch;
-
- return x.equals(y);
+ private static boolean equalsNumChar(Number xn, Character yc) {
+ char ch = yc.charValue();
+ switch (eqTypeCode(xn)) {
+ case INT:
+ return xn.intValue() == ch;
+ case LONG:
+ return xn.longValue() == ch;
+ case FLOAT:
+ return xn.floatValue() == ch;
+ case DOUBLE:
+ return xn.doubleValue() == ch;
+ default:
+ return xn.equals(yc);
+ }
}
/** Hashcode algorithm is driven by the requirements imposed
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index a93ff61a41..6467751a1f 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -123,8 +123,9 @@ object ScalaRunTime {
/** Fast path equality method for inlining; used when -optimise is set.
*/
@inline def inlinedEquals(x: Object, y: Object): Boolean =
- if (x eq null) y eq null
- else if (x.isInstanceOf[Number] || x.isInstanceOf[Character]) BoxesRunTime.equals(x, y)
+ if (x eq y) true
+ else if (x eq null) false
+ else if (x.isInstanceOf[Number] || x.isInstanceOf[Character]) BoxesRunTime.equals2(x, y)
else x.equals(y)
def _equals(x: Product, y: Any): Boolean = y match {
diff --git a/test/files/pos/t2484.scala b/test/files/pos/t2484.scala
new file mode 100755
index 0000000000..6990c46099
--- /dev/null
+++ b/test/files/pos/t2484.scala
@@ -0,0 +1,17 @@
+class Admin extends javax.swing.JApplet {
+ val jScrollPane = new javax.swing.JScrollPane (null, 0, 0)
+ def bug2484: Unit = {
+ scala.concurrent.ops.spawn {jScrollPane.synchronized {
+ def someFunction () = {}
+ //scala.concurrent.ops.spawn {someFunction ()}
+ jScrollPane.addComponentListener (new java.awt.event.ComponentAdapter {override def componentShown (e: java.awt.event.ComponentEvent) = {
+ someFunction (); jScrollPane.removeComponentListener (this)}})
+ }}
+ }
+}
+// t2630.scala
+object Test {
+ def meh(xs: List[Any]) {
+ xs map { x => (new AnyRef {}) }
+ }
+}