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_H_
      6 #define V8_SNAPSHOT_SERIALIZER_H_
      7 
      8 #include <map>
      9 
     10 #include "src/instruction-stream.h"
     11 #include "src/isolate.h"
     12 #include "src/log.h"
     13 #include "src/objects.h"
     14 #include "src/snapshot/default-serializer-allocator.h"
     15 #include "src/snapshot/serializer-common.h"
     16 #include "src/snapshot/snapshot-source-sink.h"
     17 
     18 namespace v8 {
     19 namespace internal {
     20 
     21 class CodeAddressMap : public CodeEventLogger {
     22  public:
     23   explicit CodeAddressMap(Isolate* isolate) : CodeEventLogger(isolate) {
     24     isolate->logger()->AddCodeEventListener(this);
     25   }
     26 
     27   ~CodeAddressMap() override {
     28     isolate_->logger()->RemoveCodeEventListener(this);
     29   }
     30 
     31   void CodeMoveEvent(AbstractCode* from, AbstractCode* to) override {
     32     address_to_name_map_.Move(from->address(), to->address());
     33   }
     34 
     35   void CodeDisableOptEvent(AbstractCode* code,
     36                            SharedFunctionInfo* shared) override {}
     37 
     38   const char* Lookup(Address address) {
     39     return address_to_name_map_.Lookup(address);
     40   }
     41 
     42  private:
     43   class NameMap {
     44    public:
     45     NameMap() : impl_() {}
     46 
     47     ~NameMap() {
     48       for (base::HashMap::Entry* p = impl_.Start(); p != nullptr;
     49            p = impl_.Next(p)) {
     50         DeleteArray(static_cast<const char*>(p->value));
     51       }
     52     }
     53 
     54     void Insert(Address code_address, const char* name, int name_size) {
     55       base::HashMap::Entry* entry = FindOrCreateEntry(code_address);
     56       if (entry->value == nullptr) {
     57         entry->value = CopyName(name, name_size);
     58       }
     59     }
     60 
     61     const char* Lookup(Address code_address) {
     62       base::HashMap::Entry* entry = FindEntry(code_address);
     63       return (entry != nullptr) ? static_cast<const char*>(entry->value)
     64                                 : nullptr;
     65     }
     66 
     67     void Remove(Address code_address) {
     68       base::HashMap::Entry* entry = FindEntry(code_address);
     69       if (entry != nullptr) {
     70         DeleteArray(static_cast<char*>(entry->value));
     71         RemoveEntry(entry);
     72       }
     73     }
     74 
     75     void Move(Address from, Address to) {
     76       if (from == to) return;
     77       base::HashMap::Entry* from_entry = FindEntry(from);
     78       DCHECK_NOT_NULL(from_entry);
     79       void* value = from_entry->value;
     80       RemoveEntry(from_entry);
     81       base::HashMap::Entry* to_entry = FindOrCreateEntry(to);
     82       DCHECK_NULL(to_entry->value);
     83       to_entry->value = value;
     84     }
     85 
     86    private:
     87     static char* CopyName(const char* name, int name_size) {
     88       char* result = NewArray<char>(name_size + 1);
     89       for (int i = 0; i < name_size; ++i) {
     90         char c = name[i];
     91         if (c == '\0') c = ' ';
     92         result[i] = c;
     93       }
     94       result[name_size] = '\0';
     95       return result;
     96     }
     97 
     98     base::HashMap::Entry* FindOrCreateEntry(Address code_address) {
     99       return impl_.LookupOrInsert(reinterpret_cast<void*>(code_address),
    100                                   ComputeAddressHash(code_address));
    101     }
    102 
    103     base::HashMap::Entry* FindEntry(Address code_address) {
    104       return impl_.Lookup(reinterpret_cast<void*>(code_address),
    105                           ComputeAddressHash(code_address));
    106     }
    107 
    108     void RemoveEntry(base::HashMap::Entry* entry) {
    109       impl_.Remove(entry->key, entry->hash);
    110     }
    111 
    112     base::HashMap impl_;
    113 
    114     DISALLOW_COPY_AND_ASSIGN(NameMap);
    115   };
    116 
    117   void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*,
    118                          const char* name, int length) override {
    119     address_to_name_map_.Insert(code->address(), name, length);
    120   }
    121 
    122   void LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
    123                          int length) override {
    124     UNREACHABLE();
    125   }
    126 
    127   NameMap address_to_name_map_;
    128 };
    129 
    130 template <class AllocatorT = DefaultSerializerAllocator>
    131 class Serializer : public SerializerDeserializer {
    132  public:
    133   explicit Serializer(Isolate* isolate);
    134   ~Serializer() override;
    135 
    136   std::vector<SerializedData::Reservation> EncodeReservations() const {
    137     return allocator_.EncodeReservations();
    138   }
    139 
    140   const std::vector<byte>* Payload() const { return sink_.data(); }
    141 
    142   bool ReferenceMapContains(HeapObject* o) {
    143     return reference_map()->LookupReference(o).is_valid();
    144   }
    145 
    146   Isolate* isolate() const { return isolate_; }
    147 
    148  protected:
    149   class ObjectSerializer;
    150   class RecursionScope {
    151    public:
    152     explicit RecursionScope(Serializer* serializer) : serializer_(serializer) {
    153       serializer_->recursion_depth_++;
    154     }
    155     ~RecursionScope() { serializer_->recursion_depth_--; }
    156     bool ExceedsMaximum() {
    157       return serializer_->recursion_depth_ >= kMaxRecursionDepth;
    158     }
    159 
    160    private:
    161     static const int kMaxRecursionDepth = 32;
    162     Serializer* serializer_;
    163   };
    164 
    165   void SerializeDeferredObjects();
    166   virtual void SerializeObject(HeapObject* o, HowToCode how_to_code,
    167                                WhereToPoint where_to_point, int skip) = 0;
    168 
    169   virtual bool MustBeDeferred(HeapObject* object);
    170 
    171   void VisitRootPointers(Root root, const char* description, Object** start,
    172                          Object** end) override;
    173   void SerializeRootObject(Object* object);
    174 
    175   void PutRoot(int index, HeapObject* object, HowToCode how, WhereToPoint where,
    176                int skip);
    177   void PutSmi(Smi* smi);
    178   void PutBackReference(HeapObject* object, SerializerReference reference);
    179   void PutAttachedReference(SerializerReference reference,
    180                             HowToCode how_to_code, WhereToPoint where_to_point);
    181   // Emit alignment prefix if necessary, return required padding space in bytes.
    182   int PutAlignmentPrefix(HeapObject* object);
    183   void PutNextChunk(int space);
    184 
    185   // Returns true if the object was successfully serialized as hot object.
    186   bool SerializeHotObject(HeapObject* obj, HowToCode how_to_code,
    187                           WhereToPoint where_to_point, int skip);
    188 
    189   // Returns true if the object was successfully serialized as back reference.
    190   bool SerializeBackReference(HeapObject* obj, HowToCode how_to_code,
    191                               WhereToPoint where_to_point, int skip);
    192 
    193   // Returns true if the object was successfully serialized as a builtin
    194   // reference.
    195   bool SerializeBuiltinReference(HeapObject* obj, HowToCode how_to_code,
    196                                  WhereToPoint where_to_point, int skip);
    197 
    198   // Returns true if the given heap object is a bytecode handler code object.
    199   bool ObjectIsBytecodeHandler(HeapObject* obj) const;
    200 
    201   inline void FlushSkip(int skip) {
    202     if (skip != 0) {
    203       sink_.Put(kSkip, "SkipFromSerializeObject");
    204       sink_.PutInt(skip, "SkipDistanceFromSerializeObject");
    205     }
    206   }
    207 
    208   ExternalReferenceEncoder::Value EncodeExternalReference(Address addr) {
    209     return external_reference_encoder_.Encode(addr);
    210   }
    211 
    212   // GetInt reads 4 bytes at once, requiring padding at the end.
    213   void Pad();
    214 
    215   // We may not need the code address map for logging for every instance
    216   // of the serializer.  Initialize it on demand.
    217   void InitializeCodeAddressMap();
    218 
    219   Code* CopyCode(Code* code);
    220 
    221   void QueueDeferredObject(HeapObject* obj) {
    222     DCHECK(reference_map_.LookupReference(obj).is_back_reference());
    223     deferred_objects_.push_back(obj);
    224   }
    225 
    226   void OutputStatistics(const char* name);
    227 
    228 #ifdef OBJECT_PRINT
    229   void CountInstanceType(Map* map, int size, AllocationSpace space);
    230 #endif  // OBJECT_PRINT
    231 
    232 #ifdef DEBUG
    233   void PushStack(HeapObject* o) { stack_.push_back(o); }
    234   void PopStack() { stack_.pop_back(); }
    235   void PrintStack();
    236 #endif  // DEBUG
    237 
    238   SerializerReferenceMap* reference_map() { return &reference_map_; }
    239   RootIndexMap* root_index_map() { return &root_index_map_; }
    240   AllocatorT* allocator() { return &allocator_; }
    241 
    242   SnapshotByteSink sink_;  // Used directly by subclasses.
    243 
    244  private:
    245   Isolate* isolate_;
    246   SerializerReferenceMap reference_map_;
    247   ExternalReferenceEncoder external_reference_encoder_;
    248   RootIndexMap root_index_map_;
    249   CodeAddressMap* code_address_map_ = nullptr;
    250   std::vector<byte> code_buffer_;
    251   std::vector<HeapObject*> deferred_objects_;  // To handle stack overflow.
    252   int recursion_depth_ = 0;
    253   AllocatorT allocator_;
    254 
    255 #ifdef OBJECT_PRINT
    256   static const int kInstanceTypes = LAST_TYPE + 1;
    257   int* instance_type_count_[LAST_SPACE];
    258   size_t* instance_type_size_[LAST_SPACE];
    259 #endif  // OBJECT_PRINT
    260 
    261 #ifdef DEBUG
    262   std::vector<HeapObject*> stack_;
    263 #endif  // DEBUG
    264 
    265   friend class DefaultSerializerAllocator;
    266 
    267   DISALLOW_COPY_AND_ASSIGN(Serializer);
    268 };
    269 
    270 class RelocInfoIterator;
    271 
    272 template <class AllocatorT>
    273 class Serializer<AllocatorT>::ObjectSerializer : public ObjectVisitor {
    274  public:
    275   ObjectSerializer(Serializer* serializer, HeapObject* obj,
    276                    SnapshotByteSink* sink, HowToCode how_to_code,
    277                    WhereToPoint where_to_point)
    278       : serializer_(serializer),
    279         object_(obj),
    280         sink_(sink),
    281         reference_representation_(how_to_code + where_to_point),
    282         bytes_processed_so_far_(0) {
    283 #ifdef DEBUG
    284     serializer_->PushStack(obj);
    285 #endif  // DEBUG
    286   }
    287   ~ObjectSerializer() override {
    288 #ifdef DEBUG
    289     serializer_->PopStack();
    290 #endif  // DEBUG
    291   }
    292   void Serialize();
    293   void SerializeObject();
    294   void SerializeDeferred();
    295   void VisitPointers(HeapObject* host, Object** start, Object** end) override;
    296   void VisitPointers(HeapObject* host, MaybeObject** start,
    297                      MaybeObject** end) override;
    298   void VisitEmbeddedPointer(Code* host, RelocInfo* target) override;
    299   void VisitExternalReference(Foreign* host, Address* p) override;
    300   void VisitExternalReference(Code* host, RelocInfo* rinfo) override;
    301   void VisitInternalReference(Code* host, RelocInfo* rinfo) override;
    302   void VisitCodeTarget(Code* host, RelocInfo* target) override;
    303   void VisitRuntimeEntry(Code* host, RelocInfo* reloc) override;
    304   void VisitOffHeapTarget(Code* host, RelocInfo* target) override;
    305   // Relocation info needs to be visited sorted by target_address_address.
    306   void VisitRelocInfo(RelocIterator* it) override;
    307 
    308  private:
    309   void SerializePrologue(AllocationSpace space, int size, Map* map);
    310 
    311   // This function outputs or skips the raw data between the last pointer and
    312   // up to the current position.
    313   void SerializeContent(Map* map, int size);
    314   void OutputRawData(Address up_to);
    315   void OutputCode(int size);
    316   int SkipTo(Address to);
    317   int32_t SerializeBackingStore(void* backing_store, int32_t byte_length);
    318   void SerializeJSTypedArray();
    319   void SerializeJSArrayBuffer();
    320   void SerializeExternalString();
    321   void SerializeExternalStringAsSequentialString();
    322 
    323   Serializer* serializer_;
    324   HeapObject* object_;
    325   SnapshotByteSink* sink_;
    326   std::map<void*, Smi*> backing_stores;
    327   int reference_representation_;
    328   int bytes_processed_so_far_;
    329 };
    330 
    331 }  // namespace internal
    332 }  // namespace v8
    333 
    334 #endif  // V8_SNAPSHOT_SERIALIZER_H_
    335