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   void RestoreExternalReferenceRedirectors(List<AccessorInfo*>* accessor_infos);
     90 
     91   // ---------- byte code range 0x00..0x7f ----------
     92   // Byte codes in this range represent Where, HowToCode and WhereToPoint.
     93   // Where the pointed-to object can be found:
     94   // The static assert below will trigger when the number of preallocated spaces
     95   // changed. If that happens, update the bytecode ranges in the comments below.
     96   STATIC_ASSERT(5 == kNumberOfSpaces);
     97   enum Where {
     98     // 0x00..0x04  Allocate new object, in specified space.
     99     kNewObject = 0x00,
    100     // 0x08..0x0c  Reference to previous object from space.
    101     kBackref = 0x08,
    102     // 0x10..0x14  Reference to previous object from space after skip.
    103     kBackrefWithSkip = 0x10,
    104 
    105     // 0x05       Root array item.
    106     kRootArray = 0x05,
    107     // 0x06        Object in the partial snapshot cache.
    108     kPartialSnapshotCache = 0x06,
    109     // 0x07        External reference referenced by id.
    110     kExternalReference = 0x07,
    111 
    112     // 0x0d        Object provided in the attached list.
    113     kAttachedReference = 0x0d,
    114     // 0x0e        Builtin code referenced by index.
    115     kBuiltin = 0x0e,
    116 
    117     // 0x0f        Misc, see below (incl. 0x2f, 0x4f, 0x6f).
    118     // 0x15..0x1f  Misc, see below (incl. 0x35..0x3f, 0x55..0x5f, 0x75..0x7f).
    119   };
    120 
    121   static const int kWhereMask = 0x1f;
    122   static const int kSpaceMask = 7;
    123   STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
    124 
    125   // How to code the pointer to the object.
    126   enum HowToCode {
    127     // Straight pointer.
    128     kPlain = 0,
    129     // A pointer inlined in code. What this means depends on the architecture.
    130     kFromCode = 0x20
    131   };
    132 
    133   static const int kHowToCodeMask = 0x20;
    134 
    135   // Where to point within the object.
    136   enum WhereToPoint {
    137     // Points to start of object
    138     kStartOfObject = 0,
    139     // Points to instruction in code object or payload of cell.
    140     kInnerPointer = 0x40
    141   };
    142 
    143   static const int kWhereToPointMask = 0x40;
    144 
    145   // ---------- Misc ----------
    146   // Skip.
    147   static const int kSkip = 0x0f;
    148   // Do nothing, used for padding.
    149   static const int kNop = 0x2f;
    150   // Move to next reserved chunk.
    151   static const int kNextChunk = 0x4f;
    152   // Deferring object content.
    153   static const int kDeferred = 0x6f;
    154   // Alignment prefixes 0x15..0x17
    155   static const int kAlignmentPrefix = 0x15;
    156   // A tag emitted at strategic points in the snapshot to delineate sections.
    157   // If the deserializer does not find these at the expected moments then it
    158   // is an indication that the snapshot and the VM do not fit together.
    159   // Examine the build process for architecture, version or configuration
    160   // mismatches.
    161   static const int kSynchronize = 0x18;
    162   // Repeats of variable length.
    163   static const int kVariableRepeat = 0x19;
    164   // Raw data of variable length.
    165   static const int kVariableRawData = 0x1a;
    166   // Internal reference encoded as offsets of pc and target from code entry.
    167   static const int kInternalReference = 0x1b;
    168   static const int kInternalReferenceEncoded = 0x1c;
    169   // Used for the source code of the natives, which is in the executable, but
    170   // is referred to from external strings in the snapshot.
    171   static const int kNativesStringResource = 0x1d;
    172   // Used for the source code for compiled stubs, which is in the executable,
    173   // but is referred to from external strings in the snapshot.
    174   static const int kExtraNativesStringResource = 0x1e;
    175   // Used for embedder-provided serialization data for internal fields.
    176   static const int kInternalFieldsData = 0x1f;
    177 
    178   // 8 hot (recently seen or back-referenced) objects with optional skip.
    179   static const int kNumberOfHotObjects = 8;
    180   STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize);
    181   // 0x38..0x3f
    182   static const int kHotObject = 0x38;
    183   // 0x58..0x5f
    184   static const int kHotObjectWithSkip = 0x58;
    185   static const int kHotObjectMask = 0x07;
    186 
    187   // 0x35..0x37, 0x55..0x57, 0x75..0x7f unused.
    188 
    189   // ---------- byte code range 0x80..0xff ----------
    190   // First 32 root array items.
    191   static const int kNumberOfRootArrayConstants = 0x20;
    192   // 0x80..0x9f
    193   static const int kRootArrayConstants = 0x80;
    194   // 0xa0..0xbf
    195   static const int kRootArrayConstantsWithSkip = 0xa0;
    196   static const int kRootArrayConstantsMask = 0x1f;
    197 
    198   // 32 common raw data lengths.
    199   static const int kNumberOfFixedRawData = 0x20;
    200   // 0xc0..0xdf
    201   static const int kFixedRawData = 0xc0;
    202   static const int kOnePointerRawData = kFixedRawData;
    203   static const int kFixedRawDataStart = kFixedRawData - 1;
    204 
    205   // 16 repeats lengths.
    206   static const int kNumberOfFixedRepeat = 0x10;
    207   // 0xe0..0xef
    208   static const int kFixedRepeat = 0xe0;
    209   static const int kFixedRepeatStart = kFixedRepeat - 1;
    210 
    211   // 0xf0..0xff unused.
    212 
    213   // ---------- special values ----------
    214   static const int kAnyOldSpace = -1;
    215 
    216   // Sentinel after a new object to indicate that double alignment is needed.
    217   static const int kDoubleAlignmentSentinel = 0;
    218 
    219   // ---------- member variable ----------
    220   HotObjectsList hot_objects_;
    221 };
    222 
    223 class SerializedData {
    224  public:
    225   class Reservation {
    226    public:
    227     explicit Reservation(uint32_t size)
    228         : reservation_(ChunkSizeBits::encode(size)) {}
    229 
    230     uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
    231     bool is_last() const { return IsLastChunkBits::decode(reservation_); }
    232 
    233     void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
    234 
    235    private:
    236     uint32_t reservation_;
    237   };
    238 
    239   SerializedData(byte* data, int size)
    240       : data_(data), size_(size), owns_data_(false) {}
    241   SerializedData() : data_(NULL), size_(0), owns_data_(false) {}
    242 
    243   ~SerializedData() {
    244     if (owns_data_) DeleteArray<byte>(data_);
    245   }
    246 
    247   uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
    248 
    249   class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
    250   class IsLastChunkBits : public BitField<bool, 31, 1> {};
    251 
    252   static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
    253     uint32_t external_refs = table->size();
    254     return 0xC0DE0000 ^ external_refs;
    255   }
    256 
    257  protected:
    258   void SetHeaderValue(int offset, uint32_t value) {
    259     uint32_t* address = reinterpret_cast<uint32_t*>(data_ + offset);
    260     memcpy(reinterpret_cast<uint32_t*>(address), &value, sizeof(value));
    261   }
    262 
    263   uint32_t GetHeaderValue(int offset) const {
    264     uint32_t value;
    265     memcpy(&value, reinterpret_cast<int*>(data_ + offset), sizeof(value));
    266     return value;
    267   }
    268 
    269   void AllocateData(int size);
    270 
    271   static uint32_t ComputeMagicNumber(Isolate* isolate) {
    272     return ComputeMagicNumber(ExternalReferenceTable::instance(isolate));
    273   }
    274 
    275   void SetMagicNumber(Isolate* isolate) {
    276     SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
    277   }
    278 
    279   static const int kMagicNumberOffset = 0;
    280 
    281   byte* data_;
    282   int size_;
    283   bool owns_data_;
    284 };
    285 
    286 }  // namespace internal
    287 }  // namespace v8
    288 
    289 #endif  // V8_SNAPSHOT_SERIALIZER_COMMON_H_
    290