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() {} +}