// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/wasm/wasm-subtyping.h"

#include "src/base/platform/mutex.h"
#include "src/wasm/wasm-module.h"
#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {
namespace wasm {

namespace {

using CacheKey =
    std::tuple<uint32_t, uint32_t, const WasmModule*, const WasmModule*>;

struct CacheKeyHasher {
  size_t operator()(CacheKey key) const {
    static constexpr size_t large_prime = 14887;
    return std::get<0>(key) + (std::get<1>(key) * large_prime) +
           (reinterpret_cast<size_t>(std::get<2>(key)) * large_prime *
            large_prime) +
           (reinterpret_cast<size_t>(std::get<3>(key)) * large_prime *
            large_prime * large_prime);
  }
};

class TypeJudgementCache {
 public:
  TypeJudgementCache()
      : zone_(new AccountingAllocator(), "type judgement zone"),
        subtyping_cache_(&zone_),
        type_equivalence_cache_(&zone_) {}

  static TypeJudgementCache* instance() {
    static base::LazyInstance<TypeJudgementCache>::type instance_ =
        LAZY_INSTANCE_INITIALIZER;
    return instance_.Pointer();
  }

  base::RecursiveMutex* type_cache_mutex() { return &type_cache_mutex_; }
  bool is_cached_subtype(uint32_t subtype, uint32_t supertype,
                         const WasmModule* sub_module,
                         const WasmModule* super_module) const {
    return subtyping_cache_.count(std::make_tuple(
               subtype, supertype, sub_module, super_module)) == 1;
  }
  void cache_subtype(uint32_t subtype, uint32_t supertype,
                     const WasmModule* sub_module,
                     const WasmModule* super_module) {
    subtyping_cache_.emplace(subtype, supertype, sub_module, super_module);
  }
  void uncache_subtype(uint32_t subtype, uint32_t supertype,
                       const WasmModule* sub_module,
                       const WasmModule* super_module) {
    subtyping_cache_.erase(
        std::make_tuple(subtype, supertype, sub_module, super_module));
  }
  bool is_cached_equivalent_type(uint32_t type1, uint32_t type2,
                                 const WasmModule* module1,
                                 const WasmModule* module2) const {
    if (type1 > type2) std::swap(type1, type2);
    if (reinterpret_cast<uintptr_t>(module1) >
        reinterpret_cast<uintptr_t>(module2)) {
      std::swap(module1, module2);
    }
    return type_equivalence_cache_.count(
               std::make_tuple(type1, type2, module1, module2)) == 1;
  }
  void cache_type_equivalence(uint32_t type1, uint32_t type2,
                              const WasmModule* module1,
                              const WasmModule* module2) {
    if (type1 > type2) std::swap(type1, type2);
    if (reinterpret_cast<uintptr_t>(module1) >
        reinterpret_cast<uintptr_t>(module2)) {
      std::swap(module1, module2);
    }
    type_equivalence_cache_.emplace(type1, type2, module1, module2);
  }
  void uncache_type_equivalence(uint32_t type1, uint32_t type2,
                                const WasmModule* module1,
                                const WasmModule* module2) {
    if (type1 > type2) std::swap(type1, type2);
    if (reinterpret_cast<uintptr_t>(module1) >
        reinterpret_cast<uintptr_t>(module2)) {
      std::swap(module1, module2);
    }
    type_equivalence_cache_.erase(
        std::make_tuple(type1, type2, module1, module2));
  }

 private:
  Zone zone_;
  ZoneUnorderedSet<CacheKey, CacheKeyHasher>
      // Cache for discovered subtyping pairs.
      subtyping_cache_,
      // Cache for discovered equivalent type pairs.
      // Indexes and modules are stored in increasing order.
      type_equivalence_cache_;
  // The above two caches are used from background compile jobs, so they
  // must be protected from concurrent modifications:
  base::RecursiveMutex type_cache_mutex_;
};

bool ArrayEquivalentIndices(uint32_t type_index_1, uint32_t type_index_2,
                            const WasmModule* module1,
                            const WasmModule* module2) {
  const ArrayType* sub_array = module1->types[type_index_1].array_type;
  const ArrayType* super_array = module2->types[type_index_2].array_type;
  if (sub_array->mutability() != super_array->mutability()) return false;

  // Temporarily cache type equivalence for the recursive call.
  TypeJudgementCache::instance()->cache_type_equivalence(
      type_index_1, type_index_2, module1, module2);
  if (EquivalentTypes(sub_array->element_type(), super_array->element_type(),
                      module1, module2)) {
    return true;
  } else {
    TypeJudgementCache::instance()->uncache_type_equivalence(
        type_index_1, type_index_2, module1, module2);
    // TODO(7748): Consider caching negative results as well.
    return false;
  }
}

bool StructEquivalentIndices(uint32_t type_index_1, uint32_t type_index_2,
                             const WasmModule* module1,
                             const WasmModule* module2) {
  const StructType* sub_struct = module1->types[type_index_1].struct_type;
  const StructType* super_struct = module2->types[type_index_2].struct_type;

  if (sub_struct->field_count() != super_struct->field_count()) {
    return false;
  }

  // Temporarily cache type equivalence for the recursive call.
  TypeJudgementCache::instance()->cache_type_equivalence(
      type_index_1, type_index_2, module1, module2);
  for (uint32_t i = 0; i < sub_struct->field_count(); i++) {
    if (sub_struct->mutability(i) != super_struct->mutability(i) ||
        !EquivalentTypes(sub_struct->field(i), super_struct->field(i), module1,
                         module2)) {
      TypeJudgementCache::instance()->uncache_type_equivalence(
          type_index_1, type_index_2, module1, module2);
      return false;
    }
  }
  return true;
}

bool FunctionEquivalentIndices(uint32_t type_index_1, uint32_t type_index_2,
                               const WasmModule* module1,
                               const WasmModule* module2) {
  const FunctionSig* sig1 = module1->types[type_index_1].function_sig;
  const FunctionSig* sig2 = module2->types[type_index_2].function_sig;

  if (sig1->parameter_count() != sig2->parameter_count() ||
      sig1->return_count() != sig2->return_count()) {
    return false;
  }

  auto iter1 = sig1->all();
  auto iter2 = sig2->all();

  // Temporarily cache type equivalence for the recursive call.
  TypeJudgementCache::instance()->cache_type_equivalence(
      type_index_1, type_index_2, module1, module2);
  for (int i = 0; i < iter1.size(); i++) {
    if (!EquivalentTypes(iter1[i], iter2[i], module1, module2)) {
      TypeJudgementCache::instance()->uncache_type_equivalence(
          type_index_1, type_index_2, module1, module2);
      return false;
    }
  }
  return true;
}

V8_INLINE bool EquivalentIndices(uint32_t index1, uint32_t index2,
                                 const WasmModule* module1,
                                 const WasmModule* module2) {
  DCHECK(index1 != index2 || module1 != module2);
  uint8_t kind1 = module1->type_kinds[index1];

  if (kind1 != module2->type_kinds[index2]) return false;

  base::RecursiveMutexGuard type_cache_access(
      TypeJudgementCache::instance()->type_cache_mutex());
  if (TypeJudgementCache::instance()->is_cached_equivalent_type(
          index1, index2, module1, module2)) {
    return true;
  }

  if (kind1 == kWasmStructTypeCode) {
    return StructEquivalentIndices(index1, index2, module1, module2);
  } else if (kind1 == kWasmArrayTypeCode) {
    return ArrayEquivalentIndices(index1, index2, module1, module2);
  } else {
    DCHECK_EQ(kind1, kWasmFunctionTypeCode);
    return FunctionEquivalentIndices(index1, index2, module1, module2);
  }
}

bool StructIsSubtypeOf(uint32_t subtype_index, uint32_t supertype_index,
                       const WasmModule* sub_module,
                       const WasmModule* super_module) {
  const StructType* sub_struct = sub_module->types[subtype_index].struct_type;
  const StructType* super_struct =
      super_module->types[supertype_index].struct_type;

  if (sub_struct->field_count() < super_struct->field_count()) {
    return false;
  }

  TypeJudgementCache::instance()->cache_subtype(subtype_index, supertype_index,
                                                sub_module, super_module);
  for (uint32_t i = 0; i < super_struct->field_count(); i++) {
    bool sub_mut = sub_struct->mutability(i);
    bool super_mut = super_struct->mutability(i);
    if (sub_mut != super_mut ||
        (sub_mut &&
         !EquivalentTypes(sub_struct->field(i), super_struct->field(i),
                          sub_module, super_module)) ||
        (!sub_mut && !IsSubtypeOf(sub_struct->field(i), super_struct->field(i),
                                  sub_module, super_module))) {
      TypeJudgementCache::instance()->uncache_subtype(
          subtype_index, supertype_index, sub_module, super_module);
      return false;
    }
  }
  return true;
}

bool ArrayIsSubtypeOf(uint32_t subtype_index, uint32_t supertype_index,
                      const WasmModule* sub_module,
                      const WasmModule* super_module) {
  const ArrayType* sub_array = sub_module->types[subtype_index].array_type;
  const ArrayType* super_array =
      super_module->types[supertype_index].array_type;
  bool sub_mut = sub_array->mutability();
  bool super_mut = super_array->mutability();
  TypeJudgementCache::instance()->cache_subtype(subtype_index, supertype_index,
                                                sub_module, super_module);
  if (sub_mut != super_mut ||
      (sub_mut &&
       !EquivalentTypes(sub_array->element_type(), super_array->element_type(),
                        sub_module, super_module)) ||
      (!sub_mut &&
       !IsSubtypeOf(sub_array->element_type(), super_array->element_type(),
                    sub_module, super_module))) {
    TypeJudgementCache::instance()->uncache_subtype(
        subtype_index, supertype_index, sub_module, super_module);
    return false;
  } else {
    return true;
  }
}

// TODO(7748): Expand this with function subtyping once the hiccups
// with 'exact types' have been cleared.
bool FunctionIsSubtypeOf(uint32_t subtype_index, uint32_t supertype_index,
                         const WasmModule* sub_module,
                         const WasmModule* super_module) {
  return FunctionEquivalentIndices(subtype_index, supertype_index, sub_module,
                                   super_module);
}

}  // namespace

// TODO(7748): Extend this with any-heap subtyping.
V8_NOINLINE V8_EXPORT_PRIVATE bool IsSubtypeOfImpl(
    ValueType subtype, ValueType supertype, const WasmModule* sub_module,
    const WasmModule* super_module) {
  DCHECK(subtype != supertype || sub_module != super_module);

  // This function checks for subtyping based on the kind of subtype.

  if (!subtype.is_reference_type()) return subtype == supertype;

  if (subtype.kind() == ValueType::kRtt) {
    return subtype.heap_type().is_generic()
               ? subtype == supertype
               : (supertype.kind() == ValueType::kRtt &&
                  subtype.depth() == supertype.depth() &&
                  EquivalentIndices(subtype.ref_index(), supertype.ref_index(),
                                    sub_module, super_module));
  }

  DCHECK(subtype.is_object_reference_type());

  bool compatible_references = subtype.kind() == ValueType::kOptRef
                                   ? supertype.kind() == ValueType::kOptRef
                                   : supertype.is_object_reference_type();
  if (!compatible_references) return false;

  DCHECK(supertype.is_object_reference_type());

  // Now check that sub_heap and super_heap are subtype-related.

  HeapType sub_heap = subtype.heap_type();
  HeapType super_heap = supertype.heap_type();

  if (sub_heap.representation() == HeapType::kI31 &&
      super_heap.representation() == HeapType::kEq) {
    return true;
  }
  if (sub_heap.is_generic()) return sub_heap == super_heap;

  DCHECK(sub_heap.is_index());
  uint32_t sub_index = sub_heap.ref_index();
  DCHECK(sub_module->has_type(sub_index));

  if (super_heap.representation() == HeapType::kEq) {
    return !sub_module->has_signature(sub_heap.ref_index());
  }
  if (super_heap.representation() == HeapType::kFunc) {
    return sub_module->has_signature(sub_heap.ref_index());
  }
  if (super_heap.is_generic()) return false;

  DCHECK(super_heap.is_index());
  uint32_t super_index = super_heap.ref_index();
  DCHECK(super_module->has_type(super_index));

  uint8_t sub_kind = sub_module->type_kinds[sub_index];

  if (sub_kind != super_module->type_kinds[super_index]) return false;

  // Accessing the caches for subtyping and equivalence from multiple background
  // threads is protected by a lock.
  base::RecursiveMutexGuard type_cache_access(
      TypeJudgementCache::instance()->type_cache_mutex());
  if (TypeJudgementCache::instance()->is_cached_subtype(
          sub_index, super_index, sub_module, super_module)) {
    return true;
  }

  if (sub_kind == kWasmStructTypeCode) {
    return StructIsSubtypeOf(sub_index, super_index, sub_module, super_module);
  } else if (sub_kind == kWasmArrayTypeCode) {
    return ArrayIsSubtypeOf(sub_index, super_index, sub_module, super_module);
  } else {
    DCHECK_EQ(sub_kind, kWasmFunctionTypeCode);
    return FunctionIsSubtypeOf(sub_index, super_index, sub_module,
                               super_module);
  }
}

V8_NOINLINE bool EquivalentTypes(ValueType type1, ValueType type2,
                                 const WasmModule* module1,
                                 const WasmModule* module2) {
  if (type1 == type2 && module1 == module2) return true;
  if (!type1.has_index()) return type1 == type2;
  if (type1.kind() != type2.kind()) return false;

  DCHECK(type1.has_index() && type2.has_index() &&
         (type1 != type2 || module1 != module2));

  DCHECK_IMPLIES(type1.has_depth(), type2.has_depth());  // Due to 'if' above
  if (type1.has_depth() && type1.depth() != type2.depth()) return false;

  DCHECK(type1.has_index() && module1->has_type(type1.ref_index()) &&
         type2.has_index() && module2->has_type(type2.ref_index()));

  return EquivalentIndices(type1.ref_index(), type2.ref_index(), module1,
                           module2);
}

ValueType CommonSubtype(ValueType a, ValueType b, const WasmModule* module) {
  if (a == b) return a;
  if (IsSubtypeOf(a, b, module)) return a;
  if (IsSubtypeOf(b, a, module)) return b;
  return kWasmBottom;
}

}  // namespace wasm
}  // namespace internal
}  // namespace v8
