Mercurial > people > rkennke > jdk9-shenandoah-final > nashorn
changeset 851:ca80b07bd06d
8043002: Improve performance of Nashorn equality operators
Reviewed-by: lagergren, sundar
author | attila |
---|---|
date | Tue, 13 May 2014 14:54:21 +0200 |
parents | c61d579dd5a8 |
children | fbca2b7761ae |
files | src/jdk/nashorn/internal/objects/NativeObject.java src/jdk/nashorn/internal/runtime/DebuggerSupport.java src/jdk/nashorn/internal/runtime/JSType.java src/jdk/nashorn/internal/runtime/ScriptRuntime.java |
diffstat | 4 files changed, 54 insertions(+), 34 deletions(-) [+] |
line wrap: on
line diff
--- a/src/jdk/nashorn/internal/objects/NativeObject.java Tue May 13 11:30:40 2014 +0200 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java Tue May 13 14:54:21 2014 +0200 @@ -38,7 +38,6 @@ import java.util.List; import java.util.Set; import java.util.concurrent.Callable; - import jdk.internal.dynalink.beans.BeansLinker; import jdk.internal.dynalink.beans.StaticClass; import jdk.internal.dynalink.linker.GuardedInvocation; @@ -418,7 +417,7 @@ */ @Constructor public static Object construct(final boolean newObj, final Object self, final Object value) { - final JSType type = JSType.of(value); + final JSType type = JSType.ofNoFunction(value); // Object(null), Object(undefined), Object() are same as "new Object()" @@ -429,7 +428,6 @@ case STRING: return Global.toObject(value); case OBJECT: - case FUNCTION: return value; case NULL: case UNDEFINED:
--- a/src/jdk/nashorn/internal/runtime/DebuggerSupport.java Tue May 13 11:30:40 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/DebuggerSupport.java Tue May 13 14:54:21 2014 +0200 @@ -183,7 +183,7 @@ for (long i = 0; i < length; i++) { if (object.has(i)) { final Object valueAsObject = object.get(i); - final boolean isUndefined = JSType.of(valueAsObject) == JSType.UNDEFINED; + final boolean isUndefined = valueAsObject == ScriptRuntime.UNDEFINED; if (isUndefined) { if (i != 0) {
--- a/src/jdk/nashorn/internal/runtime/JSType.java Tue May 13 11:30:40 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Tue May 13 14:54:21 2014 +0200 @@ -310,6 +310,44 @@ } /** + * Similar to {@link #of(Object)}, but does not distinguish between {@link #FUNCTION} and {@link #OBJECT}, returning + * {@link #OBJECT} in both cases. The distinction is costly, and the EQ and STRICT_EQ predicates don't care about it + * so we maintain this version for their use. + * + * @param obj an object + * + * @return the JSType for the object; returns {@link #OBJECT} instead of {@link #FUNCTION} for functions. + */ + public static JSType ofNoFunction(final Object obj) { + // Order of these statements is tuned for performance (see JDK-8024476) + if (obj == null) { + return JSType.NULL; + } + + if (obj instanceof ScriptObject) { + return JSType.OBJECT; + } + + if (obj instanceof Boolean) { + return JSType.BOOLEAN; + } + + if (obj instanceof String || obj instanceof ConsString) { + return JSType.STRING; + } + + if (obj instanceof Number) { + return JSType.NUMBER; + } + + if (obj == ScriptRuntime.UNDEFINED) { + return JSType.UNDEFINED; + } + + return JSType.OBJECT; + } + + /** * Void return method handle glue */ public static void voidReturn() {
--- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Tue May 13 11:30:40 2014 +0200 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Tue May 13 14:54:21 2014 +0200 @@ -42,7 +42,6 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; - import jdk.internal.dynalink.beans.StaticClass; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.api.scripting.ScriptObjectMirror; @@ -167,7 +166,7 @@ // But we don't need to -- all we need is the right class name // of the corresponding primitive wrapper type. - final JSType type = JSType.of(self); + final JSType type = JSType.ofNoFunction(self); switch (type) { case BOOLEAN: @@ -187,7 +186,6 @@ className = "Undefined"; break; case OBJECT: - case FUNCTION: if (self instanceof ScriptObject) { className = ((ScriptObject)self).getClassName(); } else if (self instanceof JSObject) { @@ -407,8 +405,8 @@ * @return true if both objects have the same value */ public static boolean sameValue(final Object x, final Object y) { - final JSType xType = JSType.of(x); - final JSType yType = JSType.of(y); + final JSType xType = JSType.ofNoFunction(x); + final JSType yType = JSType.ofNoFunction(y); if (xType != yType) { return false; @@ -681,8 +679,8 @@ /** ECMA 11.9.3 The Abstract Equality Comparison Algorithm */ private static boolean equals(final Object x, final Object y) { - final JSType xType = JSType.of(x); - final JSType yType = JSType.of(y); + final JSType xType = JSType.ofNoFunction(x); + final JSType yType = JSType.ofNoFunction(y); if (xType == yType) { @@ -691,13 +689,7 @@ } if (xType == JSType.NUMBER) { - final double xVal = ((Number)x).doubleValue(); - final double yVal = ((Number)y).doubleValue(); - if (Double.isNaN(xVal) || Double.isNaN(yVal)) { - return false; - } - - return xVal == yVal; + return ((Number)x).doubleValue() == ((Number)y).doubleValue(); } if (xType == JSType.STRING) { @@ -706,8 +698,7 @@ } if (xType == JSType.BOOLEAN) { - // Boolean comparison - return x.equals(y); + return ((Boolean)x).booleanValue() == ((Boolean)y).booleanValue(); } return x == y; @@ -773,8 +764,8 @@ /** ECMA 11.9.6 The Strict Equality Comparison Algorithm */ private static boolean strictEquals(final Object x, final Object y) { - final JSType xType = JSType.of(x); - final JSType yType = JSType.of(y); + final JSType xType = JSType.ofNoFunction(x); + final JSType yType = JSType.ofNoFunction(y); if (xType != yType) { return false; @@ -785,14 +776,7 @@ } if (xType == JSType.NUMBER) { - final double xVal = ((Number)x).doubleValue(); - final double yVal = ((Number)y).doubleValue(); - - if (Double.isNaN(xVal) || Double.isNaN(yVal)) { - return false; - } - - return xVal == yVal; + return ((Number)x).doubleValue() == ((Number)y).doubleValue(); } if (xType == JSType.STRING) { @@ -801,7 +785,7 @@ } if (xType == JSType.BOOLEAN) { - return x.equals(y); + return ((Boolean)x).booleanValue() == ((Boolean)y).booleanValue(); } // finally, the object identity comparison @@ -817,9 +801,9 @@ * @return true if objects are equal */ public static boolean IN(final Object property, final Object obj) { - final JSType rvalType = JSType.of(obj); + final JSType rvalType = JSType.ofNoFunction(obj); - if (rvalType == JSType.OBJECT || rvalType == JSType.FUNCTION) { + if (rvalType == JSType.OBJECT) { if (obj instanceof ScriptObject) { return ((ScriptObject)obj).has(property); } @@ -931,7 +915,7 @@ px = JSType.toPrimitive(x, Number.class); } - if (JSType.of(px) == JSType.STRING && JSType.of(py) == JSType.STRING) { + if (JSType.ofNoFunction(px) == JSType.STRING && JSType.ofNoFunction(py) == JSType.STRING) { // May be String or ConsString return px.toString().compareTo(py.toString()) < 0; }