Fix enum unboxing with large arity method

Change-Id: I5b9a19f6eecd3bba7bf48ed903ca1bb7337e1683
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/EnumUnboxingCfCodeProvider.java b/src/main/java/com/android/tools/r8/ir/synthetic/EnumUnboxingCfCodeProvider.java
index abff1ff..da1d23f 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/EnumUnboxingCfCodeProvider.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/EnumUnboxingCfCodeProvider.java
@@ -144,12 +144,20 @@
       List<CfInstruction> instructions = new ArrayList<>();
       DexMethod representative = methodMap.values().iterator().next();
       CfFrame.Builder frameBuilder = CfFrame.builder();
+      int paramRegisterSize = 0;
       for (DexType parameter : representative.getParameters()) {
         frameBuilder.appendLocal(FrameType.initialized(parameter));
+        paramRegisterSize += parameter.getRequiredRegisters();
       }
       addCfSwitch(
           instructions, this::addReturnInvoke, methodMap, superEnumMethod, frameBuilder, false);
-      return new CfCodeWithLens(getHolder(), defaultMaxStack(), defaultMaxLocals(), instructions);
+      // We need to get an estimate of the stack and local with is greater than the actual number,
+      // IR processing will compute the exact number. There are at most 255 parameters, so this is
+      // always within unsigned 16 bits bounds.
+      assert paramRegisterSize < 256;
+      int maxStack = 2 * paramRegisterSize + 16;
+      int maxLocals = paramRegisterSize + 16;
+      return new CfCodeWithLens(getHolder(), maxStack, maxLocals, instructions);
     }
 
     private void addReturnInvoke(List<CfInstruction> instructions, DexMethod method) {
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/enummerging/LargeArityEnumUnboxingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/enummerging/LargeArityEnumUnboxingTest.java
new file mode 100644
index 0000000..0e9a7c1
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/enumunboxing/enummerging/LargeArityEnumUnboxingTest.java
@@ -0,0 +1,162 @@
+// Copyright (c) 2023, 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.enumunboxing.enummerging;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.enumunboxing.EnumUnboxingTestBase;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class LargeArityEnumUnboxingTest extends EnumUnboxingTestBase {
+
+  private final TestParameters parameters;
+  private final boolean enumValueOptimization;
+  private final EnumKeepRules enumKeepRules;
+
+  @Parameters(name = "{0} valueOpt: {1} keep: {2}")
+  public static List<Object[]> data() {
+    return enumUnboxingTestParameters();
+  }
+
+  public LargeArityEnumUnboxingTest(
+      TestParameters parameters, boolean enumValueOptimization, EnumKeepRules enumKeepRules) {
+    this.parameters = parameters;
+    this.enumValueOptimization = enumValueOptimization;
+    this.enumKeepRules = enumKeepRules;
+  }
+
+  @Test
+  public void testEnumUnboxing() throws Exception {
+    testForR8(parameters.getBackend())
+        .addInnerClasses(LargeArityEnumUnboxingTest.class)
+        .addKeepMainRule(LargeArityEnum.class)
+        .addEnumUnboxingInspector(inspector -> inspector.assertUnboxed(LargeArityEnum.MyEnum.class))
+        .enableNeverClassInliningAnnotations()
+        .enableInliningAnnotations()
+        .addKeepRules(enumKeepRules.getKeepRules())
+        .addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
+        .setMinApi(parameters)
+        .run(parameters.getRuntime(), LargeArityEnum.class)
+        .assertSuccessWithOutputLines("171.0", "189.0", "271.0", "299.0");
+  }
+
+  static class LargeArityEnum {
+
+    @NeverClassInline
+    enum MyEnum {
+      A(1) {
+        @NeverInline
+        public double foo(
+            long op1,
+            long op2,
+            double op3,
+            double op4,
+            int op5,
+            int op6,
+            long op7,
+            long op8,
+            double op9,
+            double op10,
+            int op11,
+            int op12,
+            long op13,
+            long op14,
+            double op15,
+            double op16,
+            int op17,
+            int op18) {
+          return mul * op1 + op2 + op3 + op4 + op5 + op6 + op7 + op8 + op9 + op10 + op11 + op12
+              + op13 + op14 + op15 + op16 + op17 + op18;
+        }
+      },
+      B(3) {
+        @NeverInline
+        public double foo(
+            long op1,
+            long op2,
+            double op3,
+            double op4,
+            int op5,
+            int op6,
+            long op7,
+            long op8,
+            double op9,
+            double op10,
+            int op11,
+            int op12,
+            long op13,
+            long op14,
+            double op15,
+            double op16,
+            int op17,
+            int op18) {
+          return mul * mul * op1
+              + op2
+              + op3
+              + op4
+              + op5
+              + op6
+              + op7
+              + op8
+              + op9
+              + op10
+              + op11
+              + op12
+              + op13
+              + op14
+              + op15
+              + op16
+              + op17
+              + op18 * mul;
+        }
+      };
+
+      final int mul;
+
+      MyEnum(int mul) {
+        this.mul = mul;
+      }
+
+      // Method with large arity.
+      public abstract double foo(
+          long op1,
+          long op2,
+          double op3,
+          double op4,
+          int op5,
+          int op6,
+          long op7,
+          long op8,
+          double op9,
+          double op10,
+          int op11,
+          int op12,
+          long op13,
+          long op14,
+          double op15,
+          double op16,
+          int op17,
+          int op18);
+    }
+
+    @SuppressWarnings("ConstantConditions")
+    public static void main(String[] args) {
+      System.out.println(
+          MyEnum.A.foo(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18));
+      System.out.println(
+          MyEnum.A.foo(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19));
+      System.out.println(
+          MyEnum.B.foo(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20));
+      System.out.println(
+          MyEnum.B.foo(4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21));
+    }
+  }
+}