LCOV - code coverage report
Current view: top level - src/snapshot - serializer-common.h (source / functions) Hit Total Coverage
Test: app.info Lines: 25 25 100.0 %
Date: 2017-10-20 Functions: 2 5 40.0 %

          Line data    Source code
       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/base/bits.h"
      10             : #include "src/external-reference-table.h"
      11             : #include "src/globals.h"
      12             : #include "src/utils.h"
      13             : #include "src/visitors.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18             : class Isolate;
      19             : 
      20             : class ExternalReferenceEncoder {
      21             :  public:
      22             :   class Value {
      23             :    public:
      24             :     explicit Value(uint32_t raw) : value_(raw) {}
      25             :     static uint32_t Encode(uint32_t index, bool is_from_api) {
      26         100 :       return Index::encode(index) | IsFromAPI::encode(is_from_api);
      27             :     }
      28             : 
      29             :     bool is_from_api() const { return IsFromAPI::decode(value_); }
      30             :     uint32_t index() const { return Index::decode(value_); }
      31             :     uint32_t raw() const { return value_; }
      32             : 
      33             :    private:
      34             :     class Index : public BitField<uint32_t, 0, 31> {};
      35             :     class IsFromAPI : public BitField<bool, 31, 1> {};
      36             :     uint32_t value_;
      37             :   };
      38             : 
      39             :   explicit ExternalReferenceEncoder(Isolate* isolate);
      40             :   ~ExternalReferenceEncoder();
      41             : 
      42             :   Value Encode(Address key);
      43             : 
      44             :   const char* NameOfAddress(Isolate* isolate, Address address) const;
      45             : 
      46             :  private:
      47             :   AddressToIndexHashMap* map_;
      48             : 
      49             : #ifdef DEBUG
      50             :   std::vector<int> count_;
      51             :   const intptr_t* api_references_;
      52             : #endif  // DEBUG
      53             : 
      54             :   DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
      55             : };
      56             : 
      57             : class HotObjectsList {
      58             :  public:
      59      295440 :   HotObjectsList() : index_(0) {
      60     2363520 :     for (int i = 0; i < kSize; i++) circular_queue_[i] = nullptr;
      61             :   }
      62             : 
      63             :   void Add(HeapObject* object) {
      64             :     DCHECK(!AllowHeapAllocation::IsAllowed());
      65   397218541 :     circular_queue_[index_] = object;
      66   397218541 :     index_ = (index_ + 1) & kSizeMask;
      67             :   }
      68             : 
      69             :   HeapObject* Get(int index) {
      70             :     DCHECK(!AllowHeapAllocation::IsAllowed());
      71             :     DCHECK_NOT_NULL(circular_queue_[index]);
      72   365508062 :     return circular_queue_[index];
      73             :   }
      74             : 
      75             :   static const int kNotFound = -1;
      76             : 
      77             :   int Find(HeapObject* object) {
      78             :     DCHECK(!AllowHeapAllocation::IsAllowed());
      79    47519897 :     for (int i = 0; i < kSize; i++) {
      80    48662145 :       if (circular_queue_[i] == object) return i;
      81             :     }
      82             :     return kNotFound;
      83             :   }
      84             : 
      85             :   static const int kSize = 8;
      86             : 
      87             :  private:
      88             :   static_assert(base::bits::IsPowerOfTwo(kSize), "kSize must be power of two");
      89             :   static const int kSizeMask = kSize - 1;
      90             :   HeapObject* circular_queue_[kSize];
      91             :   int index_;
      92             : 
      93             :   DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
      94             : };
      95             : 
      96             : // The Serializer/Deserializer class is a common superclass for Serializer and
      97             : // Deserializer which is used to store common constants and methods used by
      98             : // both.
      99      590880 : class SerializerDeserializer : public RootVisitor {
     100             :  public:
     101             :   static void Iterate(Isolate* isolate, RootVisitor* visitor);
     102             : 
     103             :   // No reservation for large object space necessary.
     104             :   // We also handle map space differenly.
     105             :   STATIC_ASSERT(MAP_SPACE == CODE_SPACE + 1);
     106             :   static const int kNumberOfPreallocatedSpaces = CODE_SPACE + 1;
     107             :   static const int kNumberOfSpaces = LAST_SPACE + 1;
     108             : 
     109             :  protected:
     110             :   static bool CanBeDeferred(HeapObject* o);
     111             : 
     112             :   void RestoreExternalReferenceRedirectors(
     113             :       const std::vector<AccessorInfo*>& accessor_infos);
     114             : 
     115             :   // ---------- byte code range 0x00..0x7f ----------
     116             :   // Byte codes in this range represent Where, HowToCode and WhereToPoint.
     117             :   // Where the pointed-to object can be found:
     118             :   // The static assert below will trigger when the number of preallocated spaces
     119             :   // changed. If that happens, update the bytecode ranges in the comments below.
     120             :   STATIC_ASSERT(5 == kNumberOfSpaces);
     121             :   enum Where {
     122             :     // 0x00..0x04  Allocate new object, in specified space.
     123             :     kNewObject = 0x00,
     124             :     // 0x08..0x0c  Reference to previous object from space.
     125             :     kBackref = 0x08,
     126             :     // 0x10..0x14  Reference to previous object from space after skip.
     127             :     kBackrefWithSkip = 0x10,
     128             : 
     129             :     // 0x05       Root array item.
     130             :     kRootArray = 0x05,
     131             :     // 0x06        Object in the partial snapshot cache.
     132             :     kPartialSnapshotCache = 0x06,
     133             :     // 0x07        External reference referenced by id.
     134             :     kExternalReference = 0x07,
     135             : 
     136             :     // 0x0d        Object provided in the attached list.
     137             :     kAttachedReference = 0x0d,
     138             :     // 0x0e        Builtin code referenced by index.
     139             :     kBuiltin = 0x0e,
     140             : 
     141             :     // 0x0f        Misc, see below (incl. 0x2f, 0x4f, 0x6f).
     142             :     // 0x15..0x1f  Misc, see below (incl. 0x35..0x3f, 0x55..0x5f, 0x75..0x7f).
     143             :   };
     144             : 
     145             :   static const int kWhereMask = 0x1f;
     146             :   static const int kSpaceMask = 7;
     147             :   STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
     148             : 
     149             :   // How to code the pointer to the object.
     150             :   enum HowToCode {
     151             :     // Straight pointer.
     152             :     kPlain = 0,
     153             :     // A pointer inlined in code. What this means depends on the architecture.
     154             :     kFromCode = 0x20
     155             :   };
     156             : 
     157             :   static const int kHowToCodeMask = 0x20;
     158             : 
     159             :   // Where to point within the object.
     160             :   enum WhereToPoint {
     161             :     // Points to start of object
     162             :     kStartOfObject = 0,
     163             :     // Points to instruction in code object or payload of cell.
     164             :     kInnerPointer = 0x40
     165             :   };
     166             : 
     167             :   static const int kWhereToPointMask = 0x40;
     168             : 
     169             :   // ---------- Misc ----------
     170             :   // Skip.
     171             :   static const int kSkip = 0x0f;
     172             :   // Do nothing, used for padding.
     173             :   static const int kNop = 0x2f;
     174             :   // Move to next reserved chunk.
     175             :   static const int kNextChunk = 0x4f;
     176             :   // Deferring object content.
     177             :   static const int kDeferred = 0x6f;
     178             :   // Alignment prefixes 0x15..0x17
     179             :   static const int kAlignmentPrefix = 0x15;
     180             :   // A tag emitted at strategic points in the snapshot to delineate sections.
     181             :   // If the deserializer does not find these at the expected moments then it
     182             :   // is an indication that the snapshot and the VM do not fit together.
     183             :   // Examine the build process for architecture, version or configuration
     184             :   // mismatches.
     185             :   static const int kSynchronize = 0x18;
     186             :   // Repeats of variable length.
     187             :   static const int kVariableRepeat = 0x19;
     188             :   // Raw data of variable length.
     189             :   static const int kVariableRawCode = 0x1a;
     190             :   static const int kVariableRawData = 0x1b;
     191             : 
     192             :   // Used for embedder-allocated backing stores for TypedArrays.
     193             :   static const int kOffHeapBackingStore = 0x1c;
     194             : 
     195             :   // Used to encode deoptimizer entry code.
     196             :   static const int kDeoptimizerEntryPlain = 0x1d;
     197             :   static const int kDeoptimizerEntryFromCode = 0x1e;
     198             :   // Used for embedder-provided serialization data for embedder fields.
     199             :   static const int kEmbedderFieldsData = 0x1f;
     200             : 
     201             :   // Internal reference encoded as offsets of pc and target from code entry.
     202             :   static const int kInternalReference = 0x35;
     203             :   static const int kInternalReferenceEncoded = 0x36;
     204             : 
     205             :   // Used to encode external referenced provided through the API.
     206             :   static const int kApiReference = 0x37;
     207             : 
     208             :   // 8 hot (recently seen or back-referenced) objects with optional skip.
     209             :   static const int kNumberOfHotObjects = 8;
     210             :   STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize);
     211             :   // 0x38..0x3f
     212             :   static const int kHotObject = 0x38;
     213             :   // 0x58..0x5f
     214             :   static const int kHotObjectWithSkip = 0x58;
     215             :   static const int kHotObjectMask = 0x07;
     216             : 
     217             :   // 0x55..0x57, 0x75..0x7f unused.
     218             : 
     219             :   // ---------- byte code range 0x80..0xff ----------
     220             :   // First 32 root array items.
     221             :   static const int kNumberOfRootArrayConstants = 0x20;
     222             :   // 0x80..0x9f
     223             :   static const int kRootArrayConstants = 0x80;
     224             :   // 0xa0..0xbf
     225             :   static const int kRootArrayConstantsWithSkip = 0xa0;
     226             :   static const int kRootArrayConstantsMask = 0x1f;
     227             : 
     228             :   // 32 common raw data lengths.
     229             :   static const int kNumberOfFixedRawData = 0x20;
     230             :   // 0xc0..0xdf
     231             :   static const int kFixedRawData = 0xc0;
     232             :   static const int kOnePointerRawData = kFixedRawData;
     233             :   static const int kFixedRawDataStart = kFixedRawData - 1;
     234             : 
     235             :   // 16 repeats lengths.
     236             :   static const int kNumberOfFixedRepeat = 0x10;
     237             :   // 0xe0..0xef
     238             :   static const int kFixedRepeat = 0xe0;
     239             :   static const int kFixedRepeatStart = kFixedRepeat - 1;
     240             : 
     241             :   // 0xf0..0xff unused.
     242             : 
     243             :   // ---------- special values ----------
     244             :   static const int kAnyOldSpace = -1;
     245             : 
     246             :   // Sentinel after a new object to indicate that double alignment is needed.
     247             :   static const int kDoubleAlignmentSentinel = 0;
     248             : 
     249             :   // ---------- member variable ----------
     250             :   HotObjectsList hot_objects_;
     251             : };
     252             : 
     253             : class SerializedData {
     254             :  public:
     255             :   class Reservation {
     256             :    public:
     257             :     explicit Reservation(uint32_t size)
     258        3705 :         : reservation_(ChunkSizeBits::encode(size)) {}
     259             : 
     260      694200 :     uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
     261      694150 :     bool is_last() const { return IsLastChunkBits::decode(reservation_); }
     262             : 
     263        3650 :     void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
     264             : 
     265             :    private:
     266             :     uint32_t reservation_;
     267             :   };
     268             : 
     269             :   SerializedData(byte* data, int size)
     270      294671 :       : data_(data), size_(size), owns_data_(false) {}
     271         891 :   SerializedData() : data_(nullptr), size_(0), owns_data_(false) {}
     272             :   SerializedData(SerializedData&& other)
     273         300 :       : data_(other.data_), size_(other.size_), owns_data_(other.owns_data_) {
     274             :     // Ensure |other| will not attempt to destroy our data in destructor.
     275         300 :     other.owns_data_ = false;
     276             :   }
     277             : 
     278      295862 :   virtual ~SerializedData() {
     279      295862 :     if (owns_data_) DeleteArray<byte>(data_);
     280      295862 :   }
     281             : 
     282      294877 :   uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
     283             : 
     284             :   class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
     285             :   class IsLastChunkBits : public BitField<bool, 31, 1> {};
     286             : 
     287             :   static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
     288             :     uint32_t external_refs = table->size();
     289      295768 :     return 0xC0DE0000 ^ external_refs;
     290             :   }
     291             : 
     292             :   static const uint32_t kMagicNumberOffset = 0;
     293             : 
     294             :  protected:
     295             :   void SetHeaderValue(uint32_t offset, uint32_t value) {
     296             :     WriteLittleEndianValue(data_ + offset, value);
     297             :   }
     298             : 
     299             :   uint32_t GetHeaderValue(uint32_t offset) const {
     300             :     return ReadLittleEndianValue<uint32_t>(data_ + offset);
     301             :   }
     302             : 
     303             :   void AllocateData(uint32_t size);
     304             : 
     305             :   static uint32_t ComputeMagicNumber(Isolate* isolate) {
     306        1219 :     return ComputeMagicNumber(ExternalReferenceTable::instance(isolate));
     307             :   }
     308             : 
     309        1782 :   void SetMagicNumber(Isolate* isolate) {
     310             :     SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
     311         891 :   }
     312             : 
     313             :   byte* data_;
     314             :   uint32_t size_;
     315             :   bool owns_data_;
     316             : 
     317             :  private:
     318             :   DISALLOW_COPY_AND_ASSIGN(SerializedData);
     319             : };
     320             : 
     321             : }  // namespace internal
     322             : }  // namespace v8
     323             : 
     324             : #endif  // V8_SNAPSHOT_SERIALIZER_COMMON_H_

Generated by: LCOV version 1.10