// Copyright 2018 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_SNAPSHOT_EMBEDDED_EMBEDDED_DATA_H_
#define V8_SNAPSHOT_EMBEDDED_EMBEDDED_DATA_H_

#include "src/base/macros.h"
#include "src/builtins/builtins.h"
#include "src/common/globals.h"
#include "src/execution/isolate.h"

namespace v8 {
namespace internal {

class Code;
class Isolate;

// Wraps an off-heap instruction stream.
// TODO(jgruber,v8:6666): Remove this class.
class InstructionStream final : public AllStatic {
 public:
  // Returns true, iff the given pc points into an off-heap instruction stream.
  static bool PcIsOffHeap(Isolate* isolate, Address pc);

  // Returns the corresponding Code object if it exists, and nullptr otherwise.
  static Code TryLookupCode(Isolate* isolate, Address address);

  // During snapshot creation, we first create an executable off-heap area
  // containing all off-heap code. The area is guaranteed to be contiguous.
  // Note that this only applies when building the snapshot, e.g. for
  // mksnapshot. Otherwise, off-heap code is embedded directly into the binary.
  static void CreateOffHeapInstructionStream(Isolate* isolate, uint8_t** data,
                                             uint32_t* size);
  static void FreeOffHeapInstructionStream(uint8_t* data, uint32_t size);
};

class EmbeddedData final {
 public:
  static EmbeddedData FromIsolate(Isolate* isolate);

  static EmbeddedData FromBlob() {
    return EmbeddedData(Isolate::CurrentEmbeddedBlob(),
                        Isolate::CurrentEmbeddedBlobSize());
  }

  static EmbeddedData FromBlob(Isolate* isolate) {
    return EmbeddedData(isolate->embedded_blob(),
                        isolate->embedded_blob_size());
  }

  const uint8_t* data() const { return data_; }
  uint32_t size() const { return size_; }

  void Dispose() { delete[] data_; }

  Address InstructionStartOfBuiltin(int i) const;
  uint32_t InstructionSizeOfBuiltin(int i) const;

  Address InstructionStartOfBytecodeHandlers() const;
  Address InstructionEndOfBytecodeHandlers() const;

  bool ContainsBuiltin(int i) const { return InstructionSizeOfBuiltin(i) > 0; }

  uint32_t AddressForHashing(Address addr) {
    Address start = reinterpret_cast<Address>(data_);
    DCHECK(IsInRange(addr, start, start + size_));
    return static_cast<uint32_t>(addr - start);
  }

  // Padded with kCodeAlignment.
  uint32_t PaddedInstructionSizeOfBuiltin(int i) const {
    uint32_t size = InstructionSizeOfBuiltin(i);
    return (size == 0) ? 0 : PadAndAlign(size);
  }

  size_t CreateEmbeddedBlobHash() const;
  size_t EmbeddedBlobHash() const {
    return *reinterpret_cast<const size_t*>(data_ + EmbeddedBlobHashOffset());
  }

  size_t IsolateHash() const {
    return *reinterpret_cast<const size_t*>(data_ + IsolateHashOffset());
  }

  struct Metadata {
    // Blob layout information.
    uint32_t instructions_offset;
    uint32_t instructions_length;
  };
  STATIC_ASSERT(offsetof(Metadata, instructions_offset) == 0);
  STATIC_ASSERT(offsetof(Metadata, instructions_length) == kUInt32Size);
  STATIC_ASSERT(sizeof(Metadata) == kUInt32Size + kUInt32Size);

  // The layout of the blob is as follows:
  //
  // [0] hash of the remaining blob
  // [1] hash of embedded-blob-relevant heap objects
  // [2] metadata of instruction stream 0
  // ... metadata
  // ... instruction streams

  static constexpr uint32_t kTableSize = Builtins::builtin_count;
  static constexpr uint32_t EmbeddedBlobHashOffset() { return 0; }
  static constexpr uint32_t EmbeddedBlobHashSize() { return kSizetSize; }
  static constexpr uint32_t IsolateHashOffset() {
    return EmbeddedBlobHashOffset() + EmbeddedBlobHashSize();
  }
  static constexpr uint32_t IsolateHashSize() { return kSizetSize; }
  static constexpr uint32_t MetadataOffset() {
    return IsolateHashOffset() + IsolateHashSize();
  }
  static constexpr uint32_t MetadataSize() {
    return sizeof(struct Metadata) * kTableSize;
  }
  static constexpr uint32_t RawDataOffset() {
    return PadAndAlign(MetadataOffset() + MetadataSize());
  }

 private:
  EmbeddedData(const uint8_t* data, uint32_t size) : data_(data), size_(size) {
    DCHECK_NOT_NULL(data);
    DCHECK_LT(0, size);
  }

  const Metadata* Metadata() const {
    return reinterpret_cast<const struct Metadata*>(data_ + MetadataOffset());
  }
  const uint8_t* RawData() const { return data_ + RawDataOffset(); }

  static constexpr int PadAndAlign(int size) {
    // Ensure we have at least one byte trailing the actual builtin
    // instructions which we can later fill with int3.
    return RoundUp<kCodeAlignment>(size + 1);
  }

  void PrintStatistics() const;

  const uint8_t* data_;
  uint32_t size_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_SNAPSHOT_EMBEDDED_EMBEDDED_DATA_H_
