embedded-data.h 6.1 KB
Newer Older
1 2 3 4
// 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.

5 6
#ifndef V8_SNAPSHOT_EMBEDDED_EMBEDDED_DATA_H_
#define V8_SNAPSHOT_EMBEDDED_EMBEDDED_DATA_H_
7 8 9

#include "src/base/macros.h"
#include "src/builtins/builtins.h"
10
#include "src/common/globals.h"
11
#include "src/execution/isolate.h"
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

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.
33 34 35 36 37 38 39
  static void CreateOffHeapInstructionStream(Isolate* isolate, uint8_t** code,
                                             uint32_t* code_size,
                                             uint8_t** metadata,
                                             uint32_t* metadata_size);
  static void FreeOffHeapInstructionStream(uint8_t* code, uint32_t code_size,
                                           uint8_t* metadata,
                                           uint32_t metadata_size);
40 41 42 43 44 45 46
};

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

  static EmbeddedData FromBlob() {
47 48 49 50
    return EmbeddedData(Isolate::CurrentEmbeddedBlobCode(),
                        Isolate::CurrentEmbeddedBlobCodeSize(),
                        Isolate::CurrentEmbeddedBlobMetadata(),
                        Isolate::CurrentEmbeddedBlobMetadataSize());
51 52 53
  }

  static EmbeddedData FromBlob(Isolate* isolate) {
54 55 56 57
    return EmbeddedData(isolate->embedded_blob_code(),
                        isolate->embedded_blob_code_size(),
                        isolate->embedded_blob_metadata(),
                        isolate->embedded_blob_metadata_size());
58 59
  }

60 61 62 63
  const uint8_t* code() const { return code_; }
  uint32_t code_size() const { return code_size_; }
  const uint8_t* metadata() const { return metadata_; }
  uint32_t metadata_size() const { return metadata_size_; }
64

65 66 67 68 69 70
  void Dispose() {
    delete[] code_;
    code_ = nullptr;
    delete[] metadata_;
    metadata_ = nullptr;
  }
71 72 73 74

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

75 76 77
  Address InstructionStartOfBytecodeHandlers() const;
  Address InstructionEndOfBytecodeHandlers() const;

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

  uint32_t AddressForHashing(Address addr) {
81 82
    Address start = reinterpret_cast<Address>(code_);
    DCHECK(base::IsInRange(addr, start, start + code_size_));
83 84 85 86 87 88 89 90 91
    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);
  }

92 93
  size_t CreateEmbeddedBlobHash() const;
  size_t EmbeddedBlobHash() const {
94 95
    return *reinterpret_cast<const size_t*>(metadata_ +
                                            EmbeddedBlobHashOffset());
96 97 98
  }

  size_t IsolateHash() const {
99
    return *reinterpret_cast<const size_t*>(metadata_ + IsolateHashOffset());
100 101 102 103 104 105 106 107 108 109 110 111 112
  }

  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:
  //
113
  // metadata:
114
  // [0] hash of the remaining blob
115 116
  // [1] hash of embedded-blob-relevant heap objects
  // [2] metadata of instruction stream 0
117
  // ... metadata
118 119 120
  //
  // code:
  // [0] instruction streams 0
121 122 123
  // ... instruction streams

  static constexpr uint32_t kTableSize = Builtins::builtin_count;
124 125 126 127 128 129
  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; }
130
  static constexpr uint32_t MetadataTableOffset() {
131
    return IsolateHashOffset() + IsolateHashSize();
132
  }
133
  static constexpr uint32_t MetadataTableSize() {
134 135
    return sizeof(struct Metadata) * kTableSize;
  }
136
  static constexpr uint32_t RawCodeOffset() { return 0; }
137 138

 private:
139 140 141 142 143 144 145 146 147 148
  EmbeddedData(const uint8_t* code, uint32_t code_size, const uint8_t* metadata,
               uint32_t metadata_size)
      : code_(code),
        code_size_(code_size),
        metadata_(metadata),
        metadata_size_(metadata_size) {
    DCHECK_NOT_NULL(code);
    DCHECK_LT(0, code_size);
    DCHECK_NOT_NULL(metadata);
    DCHECK_LT(0, metadata_size);
149 150 151
  }

  const Metadata* Metadata() const {
152 153
    return reinterpret_cast<const struct Metadata*>(metadata_ +
                                                    MetadataTableOffset());
154
  }
155
  const uint8_t* RawCode() const { return code_ + RawCodeOffset(); }
156 157 158 159 160 161 162 163 164

  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;

165 166 167 168 169 170 171 172
  // This points to code for builtins. The contents are potentially unreadable
  // on platforms that disallow reads from the .text section.
  const uint8_t* code_;
  uint32_t code_size_;

  // This is metadata for the code.
  const uint8_t* metadata_;
  uint32_t metadata_size_;
173 174 175 176 177
};

}  // namespace internal
}  // namespace v8

178
#endif  // V8_SNAPSHOT_EMBEDDED_EMBEDDED_DATA_H_