Home | History | Annotate | Download | only in snapshot
      1 // Copyright 2016 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_SNAPSHOT_SERIALIZER_COMMON_H_
      6 #define V8_SNAPSHOT_SERIALIZER_COMMON_H_
      7 
      8 #include "src/address-map.h"
      9 #include "src/external-reference-table.h"
     10 #include "src/globals.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 
     15 class Isolate;
     16 
     17 class ExternalReferenceEncoder {
     18  public:
     19   explicit ExternalReferenceEncoder(Isolate* isolate);
     20 
     21   uint32_t Encode(Address key) const;
     22 
     23   const char* NameOfAddress(Isolate* isolate, Address address) const;
     24 
     25  private:
     26   static uint32_t Hash(Address key) {
     27     return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >>
     28                                  kPointerSizeLog2);
     29   }
     30 
     31   base::HashMap* map_;
     32 
     33   DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
     34 };
     35 
     36 class HotObjectsList {
     37  public:
     38   HotObjectsList() : index_(0) {
     39     for (int i = 0; i < kSize; i++) circular_queue_[i] = NULL;
     40   }
     41 
     42   void Add(HeapObject* object) {
     43     DCHECK(!AllowHeapAllocation::IsAllowed());
     44     circular_queue_[index_] = object;
     45     index_ = (index_ + 1) & kSizeMask;
     46   }
     47 
     48   HeapObject* Get(int index) {
     49     DCHECK(!AllowHeapAllocation::IsAllowed());
     50     DCHECK_NOT_NULL(circular_queue_[index]);
     51     return circular_queue_[index];
     52   }
     53 
     54   static const int kNotFound = -1;
     55 
     56   int Find(HeapObject* object) {
     57     DCHECK(!AllowHeapAllocation::IsAllowed());
     58     for (int i = 0; i < kSize; i++) {
     59       if (circular_queue_[i] == object) return i;
     60     }
     61     return kNotFound;
     62   }
     63 
     64   static const int kSize = 8;
     65 
     66  private:
     67   STATIC_ASSERT(IS_POWER_OF_TWO(kSize));
     68   static const int kSizeMask = kSize - 1;
     69   HeapObject* circular_queue_[kSize];
     70   int index_;
     71 
     72   DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
     73 };
     74 
     75 // The Serializer/Deserializer class is a common superclass for Serializer and
     76 // Deserializer which is used to store common constants and methods used by
     77 // both.
     78 class SerializerDeserializer : public ObjectVisitor {
     79  public:
     80   static void Iterate(Isolate* isolate, ObjectVisitor* visitor);
     81 
     82   // No reservation for large object space necessary.
     83   static const int kNumberOfPreallocatedSpaces = LAST_PAGED_SPACE + 1;
     84   static const int kNumberOfSpaces = LAST_SPACE + 1;
     85 
     86  protected:
     87   static bool CanBeDeferred(HeapObject* o);
     88 
     89   // ---------- byte code range 0x00..0x7f ----------
     90   // Byte codes in this range represent Where, HowToCode and WhereToPoint.
     91   // Where the pointed-to object can be found:
     92   // The static assert below will trigger when the number of preallocated spaces
     93   // changed. If that happens, update the bytecode ranges in the comments below.
     94   STATIC_ASSERT(5 == kNumberOfSpaces);
     95   enum Where {
     96     // 0x00..0x04  Allocate new object, in specified space.
     97     kNewObject = 0x00,
     98     // 0x08..0x0c  Reference to previous object from space.
     99     kBackref = 0x08,
    100     // 0x10..0x14  Reference to previous object from space after skip.
    101     kBackrefWithSkip = 0x10,
    102 
    103     // 0x05       Root array item.
    104     kRootArray = 0x05,
    105     // 0x06        Object in the partial snapshot cache.
    106     kPartialSnapshotCache = 0x06,
    107     // 0x07        External reference referenced by id.
    108     kExternalReference = 0x07,
    109 
    110     // 0x0d        Object provided in the attached list.
    111     kAttachedReference = 0x0d,
    112     // 0x0e        Builtin code referenced by index.
    113     kBuiltin = 0x0e,
    114 
    115     // 0x0f        Misc, see below (incl. 0x2f, 0x4f, 0x6f).
    116     // 0x15..0x1f  Misc, see below (incl. 0x35..0x3f, 0x55..0x5f, 0x75..0x7f).
    117   };
    118 
    119   static const int kWhereMask = 0x1f;
    120   static const int kSpaceMask = 7;
    121   STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
    122 
    123   // How to code the pointer to the object.
    124   enum HowToCode {
    125     // Straight pointer.
    126     kPlain = 0,
    127     // A pointer inlined in code. What this means depends on the architecture.
    128     kFromCode = 0x20
    129   };
    130 
    131   static const int kHowToCodeMask = 0x20;
    132 
    133   // Where to point within the object.
    134   enum WhereToPoint {
    135     // Points to start of object
    136     kStartOfObject = 0,
    137     // Points to instruction in code object or payload of cell.
    138     kInnerPointer = 0x40
    139   };
    140 
    141   static const int kWhereToPointMask = 0x40;
    142 
    143   // ---------- Misc ----------
    144   // Skip.
    145   static const int kSkip = 0x0f;
    146   // Do nothing, used for padding.
    147   static const int kNop = 0x2f;
    148   // Move to next reserved chunk.
    149   static const int kNextChunk = 0x4f;
    150   // Deferring object content.
    151   static const int kDeferred = 0x6f;
    152   // Alignment prefixes 0x15..0x17
    153   static const int kAlignmentPrefix = 0x15;
    154   // A tag emitted at strategic points in the snapshot to delineate sections.
    155   // If the deserializer does not find these at the expected moments then it
    156   // is an indication that the snapshot and the VM do not fit together.
    157   // Examine the build process for architecture, version or configuration
    158   // mismatches.
    159   static const int kSynchronize = 0x18;
    160   // Repeats of variable length.
    161   static const int kVariableRepeat = 0x19;
    162   // Raw data of variable length.
    163   static const int kVariableRawData = 0x1a;
    164   // Internal reference encoded as offsets of pc and target from code entry.
    165   static const int kInternalReference = 0x1b;
    166   static const int kInternalReferenceEncoded = 0x1c;
    167   // Used for the source code of the natives, which is in the executable, but
    168   // is referred to from external strings in the snapshot.
    169   static const int kNativesStringResource = 0x1d;
    170   // Used for the source code for compiled stubs, which is in the executable,
    171   // but is referred to from external strings in the snapshot.
    172   static const int kExtraNativesStringResource = 0x1e;
    173 
    174   // 8 hot (recently seen or back-referenced) objects with optional skip.
    175   static const int kNumberOfHotObjects = 8;
    176   STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize);
    177   // 0x38..0x3f
    178   static const int kHotObject = 0x38;
    179   // 0x58..0x5f
    180   static const int kHotObjectWithSkip = 0x58;
    181   static const int kHotObjectMask = 0x07;
    182 
    183   // 0x1f, 0x35..0x37, 0x55..0x57, 0x75..0x7f unused.
    184 
    185   // ---------- byte code range 0x80..0xff ----------
    186   // First 32 root array items.
    187   static const int kNumberOfRootArrayConstants = 0x20;
    188   // 0x80..0x9f
    189   static const int kRootArrayConstants = 0x80;
    190   // 0xa0..0xbf
    191   static const int kRootArrayConstantsWithSkip = 0xa0;
    192   static const int kRootArrayConstantsMask = 0x1f;
    193 
    194   // 32 common raw data lengths.
    195   static const int kNumberOfFixedRawData = 0x20;
    196   // 0xc0..0xdf
    197   static const int kFixedRawData = 0xc0;
    198   static const int kOnePointerRawData = kFixedRawData;
    199   static const int kFixedRawDataStart = kFixedRawData - 1;
    200 
    201   // 16 repeats lengths.
    202   static const int kNumberOfFixedRepeat = 0x10;
    203   // 0xe0..0xef
    204   static const int kFixedRepeat = 0xe0;
    205   static const int kFixedRepeatStart = kFixedRepeat - 1;
    206 
    207   // 0xf0..0xff unused.
    208 
    209   // ---------- special values ----------
    210   static const int kAnyOldSpace = -1;
    211 
    212   // Sentinel after a new object to indicate that double alignment is needed.
    213   static const int kDoubleAlignmentSentinel = 0;
    214 
    215   // ---------- member variable ----------
    216   HotObjectsList hot_objects_;
    217 };
    218 
    219 class SerializedData {
    220  public:
    221   class Reservation {
    222    public:
    223     explicit Reservation(uint32_t size)
    224         : reservation_(ChunkSizeBits::encode(size)) {}
    225 
    226     uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
    227     bool is_last() const { return IsLastChunkBits::decode(reservation_); }
    228 
    229     void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
    230 
    231    private:
    232     uint32_t reservation_;
    233   };
    234 
    235   SerializedData(byte* data, int size)
    236       : data_(data), size_(size), owns_data_(false) {}
    237   SerializedData() : data_(NULL), size_(0), owns_data_(false) {}
    238 
    239   ~SerializedData() {
    240     if (owns_data_) DeleteArray<byte>(data_);
    241   }
    242 
    243   uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
    244 
    245   class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
    246   class IsLastChunkBits : public BitField<bool, 31, 1> {};
    247 
    248   static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
    249     uint32_t external_refs = table->size();
    250     return 0xC0DE0000 ^ external_refs;
    251   }
    252 
    253  protected:
    254   void SetHeaderValue(int offset, uint32_t value) {
    255     uint32_t* address = reinterpret_cast<uint32_t*>(data_ + offset);
    256     memcpy(reinterpret_cast<uint32_t*>(address), &value, sizeof(value));
    257   }
    258 
    259   uint32_t GetHeaderValue(int offset) const {
    260     uint32_t value;
    261     memcpy(&value, reinterpret_cast<int*>(data_ + offset), sizeof(value));
    262     return value;
    263   }
    264 
    265   void AllocateData(int size);
    266 
    267   static uint32_t ComputeMagicNumber(Isolate* isolate) {
    268     return ComputeMagicNumber(ExternalReferenceTable::instance(isolate));
    269   }
    270 
    271   void SetMagicNumber(Isolate* isolate) {
    272     SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
    273   }
    274 
    275   static const int kMagicNumberOffset = 0;
    276 
    277   byte* data_;
    278   int size_;
    279   bool owns_data_;
    280 };
    281 
    282 }  // namespace internal
    283 }  // namespace v8
    284 
    285 #endif  // V8_SNAPSHOT_SERIALIZER_COMMON_H_
    286