Adds optimal codepath for common long/int conversions
PiperOrigin-RevId: 361296709
Change-Id: I903483d469dcaab3ca9488d9ef76a25c2c7967da
diff --git a/user/super/com/google/gwt/emul/java/lang/Long.java b/user/super/com/google/gwt/emul/java/lang/Long.java
index b4e8c9b..1c95242 100644
--- a/user/super/com/google/gwt/emul/java/lang/Long.java
+++ b/user/super/com/google/gwt/emul/java/lang/Long.java
@@ -15,6 +15,8 @@
*/
package java.lang;
+import javaemul.internal.LongUtils;
+
/** Wraps a primitive <code>long</code> as an object. */
public final class Long extends Number implements Comparable<Long> {
@@ -30,9 +32,9 @@
public static final int BYTES = SIZE / Byte.SIZE;
public static final Class<Long> TYPE = long.class;
- public static int bitCount(long i) {
- int high = (int) (i >> 32);
- int low = (int) i;
+ public static int bitCount(long l) {
+ int high = LongUtils.getHighBits(l);
+ int low = (int) l;
return Integer.bitCount(high) + Integer.bitCount(low);
}
@@ -52,17 +54,15 @@
}
public static int hashCode(long l) {
- int high = (int) (l >>> 32);
- int low = (int) l;
- return high ^ low;
+ return LongUtils.getHighBits(l) ^ (int) l;
}
- public static long highestOneBit(long i) {
- int high = (int) (i >> 32);
+ public static long highestOneBit(long l) {
+ int high = LongUtils.getHighBits(l);
if (high != 0) {
- return ((long) Integer.highestOneBit(high)) << 32;
+ return LongUtils.fromBits(0, Integer.highestOneBit(high));
} else {
- return Integer.highestOneBit((int) i) & 0xFFFFFFFFL;
+ return LongUtils.fromBits(Integer.highestOneBit((int) l), 0);
}
}
@@ -78,21 +78,21 @@
return Math.min(a, b);
}
- public static int numberOfLeadingZeros(long i) {
- int high = (int) (i >> 32);
+ public static int numberOfLeadingZeros(long l) {
+ int high = LongUtils.getHighBits(l);
if (high != 0) {
return Integer.numberOfLeadingZeros(high);
} else {
- return Integer.numberOfLeadingZeros((int) i) + 32;
+ return Integer.numberOfLeadingZeros((int) l) + 32;
}
}
- public static int numberOfTrailingZeros(long i) {
- int low = (int) i;
+ public static int numberOfTrailingZeros(long l) {
+ int low = (int) l;
if (low != 0) {
return Integer.numberOfTrailingZeros(low);
} else {
- return Integer.numberOfTrailingZeros((int) (i >> 32)) + 32;
+ return Integer.numberOfTrailingZeros(LongUtils.getHighBits(l)) + 32;
}
}
@@ -104,16 +104,16 @@
return __parseAndValidateLong(s, radix);
}
- public static long reverse(long i) {
- int high = (int) (i >>> 32);
- int low = (int) i;
- return ((long) Integer.reverse(low) << 32) | (Integer.reverse(high) & 0xffffffffL);
+ public static long reverse(long l) {
+ int high = LongUtils.getHighBits(l);
+ int low = (int) l;
+ return LongUtils.fromBits(Integer.reverse(high), Integer.reverse(low));
}
- public static long reverseBytes(long i) {
- int high = (int) (i >>> 32);
- int low = (int) i;
- return ((long) Integer.reverseBytes(low) << 32) | (Integer.reverseBytes(high) & 0xffffffffL);
+ public static long reverseBytes(long l) {
+ int high = LongUtils.getHighBits(l);
+ int low = (int) l;
+ return LongUtils.fromBits(Integer.reverseBytes(high), Integer.reverseBytes(low));
}
public static long rotateLeft(long i, int distance) {
diff --git a/user/super/com/google/gwt/emul/java/math/BigInteger.java b/user/super/com/google/gwt/emul/java/math/BigInteger.java
index c3b4660..4f27600 100644
--- a/user/super/com/google/gwt/emul/java/math/BigInteger.java
+++ b/user/super/com/google/gwt/emul/java/math/BigInteger.java
@@ -39,6 +39,7 @@
import java.io.Serializable;
import java.util.Random;
+import javaemul.internal.LongUtils;
/**
* This class represents immutable integer numbers of arbitrary length. Large
@@ -488,7 +489,7 @@
BigInteger(int sign, long val) {
// PRE: (val >= 0) && (sign >= -1) && (sign <= 1)
this.sign = sign;
- if ((val & 0xFFFFFFFF00000000L) == 0) {
+ if (LongUtils.getHighBits(val) == 0) {
// It fits in one 'int'
numberLength = 1;
digits = new int[] {(int) val};
@@ -952,9 +953,11 @@
*/
@Override
public long longValue() {
- long value = (numberLength > 1) ? (((long) digits[1]) << 32)
- | (digits[0] & 0xFFFFFFFFL) : (digits[0] & 0xFFFFFFFFL);
- return (sign * value);
+ long value =
+ numberLength > 1
+ ? LongUtils.fromBits(digits[0], digits[1])
+ : LongUtils.fromBits(digits[0], 0);
+ return sign > 0 ? value : -value;
}
/**
diff --git a/user/super/com/google/gwt/emul/java/util/BitSet.java b/user/super/com/google/gwt/emul/java/util/BitSet.java
index 56d0e77..ea8a087 100644
--- a/user/super/com/google/gwt/emul/java/util/BitSet.java
+++ b/user/super/com/google/gwt/emul/java/util/BitSet.java
@@ -19,6 +19,7 @@
import static javaemul.internal.InternalPreconditions.checkArraySize;
import javaemul.internal.ArrayHelper;
+import javaemul.internal.LongUtils;
/**
* This implementation uses a dense array holding bit groups of size 31 to keep track of when bits
@@ -815,7 +816,7 @@
private static long getLong(int[] words, int bitIndex) {
int low = getInt(words, bitIndex);
int high = getInt(words, bitIndex + 32);
- return ((long) high << 32) | (low & 0xffff_ffffL);
+ return LongUtils.fromBits(low, high);
}
public static BitSet valueOf(byte[] words) {
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
index 21bf263..160102c 100644
--- a/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
+++ b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
@@ -124,16 +124,14 @@
ArrayBuffer buf = new ArrayBuffer(8);
JsUtils.<double[]>uncheckedCast(new Float64Array(buf))[0] = value;
int[] intBits = JsUtils.<int[]>uncheckedCast(new Uint32Array(buf));
- long highBits = ((long) (intBits[1] | 0)) << 32;
- long lowBits = (intBits[0] | 0) & 0x00000000ffffffffL;
- return highBits | lowBits;
+ return LongUtils.fromBits(intBits[0] | 0, intBits[1] | 0);
}
public static double longBitsToDouble(long value) {
ArrayBuffer buf = new ArrayBuffer(8);
int[] intBits = JsUtils.<int[]>uncheckedCast(new Uint32Array(buf));
intBits[0] = (int) value;
- intBits[1] = (int) (value >>> 32);
+ intBits[1] = LongUtils.getHighBits(value);
return JsUtils.<double[]>uncheckedCast(new Float64Array(buf))[0];
}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/LongUtils.java b/user/super/com/google/gwt/emul/javaemul/internal/LongUtils.java
new file mode 100644
index 0000000..a85ac4c
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/LongUtils.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package javaemul.internal;
+
+/** Defines utility static functions for long */
+public final class LongUtils {
+
+ public static long fromBits(int lowBits, int highBits) {
+ long lowBitsLong = lowBits & 0x00000000ffffffffL;
+ long highBitsLong = (long) highBits << 32;
+ return highBitsLong | lowBitsLong;
+ }
+
+ public static int getHighBits(long value) {
+ return (int) (value >>> 32);
+ }
+
+ private LongUtils() {}
+}