LCOV - code coverage report
Current view: top level - src/snapshot - serializer.h (source / functions) Hit Total Coverage
Test: app.info Lines: 26 57 45.6 %
Date: 2017-04-26 Functions: 6 15 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_H_
       6             : #define V8_SNAPSHOT_SERIALIZER_H_
       7             : 
       8             : #include "src/isolate.h"
       9             : #include "src/log.h"
      10             : #include "src/objects.h"
      11             : #include "src/snapshot/serializer-common.h"
      12             : #include "src/snapshot/snapshot-source-sink.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17             : class CodeAddressMap : public CodeEventLogger {
      18             :  public:
      19         870 :   explicit CodeAddressMap(Isolate* isolate) : isolate_(isolate) {
      20         580 :     isolate->logger()->addCodeEventListener(this);
      21         290 :   }
      22             : 
      23         870 :   ~CodeAddressMap() override {
      24         290 :     isolate_->logger()->removeCodeEventListener(this);
      25         580 :   }
      26             : 
      27           0 :   void CodeMoveEvent(AbstractCode* from, Address to) override {
      28           0 :     address_to_name_map_.Move(from->address(), to);
      29           0 :   }
      30             : 
      31           0 :   void CodeDisableOptEvent(AbstractCode* code,
      32           0 :                            SharedFunctionInfo* shared) override {}
      33             : 
      34             :   const char* Lookup(Address address) {
      35     1559190 :     return address_to_name_map_.Lookup(address);
      36             :   }
      37             : 
      38             :  private:
      39             :   class NameMap {
      40             :    public:
      41             :     NameMap() : impl_() {}
      42             : 
      43         290 :     ~NameMap() {
      44         580 :       for (base::HashMap::Entry* p = impl_.Start(); p != NULL;
      45             :            p = impl_.Next(p)) {
      46           0 :         DeleteArray(static_cast<const char*>(p->value));
      47             :       }
      48         290 :     }
      49             : 
      50           0 :     void Insert(Address code_address, const char* name, int name_size) {
      51           0 :       base::HashMap::Entry* entry = FindOrCreateEntry(code_address);
      52           0 :       if (entry->value == NULL) {
      53           0 :         entry->value = CopyName(name, name_size);
      54             :       }
      55           0 :     }
      56             : 
      57             :     const char* Lookup(Address code_address) {
      58     1559190 :       base::HashMap::Entry* entry = FindEntry(code_address);
      59     1559190 :       return (entry != NULL) ? static_cast<const char*>(entry->value) : NULL;
      60             :     }
      61             : 
      62             :     void Remove(Address code_address) {
      63             :       base::HashMap::Entry* entry = FindEntry(code_address);
      64             :       if (entry != NULL) {
      65             :         DeleteArray(static_cast<char*>(entry->value));
      66             :         RemoveEntry(entry);
      67             :       }
      68             :     }
      69             : 
      70           0 :     void Move(Address from, Address to) {
      71           0 :       if (from == to) return;
      72           0 :       base::HashMap::Entry* from_entry = FindEntry(from);
      73             :       DCHECK(from_entry != NULL);
      74           0 :       void* value = from_entry->value;
      75             :       RemoveEntry(from_entry);
      76           0 :       base::HashMap::Entry* to_entry = FindOrCreateEntry(to);
      77             :       DCHECK(to_entry->value == NULL);
      78           0 :       to_entry->value = value;
      79             :     }
      80             : 
      81             :    private:
      82           0 :     static char* CopyName(const char* name, int name_size) {
      83           0 :       char* result = NewArray<char>(name_size + 1);
      84           0 :       for (int i = 0; i < name_size; ++i) {
      85           0 :         char c = name[i];
      86           0 :         if (c == '\0') c = ' ';
      87           0 :         result[i] = c;
      88             :       }
      89           0 :       result[name_size] = '\0';
      90           0 :       return result;
      91             :     }
      92             : 
      93           0 :     base::HashMap::Entry* FindOrCreateEntry(Address code_address) {
      94             :       return impl_.LookupOrInsert(code_address,
      95           0 :                                   ComputePointerHash(code_address));
      96             :     }
      97             : 
      98     1559190 :     base::HashMap::Entry* FindEntry(Address code_address) {
      99     1559190 :       return impl_.Lookup(code_address, ComputePointerHash(code_address));
     100             :     }
     101             : 
     102             :     void RemoveEntry(base::HashMap::Entry* entry) {
     103           0 :       impl_.Remove(entry->key, entry->hash);
     104             :     }
     105             : 
     106             :     base::HashMap impl_;
     107             : 
     108             :     DISALLOW_COPY_AND_ASSIGN(NameMap);
     109             :   };
     110             : 
     111           0 :   void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*,
     112             :                          const char* name, int length) override {
     113           0 :     address_to_name_map_.Insert(code->address(), name, length);
     114           0 :   }
     115             : 
     116             :   NameMap address_to_name_map_;
     117             :   Isolate* isolate_;
     118             : };
     119             : 
     120             : // There can be only one serializer per V8 process.
     121             : class Serializer : public SerializerDeserializer {
     122             :  public:
     123             :   explicit Serializer(Isolate* isolate);
     124             :   ~Serializer() override;
     125             : 
     126             :   void EncodeReservations(List<SerializedData::Reservation>* out) const;
     127             : 
     128             :   void SerializeDeferredObjects();
     129             : 
     130             :   Isolate* isolate() const { return isolate_; }
     131             : 
     132             :   SerializerReferenceMap* reference_map() { return &reference_map_; }
     133             :   RootIndexMap* root_index_map() { return &root_index_map_; }
     134             : 
     135             : #ifdef OBJECT_PRINT
     136             :   void CountInstanceType(Map* map, int size);
     137             : #endif  // OBJECT_PRINT
     138             : 
     139             :  protected:
     140             :   class ObjectSerializer;
     141             :   class RecursionScope {
     142             :    public:
     143             :     explicit RecursionScope(Serializer* serializer) : serializer_(serializer) {
     144     1610999 :       serializer_->recursion_depth_++;
     145             :     }
     146     1610999 :     ~RecursionScope() { serializer_->recursion_depth_--; }
     147             :     bool ExceedsMaximum() {
     148             :       return serializer_->recursion_depth_ >= kMaxRecursionDepth;
     149             :     }
     150             : 
     151             :    private:
     152             :     static const int kMaxRecursionDepth = 32;
     153             :     Serializer* serializer_;
     154             :   };
     155             : 
     156             :   virtual void SerializeObject(HeapObject* o, HowToCode how_to_code,
     157             :                                WhereToPoint where_to_point, int skip) = 0;
     158             : 
     159             :   void VisitRootPointers(Root root, Object** start, Object** end) override;
     160             : 
     161             :   void PutRoot(int index, HeapObject* object, HowToCode how, WhereToPoint where,
     162             :                int skip);
     163             : 
     164             :   void PutSmi(Smi* smi);
     165             : 
     166             :   void PutBackReference(HeapObject* object, SerializerReference reference);
     167             : 
     168             :   void PutAttachedReference(SerializerReference reference,
     169             :                             HowToCode how_to_code, WhereToPoint where_to_point);
     170             : 
     171             :   // Emit alignment prefix if necessary, return required padding space in bytes.
     172             :   int PutAlignmentPrefix(HeapObject* object);
     173             : 
     174             :   // Returns true if the object was successfully serialized as hot object.
     175             :   bool SerializeHotObject(HeapObject* obj, HowToCode how_to_code,
     176             :                           WhereToPoint where_to_point, int skip);
     177             : 
     178             :   // Returns true if the object was successfully serialized as back reference.
     179             :   bool SerializeBackReference(HeapObject* obj, HowToCode how_to_code,
     180             :                               WhereToPoint where_to_point, int skip);
     181             : 
     182     2354242 :   inline void FlushSkip(int skip) {
     183     2354242 :     if (skip != 0) {
     184             :       sink_.Put(kSkip, "SkipFromSerializeObject");
     185       33858 :       sink_.PutInt(skip, "SkipDistanceFromSerializeObject");
     186             :     }
     187     2354242 :   }
     188             : 
     189             :   bool BackReferenceIsAlreadyAllocated(SerializerReference back_reference);
     190             : 
     191             :   // This will return the space for an object.
     192             :   SerializerReference AllocateLargeObject(int size);
     193             :   SerializerReference AllocateMap();
     194             :   SerializerReference Allocate(AllocationSpace space, int size);
     195             :   int EncodeExternalReference(Address addr) {
     196      976799 :     return external_reference_encoder_.Encode(addr);
     197             :   }
     198             : 
     199             :   bool HasNotExceededFirstPageOfEachSpace();
     200             : 
     201             :   // GetInt reads 4 bytes at once, requiring padding at the end.
     202             :   void Pad();
     203             : 
     204             :   // We may not need the code address map for logging for every instance
     205             :   // of the serializer.  Initialize it on demand.
     206             :   void InitializeCodeAddressMap();
     207             : 
     208             :   Code* CopyCode(Code* code);
     209             : 
     210             :   inline uint32_t max_chunk_size(int space) const {
     211             :     DCHECK_LE(0, space);
     212             :     DCHECK_LT(space, kNumberOfSpaces);
     213     1538095 :     return max_chunk_size_[space];
     214             :   }
     215             : 
     216             :   const SnapshotByteSink* sink() const { return &sink_; }
     217             : 
     218             :   void QueueDeferredObject(HeapObject* obj) {
     219             :     DCHECK(reference_map_.Lookup(obj).is_back_reference());
     220       12437 :     deferred_objects_.Add(obj);
     221             :   }
     222             : 
     223             :   void OutputStatistics(const char* name);
     224             : 
     225             :   Isolate* isolate_;
     226             : 
     227             :   SnapshotByteSink sink_;
     228             :   ExternalReferenceEncoder external_reference_encoder_;
     229             : 
     230             :   SerializerReferenceMap reference_map_;
     231             :   RootIndexMap root_index_map_;
     232             : 
     233             :   int recursion_depth_;
     234             : 
     235             :   friend class Deserializer;
     236             :   friend class ObjectSerializer;
     237             :   friend class RecursionScope;
     238             :   friend class SnapshotData;
     239             : 
     240             :  private:
     241             :   CodeAddressMap* code_address_map_;
     242             :   // Objects from the same space are put into chunks for bulk-allocation
     243             :   // when deserializing. We have to make sure that each chunk fits into a
     244             :   // page. So we track the chunk size in pending_chunk_ of a space, but
     245             :   // when it exceeds a page, we complete the current chunk and start a new one.
     246             :   uint32_t pending_chunk_[kNumberOfPreallocatedSpaces];
     247             :   List<uint32_t> completed_chunks_[kNumberOfPreallocatedSpaces];
     248             :   uint32_t max_chunk_size_[kNumberOfPreallocatedSpaces];
     249             :   // Number of maps that we need to allocate.
     250             :   uint32_t num_maps_;
     251             : 
     252             :   // We map serialized large objects to indexes for back-referencing.
     253             :   uint32_t large_objects_total_size_;
     254             :   uint32_t seen_large_objects_index_;
     255             : 
     256             :   List<byte> code_buffer_;
     257             : 
     258             :   // To handle stack overflow.
     259             :   List<HeapObject*> deferred_objects_;
     260             : 
     261             : #ifdef OBJECT_PRINT
     262             :   static const int kInstanceTypes = 256;
     263             :   int* instance_type_count_;
     264             :   size_t* instance_type_size_;
     265             : #endif  // OBJECT_PRINT
     266             : 
     267             :   DISALLOW_COPY_AND_ASSIGN(Serializer);
     268             : };
     269             : 
     270             : class Serializer::ObjectSerializer : public ObjectVisitor {
     271             :  public:
     272             :   ObjectSerializer(Serializer* serializer, HeapObject* obj,
     273             :                    SnapshotByteSink* sink, HowToCode how_to_code,
     274             :                    WhereToPoint where_to_point)
     275             :       : serializer_(serializer),
     276             :         object_(obj),
     277             :         sink_(sink),
     278     1611029 :         reference_representation_(how_to_code + where_to_point),
     279             :         bytes_processed_so_far_(0),
     280     3234495 :         code_has_been_output_(false) {}
     281       12437 :   ~ObjectSerializer() override {}
     282             :   void Serialize();
     283             :   void SerializeContent();
     284             :   void SerializeDeferred();
     285             :   void VisitPointers(HeapObject* host, Object** start, Object** end) override;
     286             :   void VisitEmbeddedPointer(Code* host, RelocInfo* target) override;
     287             :   void VisitExternalReference(Foreign* host, Address* p) override;
     288             :   void VisitExternalReference(Code* host, RelocInfo* rinfo) override;
     289             :   void VisitInternalReference(Code* host, RelocInfo* rinfo) override;
     290             :   void VisitCodeTarget(Code* host, RelocInfo* target) override;
     291             :   void VisitCodeEntry(JSFunction* host, Address entry_address) override;
     292             :   void VisitCellPointer(Code* host, RelocInfo* rinfo) override;
     293             :   void VisitRuntimeEntry(Code* host, RelocInfo* reloc) override;
     294             : 
     295             :  private:
     296             :   bool TryEncodeDeoptimizationEntry(HowToCode how_to_code, Address target,
     297             :                                     int skip);
     298             :   void SerializePrologue(AllocationSpace space, int size, Map* map);
     299             : 
     300             : 
     301             :   enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn };
     302             :   // This function outputs or skips the raw data between the last pointer and
     303             :   // up to the current position.  It optionally can just return the number of
     304             :   // bytes to skip instead of performing a skip instruction, in case the skip
     305             :   // can be merged into the next instruction.
     306             :   int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn);
     307             :   void SerializeExternalString();
     308             :   void SerializeExternalStringAsSequentialString();
     309             : 
     310             :   Address PrepareCode();
     311             : 
     312             :   Serializer* serializer_;
     313             :   HeapObject* object_;
     314             :   SnapshotByteSink* sink_;
     315             :   int reference_representation_;
     316             :   int bytes_processed_so_far_;
     317             :   bool code_has_been_output_;
     318             : };
     319             : 
     320             : }  // namespace internal
     321             : }  // namespace v8
     322             : 
     323             : #endif  // V8_SNAPSHOT_SERIALIZER_H_

Generated by: LCOV version 1.10