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