/*
 * Copyright 2024 WebAssembly Community Group participants
 *
 * 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.
 */

// This is a J2CL specific pass that merges itables into vtables. It is meant
// to be run at the beginning before structs corresponding to Java classes are
// optimized.
//
// The motivation for embedding itables into vtables is to reduce memory usage.
//
// The pass makes the following transformation on the structs related to Java
// classes. For given type `Foo` with `Foo[vtable] = { m1, m2, m3, ... }`
// and  `Foo[itable] = { i1, i2, ...}`, this pass transforms it to
// `Foo[vtable] = { i1, i2, ...., m1, m2, m3, ... }`, and fixes all accesses
// and initializations accordingly.

#include <memory>
#include <string_view>
#include <unordered_map>

#include "ir/module-utils.h"
#include "ir/type-updating.h"
#include "pass.h"
#include "support/utilities.h"
#include "wasm-builder.h"
#include "wasm-traversal.h"
#include "wasm-type.h"
#include "wasm.h"

namespace wasm {

namespace {

// Information about the structs that have vtables and itables.
struct StructInfo {
  HeapType javaClass;
  HeapType vtable;
  HeapType itable;
};

struct J2CLItableMerging : public Pass {
  // Number of entries at the start of the descriptor that should not change
  // index. If the vtable is a custom descriptor, itable fields are inserted at
  // index 1. Index 0 is preserved for a possible JS prototype.
  static const Index kPreservedDescriptorFields = 1;

  // Keep track of all the structInfos so that they will be automatically
  // released after the pass is done.
  std::list<StructInfo> structInfos;

  // Globals that hold vtables and itables indexed by their heap type.
  // There is exactly 1 global for each vtable/itable type.
  std::unordered_map<HeapType, Global*> tableGlobalsByType;
  std::unordered_map<HeapType, StructInfo*> structInfoByVtableType;
  std::unordered_map<HeapType, StructInfo*> structInfoByITableType;

  unsigned long itableSize = 0;

  void run(Module* module) override {
    if (!module->features.hasGC()) {
      return;
    }

    if (getPassOptions().worldMode == WorldMode::Open) {
      Fatal() << "--merge-j2cl-itables requires --closed-world";
    }

    collectVtableAndItableTypes(*module);
    // Update the indices to access the functions in the vtables and update
    // the construction of the vtable instances.
    updateVtableFieldsAccesses(*module);
    // And now we can transform the accesses to the itable fields into their
    // corresponding vtable fields. Needs to be done after
    // updateVtableFieldsAccesses.
    rerouteItableAccess(*module);
    // The type structures are updated last since types are used as keys in
    // the maps used above.
    updateTypes(*module);

    // Since now vtables are initialized with `global.get` of the interface
    // vtable instances, we need to reorder the globals.
    PassRunner runner(module);
    runner.add("reorder-globals-always");
    runner.setIsNested(true);
    runner.run();
  }

  // Collects all structs corresponding to Java classes, their vtables and
  // their itables. This is very tied to the way j2cl emits these constructs.
  void collectVtableAndItableTypes(Module& wasm) {
    auto hasField =
      [](TypeNames& typeNameInfo, int index, std::string_view name) {
        auto it = typeNameInfo.fieldNames.find(index);
        return it != typeNameInfo.fieldNames.end() && it->second.equals(name);
      };

    auto publicTypes =
      ModuleUtils::getPublicHeapTypes(wasm, getPassOptions().worldMode);
    std::unordered_set<HeapType> publicTypesSet(publicTypes.begin(),
                                                publicTypes.end());

    // 1. Collect all structs that correspond that a Java type.
    for (auto [heapType, typeNameInfo] : wasm.typeNames) {
      if (!heapType.isStruct()) {
        continue;
      }

      // The vtable may either be the first field or the custom descriptor.
      HeapType vtabletype;
      HeapType itabletype;
      auto& type = heapType.getStruct();
      if (auto descriptor = heapType.getDescriptorType()) {
        if (!hasField(typeNameInfo, 0, "itable")) {
          continue;
        }

        vtabletype = *descriptor;
        // If the vtable is a descriptor, we enforce that it has at least 1
        // field for the possible JS prototype and simply assume this
        // downstream. In practice, this is necessary anyway to allow vtables to
        // subtype each other.
        if (vtabletype.getStruct().fields.size() < kPreservedDescriptorFields) {
          Fatal() << "--merge-j2cl-itables needs to be the first pass to run "
                  << "on j2cl output. (descriptor has fewer than expected "
                  << "fields)";
        }

        itabletype = type.fields[0].type.getHeapType();
      } else {
        if (!hasField(typeNameInfo, 0, "vtable") ||
            !hasField(typeNameInfo, 1, "itable")) {
          continue;
        }

        vtabletype = type.fields[0].type.getHeapType();
        itabletype = type.fields[1].type.getHeapType();
      }

      if (publicTypesSet.contains(heapType) ||
          publicTypesSet.contains(vtabletype) ||
          publicTypesSet.contains(itabletype)) {
        Fatal() << "Cannot merge itables because the J2CL type "
                << ModuleHeapType(wasm, heapType)
                << " or its dispatch tables are public";
      }

      auto structItableSize = itabletype.getStruct().fields.size();

      if (itableSize != 0 && itableSize != structItableSize) {
        Fatal() << "--merge-j2cl-itables needs to be the first pass to run "
                << "on j2cl output. (found itables with different sizes)";
      }

      itableSize = structItableSize;

      // Add a new StructInfo to the list by value so that its memory gets
      // reclaimed automatically on exit.
      structInfos.push_back(StructInfo{heapType, vtabletype, itabletype});
      // Point to the StructInfo just added to the list to be able to look it
      // up by its vtable and itable types.
      structInfoByVtableType[vtabletype] = &structInfos.back();
      structInfoByITableType[itabletype] = &structInfos.back();
    }

    // 2. Collect the globals for vtables and itables.
    for (auto& g : wasm.globals) {
      if (!g->type.isStruct()) {
        continue;
      }
      if (structInfoByVtableType.contains(g->type.getHeapType())) {
        tableGlobalsByType[g->type.getHeapType()] = g.get();
      } else if (structInfoByITableType.contains(g->type.getHeapType())) {
        tableGlobalsByType[g->type.getHeapType()] = g.get();
      }
    }

    if (itableSize == 0) {
      Fatal() << "--merge-j2cl-itables needs to be the first pass to run "
              << "on j2cl output. (no Java classes found)";
    }
  }

  // Fix the indexes of `struct.get` for vtable fields, and prepend the
  // initializers for the itable fields to `struct.new`.
  // Note that there isn't any `struct.set` because the vtable fields are
  // immutable.
  void updateVtableFieldsAccesses(Module& wasm) {
    struct Reindexer : public WalkerPass<PostWalker<Reindexer>> {
      bool isFunctionParallel() override { return true; }

      J2CLItableMerging& parent;

      Reindexer(J2CLItableMerging& parent) : parent(parent) {}

      std::unique_ptr<Pass> create() override {
        return std::make_unique<Reindexer>(parent);
      }

      void visitStructGet(StructGet* curr) {
        auto* structInfo = getStructInfoByVtableType(curr->ref->type);
        if (!structInfo) {
          return;
        }

        // This is a struct.get on the vtable.
        // It is ok to just change the index since the field has moved but
        // the type is the same.
        if (structInfo->javaClass.getDescriptorType()) {
          if (curr->index >= kPreservedDescriptorFields) {
            curr->index += parent.itableSize;
          }
        } else {
          curr->index += parent.itableSize;
        }
      }

      void visitStructNew(StructNew* curr) {
        auto* structInfo = getStructInfoByVtableType(curr->type);
        if (!structInfo) {
          return;
        }

        // The struct.new is for a vtable type and structInfo has the
        // information relating the struct types for the Java class, its vtable
        // and its itable.

        // Get the global that holds the corresponding itable instance.
        auto* itableGlobal = parent.tableGlobalsByType[structInfo->itable];
        StructNew* itableStructNew = nullptr;

        if (itableGlobal && itableGlobal->init) {
          if (itableGlobal->init->is<GlobalGet>()) {
            // The global might get initialized with the shared empty itable,
            // obtain the itable struct.new from the global.init.
            auto* globalGet = itableGlobal->init->dynCast<GlobalGet>();
            auto* global = getModule()->getGlobal(globalGet->name);
            itableStructNew = global->init->dynCast<StructNew>();
          } else {
            // The global is initialized with a struct.new of the itable.
            itableStructNew = itableGlobal->init->dynCast<StructNew>();
          }
        }

        if (!itableStructNew) {
          Fatal() << "--merge-j2cl-itables needs to be the first pass to run "
                  << "on j2cl output. (itable initializer not found)";
        }
        auto& itableFieldInitializers = itableStructNew->operands;

        size_t insertIndex =
          structInfo->javaClass.getDescriptorType().has_value()
            ? kPreservedDescriptorFields
            : 0;

        // Add the initialization for the itable fields.
        for (Index i = parent.itableSize; i > 0; i--) {
          if (itableFieldInitializers.size() >= i) {
            // The itable was initialized with a struct.new, copy the
            // initialization values.
            curr->operands.insertAt(
              insertIndex,
              ExpressionManipulator::copy(itableFieldInitializers[i - 1],
                                          *getModule()));
          } else {
            // The itable was initialized with struct.new_default. So use
            // null values to initialize the itable fields.
            Builder builder(*getModule());
            curr->operands.insertAt(
              insertIndex,
              builder.makeRefNull(itableStructNew->type.getHeapType()
                                    .getStruct()
                                    .fields[i - 1]
                                    .type.getHeapType()));
          }
        }
      }

      StructInfo* getStructInfoByVtableType(Type type) {
        if (type == Type::unreachable) {
          return nullptr;
        }
        if (auto it = parent.structInfoByVtableType.find(type.getHeapType());
            it != parent.structInfoByVtableType.end()) {
          return it->second;
        }
        return nullptr;
      }
    };

    Reindexer reindexer(*this);
    reindexer.run(getPassRunner(), &wasm);
    reindexer.runOnModuleCode(getPassRunner(), &wasm);
  }

  // Redirects all itable access by changing `struct.get` of the `itable` field
  // to `struct.get` on the to `vtable` field.
  void rerouteItableAccess(Module& wasm) {
    struct Rerouter : public WalkerPass<PostWalker<Rerouter>> {
      bool isFunctionParallel() override { return true; }

      J2CLItableMerging& parent;

      Rerouter(J2CLItableMerging& parent) : parent(parent) {}

      std::unique_ptr<Pass> create() override {
        return std::make_unique<Rerouter>(parent);
      }

      void visitStructGet(StructGet* curr) {
        // Determine if the struct.get is to get a field from the itable or the
        // to get the itable itself.

        if (auto* structInfo = getStructInfoByItableType(curr->ref->type)) {
          // This is a struct.get that returns an itable field.
          updateGetItableField(curr, structInfo->javaClass);
          return;
        }

        if (auto* structInfo = getStructInfoByItableType(curr->type)) {
          // This is a struct.get that returns an itable type.
          updateGetItable(curr, structInfo->javaClass);
          return;
        }
      }

      StructInfo* getStructInfoByItableType(Type type) {
        if (type == Type::unreachable || !type.isStruct()) {
          return nullptr;
        }
        if (auto it = parent.structInfoByITableType.find(type.getHeapType());
            it != parent.structInfoByITableType.end()) {
          return it->second;
        }
        return nullptr;
      }

      void updateGetItableField(StructGet* curr, HeapType javaClass) {
        if (!javaClass.getDescriptorType()) {
          return;
        }

        curr->index += kPreservedDescriptorFields;
        if (auto childGet = curr->ref->dynCast<StructGet>()) {
          // The reference is another struct.get. It is getting the itable for
          // the type.
          // Replace it with a ref.get_desc for the vtable, which is the
          // descriptor.
          Builder builder(*getModule());
          curr->ref = builder.makeRefGetDesc(childGet->ref);
          return;
        }

        // We expect the reference to be another struct.get.
        Fatal() << "--merge-j2cl-itables needs to be the first pass to run "
                << "on j2cl output. (itable getter not found) ";
      }

      void updateGetItable(StructGet* curr, HeapType javaClass) {
        if (javaClass.getDescriptorType()) {
          return;
        }

        // Change to return the corresponding vtable type (field 0).
        Builder builder(*getModule());
        replaceCurrent(builder.makeStructGet(
          0,
          curr->ref,
          MemoryOrder::Unordered,
          parent.structInfoByITableType[curr->type.getHeapType()]
            ->javaClass.getStruct()
            .fields[0]
            .type));
      }
    };

    Rerouter rerouter(*this);
    rerouter.run(getPassRunner(), &wasm);
    rerouter.runOnModuleCode(getPassRunner(), &wasm);
  }

  // Modify the struct definitions adding the itable fields to the vtable and
  // preserving the vtable field names.
  void updateTypes(Module& wasm) {
    class TypeRewriter : public GlobalTypeRewriter {
      J2CLItableMerging& parent;

    public:
      TypeRewriter(Module& wasm, J2CLItableMerging& parent)
        : GlobalTypeRewriter(wasm, parent.getPassOptions().worldMode),
          parent(parent) {}

      void modifyStruct(HeapType oldStructType, Struct& struct_) override {
        auto structInfoIt = parent.structInfoByVtableType.find(oldStructType);
        if (structInfoIt == parent.structInfoByVtableType.end()) {
          return;
        }

        auto& newFields = struct_.fields;

        auto* structInfo = structInfoIt->second;

        Index insertIndex =
          structInfo->javaClass.getDescriptorType().has_value()
            ? kPreservedDescriptorFields
            : 0;

        // Add the itable fields to the beginning of the vtable.
        auto& itableFields = structInfo->itable.getStruct().fields;
        newFields.insert(newFields.begin() + insertIndex,
                         itableFields.begin(),
                         itableFields.end());
        for (Index i = 0; i < parent.itableSize; i++) {
          newFields[insertIndex + i].type =
            getTempType(newFields[insertIndex + i].type);
        }

        // Update field names as well. The Type Rewriter cannot do this for
        // us, as it does not know which old fields map to which new ones
        // (it just keeps the names in sequence).
        auto& nameInfo = wasm.typeNames[oldStructType];

        // Make a copy of the old ones before clearing them.
        auto oldFieldNames = nameInfo.fieldNames;

        // Clear the old names and write the new ones.
        nameInfo.fieldNames.clear();
        // Only need to preserve the field names for the vtable fields; the
        // itable fields do not have names (in the original .wat file they
        // are accessed by index).
        for (Index i = 0; i < insertIndex; i++) {
          if (auto name = oldFieldNames[i]) {
            nameInfo.fieldNames[i] = name;
          }
        }
        for (Index i = insertIndex; i < oldFieldNames.size(); i++) {
          if (auto name = oldFieldNames[i]) {
            nameInfo.fieldNames[i + parent.itableSize] = name;
          }
        }
      }
    };

    TypeRewriter(wasm, *this).update();
  }
};

} // anonymous namespace

Pass* createJ2CLItableMergingPass() { return new J2CLItableMerging(); }
} // namespace wasm
