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

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

#include "src/assembler-inl.h"
#include "src/code-stubs.h"
#include "src/external-reference-table.h"
#include "src/objects-inl.h"
#include "src/objects.h"
#include "src/snapshot/code-serializer.h"
#include "src/snapshot/serializer-common.h"
#include "src/version.h"
#include "src/wasm/module-compiler.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/wasm-code-manager.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-result.h"

namespace v8 {
namespace internal {
namespace wasm {
namespace {

class Writer {
 public:
  explicit Writer(Vector<byte> buffer) : buffer_(buffer) {}
  template <typename T>
  void Write(const T& value) {
    if (FLAG_wasm_trace_serialization) {
      OFStream os(stdout);
      os << "wrote: " << (size_t)value << " sized: " << sizeof(T) << std::endl;
    }
    DCHECK_GE(buffer_.size(), sizeof(T));
    memcpy(buffer_.start(), reinterpret_cast<const byte*>(&value), sizeof(T));
    buffer_ = buffer_ + sizeof(T);
  }

  void WriteVector(const Vector<const byte> data) {
    DCHECK_GE(buffer_.size(), data.size());
    if (data.size() > 0) {
      memcpy(buffer_.start(), data.start(), data.size());
      buffer_ = buffer_ + data.size();
    }
    if (FLAG_wasm_trace_serialization) {
      OFStream os(stdout);
      os << "wrote vector of " << data.size() << " elements" << std::endl;
    }
  }
  Vector<byte> current_buffer() const { return buffer_; }

 private:
  Vector<byte> buffer_;
};

class Reader {
 public:
  explicit Reader(Vector<const byte> buffer) : buffer_(buffer) {}

  template <typename T>
  T Read() {
    DCHECK_GE(buffer_.size(), sizeof(T));
    T ret;
    memcpy(reinterpret_cast<byte*>(&ret), buffer_.start(), sizeof(T));
    buffer_ = buffer_ + sizeof(T);
    if (FLAG_wasm_trace_serialization) {
      OFStream os(stdout);
      os << "read: " << (size_t)ret << " sized: " << sizeof(T) << std::endl;
    }
    return ret;
  }

  Vector<const byte> GetSubvector(size_t size) {
    Vector<const byte> ret = {buffer_.start(), size};
    buffer_ = buffer_ + size;
    return ret;
  }

  void ReadIntoVector(const Vector<byte> data) {
    if (data.size() > 0) {
      DCHECK_GE(buffer_.size(), data.size());
      memcpy(data.start(), buffer_.start(), data.size());
      buffer_ = buffer_ + data.size();
    }
    if (FLAG_wasm_trace_serialization) {
      OFStream os(stdout);
      os << "read vector of " << data.size() << " elements" << std::endl;
    }
  }

  Vector<const byte> current_buffer() const { return buffer_; }

 private:
  Vector<const byte> buffer_;
};

constexpr size_t kVersionSize = 4 * sizeof(uint32_t);

void WriteVersion(Isolate* isolate, Vector<byte> buffer) {
  DCHECK_GE(buffer.size(), kVersionSize);
  Writer writer(buffer);
  writer.Write(SerializedData::ComputeMagicNumber(
      ExternalReferenceTable::instance(isolate)));
  writer.Write(Version::Hash());
  writer.Write(static_cast<uint32_t>(CpuFeatures::SupportedFeatures()));
  writer.Write(FlagList::Hash());
}

bool IsSupportedVersion(Isolate* isolate, const Vector<const byte> buffer) {
  if (buffer.size() < kVersionSize) return false;
  byte version[kVersionSize];
  WriteVersion(isolate, {version, kVersionSize});
  if (memcmp(buffer.start(), version, kVersionSize) == 0) return true;
  return false;
}

}  // namespace

enum SerializationSection { Init, Metadata, Stubs, CodeSection, Done };

class V8_EXPORT_PRIVATE NativeModuleSerializer {
 public:
  explicit NativeModuleSerializer(Isolate*, const NativeModule*);
  size_t Measure() const;
  size_t Write(Vector<byte>);
  bool IsDone() const { return state_ == Done; }

 private:
  size_t MeasureHeader() const;
  static size_t GetCodeHeaderSize();
  size_t MeasureCode(const WasmCode*) const;
  size_t MeasureCopiedStubs() const;
  FixedArray* GetHandlerTable(const WasmCode*) const;
  ByteArray* GetSourcePositions(const WasmCode*) const;

  void BufferHeader();
  // we buffer all the stubs because they are small
  void BufferCopiedStubs();
  void BufferCodeInAllocatedScratch(const WasmCode*);
  void BufferCurrentWasmCode();
  size_t DrainBuffer(Vector<byte> dest);
  uint32_t EncodeBuiltinOrStub(Address);

  Isolate* const isolate_ = nullptr;
  const NativeModule* const native_module_ = nullptr;
  SerializationSection state_ = Init;
  uint32_t index_ = 0;
  std::vector<byte> scratch_;
  Vector<byte> remaining_;
  // wasm and copied stubs reverse lookup
  std::map<Address, uint32_t> wasm_targets_lookup_;
  // immovable builtins and runtime entries lookup
  std::map<Address, uint32_t> reference_table_lookup_;
  std::map<Address, uint32_t> stub_lookup_;
  std::map<Address, uint32_t> builtin_lookup_;
};

class V8_EXPORT_PRIVATE NativeModuleDeserializer {
 public:
  explicit NativeModuleDeserializer(Isolate*, NativeModule*);
  // Currently, we don't support streamed reading, yet albeit the
  // API suggests that.
  bool Read(Vector<const byte>);

 private:
  void ExpectHeader();
  void Expect(size_t size);
  bool ReadHeader();
  bool ReadCode();
  bool ReadStubs();
  Address GetTrampolineOrStubFromTag(uint32_t);

  Isolate* const isolate_ = nullptr;
  NativeModule* const native_module_ = nullptr;
  std::vector<byte> scratch_;
  std::vector<Address> stubs_;
  Vector<const byte> unread_;
  size_t current_expectation_ = 0;
  uint32_t index_ = 0;
};

NativeModuleSerializer::NativeModuleSerializer(Isolate* isolate,
                                               const NativeModule* module)
    : isolate_(isolate), native_module_(module) {
  DCHECK_NOT_NULL(isolate_);
  DCHECK_NOT_NULL(native_module_);
  DCHECK_NULL(native_module_->lazy_builtin_);
  // TODO(mtrofin): persist the export wrappers. Ideally, we'd only persist
  // the unique ones, i.e. the cache.
  ExternalReferenceTable* table = ExternalReferenceTable::instance(isolate_);
  for (uint32_t i = 0; i < table->size(); ++i) {
    Address addr = table->address(i);
    reference_table_lookup_.insert(std::make_pair(addr, i));
  }
  // defer populating the stub_lookup_ to when we buffer the stubs
  for (auto pair : native_module_->trampolines_) {
    v8::internal::Code* code = Code::GetCodeFromTargetAddress(pair.first);
    int builtin_index = code->builtin_index();
    if (builtin_index >= 0) {
      uint32_t tag = static_cast<uint32_t>(builtin_index);
      builtin_lookup_.insert(std::make_pair(pair.second, tag));
    }
  }
  BufferHeader();
  state_ = Metadata;
}

size_t NativeModuleSerializer::MeasureHeader() const {
  return sizeof(uint32_t) +  // total wasm fct count
         sizeof(
             uint32_t) +  // imported fcts - i.e. index of first wasm function
         sizeof(uint32_t) +  // table count
         native_module_->specialization_data_.function_tables.size()
             // function table, containing pointers
             * sizeof(GlobalHandleAddress);
}

void NativeModuleSerializer::BufferHeader() {
  size_t metadata_size = MeasureHeader();
  scratch_.resize(metadata_size);
  remaining_ = {scratch_.data(), metadata_size};
  Writer writer(remaining_);
  writer.Write(native_module_->FunctionCount());
  writer.Write(native_module_->num_imported_functions());
  writer.Write(static_cast<uint32_t>(
      native_module_->specialization_data_.function_tables.size()));
  for (size_t i = 0,
              e = native_module_->specialization_data_.function_tables.size();
       i < e; ++i) {
    writer.Write(native_module_->specialization_data_.function_tables[i]);
  }
}

size_t NativeModuleSerializer::GetCodeHeaderSize() {
  return sizeof(size_t) +    // size of this section
         sizeof(size_t) +    // offset of constant pool
         sizeof(size_t) +    // offset of safepoint table
         sizeof(uint32_t) +  // stack slots
         sizeof(size_t) +    // code size
         sizeof(size_t) +    // reloc size
         sizeof(uint32_t) +  // handler size
         sizeof(uint32_t) +  // source positions size
         sizeof(size_t) +    // protected instructions size
         sizeof(bool);       // is_liftoff
}

size_t NativeModuleSerializer::MeasureCode(const WasmCode* code) const {
  FixedArray* handler_table = GetHandlerTable(code);
  ByteArray* source_positions = GetSourcePositions(code);
  return GetCodeHeaderSize() + code->instructions().size() +  // code
         code->reloc_info().size() +                          // reloc info
         (handler_table == nullptr
              ? 0
              : static_cast<uint32_t>(
                    handler_table->length())) +  // handler table
         (source_positions == nullptr
              ? 0
              : static_cast<uint32_t>(
                    source_positions->length())) +  // source positions
         code->protected_instructions().size() *
             sizeof(trap_handler::ProtectedInstructionData);
}

size_t NativeModuleSerializer::Measure() const {
  size_t ret = MeasureHeader() + MeasureCopiedStubs();
  for (uint32_t i = native_module_->num_imported_functions(),
                e = native_module_->FunctionCount();
       i < e; ++i) {
    ret += MeasureCode(native_module_->GetCode(i));
  }
  return ret;
}

size_t NativeModuleSerializer::DrainBuffer(Vector<byte> dest) {
  size_t to_write = std::min(dest.size(), remaining_.size());
  memcpy(dest.start(), remaining_.start(), to_write);
  DCHECK_GE(remaining_.size(), to_write);
  remaining_ = remaining_ + to_write;
  return to_write;
}

size_t NativeModuleSerializer::MeasureCopiedStubs() const {
  size_t ret = sizeof(uint32_t) +  // number of stubs
               native_module_->stubs_.size() * sizeof(uint32_t);  // stub keys
  for (auto pair : native_module_->trampolines_) {
    v8::internal::Code* code = Code::GetCodeFromTargetAddress(pair.first);
    int builtin_index = code->builtin_index();
    if (builtin_index < 0) ret += sizeof(uint32_t);
  }
  return ret;
}

void NativeModuleSerializer::BufferCopiedStubs() {
  // We buffer all the stubs together, because they are very likely
  // few and small. Each stub is buffered like a WasmCode would,
  // and in addition prefaced by its stub key. The whole section is prefaced
  // by the number of stubs.
  size_t buff_size = MeasureCopiedStubs();
  scratch_.resize(buff_size);
  remaining_ = {scratch_.data(), buff_size};
  Writer writer(remaining_);
  writer.Write(
      static_cast<uint32_t>((buff_size - sizeof(uint32_t)) / sizeof(uint32_t)));
  uint32_t stub_id = 0;

  for (auto pair : native_module_->stubs_) {
    uint32_t key = pair.first;
    writer.Write(key);
    stub_lookup_.insert(
        std::make_pair(pair.second->instructions().start(), stub_id));
    ++stub_id;
  }

  for (auto pair : native_module_->trampolines_) {
    v8::internal::Code* code = Code::GetCodeFromTargetAddress(pair.first);
    int builtin_index = code->builtin_index();
    if (builtin_index < 0) {
      stub_lookup_.insert(std::make_pair(pair.second, stub_id));
      writer.Write(code->stub_key());
      ++stub_id;
    }
  }
}

FixedArray* NativeModuleSerializer::GetHandlerTable(
    const WasmCode* code) const {
  if (code->kind() != WasmCode::kFunction) return nullptr;
  uint32_t index = code->index();
  // We write the address, the size, and then copy the code as-is, followed
  // by reloc info, followed by handler table and source positions.
  Object* handler_table_entry =
      native_module_->compiled_module()->handler_table()->get(
          static_cast<int>(index));
  if (handler_table_entry->IsFixedArray()) {
    return FixedArray::cast(handler_table_entry);
  }
  return nullptr;
}

ByteArray* NativeModuleSerializer::GetSourcePositions(
    const WasmCode* code) const {
  if (code->kind() != WasmCode::kFunction) return nullptr;
  uint32_t index = code->index();
  Object* source_positions_entry =
      native_module_->compiled_module()->source_positions()->get(
          static_cast<int>(index));
  if (source_positions_entry->IsByteArray()) {
    return ByteArray::cast(source_positions_entry);
  }
  return nullptr;
}

void NativeModuleSerializer::BufferCurrentWasmCode() {
  const WasmCode* code = native_module_->GetCode(index_);
  size_t size = MeasureCode(code);
  scratch_.resize(size);
  remaining_ = {scratch_.data(), size};
  BufferCodeInAllocatedScratch(code);
}

void NativeModuleSerializer::BufferCodeInAllocatedScratch(
    const WasmCode* code) {
  // We write the address, the size, and then copy the code as-is, followed
  // by reloc info, followed by handler table and source positions.
  FixedArray* handler_table_entry = GetHandlerTable(code);
  uint32_t handler_table_size = 0;
  Address handler_table = nullptr;
  if (handler_table_entry != nullptr) {
    handler_table_size = static_cast<uint32_t>(handler_table_entry->length());
    handler_table = reinterpret_cast<Address>(
        handler_table_entry->GetFirstElementAddress());
  }
  ByteArray* source_positions_entry = GetSourcePositions(code);
  Address source_positions = nullptr;
  uint32_t source_positions_size = 0;
  if (source_positions_entry != nullptr) {
    source_positions = source_positions_entry->GetDataStartAddress();
    source_positions_size =
        static_cast<uint32_t>(source_positions_entry->length());
  }
  Writer writer(remaining_);
  // write the header
  writer.Write(MeasureCode(code));
  writer.Write(code->constant_pool_offset());
  writer.Write(code->safepoint_table_offset());
  writer.Write(code->stack_slots());
  writer.Write(code->instructions().size());
  writer.Write(code->reloc_info().size());
  writer.Write(handler_table_size);
  writer.Write(source_positions_size);
  writer.Write(code->protected_instructions().size());
  writer.Write(code->is_liftoff());
  // next is the code, which we have to reloc.
  Address serialized_code_start = writer.current_buffer().start();
  // write the code and everything else
  writer.WriteVector(code->instructions());
  writer.WriteVector(code->reloc_info());
  writer.WriteVector({handler_table, handler_table_size});
  writer.WriteVector({source_positions, source_positions_size});
  writer.WriteVector(
      {reinterpret_cast<const byte*>(code->protected_instructions().data()),
       sizeof(trap_handler::ProtectedInstructionData) *
           code->protected_instructions().size()});
  // now relocate the code
  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
             RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
             RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
  RelocIterator orig_iter(code->instructions(), code->reloc_info(),
                          code->constant_pool(), mask);
  for (RelocIterator
           iter({serialized_code_start, code->instructions().size()},
                code->reloc_info(),
                serialized_code_start + code->constant_pool_offset(), mask);
       !iter.done(); iter.next(), orig_iter.next()) {
    RelocInfo::Mode mode = orig_iter.rinfo()->rmode();
    switch (mode) {
      case RelocInfo::CODE_TARGET: {
        Address orig_target = orig_iter.rinfo()->target_address();
        uint32_t tag = EncodeBuiltinOrStub(orig_target);
        SetWasmCalleeTag(iter.rinfo(), tag);
      } break;
      case RelocInfo::WASM_CALL: {
        Address orig_target = orig_iter.rinfo()->wasm_call_address();
        uint32_t tag = wasm_targets_lookup_[orig_target];
        SetWasmCalleeTag(iter.rinfo(), tag);
      } break;
      case RelocInfo::RUNTIME_ENTRY: {
        Address orig_target = orig_iter.rinfo()->target_address();
        uint32_t tag = reference_table_lookup_[orig_target];
        SetWasmCalleeTag(iter.rinfo(), tag);
      } break;
      default:
        UNREACHABLE();
    }
  }
}

uint32_t NativeModuleSerializer::EncodeBuiltinOrStub(Address address) {
  auto builtin_iter = builtin_lookup_.find(address);
  uint32_t tag = 0;
  if (builtin_iter != builtin_lookup_.end()) {
    uint32_t id = builtin_iter->second;
    DCHECK_LT(id, std::numeric_limits<uint16_t>::max());
    tag = id << 16;
  } else {
    auto stub_iter = stub_lookup_.find(address);
    DCHECK(stub_iter != stub_lookup_.end());
    uint32_t id = stub_iter->second;
    DCHECK_LT(id, std::numeric_limits<uint16_t>::max());
    tag = id & 0x0000FFFF;
  }
  return tag;
}

size_t NativeModuleSerializer::Write(Vector<byte> dest) {
  Vector<byte> original = dest;
  while (dest.size() > 0) {
    switch (state_) {
      case Metadata: {
        dest = dest + DrainBuffer(dest);
        if (remaining_.size() == 0) {
          BufferCopiedStubs();
          state_ = Stubs;
        }
        break;
      }
      case Stubs: {
        dest = dest + DrainBuffer(dest);
        if (remaining_.size() == 0) {
          index_ = native_module_->num_imported_functions();
          if (index_ < native_module_->FunctionCount()) {
            BufferCurrentWasmCode();
            state_ = CodeSection;
          } else {
            state_ = Done;
          }
        }
        break;
      }
      case CodeSection: {
        dest = dest + DrainBuffer(dest);
        if (remaining_.size() == 0) {
          ++index_;  // Move to next code object.
          if (index_ < native_module_->FunctionCount()) {
            BufferCurrentWasmCode();
          } else {
            state_ = Done;
          }
        }
        break;
      }
      default:
        UNREACHABLE();
    }
  }
  DCHECK_GE(original.size(), dest.size());
  return original.size() - dest.size();
}

// static
std::pair<std::unique_ptr<const byte[]>, size_t> SerializeNativeModule(
    Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
  if (!FLAG_wasm_jit_to_native) {
    std::unique_ptr<ScriptData> script_data =
        WasmCompiledModuleSerializer::SerializeWasmModule(isolate,
                                                          compiled_module);
    script_data->ReleaseDataOwnership();
    size_t size = static_cast<size_t>(script_data->length());
    return {std::unique_ptr<const byte[]>(script_data->data()), size};
  }
  NativeModule* native_module = compiled_module->GetNativeModule();
  NativeModuleSerializer serializer(isolate, native_module);
  size_t version_size = kVersionSize;
  size_t buff_size = serializer.Measure() + version_size;
  std::unique_ptr<byte[]> ret(new byte[buff_size]);
  WriteVersion(isolate, {ret.get(), buff_size});

  size_t written =
      serializer.Write({ret.get() + version_size, buff_size - version_size});
  if (written != buff_size - version_size) return {};

  return {std::move(ret), buff_size};
}

NativeModuleDeserializer::NativeModuleDeserializer(Isolate* isolate,
                                                   NativeModule* native_module)
    : isolate_(isolate), native_module_(native_module) {}

void NativeModuleDeserializer::Expect(size_t size) {
  scratch_.resize(size);
  current_expectation_ = size;
  unread_ = {scratch_.data(), size};
}

bool NativeModuleDeserializer::Read(Vector<const byte> data) {
  unread_ = data;
  if (!ReadHeader()) return false;
  if (!ReadStubs()) return false;
  index_ = native_module_->num_imported_functions();
  for (; index_ < native_module_->FunctionCount(); ++index_) {
    if (!ReadCode()) return false;
  }
  native_module_->LinkAll();
  return data.size() - unread_.size();
}

bool NativeModuleDeserializer::ReadHeader() {
  size_t start_size = unread_.size();
  Reader reader(unread_);
  size_t functions = reader.Read<uint32_t>();
  size_t imports = reader.Read<uint32_t>();
  bool ok = functions == native_module_->FunctionCount() &&
            imports == native_module_->num_imported_functions();
  if (!ok) return false;
  size_t table_count = reader.Read<uint32_t>();

  std::vector<GlobalHandleAddress> funcs(table_count);
  for (size_t i = 0; i < table_count; ++i) {
    funcs[i] = reader.Read<GlobalHandleAddress>();
  }
  native_module_->function_tables() = funcs;
  // resize, so that from here on the native module can be
  // asked about num_function_tables().
  native_module_->empty_function_tables().resize(table_count);

  unread_ = unread_ + (start_size - reader.current_buffer().size());
  return true;
}

bool NativeModuleDeserializer::ReadStubs() {
  size_t start_size = unread_.size();
  Reader reader(unread_);
  size_t nr_stubs = reader.Read<uint32_t>();
  stubs_.reserve(nr_stubs);
  for (size_t i = 0; i < nr_stubs; ++i) {
    uint32_t key = reader.Read<uint32_t>();
    v8::internal::Code* stub =
        *(v8::internal::CodeStub::GetCode(isolate_, key).ToHandleChecked());
    stubs_.push_back(native_module_->GetLocalAddressFor(handle(stub)));
  }
  unread_ = unread_ + (start_size - reader.current_buffer().size());
  return true;
}

bool NativeModuleDeserializer::ReadCode() {
  size_t start_size = unread_.size();
  Reader reader(unread_);
  size_t code_section_size = reader.Read<size_t>();
  USE(code_section_size);
  size_t constant_pool_offset = reader.Read<size_t>();
  size_t safepoint_table_offset = reader.Read<size_t>();
  uint32_t stack_slot_count = reader.Read<uint32_t>();
  size_t code_size = reader.Read<size_t>();
  size_t reloc_size = reader.Read<size_t>();
  uint32_t handler_size = reader.Read<uint32_t>();
  uint32_t source_position_size = reader.Read<uint32_t>();
  size_t protected_instructions_size = reader.Read<size_t>();
  bool is_liftoff = reader.Read<bool>();
  std::shared_ptr<ProtectedInstructions> protected_instructions(
      new ProtectedInstructions(protected_instructions_size));
  DCHECK_EQ(protected_instructions_size, protected_instructions->size());

  Vector<const byte> code_buffer = reader.GetSubvector(code_size);
  std::unique_ptr<byte[]> reloc_info;
  if (reloc_size > 0) {
    reloc_info.reset(new byte[reloc_size]);
    reader.ReadIntoVector({reloc_info.get(), reloc_size});
  }
  WasmCode* ret = native_module_->AddOwnedCode(
      code_buffer, std::move(reloc_info), reloc_size, Just(index_),
      WasmCode::kFunction, constant_pool_offset, stack_slot_count,
      safepoint_table_offset, protected_instructions, is_liftoff);
  if (ret == nullptr) return false;
  native_module_->SetCodeTable(index_, ret);

  // now relocate the code
  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
             RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
             RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
  for (RelocIterator iter(ret->instructions(), ret->reloc_info(),
                          ret->constant_pool(), mask);
       !iter.done(); iter.next()) {
    RelocInfo::Mode mode = iter.rinfo()->rmode();
    switch (mode) {
      case RelocInfo::EMBEDDED_OBJECT: {
        // We only expect {undefined}. We check for that when we add code.
        iter.rinfo()->set_target_object(isolate_->heap()->undefined_value(),
                                        SKIP_WRITE_BARRIER);
        break;
      }
      case RelocInfo::CODE_TARGET: {
        uint32_t tag = GetWasmCalleeTag(iter.rinfo());
        Address target = GetTrampolineOrStubFromTag(tag);
        iter.rinfo()->set_target_address(nullptr, target, SKIP_WRITE_BARRIER,
                                         SKIP_ICACHE_FLUSH);
        break;
      }
      case RelocInfo::RUNTIME_ENTRY: {
        uint32_t orig_target = static_cast<uint32_t>(
            reinterpret_cast<intptr_t>(iter.rinfo()->target_address()));
        Address address =
            ExternalReferenceTable::instance(isolate_)->address(orig_target);
        iter.rinfo()->set_target_runtime_entry(
            nullptr, address, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
        break;
      }
      default:
        break;
    }
  }
  if (handler_size > 0) {
    Handle<FixedArray> handler_table = isolate_->factory()->NewFixedArray(
        static_cast<int>(handler_size), TENURED);
    reader.ReadIntoVector(
        {reinterpret_cast<Address>(handler_table->GetFirstElementAddress()),
         handler_size});
    native_module_->compiled_module()->handler_table()->set(
        static_cast<int>(index_), *handler_table);
  }
  if (source_position_size > 0) {
    Handle<ByteArray> source_positions = isolate_->factory()->NewByteArray(
        static_cast<int>(source_position_size), TENURED);
    reader.ReadIntoVector(
        {source_positions->GetDataStartAddress(), source_position_size});
    native_module_->compiled_module()->source_positions()->set(
        static_cast<int>(index_), *source_positions);
  }
  if (protected_instructions_size > 0) {
    reader.ReadIntoVector(
        {reinterpret_cast<byte*>(protected_instructions->data()),
         sizeof(trap_handler::ProtectedInstructionData) *
             protected_instructions->size()});
  }
  unread_ = unread_ + (start_size - reader.current_buffer().size());
  return true;
}

Address NativeModuleDeserializer::GetTrampolineOrStubFromTag(uint32_t tag) {
  if ((tag & 0x0000FFFF) == 0) {
    int builtin_id = static_cast<int>(tag >> 16);
    v8::internal::Code* builtin = isolate_->builtins()->builtin(builtin_id);
    return native_module_->GetLocalAddressFor(handle(builtin));
  } else {
    DCHECK_EQ(tag & 0xFFFF0000, 0);
    return stubs_[tag];
  }
}

MaybeHandle<WasmCompiledModule> DeserializeNativeModule(
    Isolate* isolate, Vector<const byte> data, Vector<const byte> wire_bytes) {
  if (!FLAG_wasm_jit_to_native) {
    ScriptData script_data(data.start(), data.length());
    Handle<FixedArray> compiled_module;
    if (!WasmCompiledModuleSerializer::DeserializeWasmModule(
             isolate, &script_data, wire_bytes)
             .ToHandle(&compiled_module)) {
      return {};
    }
    return Handle<WasmCompiledModule>::cast(compiled_module);
  }
  if (!IsWasmCodegenAllowed(isolate, isolate->native_context())) {
    return {};
  }
  if (!IsSupportedVersion(isolate, data)) {
    return {};
  }
  data = data + kVersionSize;
  ModuleResult decode_result =
      SyncDecodeWasmModule(isolate, wire_bytes.start(), wire_bytes.end(), false,
                           i::wasm::kWasmOrigin);
  if (!decode_result.ok()) return {};
  CHECK_NOT_NULL(decode_result.val);
  Handle<String> module_bytes =
      isolate->factory()
          ->NewStringFromOneByte(
              {wire_bytes.start(), static_cast<size_t>(wire_bytes.length())},
              TENURED)
          .ToHandleChecked();
  DCHECK(module_bytes->IsSeqOneByteString());
  // The {module_wrapper} will take ownership of the {WasmModule} object,
  // and it will be destroyed when the GC reclaims the wrapper object.
  Handle<WasmModuleWrapper> module_wrapper =
      WasmModuleWrapper::From(isolate, decode_result.val.release());
  Handle<Script> script = CreateWasmScript(isolate, wire_bytes);
  Handle<WasmSharedModuleData> shared = WasmSharedModuleData::New(
      isolate, module_wrapper, Handle<SeqOneByteString>::cast(module_bytes),
      script, Handle<ByteArray>::null());
  int export_wrappers_size =
      static_cast<int>(shared->module()->num_exported_functions);
  Handle<FixedArray> export_wrappers = isolate->factory()->NewFixedArray(
      static_cast<int>(export_wrappers_size), TENURED);

  Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New(
      isolate, shared->module(), isolate->factory()->empty_fixed_array(),
      export_wrappers, std::vector<wasm::GlobalHandleAddress>(),
      trap_handler::IsTrapHandlerEnabled());
  compiled_module->OnWasmModuleDecodingComplete(shared);
  script->set_wasm_compiled_module(*compiled_module);
  NativeModuleDeserializer deserializer(isolate,
                                        compiled_module->GetNativeModule());
  if (!deserializer.Read(data)) return {};

  CompileJsToWasmWrappers(isolate, compiled_module, isolate->counters());
  WasmCompiledModule::ReinitializeAfterDeserialization(isolate,
                                                       compiled_module);
  return compiled_module;
}

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