// Copyright (c) 2017, 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 stringconcat;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class TestGenerator {
  private static final String RECIPE_PREFIX = "RECIPE:";

  private static final String STRING_CONCAT_FACTORY = "java/lang/invoke/StringConcatFactory";

  private static final Handle MAKE_CONCAT_WITH_CONSTANTS = new Handle(
      Opcodes.H_INVOKESTATIC, STRING_CONCAT_FACTORY, "makeConcatWithConstants",
      MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
          MethodType.class, String.class, Object[].class).toMethodDescriptorString(),
      false);

  private static final Handle MAKE_CONCAT = new Handle(
      Opcodes.H_INVOKESTATIC, STRING_CONCAT_FACTORY, "makeConcat",
      MethodType.methodType(CallSite.class, MethodHandles.Lookup.class,
          String.class, MethodType.class).toMethodDescriptorString(),
      false);

  public static void main(String[] args) throws IOException {
    assert args.length == 1;
    generateTests(Paths.get(args[0],
        TestGenerator.class.getPackage().getName(),
        StringConcat.class.getSimpleName() + ".class"));
  }

  private static void generateTests(Path classNamePath) throws IOException {
    try (InputStream input = Files.newInputStream(classNamePath)) {
      ClassReader cr = new ClassReader(input);
      ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
      cr.accept(
          new ClassVisitor(Opcodes.ASM7, cw) {
            @Override
            public MethodVisitor visitMethod(int access,
                final String methodName, String desc, String signature, String[] exceptions) {
              MethodVisitor mv = super.visitMethod(access, methodName, desc, signature, exceptions);
              return new MethodVisitor(Opcodes.ASM7, mv) {
                private List<Object> recentConstants = new ArrayList<>();

                @Override
                public void visitLdcInsn(Object cst) {
                  if (!recentConstants.isEmpty() ||
                      (cst instanceof String && ((String) cst).startsWith(RECIPE_PREFIX))) {
                    // Add the constant, don't push anything on stack.
                    recentConstants.add(cst);
                    return;
                  }
                  super.visitLdcInsn(cst);
                }

                @Override
                public void visitMethodInsn(
                    int opcode, String owner, String name, String desc, boolean itf) {
                  // Replace calls to 'makeConcat(...)' with appropriate `invokedynamic`.
                  if (opcode == Opcodes.INVOKESTATIC && name.equals("makeConcat")) {
                    mv.visitInvokeDynamicInsn(MAKE_CONCAT.getName(), desc, MAKE_CONCAT);
                    recentConstants.clear();
                    return;
                  }

                  // Replace calls to 'makeConcat(...)' with appropriate `invokedynamic`.
                  if (opcode == Opcodes.INVOKESTATIC && name.equals("makeConcatWithConstants")) {
                    if (recentConstants.isEmpty()) {
                      throw new AssertionError("No constants detected in `" +
                          methodName + "`: call to " + name + desc);
                    }
                    recentConstants.set(0,
                        ((String) recentConstants.get(0)).substring(RECIPE_PREFIX.length()));

                    mv.visitInvokeDynamicInsn(
                        MAKE_CONCAT_WITH_CONSTANTS.getName(),
                        removeLastParams(desc, recentConstants.size()),
                        MAKE_CONCAT_WITH_CONSTANTS,
                        recentConstants.toArray());
                    recentConstants.clear();
                    return;
                  }

                  // Otherwise fall back to default implementation.
                  super.visitMethodInsn(opcode, owner, name, desc, itf);
                }

                private String removeLastParams(String descr, int paramsToRemove) {
                  MethodType methodType =
                      MethodType.fromMethodDescriptorString(
                          descr, this.getClass().getClassLoader());
                  return methodType
                      .dropParameterTypes(
                          methodType.parameterCount() - paramsToRemove,
                          methodType.parameterCount())
                      .toMethodDescriptorString();
                }

                @Override
                public void visitInsn(int opcode) {
                  switch (opcode) {
                    case Opcodes.ICONST_0:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(0);
                        return;
                      }
                      break;
                    case Opcodes.ICONST_1:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(1);
                        return;
                      }
                      break;
                    case Opcodes.ICONST_2:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(2);
                        return;
                      }
                      break;
                    case Opcodes.ICONST_3:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(3);
                        return;
                      }
                      break;
                    case Opcodes.ICONST_4:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(4);
                        return;
                      }
                      break;
                    case Opcodes.ICONST_5:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(5);
                        return;
                      }
                      break;
                    case Opcodes.ICONST_M1:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(-1);
                        return;
                      }
                      break;
                    default:
                      recentConstants.clear();
                      break;
                  }
                  super.visitInsn(opcode);
                }

                @Override
                public void visitIntInsn(int opcode, int operand) {
                  recentConstants.clear();
                  super.visitIntInsn(opcode, operand);
                }

                @Override
                public void visitVarInsn(int opcode, int var) {
                  recentConstants.clear();
                  super.visitVarInsn(opcode, var);
                }

                @Override
                public void visitTypeInsn(int opcode, String type) {
                  recentConstants.clear();
                  super.visitTypeInsn(opcode, type);
                }

                @Override
                public void visitFieldInsn(int opcode, String owner, String name, String desc) {
                  recentConstants.clear();
                  super.visitFieldInsn(opcode, owner, name, desc);
                }

                @Override
                public void visitJumpInsn(int opcode, Label label) {
                  recentConstants.clear();
                  super.visitJumpInsn(opcode, label);
                }

                @Override
                public void visitIincInsn(int var, int increment) {
                  recentConstants.clear();
                  super.visitIincInsn(var, increment);
                }

                @Override
                public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
                  recentConstants.clear();
                  super.visitTableSwitchInsn(min, max, dflt, labels);
                }

                @Override
                public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
                  recentConstants.clear();
                  super.visitLookupSwitchInsn(dflt, keys, labels);
                }

                @Override
                public void visitMultiANewArrayInsn(String desc, int dims) {
                  recentConstants.clear();
                  super.visitMultiANewArrayInsn(desc, dims);
                }
              };
            }
          }, 0);
      try (OutputStream output = Files.newOutputStream(classNamePath)) {
        output.write(cw.toByteArray());
      }
    }
  }
}
