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   AddressToIndexHashMap* map_;
     27 #ifdef DEBUG
     28   ExternalReferenceTable* table_;
     29 #endif  // DEBUG
     30 
     31   DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
     32 };
     33 
     34 class HotObjectsList {
     35  public:
     36   HotObjectsList() : index_(0) {
     37     for (int i = 0; i < kSize; i++) circular_queue_[i] = NULL;
     38   }
     39 
     40   void Add(HeapObject* object) {
     41     DCHECK(!AllowHeapAllocation::IsAllowed());
     42     circular_queue_[index_] = object;
     43     index_ = (index_ + 1) & kSizeMask;
     44   }
     45 
     46   HeapObject* Get(int index) {
     47     DCHECK(!AllowHeapAllocation::IsAllowed());
     48     DCHECK_NOT_NULL(circular_queue_[index]);
     49     return circular_queue_[index];
     50   }
     51 
     52   static const int kNotFound = -1;
     53 
     54   int Find(HeapObject* object) {
     55     DCHECK(!AllowHeapAllocation::IsAllowed());
     56     for (int i = 0; i < kSize; i++) {
     57       if (circular_queue_[i] == object) return i;
     58     }
     59     return kNotFound;
     60   }
     61 
     62   static const int kSize = 8;
     63 
     64  private:
     65   STATIC_ASSERT(IS_POWER_OF_TWO(kSize));
     66   static const int kSizeMask = kSize - 1;
     67   HeapObject* circular_queue_[kSize];
     68   int index_;
     69 
     70   DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
     71 };
     72 
     73 // The Serializer/Deserializer class is a common superclass for Serializer and
     74 // Deserializer which is used to store common constants and methods used by
     75 // both.
     76 class SerializerDeserializer : public ObjectVisitor {
     77  public:
     78   static void Iterate(Isolate* isolate, ObjectVisitor* visitor);
     79 
     80   // No reservation for large object space necessary.
     81   // We also handle map space differenly.
     82   STATIC_ASSERT(MAP_SPACE == CODE_SPACE + 1);
     83   static const int kNumberOfPreallocatedSpaces = CODE_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   // Used for embedder-provided serialization data for internal fields.
    174   static const int kInternalFieldsData = 0x1f;
    175 
    176   // 8 hot (recently seen or back-referenced) objects with optional skip.
    177   static const int kNumberOfHotObjects = 8;
    178   STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize);
    179   // 0x38..0x3f
    180   static const int kHotObject = 0x38;
    181   // 0x58..0x5f
    182   static const int kHotObjectWithSkip = 0x58;
    183   static const int kHotObjectMask = 0x07;
    184 
    185   // 0x35..0x37, 0x55..0x57, 0x75..0x7f unused.
    186 
    187   // ---------- byte code range 0x80..0xff ----------
    188   // First 32 root array items.
    189   static const int kNumberOfRootArrayConstants = 0x20;
    190   // 0x80..0x9f
    191   static const int kRootArrayConstants = 0x80;
    192   // 0xa0..0xbf
    193   static const int kRootArrayConstantsWithSkip = 0xa0;
    194   static const int kRootArrayConstantsMask = 0x1f;
    195 
    196   // 32 common raw data lengths.
    197   static const int kNumberOfFixedRawData = 0x20;
    198   // 0xc0..0xdf
    199   static const int kFixedRawData = 0xc0;
    200   static const int kOnePointerRawData = kFixedRawData;
    201   static const int kFixedRawDataStart = kFixedRawData - 1;
    202 
    203   // 16 repeats lengths.
    204   static const int kNumberOfFixedRepeat = 0x10;
    205   // 0xe0..0xef
    206   static const int kFixedRepeat = 0xe0;
    207   static const int kFixedRepeatStart = kFixedRepeat - 1;
    208 
    209   // 0xf0..0xff unused.
    210 
    211   // ---------- special values ----------
    212   static const int kAnyOldSpace = -1;
    213 
    214   // Sentinel after a new object to indicate that double alignment is needed.
    215   static const int kDoubleAlignmentSentinel = 0;
    216 
    217   // ---------- member variable ----------
    218   HotObjectsList hot_objects_;
    219 };
    220 
    221 class SerializedData {
    222  public:
    223   class Reservation {
    224    public:
    225     explicit Reservation(uint32_t size)
    226         : reservation_(ChunkSizeBits::encode(size)) {}
    227 
    228     uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
    229     bool is_last() const { return IsLastChunkBits::decode(reservation_); }
    230 
    231     void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
    232 
    233    private:
    234     uint32_t reservation_;
    235   };
    236 
    237   SerializedData(byte* data, int size)
    238       : data_(data), size_(size), owns_data_(false) {}
    239   SerializedData() : data_(NULL), size_(0), owns_data_(false) {}
    240 
    241   ~SerializedData() {
    242     if (owns_data_) DeleteArray<byte>(data_);
    243   }
    244 
    245   uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
    246 
    247   class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
    248   class IsLastChunkBits : public BitField<bool, 31, 1> {};
    249 
    250   static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
    251     uint32_t external_refs = table->size();
    252     return 0xC0DE0000 ^ external_refs;
    253   }
    254 
    255  protected:
    256   void SetHeaderValue(int offset, uint32_t value) {
    257     uint32_t* address = reinterpret_cast<uint32_t*>(data_ + offset);
    258     memcpy(reinterpret_cast<uint32_t*>(address), &value, sizeof(value));
    259   }
    260 
    261   uint32_t GetHeaderValue(int offset) const {
    262     uint32_t value;
    263     memcpy(&value, reinterpret_cast<int*>(data_ + offset), sizeof(value));
    264     return value;
    265   }
    266 
    267   void AllocateData(int size);
    268 
    269   static uint32_t ComputeMagicNumber(Isolate* isolate) {
    270     return ComputeMagicNumber(ExternalReferenceTable::instance(isolate));
    271   }
    272 
    273   void SetMagicNumber(Isolate* isolate) {
    274     SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
    275   }
    276 
    277   static const int kMagicNumberOffset = 0;
    278 
    279   byte* data_;
    280   int size_;
    281   bool owns_data_;
    282 };
    283 
    284 }  // namespace internal
    285 }  // namespace v8
    286 
    287 #endif  // V8_SNAPSHOT_SERIALIZER_COMMON_H_
    288