LCOV - code coverage report
Current view: top level - src/snapshot - serializer-common.h (source / functions) Hit Total Coverage
Test: app.info Lines: 36 37 97.3 %
Date: 2019-04-17 Functions: 0 2 0.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      217734 :   HotObjectsList() : index_(0) {}
      64             : 
      65             :   void Add(HeapObject object) {
      66             :     DCHECK(!AllowHeapAllocation::IsAllowed());
      67   398681505 :     circular_queue_[index_] = object;
      68   398681505 :     index_ = (index_ + 1) & kSizeMask;
      69             :   }
      70             : 
      71             :   HeapObject Get(int index) {
      72             :     DCHECK(!AllowHeapAllocation::IsAllowed());
      73             :     DCHECK(!circular_queue_[index].is_null());
      74   512093619 :     return circular_queue_[index];
      75             :   }
      76             : 
      77             :   static const int kNotFound = -1;
      78             : 
      79             :   int Find(HeapObject object) {
      80             :     DCHECK(!AllowHeapAllocation::IsAllowed());
      81   131018928 :     for (int i = 0; i < kSize; i++) {
      82    63229345 :       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      653232 : 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             : // clang-format off
     127             : #define UNUSED_SERIALIZER_BYTE_CODES(V)                           \
     128             :   V(0x06) V(0x07) V(0x0e) V(0x0f)                                 \
     129             :   /* Free range 0x26..0x2f */                                     \
     130             :   V(0x26) V(0x27)                                                 \
     131             :   V(0x28) V(0x29) V(0x2a) V(0x2b) V(0x2c) V(0x2d) V(0x2e) V(0x2f) \
     132             :   /* Free range 0x30..0x3f */                                     \
     133             :   V(0x30) V(0x31) V(0x32) V(0x33) V(0x34) V(0x35) V(0x36) V(0x37) \
     134             :   V(0x38) V(0x39) V(0x3a) V(0x3b) V(0x3c) V(0x3d) V(0x3e) V(0x3f) \
     135             :   /* Free range 0x97..0x9f */                                     \
     136             :   V(0x98) V(0x99) V(0x9a) V(0x9b) V(0x9c) V(0x9d) V(0x9e) V(0x9f) \
     137             :   /* Free range 0xa0..0xaf */                                     \
     138             :   V(0xa0) V(0xa1) V(0xa2) V(0xa3) V(0xa4) V(0xa5) V(0xa6) V(0xa7) \
     139             :   V(0xa8) V(0xa9) V(0xaa) V(0xab) V(0xac) V(0xad) V(0xae) V(0xaf) \
     140             :   /* Free range 0xb0..0xbf */                                     \
     141             :   V(0xb0) V(0xb1) V(0xb2) V(0xb3) V(0xb4) V(0xb5) V(0xb6) V(0xb7) \
     142             :   V(0xb8) V(0xb9) V(0xba) V(0xbb) V(0xbc) V(0xbd) V(0xbe) V(0xbf) \
     143             :   /* Free range 0xc0..0xcf */                                     \
     144             :   V(0xc0) V(0xc1) V(0xc2) V(0xc3) V(0xc4) V(0xc5) V(0xc6) V(0xc7) \
     145             :   V(0xc8) V(0xc9) V(0xca) V(0xcb) V(0xcc) V(0xcd) V(0xce) V(0xcf) \
     146             :   /* Free range 0xd0..0xdf */                                     \
     147             :   V(0xd0) V(0xd1) V(0xd2) V(0xd3) V(0xd4) V(0xd5) V(0xd6) V(0xd7) \
     148             :   V(0xd8) V(0xd9) V(0xda) V(0xdb) V(0xdc) V(0xdd) V(0xde) V(0xdf) \
     149             :   /* Free range 0xe0..0xef */                                     \
     150             :   V(0xe0) V(0xe1) V(0xe2) V(0xe3) V(0xe4) V(0xe5) V(0xe6) V(0xe7) \
     151             :   V(0xe8) V(0xe9) V(0xea) V(0xeb) V(0xec) V(0xed) V(0xee) V(0xef) \
     152             :   /* Free range 0xf0..0xff */                                     \
     153             :   V(0xf0) V(0xf1) V(0xf2) V(0xf3) V(0xf4) V(0xf5) V(0xf6) V(0xf7) \
     154             :   V(0xf8) V(0xf9) V(0xfa) V(0xfb) V(0xfc) V(0xfd) V(0xfe) V(0xff)
     155             :   // clang-format on
     156             : 
     157             :   // The static assert below will trigger when the number of preallocated spaces
     158             :   // changed. If that happens, update the kNewObject and kBackref bytecode
     159             :   // ranges in the comments below.
     160             :   STATIC_ASSERT(6 == kNumberOfSpaces);
     161             :   static const int kSpaceMask = 7;
     162             :   STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
     163             : 
     164             :   // First 32 root array items.
     165             :   static const int kNumberOfRootArrayConstants = 0x20;
     166             :   static const int kRootArrayConstantsMask = 0x1f;
     167             : 
     168             :   // 32 common raw data lengths.
     169             :   static const int kNumberOfFixedRawData = 0x20;
     170             : 
     171             :   // 16 repeats lengths.
     172             :   static const int kNumberOfFixedRepeat = 0x10;
     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             :   static const int kHotObjectMask = 0x07;
     178             : 
     179             :   enum Bytecode {
     180             :     //
     181             :     // ---------- byte code range 0x00..0x0f ----------
     182             :     //
     183             : 
     184             :     // 0x00..0x05  Allocate new object, in specified space.
     185             :     kNewObject = 0x00,
     186             :     // 0x08..0x0d  Reference to previous object from specified space.
     187             :     kBackref = 0x08,
     188             : 
     189             :     //
     190             :     // ---------- byte code range 0x10..0x25 ----------
     191             :     //
     192             : 
     193             :     // Object in the partial snapshot cache.
     194             :     kPartialSnapshotCache = 0x10,
     195             :     // Root array item.
     196             :     kRootArray,
     197             :     // Object provided in the attached list.
     198             :     kAttachedReference,
     199             :     // Object in the read-only object cache.
     200             :     kReadOnlyObjectCache,
     201             :     // Do nothing, used for padding.
     202             :     kNop,
     203             :     // Move to next reserved chunk.
     204             :     kNextChunk,
     205             :     // Deferring object content.
     206             :     kDeferred,
     207             :     // 3 alignment prefixes 0x17..0x19
     208             :     kAlignmentPrefix = 0x17,
     209             :     // A tag emitted at strategic points in the snapshot to delineate sections.
     210             :     // If the deserializer does not find these at the expected moments then it
     211             :     // is an indication that the snapshot and the VM do not fit together.
     212             :     // Examine the build process for architecture, version or configuration
     213             :     // mismatches.
     214             :     kSynchronize = 0x1a,
     215             :     // Repeats of variable length.
     216             :     kVariableRepeat,
     217             :     // Used for embedder-allocated backing stores for TypedArrays.
     218             :     kOffHeapBackingStore,
     219             :     // Used for embedder-provided serialization data for embedder fields.
     220             :     kEmbedderFieldsData,
     221             :     // Raw data of variable length.
     222             :     kVariableRawCode,
     223             :     kVariableRawData,
     224             :     // Used to encode external references provided through the API.
     225             :     kApiReference,
     226             :     // External reference referenced by id.
     227             :     kExternalReference,
     228             :     // Internal reference of a code objects in code stream.
     229             :     kInternalReference,
     230             :     // In-place weak references.
     231             :     kClearedWeakReference,
     232             :     kWeakPrefix,
     233             :     // Encodes an off-heap instruction stream target.
     234             :     kOffHeapTarget,
     235             : 
     236             :     //
     237             :     // ---------- byte code range 0x40..0x7f ----------
     238             :     //
     239             : 
     240             :     // 0x40..0x5f
     241             :     kRootArrayConstants = 0x40,
     242             : 
     243             :     // 0x60..0x7f
     244             :     kFixedRawData = 0x60,
     245             :     kOnePointerRawData = kFixedRawData,
     246             :     kFixedRawDataStart = kFixedRawData - 1,
     247             : 
     248             :     //
     249             :     // ---------- byte code range 0x80..0x9f ----------
     250             :     //
     251             : 
     252             :     // 0x80..0x8f
     253             :     kFixedRepeat = 0x80,
     254             : 
     255             :     // 0x90..0x97
     256             :     kHotObject = 0x90,
     257             :   };
     258             : 
     259             :   //
     260             :   // Some other constants.
     261             :   //
     262             :   static const int kAnyOldSpace = -1;
     263             : 
     264             :   // Sentinel after a new object to indicate that double alignment is needed.
     265             :   static const int kDoubleAlignmentSentinel = 0;
     266             : 
     267             :   // Repeat count encoding helpers.
     268             :   static const int kFirstEncodableRepeatCount = 2;
     269             :   static const int kLastEncodableFixedRepeatCount =
     270             :       kFirstEncodableRepeatCount + kNumberOfFixedRepeat - 1;
     271             :   static const int kFirstEncodableVariableRepeatCount =
     272             :       kLastEncodableFixedRepeatCount + 1;
     273             : 
     274             :   // Encodes repeat count into a fixed repeat bytecode.
     275             :   static int EncodeFixedRepeat(int repeat_count) {
     276             :     DCHECK(IsInRange(repeat_count, kFirstEncodableRepeatCount,
     277             :                      kLastEncodableFixedRepeatCount));
     278      475652 :     return kFixedRepeat + repeat_count - kFirstEncodableRepeatCount;
     279             :   }
     280             : 
     281             :   // Decodes repeat count from a fixed repeat bytecode.
     282             :   static int DecodeFixedRepeatCount(int bytecode) {
     283             :     DCHECK(IsInRange(bytecode, kFixedRepeat + 0,
     284             :                      kFixedRepeat + kNumberOfFixedRepeat));
     285    86993233 :     return bytecode - kFixedRepeat + kFirstEncodableRepeatCount;
     286             :   }
     287             : 
     288             :   // Encodes repeat count into a serialized variable repeat count value.
     289             :   static int EncodeVariableRepeatCount(int repeat_count) {
     290             :     DCHECK_LE(kFirstEncodableVariableRepeatCount, repeat_count);
     291        1869 :     return repeat_count - kFirstEncodableVariableRepeatCount;
     292             :   }
     293             : 
     294             :   // Decodes repeat count from a serialized variable repeat count value.
     295             :   static int DecodeVariableRepeatCount(int value) {
     296             :     DCHECK_LE(0, value);
     297      524559 :     return value + kFirstEncodableVariableRepeatCount;
     298             :   }
     299             : 
     300             :   // ---------- member variable ----------
     301             :   HotObjectsList hot_objects_;
     302             : };
     303             : 
     304             : class SerializedData {
     305             :  public:
     306             :   class Reservation {
     307             :    public:
     308     3595471 :     Reservation() : reservation_(0) {}
     309             :     explicit Reservation(uint32_t size)
     310       16931 :         : reservation_(ChunkSizeBits::encode(size)) {}
     311             : 
     312     3595269 :     uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); }
     313     3595055 :     bool is_last() const { return IsLastChunkBits::decode(reservation_); }
     314             : 
     315        6822 :     void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); }
     316             : 
     317             :    private:
     318             :     uint32_t reservation_;
     319             :   };
     320             : 
     321             :   SerializedData(byte* data, int size)
     322      216648 :       : data_(data), size_(size), owns_data_(false) {}
     323        1137 :   SerializedData() : data_(nullptr), size_(0), owns_data_(false) {}
     324             :   SerializedData(SerializedData&& other) V8_NOEXCEPT
     325         209 :       : data_(other.data_),
     326         209 :         size_(other.size_),
     327         627 :         owns_data_(other.owns_data_) {
     328             :     // Ensure |other| will not attempt to destroy our data in destructor.
     329         209 :     other.owns_data_ = false;
     330             :   }
     331             : 
     332      436036 :   virtual ~SerializedData() {
     333      218018 :     if (owns_data_) DeleteArray<byte>(data_);
     334           0 :   }
     335             : 
     336             :   uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
     337             : 
     338             :   class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
     339             :   class IsLastChunkBits : public BitField<bool, 31, 1> {};
     340             : 
     341             :   static constexpr uint32_t kMagicNumberOffset = 0;
     342             :   static constexpr uint32_t kMagicNumber =
     343             :       0xC0DE0000 ^ ExternalReferenceTable::kSize;
     344             : 
     345             :  protected:
     346             :   void SetHeaderValue(uint32_t offset, uint32_t value) {
     347        4144 :     WriteLittleEndianValue(reinterpret_cast<Address>(data_) + offset, value);
     348             :   }
     349             : 
     350             :   uint32_t GetHeaderValue(uint32_t offset) const {
     351      651411 :     return ReadLittleEndianValue<uint32_t>(reinterpret_cast<Address>(data_) +
     352             :                                            offset);
     353             :   }
     354             : 
     355             :   void AllocateData(uint32_t size);
     356             : 
     357             :   void SetMagicNumber() { SetHeaderValue(kMagicNumberOffset, kMagicNumber); }
     358             : 
     359             :   byte* data_;
     360             :   uint32_t size_;
     361             :   bool owns_data_;
     362             : 
     363             :  private:
     364             :   DISALLOW_COPY_AND_ASSIGN(SerializedData);
     365             : };
     366             : 
     367             : class Checksum {
     368             :  public:
     369             :   explicit Checksum(Vector<const byte> payload) {
     370             : #ifdef MEMORY_SANITIZER
     371             :     // Computing the checksum includes padding bytes for objects like strings.
     372             :     // Mark every object as initialized in the code serializer.
     373             :     MSAN_MEMORY_IS_INITIALIZED(payload.start(), payload.length());
     374             : #endif  // MEMORY_SANITIZER
     375             :     // Fletcher's checksum. Modified to reduce 64-bit sums to 32-bit.
     376             :     uintptr_t a = 1;
     377             :     uintptr_t b = 0;
     378             :     const uintptr_t* cur = reinterpret_cast<const uintptr_t*>(payload.start());
     379             :     DCHECK(IsAligned(payload.length(), kIntptrSize));
     380       63106 :     const uintptr_t* end = cur + payload.length() / kIntptrSize;
     381  1971490351 :     while (cur < end) {
     382             :       // Unsigned overflow expected and intended.
     383  1971427245 :       a += *cur++;
     384  1971427245 :       b += a;
     385             :     }
     386             : #if V8_HOST_ARCH_64_BIT
     387       63106 :     a ^= a >> 32;
     388       63106 :     b ^= b >> 32;
     389             : #endif  // V8_HOST_ARCH_64_BIT
     390       63106 :     a_ = static_cast<uint32_t>(a);
     391       63106 :     b_ = static_cast<uint32_t>(b);
     392             :   }
     393             : 
     394       62535 :   bool Check(uint32_t a, uint32_t b) const { return a == a_ && b == b_; }
     395             : 
     396             :   uint32_t a() const { return a_; }
     397             :   uint32_t b() const { return b_; }
     398             : 
     399             :  private:
     400             :   uint32_t a_;
     401             :   uint32_t b_;
     402             : 
     403             :   DISALLOW_COPY_AND_ASSIGN(Checksum);
     404             : };
     405             : 
     406             : }  // namespace internal
     407             : }  // namespace v8
     408             : 
     409             : #endif  // V8_SNAPSHOT_SERIALIZER_COMMON_H_

Generated by: LCOV version 1.10