Add backporting more Java 9 methods

  Long.parseUnsignedLong(CharSequence s, int beginIndex, int endIndex, int radix)
  Long.parseLong(CharSequence s, int beginIndex, int endIndex, int radix)
  Integer.parseInt(CharSequence s, int beginIndex, int endIndex, int radix)

Bug: 181533278
Change-Id: Id4f6a55fabef9385eed220a21788e0d96790679c
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index bd5c0b3..7d07a7d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -194,6 +194,7 @@
       }
 
       // These are currently not implemented at any API level in Android.
+      initializeJava9MethodProviders(factory);
       initializeJava10MethodProviders(factory);
       initializeJava11MethodProviders(factory);
     }
@@ -1043,6 +1044,60 @@
       }
     }
 
+    private void initializeJava9MethodProviders(DexItemFactory factory) {
+      // Integer
+      DexType type = factory.boxedIntType;
+      // long Long.parseLong(CharSequence s, int beginIndex, int endIndex, int radix)
+      DexString name = factory.createString("parseInt");
+      DexProto proto =
+          factory.createProto(
+              factory.intType,
+              factory.charSequenceType,
+              factory.intType,
+              factory.intType,
+              factory.intType);
+      DexMethod method = factory.createMethod(type, proto, name);
+      addProvider(
+          new MethodGenerator(
+              method,
+              BackportedMethods::IntegerMethods_parseIntSubsequenceWithRadix,
+              "parseIntSubsequenceWithRadix"));
+
+      // Long
+      type = factory.boxedLongType;
+      // long Long.parseLong(CharSequence s, int beginIndex, int endIndex, int radix)
+      name = factory.createString("parseLong");
+      proto =
+          factory.createProto(
+              factory.longType,
+              factory.charSequenceType,
+              factory.intType,
+              factory.intType,
+              factory.intType);
+      method = factory.createMethod(type, proto, name);
+      addProvider(
+          new MethodGenerator(
+              method,
+              BackportedMethods::LongMethods_parseLongSubsequenceWithRadix,
+              "parseLongSubsequenceWithRadix"));
+
+      // long Long.parseUnsignedLong(CharSequence s, int beginIndex, int endIndex, int radix)
+      name = factory.createString("parseUnsignedLong");
+      proto =
+          factory.createProto(
+              factory.longType,
+              factory.charSequenceType,
+              factory.intType,
+              factory.intType,
+              factory.intType);
+      method = factory.createMethod(type, proto, name);
+      addProvider(
+          new MethodGenerator(
+              method,
+              BackportedMethods::LongMethods_parseUnsignedLongSubsequenceWithRadix,
+              "parseUnsignedLongSubsequenceWithRadix"));
+    }
+
     private void initializeJava10MethodProviders(DexItemFactory factory) {
       // List
       DexType type = factory.listType;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
index da56b69..b7b0db0 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
@@ -2115,6 +2115,53 @@
         ImmutableList.of());
   }
 
+  public static CfCode IntegerMethods_parseIntSubsequenceWithRadix(
+      InternalOptions options, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        3,
+        4,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.INT, 1),
+            new CfLoad(ValueType.INT, 2),
+            new CfInvoke(
+                185,
+                options.itemFactory.createMethod(
+                    options.itemFactory.charSequenceType,
+                    options.itemFactory.createProto(
+                        options.itemFactory.charSequenceType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType),
+                    options.itemFactory.createString("subSequence")),
+                true),
+            new CfInvoke(
+                185,
+                options.itemFactory.createMethod(
+                    options.itemFactory.charSequenceType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
+                    options.itemFactory.createString("toString")),
+                true),
+            new CfLoad(ValueType.INT, 3),
+            new CfInvoke(
+                184,
+                options.itemFactory.createMethod(
+                    options.itemFactory.createType("Ljava/lang/Integer;"),
+                    options.itemFactory.createProto(
+                        options.itemFactory.intType,
+                        options.itemFactory.stringType,
+                        options.itemFactory.intType),
+                    options.itemFactory.createString("parseInt")),
+                false),
+            new CfReturn(ValueType.INT),
+            label1),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
   public static CfCode IntegerMethods_parseUnsignedInt(InternalOptions options, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
@@ -2643,6 +2690,53 @@
         ImmutableList.of());
   }
 
+  public static CfCode LongMethods_parseLongSubsequenceWithRadix(
+      InternalOptions options, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        3,
+        4,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.INT, 1),
+            new CfLoad(ValueType.INT, 2),
+            new CfInvoke(
+                185,
+                options.itemFactory.createMethod(
+                    options.itemFactory.charSequenceType,
+                    options.itemFactory.createProto(
+                        options.itemFactory.charSequenceType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType),
+                    options.itemFactory.createString("subSequence")),
+                true),
+            new CfInvoke(
+                185,
+                options.itemFactory.createMethod(
+                    options.itemFactory.charSequenceType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
+                    options.itemFactory.createString("toString")),
+                true),
+            new CfLoad(ValueType.INT, 3),
+            new CfInvoke(
+                184,
+                options.itemFactory.createMethod(
+                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createProto(
+                        options.itemFactory.longType,
+                        options.itemFactory.stringType,
+                        options.itemFactory.intType),
+                    options.itemFactory.createString("parseLong")),
+                false),
+            new CfReturn(ValueType.LONG),
+            label1),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
   public static CfCode LongMethods_parseUnsignedLong(InternalOptions options, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
@@ -2670,7 +2764,7 @@
         ImmutableList.of());
   }
 
-  public static CfCode LongMethods_parseUnsignedLongWithRadix(
+  public static CfCode LongMethods_parseUnsignedLongSubsequenceWithRadix(
       InternalOptions options, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
@@ -2697,20 +2791,15 @@
     return new CfCode(
         method.holder,
         5,
-        10,
+        12,
         ImmutableList.of(
             label0,
-            new CfLoad(ValueType.OBJECT, 0),
-            new CfInvoke(
-                182,
-                options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
-                    options.itemFactory.createProto(options.itemFactory.intType),
-                    options.itemFactory.createString("length")),
-                false),
-            new CfStore(ValueType.INT, 2),
-            label1,
             new CfLoad(ValueType.INT, 2),
+            new CfLoad(ValueType.INT, 1),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
+            new CfStore(ValueType.INT, 4),
+            label1,
+            new CfLoad(ValueType.INT, 4),
             new CfIf(If.Type.NE, ValueType.INT, label3),
             label2,
             new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
@@ -2728,25 +2817,29 @@
             label3,
             new CfFrame(
                 new Int2ReferenceAVLTreeMap<>(
-                    new int[] {0, 1, 2},
+                    new int[] {0, 1, 2, 3, 4},
                     new FrameType[] {
-                      FrameType.initialized(options.itemFactory.stringType),
+                      FrameType.initialized(options.itemFactory.charSequenceType),
+                      FrameType.initialized(options.itemFactory.intType),
+                      FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType)
                     }),
                 new ArrayDeque<>(Arrays.asList())),
-            new CfLoad(ValueType.INT, 1),
+            new CfLoad(ValueType.INT, 3),
             new CfConstNumber(2, ValueType.INT),
             new CfIfCmp(If.Type.LT, ValueType.INT, label4),
-            new CfLoad(ValueType.INT, 1),
+            new CfLoad(ValueType.INT, 3),
             new CfConstNumber(36, ValueType.INT),
             new CfIfCmp(If.Type.LE, ValueType.INT, label5),
             label4,
             new CfFrame(
                 new Int2ReferenceAVLTreeMap<>(
-                    new int[] {0, 1, 2},
+                    new int[] {0, 1, 2, 3, 4},
                     new FrameType[] {
-                      FrameType.initialized(options.itemFactory.stringType),
+                      FrameType.initialized(options.itemFactory.charSequenceType),
+                      FrameType.initialized(options.itemFactory.intType),
+                      FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType)
                     }),
@@ -2754,7 +2847,7 @@
             new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfConstString(options.itemFactory.createString("illegal radix: ")),
-            new CfLoad(ValueType.INT, 1),
+            new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
@@ -2783,15 +2876,17 @@
             label5,
             new CfFrame(
                 new Int2ReferenceAVLTreeMap<>(
-                    new int[] {0, 1, 2},
+                    new int[] {0, 1, 2, 3, 4},
                     new FrameType[] {
-                      FrameType.initialized(options.itemFactory.stringType),
+                      FrameType.initialized(options.itemFactory.charSequenceType),
+                      FrameType.initialized(options.itemFactory.intType),
+                      FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType)
                     }),
                 new ArrayDeque<>(Arrays.asList())),
             new CfConstNumber(-1, ValueType.LONG),
-            new CfLoad(ValueType.INT, 1),
+            new CfLoad(ValueType.INT, 3),
             new CfNumberConversion(NumericType.INT, NumericType.LONG),
             new CfInvoke(
                 184,
@@ -2803,62 +2898,70 @@
                         options.itemFactory.longType),
                     options.itemFactory.createString("divideUnsigned")),
                 false),
-            new CfStore(ValueType.LONG, 3),
+            new CfStore(ValueType.LONG, 5),
             label6,
             new CfLoad(ValueType.OBJECT, 0),
-            new CfConstNumber(0, ValueType.INT),
+            new CfLoad(ValueType.INT, 1),
             new CfInvoke(
-                182,
+                185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
+                    options.itemFactory.charSequenceType,
                     options.itemFactory.createProto(
                         options.itemFactory.charType, options.itemFactory.intType),
                     options.itemFactory.createString("charAt")),
-                false),
+                true),
             new CfConstNumber(43, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label7),
-            new CfLoad(ValueType.INT, 2),
+            new CfLoad(ValueType.INT, 4),
             new CfConstNumber(1, ValueType.INT),
             new CfIfCmp(If.Type.LE, ValueType.INT, label7),
+            new CfLoad(ValueType.INT, 1),
             new CfConstNumber(1, ValueType.INT),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
             new CfGoto(label8),
             label7,
             new CfFrame(
                 new Int2ReferenceAVLTreeMap<>(
-                    new int[] {0, 1, 2, 3},
+                    new int[] {0, 1, 2, 3, 4, 5},
                     new FrameType[] {
-                      FrameType.initialized(options.itemFactory.stringType),
+                      FrameType.initialized(options.itemFactory.charSequenceType),
+                      FrameType.initialized(options.itemFactory.intType),
+                      FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.longType)
                     }),
                 new ArrayDeque<>(Arrays.asList())),
-            new CfConstNumber(0, ValueType.INT),
+            new CfLoad(ValueType.INT, 1),
             label8,
             new CfFrame(
                 new Int2ReferenceAVLTreeMap<>(
-                    new int[] {0, 1, 2, 3},
+                    new int[] {0, 1, 2, 3, 4, 5},
                     new FrameType[] {
-                      FrameType.initialized(options.itemFactory.stringType),
+                      FrameType.initialized(options.itemFactory.charSequenceType),
+                      FrameType.initialized(options.itemFactory.intType),
+                      FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.longType)
                     }),
                 new ArrayDeque<>(
                     Arrays.asList(FrameType.initialized(options.itemFactory.intType)))),
-            new CfStore(ValueType.INT, 5),
+            new CfStore(ValueType.INT, 7),
             label9,
             new CfConstNumber(0, ValueType.LONG),
-            new CfStore(ValueType.LONG, 6),
+            new CfStore(ValueType.LONG, 8),
             label10,
-            new CfLoad(ValueType.INT, 5),
-            new CfStore(ValueType.INT, 8),
+            new CfLoad(ValueType.INT, 7),
+            new CfStore(ValueType.INT, 10),
             label11,
             new CfFrame(
                 new Int2ReferenceAVLTreeMap<>(
-                    new int[] {0, 1, 2, 3, 5, 6, 8},
+                    new int[] {0, 1, 2, 3, 4, 5, 7, 8, 10},
                     new FrameType[] {
-                      FrameType.initialized(options.itemFactory.stringType),
+                      FrameType.initialized(options.itemFactory.charSequenceType),
+                      FrameType.initialized(options.itemFactory.intType),
+                      FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.longType),
@@ -2867,21 +2970,21 @@
                       FrameType.initialized(options.itemFactory.intType)
                     }),
                 new ArrayDeque<>(Arrays.asList())),
-            new CfLoad(ValueType.INT, 8),
+            new CfLoad(ValueType.INT, 10),
             new CfLoad(ValueType.INT, 2),
             new CfIfCmp(If.Type.GE, ValueType.INT, label20),
             label12,
             new CfLoad(ValueType.OBJECT, 0),
-            new CfLoad(ValueType.INT, 8),
+            new CfLoad(ValueType.INT, 10),
             new CfInvoke(
-                182,
+                185,
                 options.itemFactory.createMethod(
-                    options.itemFactory.stringType,
+                    options.itemFactory.charSequenceType,
                     options.itemFactory.createProto(
                         options.itemFactory.charType, options.itemFactory.intType),
                     options.itemFactory.createString("charAt")),
-                false),
-            new CfLoad(ValueType.INT, 1),
+                true),
+            new CfLoad(ValueType.INT, 3),
             new CfInvoke(
                 184,
                 options.itemFactory.createMethod(
@@ -2892,9 +2995,9 @@
                         options.itemFactory.intType),
                     options.itemFactory.createString("digit")),
                 false),
-            new CfStore(ValueType.INT, 9),
+            new CfStore(ValueType.INT, 11),
             label13,
-            new CfLoad(ValueType.INT, 9),
+            new CfLoad(ValueType.INT, 11),
             new CfConstNumber(-1, ValueType.INT),
             new CfIfCmp(If.Type.NE, ValueType.INT, label15),
             label14,
@@ -2902,6 +3005,13 @@
             new CfStackInstruction(CfStackInstruction.Opcode.Dup),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
+                185,
+                options.itemFactory.createMethod(
+                    options.itemFactory.charSequenceType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
+                    options.itemFactory.createString("toString")),
+                true),
+            new CfInvoke(
                 183,
                 options.itemFactory.createMethod(
                     options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
@@ -2913,9 +3023,11 @@
             label15,
             new CfFrame(
                 new Int2ReferenceAVLTreeMap<>(
-                    new int[] {0, 1, 2, 3, 5, 6, 8, 9},
+                    new int[] {0, 1, 2, 3, 4, 5, 7, 8, 10, 11},
                     new FrameType[] {
-                      FrameType.initialized(options.itemFactory.stringType),
+                      FrameType.initialized(options.itemFactory.charSequenceType),
+                      FrameType.initialized(options.itemFactory.intType),
+                      FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.longType),
@@ -2925,21 +3037,21 @@
                       FrameType.initialized(options.itemFactory.intType)
                     }),
                 new ArrayDeque<>(Arrays.asList())),
-            new CfLoad(ValueType.LONG, 6),
+            new CfLoad(ValueType.LONG, 8),
             new CfConstNumber(0, ValueType.LONG),
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.LT, ValueType.INT, label17),
-            new CfLoad(ValueType.LONG, 6),
-            new CfLoad(ValueType.LONG, 3),
+            new CfLoad(ValueType.LONG, 8),
+            new CfLoad(ValueType.LONG, 5),
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.GT, ValueType.INT, label17),
-            new CfLoad(ValueType.LONG, 6),
-            new CfLoad(ValueType.LONG, 3),
+            new CfLoad(ValueType.LONG, 8),
+            new CfLoad(ValueType.LONG, 5),
             new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
             new CfIf(If.Type.NE, ValueType.INT, label18),
-            new CfLoad(ValueType.INT, 9),
+            new CfLoad(ValueType.INT, 11),
             new CfConstNumber(-1, ValueType.LONG),
-            new CfLoad(ValueType.INT, 1),
+            new CfLoad(ValueType.INT, 3),
             new CfNumberConversion(NumericType.INT, NumericType.LONG),
             label16,
             new CfInvoke(
@@ -2957,9 +3069,11 @@
             label17,
             new CfFrame(
                 new Int2ReferenceAVLTreeMap<>(
-                    new int[] {0, 1, 2, 3, 5, 6, 8, 9},
+                    new int[] {0, 1, 2, 3, 4, 5, 7, 8, 10, 11},
                     new FrameType[] {
-                      FrameType.initialized(options.itemFactory.stringType),
+                      FrameType.initialized(options.itemFactory.charSequenceType),
+                      FrameType.initialized(options.itemFactory.intType),
+                      FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.longType),
@@ -2974,6 +3088,13 @@
             new CfConstString(options.itemFactory.createString("Too large for unsigned long: ")),
             new CfLoad(ValueType.OBJECT, 0),
             new CfInvoke(
+                185,
+                options.itemFactory.createMethod(
+                    options.itemFactory.charSequenceType,
+                    options.itemFactory.createProto(options.itemFactory.stringType),
+                    options.itemFactory.createString("toString")),
+                true),
+            new CfInvoke(
                 182,
                 options.itemFactory.createMethod(
                     options.itemFactory.stringType,
@@ -2993,9 +3114,11 @@
             label18,
             new CfFrame(
                 new Int2ReferenceAVLTreeMap<>(
-                    new int[] {0, 1, 2, 3, 5, 6, 8, 9},
+                    new int[] {0, 1, 2, 3, 4, 5, 7, 8, 10, 11},
                     new FrameType[] {
-                      FrameType.initialized(options.itemFactory.stringType),
+                      FrameType.initialized(options.itemFactory.charSequenceType),
+                      FrameType.initialized(options.itemFactory.intType),
+                      FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.longType),
@@ -3005,23 +3128,25 @@
                       FrameType.initialized(options.itemFactory.intType)
                     }),
                 new ArrayDeque<>(Arrays.asList())),
-            new CfLoad(ValueType.LONG, 6),
-            new CfLoad(ValueType.INT, 1),
+            new CfLoad(ValueType.LONG, 8),
+            new CfLoad(ValueType.INT, 3),
             new CfNumberConversion(NumericType.INT, NumericType.LONG),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
-            new CfLoad(ValueType.INT, 9),
+            new CfLoad(ValueType.INT, 11),
             new CfNumberConversion(NumericType.INT, NumericType.LONG),
             new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
-            new CfStore(ValueType.LONG, 6),
+            new CfStore(ValueType.LONG, 8),
             label19,
-            new CfIinc(8, 1),
+            new CfIinc(10, 1),
             new CfGoto(label11),
             label20,
             new CfFrame(
                 new Int2ReferenceAVLTreeMap<>(
-                    new int[] {0, 1, 2, 3, 5, 6},
+                    new int[] {0, 1, 2, 3, 4, 5, 7, 8},
                     new FrameType[] {
-                      FrameType.initialized(options.itemFactory.stringType),
+                      FrameType.initialized(options.itemFactory.charSequenceType),
+                      FrameType.initialized(options.itemFactory.intType),
+                      FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.intType),
                       FrameType.initialized(options.itemFactory.longType),
@@ -3029,13 +3154,52 @@
                       FrameType.initialized(options.itemFactory.longType)
                     }),
                 new ArrayDeque<>(Arrays.asList())),
-            new CfLoad(ValueType.LONG, 6),
+            new CfLoad(ValueType.LONG, 8),
             new CfReturn(ValueType.LONG),
             label21),
         ImmutableList.of(),
         ImmutableList.of());
   }
 
+  public static CfCode LongMethods_parseUnsignedLongWithRadix(
+      InternalOptions options, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        4,
+        2,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfConstNumber(0, ValueType.INT),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInvoke(
+                182,
+                options.itemFactory.createMethod(
+                    options.itemFactory.stringType,
+                    options.itemFactory.createProto(options.itemFactory.intType),
+                    options.itemFactory.createString("length")),
+                false),
+            new CfLoad(ValueType.INT, 1),
+            new CfInvoke(
+                184,
+                options.itemFactory.createMethod(
+                    options.itemFactory.createType("Ljava/lang/Long;"),
+                    options.itemFactory.createProto(
+                        options.itemFactory.longType,
+                        options.itemFactory.charSequenceType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType,
+                        options.itemFactory.intType),
+                    options.itemFactory.createString("parseUnsignedLong")),
+                false),
+            new CfReturn(ValueType.LONG),
+            label1),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
   public static CfCode LongMethods_remainderUnsigned(InternalOptions options, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
diff --git a/src/test/examplesJava9/backport/IntegerBackportJava9Main.java b/src/test/examplesJava9/backport/IntegerBackportJava9Main.java
new file mode 100644
index 0000000..10c86f2
--- /dev/null
+++ b/src/test/examplesJava9/backport/IntegerBackportJava9Main.java
@@ -0,0 +1,97 @@
+// Copyright (c) 2021, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package backport;
+
+import java.math.BigInteger;
+
+public final class IntegerBackportJava9Main {
+  private static final int[] interestingValues = {
+    Integer.MIN_VALUE,
+    Integer.MAX_VALUE,
+    Short.MIN_VALUE,
+    Short.MAX_VALUE,
+    Byte.MIN_VALUE,
+    Byte.MAX_VALUE,
+    0,
+    -1,
+    1,
+    -42,
+    42
+  };
+
+  public static void main(String[] args) {
+    testParseIntegerSubsequenceWithRadix();
+  }
+
+  private static void testParseIntegerSubsequenceWithRadix() {
+    for (int value : interestingValues) {
+      for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+        for (String prefix : new String[] {"", "x", "xxx"}) {
+          for (String postfix : new String[] {"", "x", "xxx"}) {
+            String valueString = prefix + Long.toString(value, radix) + postfix;
+            int start = prefix.length();
+            int end = valueString.length() - postfix.length();
+            assertEquals(valueString, value, Integer.parseInt(valueString, start, end, radix));
+            if (value > 0) {
+              valueString = prefix + '+' + Long.toString(value, radix) + postfix;
+              end++;
+              assertEquals(valueString, value, Integer.parseInt(valueString, start, end, radix));
+            }
+          }
+        }
+      }
+    }
+
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MIN_RADIX - 1));
+    } catch (IllegalArgumentException expected) {
+    }
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MAX_RADIX + 1));
+    } catch (IllegalArgumentException expected) {
+    }
+
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("", 0, 0, 16));
+    } catch (NumberFormatException expected) {
+    }
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("-", 0, 1, 16));
+    } catch (NumberFormatException expected) {
+    }
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("+", 0, 1, 16));
+    } catch (NumberFormatException expected) {
+    }
+
+    BigInteger overflow = new BigInteger("18446744073709551616");
+    for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+      for (String prefix : new String[] {"", "x", "xxx"}) {
+        for (String postfix : new String[] {"", "x", "xxx"}) {
+          String overflowString = prefix + overflow.toString(radix) + postfix;
+          int start = prefix.length();
+          int end = overflowString.length() - postfix.length();
+          try {
+            throw new AssertionError(Long.parseLong(overflowString, start, end, radix));
+          } catch (NumberFormatException expected) {
+          }
+          String underflowString = prefix + '-' + overflow.toString(radix) + postfix;
+          start = prefix.length();
+          end = underflowString.length() - postfix.length();
+          try {
+            throw new AssertionError(Long.parseLong(underflowString, start, end, radix));
+          } catch (NumberFormatException expected) {
+          }
+        }
+      }
+    }
+  }
+
+  private static void assertEquals(String m, int expected, int actual) {
+    if (expected != actual) {
+      throw new AssertionError(m + " Expected <" + expected + "> but was <" + actual + '>');
+    }
+  }
+}
diff --git a/src/test/examplesJava9/backport/LongBackportJava9Main.java b/src/test/examplesJava9/backport/LongBackportJava9Main.java
new file mode 100644
index 0000000..1634a43
--- /dev/null
+++ b/src/test/examplesJava9/backport/LongBackportJava9Main.java
@@ -0,0 +1,154 @@
+// Copyright (c) 2021, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package backport;
+
+import java.math.BigInteger;
+
+public final class LongBackportJava9Main {
+  private static final long[] interestingValues = {
+    Long.MIN_VALUE,
+    Long.MAX_VALUE,
+    Integer.MIN_VALUE,
+    Integer.MAX_VALUE,
+    Short.MIN_VALUE,
+    Short.MAX_VALUE,
+    Byte.MIN_VALUE,
+    Byte.MAX_VALUE,
+    0L,
+    -1L,
+    1L,
+    -42L,
+    42L
+  };
+
+  public static void main(String[] args) {
+    testParseLongSubsequenceWithRadix(args.length == 0 || !args[0].startsWith("4."));
+    testParseUnsignedLongSubsequenceWithRadix();
+  }
+
+  private static void testParseLongSubsequenceWithRadix(boolean supportsPlusPrefix) {
+    for (long value : interestingValues) {
+      for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+        for (String prefix : new String[] {"", "x", "xxx"}) {
+          for (String postfix : new String[] {"", "x", "xxx"}) {
+            String valueString = prefix + Long.toString(value, radix) + postfix;
+            int start = prefix.length();
+            int end = valueString.length() - postfix.length();
+            assertEquals(valueString, value, Long.parseLong(valueString, start, end, radix));
+            if (value > 0 && supportsPlusPrefix) {
+              valueString = prefix + "+" + Long.toString(value, radix) + postfix;
+              end++;
+              assertEquals(valueString, value, Long.parseLong(valueString, start, end, radix));
+            }
+          }
+        }
+      }
+    }
+
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MIN_RADIX - 1));
+    } catch (IllegalArgumentException expected) {
+    }
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MAX_RADIX + 1));
+    } catch (IllegalArgumentException expected) {
+    }
+
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("", 0, 0, 16));
+    } catch (NumberFormatException expected) {
+    }
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("-", 0, 1, 16));
+    } catch (NumberFormatException expected) {
+    }
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("+", 0, 1, 16));
+    } catch (NumberFormatException expected) {
+    }
+
+    BigInteger overflow = new BigInteger("18446744073709551616");
+    for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+      for (String prefix : new String[] {"", "x", "xxx"}) {
+        for (String postfix : new String[] {"", "x", "xxx"}) {
+          String overflowString = prefix + overflow.toString(radix) + postfix;
+          int start = prefix.length();
+          int end = overflowString.length() - postfix.length();
+          try {
+            throw new AssertionError(Long.parseLong(overflowString, start, end, radix));
+          } catch (NumberFormatException expected) {
+          }
+        }
+      }
+    }
+  }
+
+  private static void testParseUnsignedLongSubsequenceWithRadix() {
+    for (long value : interestingValues) {
+      for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+        for (String prefix : new String[] {"", "x", "xxx"}) {
+          for (String postfix : new String[] {"", "x", "xxx"}) {
+            String valueString = prefix + unsignedLongToBigInteger(value).toString(radix) + postfix;
+            int start = prefix.length();
+            int end = valueString.length() - postfix.length();
+            assertEquals(
+                valueString, value, Long.parseUnsignedLong(valueString, start, end, radix));
+            valueString = prefix + "+" + unsignedLongToBigInteger(value).toString(radix) + postfix;
+            end++;
+            assertEquals(
+                valueString, value, Long.parseUnsignedLong(valueString, start, end, radix));
+          }
+        }
+      }
+    }
+
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MIN_RADIX - 1));
+    } catch (IllegalArgumentException expected) {
+    }
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MAX_RADIX + 1));
+    } catch (IllegalArgumentException expected) {
+    }
+
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("", 0, 0, 16));
+    } catch (NumberFormatException expected) {
+    }
+    try {
+      throw new AssertionError(Long.parseUnsignedLong("+", 0, 1, 16));
+    } catch (NumberFormatException expected) {
+    }
+
+    BigInteger overflow = new BigInteger("18446744073709551616");
+    for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+      for (String prefix : new String[] {"", "x", "xxx", "+", "x+", "xxx+"}) {
+        for (String postfix : new String[] {"", "x", "xxx"}) {
+          String overflowString = prefix + overflow.toString(radix) + postfix;
+          int start = prefix.length();
+          int end = overflowString.length() - postfix.length();
+          try {
+            throw new AssertionError(Long.parseUnsignedLong(overflowString, start, end, radix));
+          } catch (NumberFormatException expected) {
+          }
+        }
+      }
+    }
+  }
+
+  private static BigInteger unsignedLongToBigInteger(long value) {
+    BigInteger bigInt = BigInteger.valueOf(value & 0x7fffffffffffffffL);
+    if (value < 0) {
+      bigInt = bigInt.setBit(Long.SIZE - 1);
+    }
+    return bigInt;
+  }
+
+  private static void assertEquals(String m, long expected, long actual) {
+    if (expected != actual) {
+      throw new AssertionError(m + " Expected <" + expected + "> but was <" + actual + '>');
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java b/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
index 4161d87..fcc79dc 100644
--- a/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
+++ b/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.cf.CfCodePrinter;
+import com.android.tools.r8.graph.CfCode;
 import com.android.tools.r8.graph.ClassKind;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -18,6 +19,7 @@
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.StringUtils;
 import com.google.common.collect.ImmutableList;
 import java.io.File;
@@ -66,6 +68,10 @@
     return Paths.get(ToolHelper.SOURCE_DIR, getGeneratedType().getInternalName() + ".java");
   }
 
+  protected CfCode getCode(String holderName, String methodName, CfCode code) {
+    return code;
+  }
+
   private String getGeneratedClassName() {
     return getGeneratedType().getName();
   }
@@ -94,7 +100,7 @@
   }
 
   private void readMethodTemplatesInto(CfCodePrinter codePrinter) throws IOException {
-    InternalOptions options = new InternalOptions();
+    InternalOptions options = new InternalOptions(factory, new Reporter());
     options.testing.readInputStackMaps = true;
     JarClassFileReader<DexProgramClass> reader =
         new JarClassFileReader<>(
@@ -104,9 +110,13 @@
                 if (method.isInitializer()) {
                   continue;
                 }
-                String methodName =
-                    method.getHolderType().getName() + "_" + method.method.name.toString();
-                codePrinter.visitMethod(methodName, method.getCode().asCfCode());
+                String holderName = method.getHolderType().getName();
+                String methodName = method.method.name.toString();
+                String generatedMethodName = holderName + "_" + methodName;
+                CfCode code = getCode(holderName, methodName, method.getCode().asCfCode());
+                if (code != null) {
+                  codePrinter.visitMethod(generatedMethodName, code);
+                }
               }
             },
             ClassKind.PROGRAM);
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
index 646dbf9..784e875 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
@@ -102,7 +102,10 @@
           .apply(this::configureProgram)
           .setIncludeClassesChecksum(true)
           .compile()
-          .run(parameters.getRuntime(), testClassName)
+          .run(
+              parameters.getRuntime(),
+              testClassName,
+              parameters.getRuntime().asDex().getVm().getVersion().toString())
           .assertSuccess()
           .inspect(this::assertDesugaring);
     }
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/IntegerBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/IntegerBackportJava9Test.java
new file mode 100644
index 0000000..a2e1120
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/IntegerBackportJava9Test.java
@@ -0,0 +1,37 @@
+// Copyright (c) 2021, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.desugar.backports;
+
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public final class IntegerBackportJava9Test extends AbstractBackportTest {
+  @Parameters(name = "{0}")
+  public static Iterable<?> data() {
+    return getTestParameters()
+        .withCfRuntimesStartingFromIncluding(CfVm.JDK9)
+        .withDexRuntimes()
+        .withAllApiLevels()
+        .build();
+  }
+
+  private static final Path TEST_JAR =
+      Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+
+  public IntegerBackportJava9Test(TestParameters parameters) {
+    super(parameters, Short.class, TEST_JAR, "backport.IntegerBackportJava9Main");
+    // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
+    // an actual API level, migrate these tests to IntegerBackportTest.
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/LongBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/LongBackportJava9Test.java
new file mode 100644
index 0000000..4bd90c8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/LongBackportJava9Test.java
@@ -0,0 +1,37 @@
+// Copyright (c) 2021, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.desugar.backports;
+
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public final class LongBackportJava9Test extends AbstractBackportTest {
+  @Parameters(name = "{0}")
+  public static Iterable<?> data() {
+    return getTestParameters()
+        .withCfRuntimesStartingFromIncluding(CfVm.JDK9)
+        .withDexRuntimes()
+        .withAllApiLevels()
+        .build();
+  }
+
+  private static final Path TEST_JAR =
+      Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+
+  public LongBackportJava9Test(TestParameters parameters) {
+    super(parameters, Short.class, TEST_JAR, "backport.LongBackportJava9Main");
+    // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
+    // an actual API level, migrate these tests to LongBackportTest.
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
index d78a1c7..455c5c2 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
@@ -9,7 +9,11 @@
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
 import com.android.tools.r8.cfmethodgeneration.MethodGenerationBase;
+import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.utils.FileUtils;
 import com.google.common.collect.ImmutableList;
@@ -17,6 +21,7 @@
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
+import java.util.stream.Collectors;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -73,6 +78,44 @@
     return 2020;
   }
 
+  private static CfInstruction rewriteToJava9API(
+      DexItemFactory itemFactory, CfInstruction instruction) {
+    // Rewrite static invoke of javaUtilLongParseUnsignedLongStub to j.l.Long.parseUnsignedLong.
+    if (instruction.isInvoke()
+        && instruction
+            .asInvoke()
+            .getMethod()
+            .getName()
+            .toString()
+            .equals("javaLangLongParseUnsignedLongStub")) {
+      CfInvoke invoke = instruction.asInvoke();
+      return new CfInvoke(
+          invoke.getOpcode(),
+          itemFactory.createMethod(
+              itemFactory.createType("Ljava/lang/Long;"),
+              invoke.getMethod().getProto(),
+              itemFactory.createString("parseUnsignedLong")),
+          invoke.isInterface());
+    } else {
+      return instruction;
+    }
+  }
+
+  @Override
+  protected CfCode getCode(String holderName, String methodName, CfCode code) {
+    if (methodName.endsWith("Stub")) {
+      // Don't include stubs targeted only for rewriting in the generated code.
+      return null;
+    }
+    if (holderName.equals("LongMethods") && methodName.equals("parseUnsignedLongWithRadix")) {
+      code.setInstructions(
+          code.getInstructions().stream()
+              .map(instruction -> rewriteToJava9API(factory, instruction))
+              .collect(Collectors.toList()));
+    }
+    return code;
+  }
+
   @Test
   public void testBackportsGenerated() throws Exception {
     ArrayList<Class<?>> sorted = new ArrayList<>(getMethodTemplateClasses());
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/IntegerMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/IntegerMethods.java
index 0560b97..a3bd157 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/IntegerMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/IntegerMethods.java
@@ -57,4 +57,9 @@
     long asLong = i & 0xffffffffL;
     return Long.toString(asLong, radix);
   }
+
+  public static int parseIntSubsequenceWithRadix(
+      CharSequence s, int beginIndex, int endIndex, int radix) throws NumberFormatException {
+    return Integer.parseInt(s.subSequence(beginIndex, endIndex).toString(), radix);
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/LongMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/LongMethods.java
index 643d295..65a60ef 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/LongMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/LongMethods.java
@@ -10,6 +10,11 @@
     return (int) (l ^ (l >>> 32));
   }
 
+  public static long parseLongSubsequenceWithRadix(
+      CharSequence s, int beginIndex, int endIndex, int radix) {
+    return Long.parseLong(s.subSequence(beginIndex, endIndex).toString(), radix);
+  }
+
   public static long divideUnsigned(long dividend, long divisor) {
     // This implementation is adapted from Guava's UnsignedLongs.java and Longs.java.
 
@@ -92,10 +97,20 @@
     return Long.parseUnsignedLong(s, 10);
   }
 
+  private static long javaLangLongParseUnsignedLongStub(
+      CharSequence s, int beginIndex, int endIndex, int radix) {
+    throw new RuntimeException("Stub invoked");
+  }
+
   public static long parseUnsignedLongWithRadix(String s, int radix) {
+    return javaLangLongParseUnsignedLongStub(s, 0, s.length(), radix);
+  }
+
+  public static long parseUnsignedLongSubsequenceWithRadix(
+      CharSequence s, int beginIndex, int endIndex, int radix) {
     // This implementation is adapted from Guava's UnsignedLongs.java
 
-    int length = s.length();
+    int length = endIndex - beginIndex;
     if (length == 0) {
       throw new NumberFormatException("empty string");
     }
@@ -106,23 +121,23 @@
     long maxValueBeforeRadixMultiply = Long.divideUnsigned(-1L, radix);
 
     // If the string starts with '+' and contains at least two characters, skip the plus.
-    int start = s.charAt(0) == '+' && length > 1 ? 1 : 0;
+    int start = s.charAt(beginIndex) == '+' && length > 1 ? beginIndex + 1 : beginIndex;
 
     long value = 0;
-    for (int pos = start; pos < length; pos++) {
+    for (int pos = start; pos < endIndex; pos++) {
       int digit = Character.digit(s.charAt(pos), radix);
       if (digit == -1) {
-        throw new NumberFormatException(s);
+        throw new NumberFormatException(s.toString());
       }
-      if (// high bit is already set
-          value < 0
+      if ( // high bit is already set
+      value < 0
           // or radix multiply will overflow
           || value > maxValueBeforeRadixMultiply
           // or digit add will overflow after radix multiply
           || (value == maxValueBeforeRadixMultiply
               && digit > (int) Long.remainderUnsigned(-1L, radix))) {
         // Explicit String.concat to work around https://issuetracker.google.com/issues/136596951.
-        throw new NumberFormatException("Too large for unsigned long: ".concat(s));
+        throw new NumberFormatException("Too large for unsigned long: ".concat(s.toString()));
       }
       value = (value * radix) + digit;
     }