LCOV - code coverage report
Current view: top level - src/snapshot - serializer-common.h (source / functions) Hit Total Coverage
Test: app.info Lines: 33 33 100.0 %
Date: 2019-01-20 Functions: 1 4 25.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/msan.h"
      13             : #include "src/snapshot/references.h"
      14             : #include "src/v8memory.h"
      15             : #include "src/visitors.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : 
      20             : class CallHandlerInfo;
      21             : class Isolate;
      22             : 
      23             : class ExternalReferenceEncoder {
      24             :  public:
      25             :   class Value {
      26             :    public:
      27             :     explicit Value(uint32_t raw) : value_(raw) {}
      28             :     Value() : value_(0) {}
      29             :     static uint32_t Encode(uint32_t index, bool is_from_api) {
      30         150 :       return Index::encode(index) | IsFromAPI::encode(is_from_api);
      31             :     }
      32             : 
      33             :     bool is_from_api() const { return IsFromAPI::decode(value_); }
      34             :     uint32_t index() const { return Index::decode(value_); }
      35             : 
      36             :    private:
      37             :     class Index : public BitField<uint32_t, 0, 31> {};
      38             :     class IsFromAPI : public BitField<bool, 31, 1> {};
      39             :     uint32_t value_;
      40             :   };
      41             : 
      42             :   explicit ExternalReferenceEncoder(Isolate* isolate);
      43             :   ~ExternalReferenceEncoder();  // NOLINT (modernize-use-equals-default)
      44             : 
      45             :   Value Encode(Address key);
      46             :   Maybe<Value> TryEncode(Address key);
      47             : 
      48             :   const char* NameOfAddress(Isolate* isolate, Address address) const;
      49             : 
      50             :  private:
      51             :   AddressToIndexHashMap* map_;
      52             : 
      53             : #ifdef DEBUG
      54             :   std::vector<int> count_;
      55             :   const intptr_t* api_references_;
      56             : #endif  // DEBUG
      57             : 
      58             :   DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
      59             : };
      60             : 
      61             : class HotObjectsList {
      62             :  public:
      63     1968957 :   HotObjectsList() : index_(0) {}
      64             : 
      65             :   void Add(HeapObject object) {
      66             :     DCHECK(!AllowHeapAllocation::IsAllowed());
      67   391790365 :     circular_queue_[index_] = object;
      68   391790365 :     index_ = (index_ + 1) & kSizeMask;
      69             :   }
      70             : 
      71             :   HeapObject Get(int index) {
      72             :     DCHECK(!AllowHeapAllocation::IsAllowed());
      73             :     DCHECK(!circular_queue_[index].is_null());
      74   506144897 :     return circular_queue_[index];
      75             :   }
      76             : 
      77             :   static const int kNotFound = -1;
      78             : 
      79             :   int Find(HeapObject object) {
      80             :     DCHECK(!AllowHeapAllocation::IsAllowed());
      81    60148873 :     for (int i = 0; i < kSize; i++) {
      82   124640288 :       if (circular_queue_[i] == object) return i;
      83             :     }
      84             :     return kNotFound;
      85             :   }
      86             : 
      87             :   static const int kSize = 8;
      88             : 
      89             :  private:
      90             :   static_assert(base::bits::IsPowerOfTwo(kSize), "kSize must be power of two");
      91             :   static const int kSizeMask = kSize - 1;
      92             :   HeapObject circular_queue_[kSize];
      93             :   int index_;
      94             : 
      95             :   DISALLOW_COPY_AND_ASSIGN(HotObjectsList);
      96             : };
      97             : 
      98             : // The Serializer/Deserializer class is a common superclass for Serializer and
      99             : // Deserializer which is used to store common constants and methods used by
     100             : // both.
     101      437548 : class SerializerDeserializer : public RootVisitor {
     102             :  public:
     103             :   static void Iterate(Isolate* isolate, RootVisitor* visitor);
     104             : 
     105             :   // No reservation for large object space necessary.
     106             :   // We also handle map space differenly.
     107             :   STATIC_ASSERT(MAP_SPACE == CODE_SPACE + 1);
     108             : 
     109             :   // We do not support young generation large objects and large code objects.
     110             :   STATIC_ASSERT(LAST_SPACE == NEW_LO_SPACE);
     111             :   STATIC_ASSERT(LAST_SPACE - 2 == LO_SPACE);
     112             :   static const int kNumberOfPreallocatedSpaces = CODE_SPACE + 1;
     113             : 
     114             :   // The number of spaces supported by the serializer. Spaces after LO_SPACE
     115             :   // (NEW_LO_SPACE and CODE_LO_SPACE) are not supported.
     116             :   static const int kNumberOfSpaces = LO_SPACE + 1;
     117             : 
     118             :  protected:
     119             :   static bool CanBeDeferred(HeapObject o);
     120             : 
     121             :   void RestoreExternalReferenceRedirectors(
     122             :       const std::vector<AccessorInfo>& accessor_infos);
     123             :   void RestoreExternalReferenceRedirectors(
     124             :       const std::vector<CallHandlerInfo>& call_handler_infos);
     125             : 
     126             : #define UNUSED_SERIALIZER_BYTE_CODES(V) \
     127             :   V(0x0e)                               \
     128             :   V(0x2e)                               \
     129             :   V(0x3e)                               \
     130             :   V(0x3f)                               \
     131             :   V(0x4e)                               \
     132             :   V(0x58)                               \
     133             :   V(0x59)                               \
     134             :   V(0x5a)                               \
     135             :   V(0x5b)                               \
     136             :   V(0x5c)                               \
     137             :   V(0x5d)                               \
     138             :   V(0x5e)                               \
     139             :   V(0x5f)                               \
     140             :   V(0x67)                               \
     141             :   V(0x6e)                               \
     142             :   V(0x76)                               \
     143             :   V(0x79)                               \
     144             :   V(0x7a)                               \
     145             :   V(0x7b)                               \
     146             :   V(0x7c)
     147             : 
     148             :   // ---------- byte code range 0x00..0x7f ----------
     149             :   // Byte codes in this range represent Where, HowToCode and WhereToPoint.
     150             :   // Where the pointed-to object can be found:
     151             :   // The static assert below will trigger when the number of preallocated spaces
     152             :   // changed. If that happens, update the bytecode ranges in the comments below.
     153             :   STATIC_ASSERT(6 == kNumberOfSpaces);
     154             :   enum Where {
     155             :     // 0x00..0x05  Allocate new object, in specified space.
     156             :     kNewObject = 0x00,
     157             :     // 0x08..0x0d  Reference to previous object from space.
     158             :     kBackref = 0x08,
     159             :     // 0x10..0x15  Reference to previous object from space after skip.
     160             :     kBackrefWithSkip = 0x10,
     161             : 
     162             :     // 0x06        Object in the partial snapshot cache.
     163             :     kPartialSnapshotCache = 0x06,
     164             :     // 0x07        External reference referenced by id.
     165             :     kExternalReference = 0x07,
     166             : 
     167             :     // 0x16       Root array item.
     168             :     kRootArray = 0x16,
     169             :     // 0x17        Object provided in the attached list.
     170             :     kAttachedReference = 0x17,
     171             :     // 0x18        Object in the read-only object cache.
     172             :     kReadOnlyObjectCache = 0x18,
     173             : 
     174             :     // 0x0f        Misc, see below (incl. 0x2f, 0x4f, 0x6f).
     175             :     // 0x18..0x1f  Misc, see below (incl. 0x38..0x3f, 0x58..0x5f, 0x78..0x7f).
     176             :   };
     177             : 
     178             :   static const int kWhereMask = 0x1f;
     179             :   static const int kSpaceMask = 7;
     180             :   STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
     181             : 
     182             :   // How to code the pointer to the object.
     183             :   enum HowToCode {
     184             :     // Straight pointer.
     185             :     kPlain = 0,
     186             :     // A pointer inlined in code. What this means depends on the architecture.
     187             :     kFromCode = 0x20
     188             :   };
     189             : 
     190             :   static const int kHowToCodeMask = 0x20;
     191             : 
     192             :   // Where to point within the object.
     193             :   enum WhereToPoint {
     194             :     // Points to start of object
     195             :     kStartOfObject = 0,
     196             :     // Points to instruction in code object or payload of cell.
     197             :     kInnerPointer = 0x40
     198             :   };
     199             : 
     200             :   static const int kWhereToPointMask = 0x40;
     201             : 
     202             :   // ---------- Misc ----------
     203             :   // Skip.
     204             :   static const int kSkip = 0x0f;
     205             :   // Do nothing, used for padding.
     206             :   static const int kNop = 0x2f;
     207             :   // Move to next reserved chunk.
     208             :   static const int kNextChunk = 0x4f;
     209             :   // Deferring object content.
     210             :   static const int kDeferred = 0x6f;
     211             :   // Alignment prefixes 0x19..0x1b
     212             :   static const int kAlignmentPrefix = 0x19;
     213             :   // A tag emitted at strategic points in the snapshot to delineate sections.
     214             :   // If the deserializer does not find these at the expected moments then it
     215             :   // is an indication that the snapshot and the VM do not fit together.
     216             :   // Examine the build process for architecture, version or configuration
     217             :   // mismatches.
     218             :   static const int kSynchronize = 0x1c;
     219             :   // Repeats of variable length.
     220             :   static const int kVariableRepeat = 0x1d;
     221             :   // Raw data of variable length.
     222             : 
     223             :   // Used for embedder-allocated backing stores for TypedArrays.
     224             :   static const int kOffHeapBackingStore = 0x1e;
     225             : 
     226             :   // Used for embedder-provided serialization data for embedder fields.
     227             :   static const int kEmbedderFieldsData = 0x1f;
     228             : 
     229             :   static const int kVariableRawCode = 0x39;
     230             :   static const int kVariableRawData = 0x3a;
     231             : 
     232             :   static const int kInternalReference = 0x3b;
     233             :   static const int kInternalReferenceEncoded = 0x3c;
     234             : 
     235             :   // Used to encode external references provided through the API.
     236             :   static const int kApiReference = 0x3d;
     237             : 
     238             :   // In-place weak references
     239             :   static const int kClearedWeakReference = 0x7d;
     240             :   static const int kWeakPrefix = 0x7e;
     241             : 
     242             :   // Encodes an off-heap instruction stream target.
     243             :   static const int kOffHeapTarget = 0x7f;
     244             : 
     245             :   // ---------- byte code range 0x80..0xff ----------
     246             :   // First 32 root array items.
     247             :   static const int kNumberOfRootArrayConstants = 0x20;
     248             :   // 0x80..0x9f
     249             :   static const int kRootArrayConstants = 0x80;
     250             :   // 0xa0..0xbf
     251             :   static const int kRootArrayConstantsWithSkip = 0xa0;
     252             :   static const int kRootArrayConstantsMask = 0x1f;
     253             : 
     254             :   // 32 common raw data lengths.
     255             :   static const int kNumberOfFixedRawData = 0x20;
     256             :   // 0xc0..0xdf
     257             :   static const int kFixedRawData = 0xc0;
     258             :   static const int kOnePointerRawData = kFixedRawData;
     259             :   static const int kFixedRawDataStart = kFixedRawData - 1;
     260             : 
     261             :   // 16 repeats lengths.
     262             :   static const int kNumberOfFixedRepeat = 0x10;
     263             :   // 0xe0..0xef
     264             :   static const int kFixedRepeat = 0xe0;
     265             :   static const int kFixedRepeatStart = kFixedRepeat - 1;
     266             : 
     267             :   // 8 hot (recently seen or back-referenced) objects with optional skip.
     268             :   static const int kNumberOfHotObjects = 8;
     269             :   STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize);
     270             :   // 0xf0..0xf7
     271             :   static const int kHotObject = 0xf0;
     272             :   // 0xf8..0xff
     273             :   static const int kHotObjectWithSkip = 0xf8;
     274             :   static const int kHotObjectMask = 0x07;
     275             : 
     276             :   // ---------- special values ----------
     277             :   static const int kAnyOldSpace = -1;
     278             : 
     279             :   // Sentinel after a new object to indicate that double alignment is needed.
     280             :   static const int kDoubleAlignmentSentinel = 0;
     281             : 
     282             :   // ---------- member variable ----------
     283             :   HotObjectsList hot_objects_;
     284             : };
     285             : 
     286             : class SerializedData {
     287             :  public:
     288             :   class Reservation {
     289             :    public:
     290     3421465 :     Reservation() : reservation_(0) {}
     291             :     explicit Reservation(uint32_t size)
     292       16022 :         : reservation_(ChunkSizeBits::encode(size)) {}
     293             : 
     294     3421296 :     uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
     295     3421092 :     bool is_last() const { return IsLastChunkBits::decode(reservation_); }
     296             : 
     297        6672 :     void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
     298             : 
     299             :    private:
     300             :     uint32_t reservation_;
     301             :   };
     302             : 
     303             :   SerializedData(byte* data, int size)
     304      217720 :       : data_(data), size_(size), owns_data_(false) {}
     305        1112 :   SerializedData() : data_(nullptr), size_(0), owns_data_(false) {}
     306             :   SerializedData(SerializedData&& other) V8_NOEXCEPT
     307             :       : data_(other.data_),
     308             :         size_(other.size_),
     309         214 :         owns_data_(other.owns_data_) {
     310             :     // Ensure |other| will not attempt to destroy our data in destructor.
     311         214 :     other.owns_data_ = false;
     312             :   }
     313             : 
     314      219049 :   virtual ~SerializedData() {
     315      219049 :     if (owns_data_) DeleteArray<byte>(data_);
     316      219049 :   }
     317             : 
     318      217895 :   uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
     319             : 
     320             :   class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
     321             :   class IsLastChunkBits : public BitField<bool, 31, 1> {};
     322             : 
     323             :   static constexpr uint32_t kMagicNumberOffset = 0;
     324             :   static constexpr uint32_t kMagicNumber =
     325             :       0xC0DE0000 ^ ExternalReferenceTable::kSize;
     326             : 
     327             :  protected:
     328             :   void SetHeaderValue(uint32_t offset, uint32_t value) {
     329        4498 :     WriteLittleEndianValue(reinterpret_cast<Address>(data_) + offset, value);
     330             :   }
     331             : 
     332             :   uint32_t GetHeaderValue(uint32_t offset) const {
     333             :     return ReadLittleEndianValue<uint32_t>(reinterpret_cast<Address>(data_) +
     334      654866 :                                            offset);
     335             :   }
     336             : 
     337             :   void AllocateData(uint32_t size);
     338             : 
     339        1112 :   void SetMagicNumber() { SetHeaderValue(kMagicNumberOffset, kMagicNumber); }
     340             : 
     341             :   byte* data_;
     342             :   uint32_t size_;
     343             :   bool owns_data_;
     344             : 
     345             :  private:
     346             :   DISALLOW_COPY_AND_ASSIGN(SerializedData);
     347             : };
     348             : 
     349             : class Checksum {
     350             :  public:
     351             :   explicit Checksum(Vector<const byte> payload) {
     352             : #ifdef MEMORY_SANITIZER
     353             :     // Computing the checksum includes padding bytes for objects like strings.
     354             :     // Mark every object as initialized in the code serializer.
     355             :     MSAN_MEMORY_IS_INITIALIZED(payload.start(), payload.length());
     356             : #endif  // MEMORY_SANITIZER
     357             :     // Fletcher's checksum. Modified to reduce 64-bit sums to 32-bit.
     358             :     uintptr_t a = 1;
     359             :     uintptr_t b = 0;
     360             :     const uintptr_t* cur = reinterpret_cast<const uintptr_t*>(payload.start());
     361             :     DCHECK(IsAligned(payload.length(), kIntptrSize));
     362       63566 :     const uintptr_t* end = cur + payload.length() / kIntptrSize;
     363  1946815646 :     while (cur < end) {
     364             :       // Unsigned overflow expected and intended.
     365  1946752080 :       a += *cur++;
     366  1946752080 :       b += a;
     367             :     }
     368             : #if V8_HOST_ARCH_64_BIT
     369       63566 :     a ^= a >> 32;
     370       63566 :     b ^= b >> 32;
     371             : #endif  // V8_HOST_ARCH_64_BIT
     372       63566 :     a_ = static_cast<uint32_t>(a);
     373       63566 :     b_ = static_cast<uint32_t>(b);
     374             :   }
     375             : 
     376       63001 :   bool Check(uint32_t a, uint32_t b) const { return a == a_ && b == b_; }
     377             : 
     378             :   uint32_t a() const { return a_; }
     379             :   uint32_t b() const { return b_; }
     380             : 
     381             :  private:
     382             :   uint32_t a_;
     383             :   uint32_t b_;
     384             : 
     385             :   DISALLOW_COPY_AND_ASSIGN(Checksum);
     386             : };
     387             : 
     388             : }  // namespace internal
     389             : }  // namespace v8
     390             : 
     391             : #endif  // V8_SNAPSHOT_SERIALIZER_COMMON_H_

Generated by: LCOV version 1.10