// Copyright 2017 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.

#ifndef V8_WASM_HEAP_H_
#define V8_WASM_HEAP_H_

#include <functional>
#include <list>
#include <map>
#include <unordered_map>
#include <unordered_set>

#include "src/base/macros.h"
#include "src/handles.h"
#include "src/trap-handler/trap-handler.h"
#include "src/vector.h"

namespace v8 {
class Isolate;
namespace internal {

struct CodeDesc;
class Code;
class WasmCompiledModule;

namespace wasm {

using GlobalHandleAddress = Address;
class NativeModule;
struct WasmModule;

struct AddressHasher {
  size_t operator()(const Address& addr) const {
    return std::hash<intptr_t>()(reinterpret_cast<intptr_t>(addr));
  }
};

// Sorted, disjoint and non-overlapping memory ranges. A range is of the
// form [start, end). So there's no [start, end), [end, other_end),
// because that should have been reduced to [start, other_end).
using AddressRange = std::pair<Address, Address>;
class V8_EXPORT_PRIVATE DisjointAllocationPool final {
 public:
  enum ExtractionMode : bool { kAny = false, kContiguous = true };
  DisjointAllocationPool() {}

  explicit DisjointAllocationPool(Address, Address);

  DisjointAllocationPool(DisjointAllocationPool&& other) = default;
  DisjointAllocationPool& operator=(DisjointAllocationPool&& other) = default;

  // Merge the ranges of the parameter into this object. Ordering is
  // preserved. The assumption is that the passed parameter is
  // not intersecting this object - for example, it was obtained
  // from a previous Allocate{Pool}.
  void Merge(DisjointAllocationPool&&);

  // Allocate a contiguous range of size {size}. Return an empty pool on
  // failure.
  DisjointAllocationPool Allocate(size_t size) {
    return Extract(size, kContiguous);
  }

  // Allocate a sub-pool of size {size}. Return an empty pool on failure.
  DisjointAllocationPool AllocatePool(size_t size) {
    return Extract(size, kAny);
  }

  bool IsEmpty() const { return ranges_.empty(); }
  const std::list<AddressRange>& ranges() const { return ranges_; }

 private:
  // Extract out a total of {size}. By default, the return may
  // be more than one range. If kContiguous is passed, the return
  // will be one range. If the operation fails, this object is
  // unchanged, and the return {IsEmpty()}
  DisjointAllocationPool Extract(size_t size, ExtractionMode mode);

  std::list<AddressRange> ranges_;

  DISALLOW_COPY_AND_ASSIGN(DisjointAllocationPool)
};

using ProtectedInstructions =
    std::vector<trap_handler::ProtectedInstructionData>;

class V8_EXPORT_PRIVATE WasmCode final {
 public:
  enum Kind {
    kFunction,
    kWasmToWasmWrapper,
    kWasmToJsWrapper,
    kLazyStub,
    kInterpreterStub,
    kCopiedStub,
    kTrampoline
  };

  Vector<byte> instructions() const { return instructions_; }
  Vector<const byte> reloc_info() const {
    return {reloc_info_.get(), reloc_size_};
  }

  uint32_t index() const { return index_.ToChecked(); }
  // Anonymous functions are functions that don't carry an index, like
  // trampolines.
  bool IsAnonymous() const { return index_.IsNothing(); }
  Kind kind() const { return kind_; }
  NativeModule* owner() const { return owner_; }
  Address constant_pool() const;
  size_t constant_pool_offset() const { return constant_pool_offset_; }
  size_t safepoint_table_offset() const { return safepoint_table_offset_; }
  uint32_t stack_slots() const { return stack_slots_; }
  bool is_liftoff() const { return is_liftoff_; }

  size_t trap_handler_index() const;
  void set_trap_handler_index(size_t);
  bool HasTrapHandlerIndex() const;
  void ResetTrapHandlerIndex();

  const ProtectedInstructions& protected_instructions() const {
    return *protected_instructions_.get();
  }

  void Print(Isolate* isolate) const;
  void Disassemble(const char* name, Isolate* isolate, std::ostream& os) const;

  ~WasmCode();

 private:
  friend class NativeModule;
  friend class NativeModuleDeserializer;

  // A constructor used just for implementing Lookup.
  WasmCode(Address pc) : instructions_(pc, 0), index_(Nothing<uint32_t>()) {}

  WasmCode(Vector<byte> instructions,
           std::unique_ptr<const byte[]>&& reloc_info, size_t reloc_size,
           NativeModule* owner, Maybe<uint32_t> index, Kind kind,
           size_t constant_pool_offset, uint32_t stack_slots,
           size_t safepoint_table_offset,
           std::shared_ptr<ProtectedInstructions> protected_instructions,
           bool is_liftoff = false)
      : instructions_(instructions),
        reloc_info_(std::move(reloc_info)),
        reloc_size_(reloc_size),
        owner_(owner),
        index_(index),
        kind_(kind),
        constant_pool_offset_(constant_pool_offset),
        stack_slots_(stack_slots),
        safepoint_table_offset_(safepoint_table_offset),
        protected_instructions_(std::move(protected_instructions)),
        is_liftoff_(is_liftoff) {}

  WasmCode(const WasmCode&) = delete;
  WasmCode& operator=(const WasmCode&) = delete;

  Vector<byte> instructions_;
  std::unique_ptr<const byte[]> reloc_info_;
  size_t reloc_size_ = 0;
  NativeModule* owner_ = nullptr;
  Maybe<uint32_t> index_;
  Kind kind_;
  size_t constant_pool_offset_ = 0;
  uint32_t stack_slots_ = 0;
  // we care about safepoint data for wasm-to-js functions,
  // since there may be stack/register tagged values for large number
  // conversions.
  size_t safepoint_table_offset_ = 0;
  intptr_t trap_handler_index_ = -1;
  std::shared_ptr<ProtectedInstructions> protected_instructions_;
  bool is_liftoff_;
};

// Return a textual description of the kind.
const char* GetWasmCodeKindAsString(WasmCode::Kind);

class WasmCodeManager;

// Note that we currently need to add code on the main thread, because we may
// trigger a GC if we believe there's a chance the GC would clear up native
// modules. The code is ready for concurrency otherwise, we just need to be
// careful about this GC consideration. See WouldGCHelp and
// WasmCodeManager::Commit.
class V8_EXPORT_PRIVATE NativeModule final {
 public:
  std::unique_ptr<NativeModule> Clone();

  WasmCode* AddCode(const CodeDesc& desc, uint32_t frame_count, uint32_t index,
                    size_t safepoint_table_offset,
                    std::unique_ptr<ProtectedInstructions>,
                    bool is_liftoff = false);

  // A way to copy over JS-allocated code. This is because we compile
  // certain wrappers using a different pipeline.
  WasmCode* AddCodeCopy(Handle<Code> code, WasmCode::Kind kind, uint32_t index);

  // Add an interpreter wrapper. For the same reason as AddCodeCopy, we
  // currently compile these using a different pipeline and we can't get a
  // CodeDesc here. When adding interpreter wrappers, we do not insert them in
  // the code_table, however, we let them self-identify as the {index} function
  WasmCode* AddInterpreterWrapper(Handle<Code> code, uint32_t index);

  // When starting lazy compilation, provide the WasmLazyCompile builtin by
  // calling SetLazyBuiltin. It will initialize the code table with it, and the
  // lazy_builtin_ field. The latter is used when creating entries for exported
  // functions and indirect callable functions, so that they may be identified
  // by the runtime.
  WasmCode* SetLazyBuiltin(Handle<Code> code);

  // ExportedWrappers are WasmToWasmWrappers for functions placed on import
  // tables. We construct them as-needed.
  WasmCode* GetExportedWrapper(uint32_t index);
  WasmCode* AddExportedWrapper(Handle<Code> code, uint32_t index);

  // FunctionCount is WasmModule::functions.size().
  uint32_t FunctionCount() const;
  WasmCode* GetCode(uint32_t index) const;

  WasmCode* lazy_builtin() const { return lazy_builtin_; }

  // We special-case lazy cloning because we currently rely on making copies
  // of the lazy builtin, to be able to identify, in the runtime, which function
  // the lazy builtin is a placeholder of. If we used trampolines, we would call
  // the runtime function from a common pc. We could, then, figure who the
  // caller was if the trampolines called rather than jumped to the common
  // builtin. The logic for seeking though frames would change, though.
  // TODO(mtrofin): perhaps we can do exactly that - either before or after
  // this change.
  WasmCode* CloneLazyBuiltinInto(uint32_t);

  bool SetExecutable(bool executable);

  // For cctests, where we build both WasmModule and the runtime objects
  // on the fly, and bypass the instance builder pipeline.
  void ResizeCodeTableForTest(size_t);
  void LinkAll();
  void Link(uint32_t index);

  // TODO(mtrofin): needed until we sort out exception handlers and
  // source positions, which are still on the  GC-heap.
  WasmCompiledModule* compiled_module() const;
  void SetCompiledModule(Handle<WasmCompiledModule>);

  // Shorthand accessors to the specialization data content.
  std::vector<wasm::GlobalHandleAddress>& function_tables() {
    return specialization_data_.function_tables;
  }

  std::vector<wasm::GlobalHandleAddress>& empty_function_tables() {
    return specialization_data_.empty_function_tables;
  }

  uint32_t num_imported_functions() const { return num_imported_functions_; }
  size_t num_function_tables() const {
    return specialization_data_.empty_function_tables.size();
  }

  size_t committed_memory() const { return committed_memory_; }
  const size_t instance_id = 0;
  ~NativeModule();

 private:
  friend class WasmCodeManager;
  friend class NativeModuleSerializer;
  friend class NativeModuleDeserializer;

  struct WasmCodeUniquePtrComparer {
    bool operator()(const std::unique_ptr<WasmCode>& a,
                    const std::unique_ptr<WasmCode>& b) {
      DCHECK(a);
      DCHECK(b);
      return a->instructions().start() < b->instructions().start();
    }
  };

  static base::AtomicNumber<uint32_t> next_id_;
  NativeModule(const NativeModule&) = delete;
  NativeModule& operator=(const NativeModule&) = delete;
  NativeModule(uint32_t num_functions, uint32_t num_imports,
               bool can_request_more, VirtualMemory* vmem,
               WasmCodeManager* code_manager);

  WasmCode* AddAnonymousCode(Handle<Code>, WasmCode::Kind kind);
  Address AllocateForCode(size_t size);

  // Primitive for adding code to the native module. All code added to a native
  // module is owned by that module. Various callers get to decide on how the
  // code is obtained (CodeDesc vs, as a point in time, Code*), the kind,
  // whether it has an index or is anonymous, etc.
  WasmCode* AddOwnedCode(Vector<const byte> orig_instructions,
                         std::unique_ptr<const byte[]> reloc_info,
                         size_t reloc_size, Maybe<uint32_t> index,
                         WasmCode::Kind kind, size_t constant_pool_offset,
                         uint32_t stack_slots, size_t safepoint_table_offset,
                         std::shared_ptr<ProtectedInstructions>,
                         bool is_liftoff = false);
  void SetCodeTable(uint32_t, wasm::WasmCode*);
  WasmCode* CloneCode(const WasmCode*);
  bool CloneTrampolinesAndStubs(const NativeModule* other);
  WasmCode* Lookup(Address);
  Address GetLocalAddressFor(Handle<Code>);
  Address CreateTrampolineTo(Handle<Code>);

  std::vector<std::unique_ptr<WasmCode>> owned_code_;
  std::unordered_map<uint32_t, WasmCode*> exported_wasm_to_wasm_wrappers_;

  WasmCodeUniquePtrComparer owned_code_comparer_;

  std::vector<WasmCode*> code_table_;
  uint32_t num_imported_functions_;

  std::unordered_map<Address, Address, AddressHasher> trampolines_;
  std::unordered_map<uint32_t, WasmCode*> stubs_;

  DisjointAllocationPool free_memory_;
  DisjointAllocationPool allocated_memory_;
  std::list<VirtualMemory> owned_memory_;
  WasmCodeManager* wasm_code_manager_;
  wasm::WasmCode* lazy_builtin_ = nullptr;
  base::Mutex allocation_mutex_;
  Handle<WasmCompiledModule> compiled_module_;
  size_t committed_memory_ = 0;
  bool can_request_more_memory_;
  bool is_executable_ = false;

  // Specialization data that needs to be serialized and cloned.
  // Keeping it groupped together because it makes cloning of all these
  // elements a 1 line copy.
  struct {
    std::vector<wasm::GlobalHandleAddress> function_tables;
    std::vector<wasm::GlobalHandleAddress> empty_function_tables;
  } specialization_data_;
};

class V8_EXPORT_PRIVATE WasmCodeManager final {
 public:
  // The only reason we depend on Isolate is to report native memory used
  // and held by a GC-ed object. We'll need to mitigate that when we
  // start sharing wasm heaps.
  WasmCodeManager(v8::Isolate*, size_t max_committed);
  // Create a new NativeModule. The caller is responsible for its
  // lifetime. The native module will be given some memory for code,
  // which will be page size aligned. The size of the initial memory
  // is determined with a heuristic based on the total size of wasm
  // code. The native module may later request more memory.
  std::unique_ptr<NativeModule> NewNativeModule(const WasmModule&);
  std::unique_ptr<NativeModule> NewNativeModule(size_t memory_estimate,
                                                uint32_t num_functions,
                                                uint32_t num_imported_functions,
                                                bool can_request_more);

  WasmCode* LookupCode(Address pc) const;
  WasmCode* GetCodeFromStartAddress(Address pc) const;
  intptr_t remaining_uncommitted() const;

  // TODO(mtrofin): replace this API with an alternative that is Isolate-
  // independent.
  void FlushICache(Address start, size_t size);

 private:
  friend class NativeModule;

  WasmCodeManager(const WasmCodeManager&) = delete;
  WasmCodeManager& operator=(const WasmCodeManager&) = delete;
  void TryAllocate(size_t size, VirtualMemory*, void* hint = nullptr);
  bool Commit(Address, size_t);
  // Currently, we uncommit a whole module, so all we need is account
  // for the freed memory size. We do that in FreeNativeModuleMemories.
  // There's no separate Uncommit.

  void FreeNativeModuleMemories(NativeModule*);
  void Free(VirtualMemory* mem);
  void AssignRanges(void* start, void* end, NativeModule*);
  size_t GetAllocationChunk(const WasmModule& module);
  bool WouldGCHelp() const;

  std::map<Address, std::pair<Address, NativeModule*>> lookup_map_;
  // count of NativeModules not yet collected. Helps determine if it's
  // worth requesting a GC on memory pressure.
  size_t active_ = 0;
  base::AtomicNumber<intptr_t> remaining_uncommitted_;

  // TODO(mtrofin): remove the dependency on isolate.
  v8::Isolate* isolate_;
};

// Within the scope, the native_module is writable and not executable.
// At the scope's destruction, the native_module is executable and not writable.
// The states inside the scope and at the scope termination are irrespective of
// native_module's state when entering the scope.
// We currently mark the entire module's memory W^X:
//  - for AOT, that's as efficient as it can be.
//  - for Lazy, we don't have a heuristic for functions that may need patching,
//    and even if we did, the resulting set of pages may be fragmented.
//    Currently, we try and keep the number of syscalls low.
// -  similar argument for debug time.
class NativeModuleModificationScope final {
 public:
  explicit NativeModuleModificationScope(NativeModule* native_module);
  ~NativeModuleModificationScope();

 private:
  NativeModule* native_module_;
};

// Utilities specific to wasm code generation. We embed a tag for call sites -
// the index of the called function - when serializing and when creating the
// code, initially. These APIs offer accessors. The implementation has platform
// specific nuances.
void SetWasmCalleeTag(RelocInfo* rinfo, uint32_t tag);
uint32_t GetWasmCalleeTag(RelocInfo* rinfo);

}  // namespace wasm
}  // namespace internal
}  // namespace v8
#endif
