changeset 1067:094f0d95ef78

8061955: asm.js idioms result in unnecessarily code emission Reviewed-by: hannesw, jlaskey
author attila
date Fri, 24 Oct 2014 13:25:23 +0200
parents 375a3a3256d0
children 78eb2b415108
files src/jdk/nashorn/internal/codegen/CodeGenerator.java src/jdk/nashorn/internal/codegen/FoldConstants.java src/jdk/nashorn/internal/objects/NativeArray.java src/jdk/nashorn/internal/objects/NativeDataView.java src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java src/jdk/nashorn/internal/objects/NativeUint32Array.java src/jdk/nashorn/internal/runtime/JSType.java src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java
diffstat 8 files changed, 54 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Oct 23 18:07:16 2014 +0200
+++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Fri Oct 24 13:25:23 2014 +0200
@@ -208,6 +208,8 @@
     private static final Type ITERATOR_TYPE = Type.typeFor(ITERATOR_CLASS);
     private static final Type EXCEPTION_TYPE = Type.typeFor(CompilerConstants.EXCEPTION_PREFIX.type());
 
+    private static final Integer INT_ZERO = Integer.valueOf(0);
+
     /** Constant data & installation. The only reason the compiler keeps this is because it is assigned
      *  by reflection in class installation */
     private final Compiler compiler;
@@ -3817,7 +3819,12 @@
 
     private void doSHR() {
         // TODO: make SHR optimistic
-        method.shr().convert(Type.LONG).load(JSType.MAX_UINT).and();
+        method.shr();
+        toUint();
+    }
+
+    private void toUint() {
+        JSType.TO_UINT32_I.invoke(method);
     }
 
     private void loadASSIGN_SUB(final BinaryNode binaryNode) {
@@ -3879,8 +3886,18 @@
     }
 
     private void loadBIT_OR(final BinaryNode binaryNode) {
-        loadBinaryOperands(binaryNode);
-        method.or();
+        // Optimize x|0 to (int)x
+        if (isRhsZero(binaryNode)) {
+            loadExpressionAsType(binaryNode.lhs(), Type.INT);
+        } else {
+            loadBinaryOperands(binaryNode);
+            method.or();
+        }
+    }
+
+    private static boolean isRhsZero(final BinaryNode binaryNode) {
+        final Expression rhs = binaryNode.rhs();
+        return rhs instanceof LiteralNode && INT_ZERO.equals(((LiteralNode)rhs).getValue());
     }
 
     private void loadBIT_XOR(final BinaryNode binaryNode) {
@@ -3957,8 +3974,14 @@
     }
 
     private void loadSHR(final BinaryNode binaryNode) {
-        loadBinaryOperands(binaryNode);
-        doSHR();
+        // Optimize x >>> 0 to (uint)x
+        if (isRhsZero(binaryNode)) {
+            loadExpressionAsType(binaryNode.lhs(), Type.INT);
+            toUint();
+        } else {
+            loadBinaryOperands(binaryNode);
+            doSHR();
+        }
     }
 
     private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) {
--- a/src/jdk/nashorn/internal/codegen/FoldConstants.java	Thu Oct 23 18:07:16 2014 +0200
+++ b/src/jdk/nashorn/internal/codegen/FoldConstants.java	Fri Oct 24 13:25:23 2014 +0200
@@ -291,7 +291,7 @@
                 value = lhs.getNumber() - rhs.getNumber();
                 break;
             case SHR:
-                return LiteralNode.newInstance(token, finish, (lhs.getInt32() >>> rhs.getInt32()) & JSType.MAX_UINT);
+                return LiteralNode.newInstance(token, finish, JSType.toUint32(lhs.getInt32() >>> rhs.getInt32()));
             case SAR:
                 return LiteralNode.newInstance(token, finish, lhs.getInt32() >> rhs.getInt32());
             case SHL:
--- a/src/jdk/nashorn/internal/objects/NativeArray.java	Thu Oct 23 18:07:16 2014 +0200
+++ b/src/jdk/nashorn/internal/objects/NativeArray.java	Fri Oct 24 13:25:23 2014 +0200
@@ -33,6 +33,7 @@
 import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator;
 import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator;
 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
+
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.SwitchPoint;
 import java.util.ArrayList;
@@ -266,7 +267,7 @@
 
     @Override
     public Object getLength() {
-        final long length = getArray().length() & JSType.MAX_UINT;
+        final long length = JSType.toUint32(getArray().length());
         if(length < Integer.MAX_VALUE) {
             return (int)length;
         }
@@ -476,7 +477,7 @@
     @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
     public static Object length(final Object self) {
         if (isArray(self)) {
-            return ((ScriptObject) self).getArray().length() & JSType.MAX_UINT;
+            return JSType.toUint32(((ScriptObject) self).getArray().length());
         }
 
         return 0;
--- a/src/jdk/nashorn/internal/objects/NativeDataView.java	Thu Oct 23 18:07:16 2014 +0200
+++ b/src/jdk/nashorn/internal/objects/NativeDataView.java	Fri Oct 24 13:25:23 2014 +0200
@@ -27,6 +27,7 @@
 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import jdk.nashorn.internal.objects.annotations.Attribute;
@@ -432,7 +433,7 @@
     @SpecializedFunction
     public static long getUint32(final Object self, final int byteOffset) {
         try {
-            return JSType.MAX_UINT & getBuffer(self, false).getInt(JSType.toInt32(byteOffset));
+            return JSType.toUint32(getBuffer(self, false).getInt(JSType.toInt32(byteOffset)));
         } catch (final IllegalArgumentException iae) {
             throw rangeError(iae, "dataview.offset");
         }
@@ -449,7 +450,7 @@
     @SpecializedFunction
     public static long getUint32(final Object self, final int byteOffset, final boolean littleEndian) {
         try {
-            return JSType.MAX_UINT & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset));
+            return JSType.toUint32(getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)));
         } catch (final IllegalArgumentException iae) {
             throw rangeError(iae, "dataview.offset");
         }
--- a/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java	Thu Oct 23 18:07:16 2014 +0200
+++ b/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java	Fri Oct 24 13:25:23 2014 +0200
@@ -74,7 +74,7 @@
     @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
     public static Object length(final Object self) {
         if (self instanceof ScriptObject) {
-            return ((ScriptObject)self).getArray().length() & JSType.MAX_UINT;
+            return JSType.toUint32(((ScriptObject)self).getArray().length());
         }
 
         return 0;
--- a/src/jdk/nashorn/internal/objects/NativeUint32Array.java	Thu Oct 23 18:07:16 2014 +0200
+++ b/src/jdk/nashorn/internal/objects/NativeUint32Array.java	Fri Oct 24 13:25:23 2014 +0200
@@ -105,7 +105,7 @@
 
         private long getElem(final int index) {
             try {
-                return nb.get(index) & JSType.MAX_UINT;
+                return JSType.toUint32(nb.get(index));
             } catch (final IndexOutOfBoundsException e) {
                 throw new ClassCastException(); //force relink - this works for unoptimistic too
             }
--- a/src/jdk/nashorn/internal/runtime/JSType.java	Thu Oct 23 18:07:16 2014 +0200
+++ b/src/jdk/nashorn/internal/runtime/JSType.java	Fri Oct 24 13:25:23 2014 +0200
@@ -115,6 +115,9 @@
     /** JavaScript compliant conversion function from double to int32 */
     public static final Call TO_INT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, double.class);
 
+    /** JavaScript compliant conversion function from int to uint32 */
+    public static final Call TO_UINT32_I = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, int.class);
+
     /** JavaScript compliant conversion function from Object to uint32 */
     public static final Call TO_UINT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, Object.class);
 
@@ -1002,6 +1005,16 @@
     }
 
     /**
+     * JavaScript compliant int to uint32 conversion
+     *
+     * @param num an int
+     * @return a uint32
+     */
+    public static long toUint32(final int num) {
+        return num & MAX_UINT;
+    }
+
+    /**
      * JavaScript compliant Object to uint16 conversion
      * ECMA 9.7 ToUint16: (Unsigned 16 Bit Integer)
      *
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java	Thu Oct 23 18:07:16 2014 +0200
+++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java	Fri Oct 24 13:25:23 2014 +0200
@@ -182,15 +182,15 @@
     }
 
     /**
-     * Convert an index to a long value. This basically amounts to ANDing it
-     * with {@link JSType#MAX_UINT}, as the maximum array index in JavaScript
+     * Convert an index to a long value. This basically amounts to converting it into a
+     * {@link JSType#toUint32(int)} uint32} as the maximum array index in JavaScript
      * is 0xfffffffe
      *
      * @param index index to convert to long form
      * @return index as uint32 in a long
      */
     public static long toLongIndex(final int index) {
-        return index & JSType.MAX_UINT;
+        return JSType.toUint32(index);
     }
 
     /**
@@ -201,7 +201,7 @@
      * @return index as string
      */
     public static String toKey(final int index) {
-        return Long.toString(index & JSType.MAX_UINT);
+        return Long.toString(JSType.toUint32(index));
     }
 
 }