From 47ff60552398b09a8b757345cd56f12091d97b92 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 9 Nov 2009 10:35:54 +0000 Subject: fast path equals and hash methods. --- src/library/scala/Predef.scala | 5 +++ src/library/scala/runtime/BoxesRunTime.java | 56 +++++++++++++++++++--------- src/library/scala/runtime/ScalaRunTime.scala | 7 ++++ 3 files changed, 51 insertions(+), 17 deletions(-) (limited to 'src/library') diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index cab32b0595..c3f6ad9eff 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -91,6 +91,11 @@ object Predef extends LowPriorityImplicits { def currentThread = java.lang.Thread.currentThread() + // hashcode and equality ------------------------------------------------- + + @inline def hash(x: Any): Int = + if (x.isInstanceOf[Number]) (x.asInstanceOf[Number]).intValue else x.hashCode + // errors and asserts ------------------------------------------------- def error(message: String): Nothing = throw new RuntimeException(message) diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java index 3e75cb213e..b5df9d8ce8 100644 --- a/src/library/scala/runtime/BoxesRunTime.java +++ b/src/library/scala/runtime/BoxesRunTime.java @@ -139,6 +139,45 @@ public class BoxesRunTime /* COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON */ + // That's the method we should use from now on. + public static boolean equals(Object x, Object y) { + if (x instanceof Number) { + Number xn = (Number)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(); + return xn.intValue() == yn.intValue(); + } + if (y instanceof Character) + return equalsNumChar(xn, (Character)y); + } else if (x instanceof Character) { + Character xc = (Character)x; + if (y instanceof Character) + 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; + return x.intValue() == ch; + } + private static boolean equalsBonusLogicFromScala27(Object a, Object b) { if (a instanceof Number || a instanceof Character || b instanceof Number || b instanceof Character) { int acode = typeCode(a); @@ -188,23 +227,6 @@ public class BoxesRunTime } } - /** The current equals method. **/ - public static boolean equals(Object a, Object b) { - if (a == null || b == null) - return a == b; - - verifyEqEq(a, b, - (Equality.dieOnBoxedCompare || Equality.dieOnBoxedCompareIfValuesAreEqual), - (Equality.warnOnBoxedCompareIfValuesAreEqual || Equality.dieOnBoxedCompareIfValuesAreEqual) - ); - - if (a.equals(b)) - return true; - - if (Equality.use28Semantics) return false; - else return equalsBonusLogicFromScala27(a, b); - } - /* OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS */ /** arg1 + arg2 */ diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala index 4541c0147c..a93ff61a41 100644 --- a/src/library/scala/runtime/ScalaRunTime.scala +++ b/src/library/scala/runtime/ScalaRunTime.scala @@ -120,6 +120,13 @@ object ScalaRunTime { code } + /** 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) + else x.equals(y) + def _equals(x: Product, y: Any): Boolean = y match { case y1: Product if x.productArity == y1.productArity => val arity = x.productArity -- cgit v1.2.3