8061955: asm.js idioms result in unnecessarily code emission
Reviewed-by: hannesw, jlaskey
This commit is contained in:
parent
4b4e46f1fb
commit
3dadb9d8e3
@ -208,6 +208,8 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
|||||||
private static final Type ITERATOR_TYPE = Type.typeFor(ITERATOR_CLASS);
|
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 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
|
/** Constant data & installation. The only reason the compiler keeps this is because it is assigned
|
||||||
* by reflection in class installation */
|
* by reflection in class installation */
|
||||||
private final Compiler compiler;
|
private final Compiler compiler;
|
||||||
@ -3817,7 +3819,12 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
|||||||
|
|
||||||
private void doSHR() {
|
private void doSHR() {
|
||||||
// TODO: make SHR optimistic
|
// 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) {
|
private void loadASSIGN_SUB(final BinaryNode binaryNode) {
|
||||||
@ -3879,8 +3886,18 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void loadBIT_OR(final BinaryNode binaryNode) {
|
private void loadBIT_OR(final BinaryNode binaryNode) {
|
||||||
loadBinaryOperands(binaryNode);
|
// Optimize x|0 to (int)x
|
||||||
method.or();
|
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) {
|
private void loadBIT_XOR(final BinaryNode binaryNode) {
|
||||||
@ -3957,8 +3974,14 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void loadSHR(final BinaryNode binaryNode) {
|
private void loadSHR(final BinaryNode binaryNode) {
|
||||||
loadBinaryOperands(binaryNode);
|
// Optimize x >>> 0 to (uint)x
|
||||||
doSHR();
|
if (isRhsZero(binaryNode)) {
|
||||||
|
loadExpressionAsType(binaryNode.lhs(), Type.INT);
|
||||||
|
toUint();
|
||||||
|
} else {
|
||||||
|
loadBinaryOperands(binaryNode);
|
||||||
|
doSHR();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) {
|
private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) {
|
||||||
|
@ -291,7 +291,7 @@ final class FoldConstants extends NodeVisitor<LexicalContext> implements Loggabl
|
|||||||
value = lhs.getNumber() - rhs.getNumber();
|
value = lhs.getNumber() - rhs.getNumber();
|
||||||
break;
|
break;
|
||||||
case SHR:
|
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:
|
case SAR:
|
||||||
return LiteralNode.newInstance(token, finish, lhs.getInt32() >> rhs.getInt32());
|
return LiteralNode.newInstance(token, finish, lhs.getInt32() >> rhs.getInt32());
|
||||||
case SHL:
|
case SHL:
|
||||||
|
@ -33,6 +33,7 @@ import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
|
|||||||
import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator;
|
import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator;
|
||||||
import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator;
|
import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator;
|
||||||
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
|
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.SwitchPoint;
|
import java.lang.invoke.SwitchPoint;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -269,7 +270,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getLength() {
|
public Object getLength() {
|
||||||
final long length = getArray().length() & JSType.MAX_UINT;
|
final long length = JSType.toUint32(getArray().length());
|
||||||
if(length < Integer.MAX_VALUE) {
|
if(length < Integer.MAX_VALUE) {
|
||||||
return (int)length;
|
return (int)length;
|
||||||
}
|
}
|
||||||
@ -479,7 +480,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
|
|||||||
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
|
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
|
||||||
public static Object length(final Object self) {
|
public static Object length(final Object self) {
|
||||||
if (isArray(self)) {
|
if (isArray(self)) {
|
||||||
return ((ScriptObject) self).getArray().length() & JSType.MAX_UINT;
|
return JSType.toUint32(((ScriptObject) self).getArray().length());
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -27,6 +27,7 @@ package jdk.nashorn.internal.objects;
|
|||||||
import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
|
import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
|
||||||
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
|
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
|
||||||
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
|
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import jdk.nashorn.internal.objects.annotations.Attribute;
|
import jdk.nashorn.internal.objects.annotations.Attribute;
|
||||||
@ -432,7 +433,7 @@ public class NativeDataView extends ScriptObject {
|
|||||||
@SpecializedFunction
|
@SpecializedFunction
|
||||||
public static long getUint32(final Object self, final int byteOffset) {
|
public static long getUint32(final Object self, final int byteOffset) {
|
||||||
try {
|
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) {
|
} catch (final IllegalArgumentException iae) {
|
||||||
throw rangeError(iae, "dataview.offset");
|
throw rangeError(iae, "dataview.offset");
|
||||||
}
|
}
|
||||||
@ -449,7 +450,7 @@ public class NativeDataView extends ScriptObject {
|
|||||||
@SpecializedFunction
|
@SpecializedFunction
|
||||||
public static long getUint32(final Object self, final int byteOffset, final boolean littleEndian) {
|
public static long getUint32(final Object self, final int byteOffset, final boolean littleEndian) {
|
||||||
try {
|
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) {
|
} catch (final IllegalArgumentException iae) {
|
||||||
throw rangeError(iae, "dataview.offset");
|
throw rangeError(iae, "dataview.offset");
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ public final class NativeRegExpExecResult extends ScriptObject {
|
|||||||
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
|
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
|
||||||
public static Object length(final Object self) {
|
public static Object length(final Object self) {
|
||||||
if (self instanceof ScriptObject) {
|
if (self instanceof ScriptObject) {
|
||||||
return ((ScriptObject)self).getArray().length() & JSType.MAX_UINT;
|
return JSType.toUint32(((ScriptObject)self).getArray().length());
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -105,7 +105,7 @@ public final class NativeUint32Array extends ArrayBufferView {
|
|||||||
|
|
||||||
private long getElem(final int index) {
|
private long getElem(final int index) {
|
||||||
try {
|
try {
|
||||||
return nb.get(index) & JSType.MAX_UINT;
|
return JSType.toUint32(nb.get(index));
|
||||||
} catch (final IndexOutOfBoundsException e) {
|
} catch (final IndexOutOfBoundsException e) {
|
||||||
throw new ClassCastException(); //force relink - this works for unoptimistic too
|
throw new ClassCastException(); //force relink - this works for unoptimistic too
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,9 @@ public enum JSType {
|
|||||||
/** JavaScript compliant conversion function from double to int32 */
|
/** 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);
|
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 */
|
/** JavaScript compliant conversion function from Object to uint32 */
|
||||||
public static final Call TO_UINT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, Object.class);
|
public static final Call TO_UINT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, Object.class);
|
||||||
|
|
||||||
@ -1000,6 +1003,16 @@ public enum JSType {
|
|||||||
return doubleToInt32(num) & MAX_UINT;
|
return doubleToInt32(num) & MAX_UINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* JavaScript compliant Object to uint16 conversion
|
||||||
* ECMA 9.7 ToUint16: (Unsigned 16 Bit Integer)
|
* ECMA 9.7 ToUint16: (Unsigned 16 Bit Integer)
|
||||||
|
@ -182,15 +182,15 @@ public final class ArrayIndex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an index to a long value. This basically amounts to ANDing it
|
* Convert an index to a long value. This basically amounts to converting it into a
|
||||||
* with {@link JSType#MAX_UINT}, as the maximum array index in JavaScript
|
* {@link JSType#toUint32(int)} uint32} as the maximum array index in JavaScript
|
||||||
* is 0xfffffffe
|
* is 0xfffffffe
|
||||||
*
|
*
|
||||||
* @param index index to convert to long form
|
* @param index index to convert to long form
|
||||||
* @return index as uint32 in a long
|
* @return index as uint32 in a long
|
||||||
*/
|
*/
|
||||||
public static long toLongIndex(final int index) {
|
public static long toLongIndex(final int index) {
|
||||||
return index & JSType.MAX_UINT;
|
return JSType.toUint32(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -201,7 +201,7 @@ public final class ArrayIndex {
|
|||||||
* @return index as string
|
* @return index as string
|
||||||
*/
|
*/
|
||||||
public static String toKey(final int index) {
|
public static String toKey(final int index) {
|
||||||
return Long.toString(index & JSType.MAX_UINT);
|
return Long.toString(JSType.toUint32(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user