OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_SERIALIZE_H_ | 5 #ifndef V8_SERIALIZE_H_ |
6 #define V8_SERIALIZE_H_ | 6 #define V8_SERIALIZE_H_ |
7 | 7 |
8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
9 #include "src/hashmap.h" | 9 #include "src/hashmap.h" |
10 #include "src/heap-profiler.h" | 10 #include "src/heap-profiler.h" |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
383 | 383 |
384 // A bitmask for getting the space out of an instruction. | 384 // A bitmask for getting the space out of an instruction. |
385 static const int kSpaceMask = 7; | 385 static const int kSpaceMask = 7; |
386 STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1); | 386 STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1); |
387 | 387 |
388 // Sentinel after a new object to indicate that double alignment is needed. | 388 // Sentinel after a new object to indicate that double alignment is needed. |
389 static const int kDoubleAlignmentSentinel = 0; | 389 static const int kDoubleAlignmentSentinel = 0; |
390 }; | 390 }; |
391 | 391 |
392 | 392 |
393 class SerializedData { | |
394 public: | |
395 class Reservation { | |
396 public: | |
397 explicit Reservation(uint32_t size) | |
398 : reservation_(ChunkSizeBits::encode(size)) {} | |
399 | |
400 uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation_); } | |
401 bool is_last() const { return IsLastChunkBits::decode(reservation_); } | |
402 | |
403 void mark_as_last() { reservation_ |= IsLastChunkBits::encode(true); } | |
404 | |
405 private: | |
406 uint32_t reservation_; | |
407 }; | |
408 | |
409 SerializedData(byte* data, int size) | |
410 : data_(data), size_(size), owns_data_(false) {} | |
411 SerializedData() : data_(NULL), size_(0), owns_data_(true) {} | |
vogelheim
2014/12/03 18:49:25
Here, owns_data_ == (data_ == NULL), which doesn't
Yang
2014/12/04 08:51:43
Acknowledged.
| |
412 | |
413 virtual ~SerializedData() { | |
414 if (owns_data_) DeleteArray<byte>(data_); | |
415 } | |
416 | |
417 virtual Vector<const Reservation> Reservations() const = 0; | |
418 virtual Vector<const byte> Payload() const = 0; | |
419 | |
420 class ChunkSizeBits : public BitField<uint32_t, 0, 31> {}; | |
421 class IsLastChunkBits : public BitField<bool, 31, 1> {}; | |
422 | |
423 protected: | |
424 void SetHeaderValue(int offset, int value) { | |
425 reinterpret_cast<int*>(data_)[offset] = value; | |
426 } | |
427 | |
428 int GetHeaderValue(int offset) const { | |
429 return reinterpret_cast<const int*>(data_)[offset]; | |
430 } | |
431 | |
432 byte* data_; | |
433 int size_; | |
434 bool owns_data_; | |
435 }; | |
436 | |
437 | |
393 // A Deserializer reads a snapshot and reconstructs the Object graph it defines. | 438 // A Deserializer reads a snapshot and reconstructs the Object graph it defines. |
394 class Deserializer: public SerializerDeserializer { | 439 class Deserializer: public SerializerDeserializer { |
395 public: | 440 public: |
396 // Create a deserializer from a snapshot byte source. | 441 // Create a deserializer from a snapshot byte source. |
397 explicit Deserializer(SnapshotByteSource* source); | 442 explicit Deserializer(SerializedData* serialized_data); |
398 | 443 |
399 virtual ~Deserializer(); | 444 virtual ~Deserializer(); |
400 | 445 |
401 // Deserialize the snapshot into an empty heap. | 446 // Deserialize the snapshot into an empty heap. |
402 void Deserialize(Isolate* isolate); | 447 void Deserialize(Isolate* isolate); |
403 | 448 |
404 enum OnOOM { FATAL_ON_OOM, NULL_ON_OOM }; | 449 enum OnOOM { FATAL_ON_OOM, NULL_ON_OOM }; |
405 | 450 |
406 // Deserialize a single object and the objects reachable from it. | 451 // Deserialize a single object and the objects reachable from it. |
407 // We may want to abort gracefully even if deserialization fails. | 452 // We may want to abort gracefully even if deserialization fails. |
408 void DeserializePartial(Isolate* isolate, Object** root, | 453 void DeserializePartial(Isolate* isolate, Object** root, |
409 OnOOM on_oom = FATAL_ON_OOM); | 454 OnOOM on_oom = FATAL_ON_OOM); |
410 | 455 |
411 void AddReservation(int space, uint32_t chunk) { | |
412 DCHECK(space >= 0); | |
413 DCHECK(space < kNumberOfSpaces); | |
414 reservations_[space].Add({chunk, NULL, NULL}); | |
415 } | |
416 | |
417 void FlushICacheForNewCodeObjects(); | 456 void FlushICacheForNewCodeObjects(); |
418 | 457 |
419 // Serialized user code reference certain objects that are provided in a list | 458 // Serialized user code reference certain objects that are provided in a list |
420 // By calling this method, we assume that we are deserializing user code. | 459 // By calling this method, we assume that we are deserializing user code. |
421 void SetAttachedObjects(Vector<Handle<Object> >* attached_objects) { | 460 void SetAttachedObjects(Vector<Handle<Object> >* attached_objects) { |
422 attached_objects_ = attached_objects; | 461 attached_objects_ = attached_objects; |
423 } | 462 } |
424 | 463 |
425 bool deserializing_user_code() { return attached_objects_ != NULL; } | 464 bool deserializing_user_code() { return attached_objects_ != NULL; } |
426 | 465 |
(...skipping 21 matching lines...) Expand all Loading... | |
448 Address Allocate(int space_index, int size); | 487 Address Allocate(int space_index, int size); |
449 | 488 |
450 // Special handling for serialized code like hooking up internalized strings. | 489 // Special handling for serialized code like hooking up internalized strings. |
451 HeapObject* ProcessNewObjectFromSerializedCode(HeapObject* obj); | 490 HeapObject* ProcessNewObjectFromSerializedCode(HeapObject* obj); |
452 Object* ProcessBackRefInSerializedCode(Object* obj); | 491 Object* ProcessBackRefInSerializedCode(Object* obj); |
453 | 492 |
454 // This returns the address of an object that has been described in the | 493 // This returns the address of an object that has been described in the |
455 // snapshot by chunk index and offset. | 494 // snapshot by chunk index and offset. |
456 HeapObject* GetBackReferencedObject(int space) { | 495 HeapObject* GetBackReferencedObject(int space) { |
457 if (space == LO_SPACE) { | 496 if (space == LO_SPACE) { |
458 uint32_t index = source_->GetInt(); | 497 uint32_t index = source_.GetInt(); |
459 return deserialized_large_objects_[index]; | 498 return deserialized_large_objects_[index]; |
460 } else { | 499 } else { |
461 BackReference back_reference(source_->GetInt()); | 500 BackReference back_reference(source_.GetInt()); |
462 DCHECK(space < kNumberOfPreallocatedSpaces); | 501 DCHECK(space < kNumberOfPreallocatedSpaces); |
463 uint32_t chunk_index = back_reference.chunk_index(); | 502 uint32_t chunk_index = back_reference.chunk_index(); |
464 DCHECK_LE(chunk_index, current_chunk_[space]); | 503 DCHECK_LE(chunk_index, current_chunk_[space]); |
465 uint32_t chunk_offset = back_reference.chunk_offset(); | 504 uint32_t chunk_offset = back_reference.chunk_offset(); |
466 return HeapObject::FromAddress(reservations_[space][chunk_index].start + | 505 return HeapObject::FromAddress(reservations_[space][chunk_index].start + |
467 chunk_offset); | 506 chunk_offset); |
468 } | 507 } |
469 } | 508 } |
470 | 509 |
471 // Cached current isolate. | 510 // Cached current isolate. |
472 Isolate* isolate_; | 511 Isolate* isolate_; |
473 | 512 |
474 // Objects from the attached object descriptions in the serialized user code. | 513 // Objects from the attached object descriptions in the serialized user code. |
475 Vector<Handle<Object> >* attached_objects_; | 514 Vector<Handle<Object> >* attached_objects_; |
476 | 515 |
477 SnapshotByteSource* source_; | 516 SnapshotByteSource source_; |
478 // The address of the next object that will be allocated in each space. | 517 // The address of the next object that will be allocated in each space. |
479 // Each space has a number of chunks reserved by the GC, with each chunk | 518 // Each space has a number of chunks reserved by the GC, with each chunk |
480 // fitting into a page. Deserialized objects are allocated into the | 519 // fitting into a page. Deserialized objects are allocated into the |
481 // current chunk of the target space by bumping up high water mark. | 520 // current chunk of the target space by bumping up high water mark. |
482 Heap::Reservation reservations_[kNumberOfSpaces]; | 521 Heap::Reservation reservations_[kNumberOfSpaces]; |
483 uint32_t current_chunk_[kNumberOfPreallocatedSpaces]; | 522 uint32_t current_chunk_[kNumberOfPreallocatedSpaces]; |
484 Address high_water_[kNumberOfPreallocatedSpaces]; | 523 Address high_water_[kNumberOfPreallocatedSpaces]; |
485 | 524 |
486 ExternalReferenceDecoder* external_reference_decoder_; | 525 ExternalReferenceDecoder* external_reference_decoder_; |
487 | 526 |
488 List<HeapObject*> deserialized_large_objects_; | 527 List<HeapObject*> deserialized_large_objects_; |
489 | 528 |
490 DISALLOW_COPY_AND_ASSIGN(Deserializer); | 529 DISALLOW_COPY_AND_ASSIGN(Deserializer); |
491 }; | 530 }; |
492 | 531 |
493 | 532 |
494 class CodeAddressMap; | 533 class CodeAddressMap; |
495 | 534 |
496 // There can be only one serializer per V8 process. | 535 // There can be only one serializer per V8 process. |
497 class Serializer : public SerializerDeserializer { | 536 class Serializer : public SerializerDeserializer { |
498 public: | 537 public: |
499 Serializer(Isolate* isolate, SnapshotByteSink* sink); | 538 Serializer(Isolate* isolate, SnapshotByteSink* sink); |
500 ~Serializer(); | 539 ~Serializer(); |
501 virtual void VisitPointers(Object** start, Object** end) OVERRIDE; | 540 virtual void VisitPointers(Object** start, Object** end) OVERRIDE; |
502 | 541 |
503 void FinalizeAllocation(); | 542 void EncodeReservations(List<SerializedData::Reservation>* out) const; |
504 | |
505 Vector<const uint32_t> FinalAllocationChunks(int space) const { | |
506 if (space == LO_SPACE) { | |
507 return Vector<const uint32_t>(&large_objects_total_size_, 1); | |
508 } else { | |
509 DCHECK_EQ(0, pending_chunk_[space]); // No pending chunks. | |
510 return completed_chunks_[space].ToConstVector(); | |
511 } | |
512 } | |
513 | 543 |
514 Isolate* isolate() const { return isolate_; } | 544 Isolate* isolate() const { return isolate_; } |
515 | 545 |
516 BackReferenceMap* back_reference_map() { return &back_reference_map_; } | 546 BackReferenceMap* back_reference_map() { return &back_reference_map_; } |
517 RootIndexMap* root_index_map() { return &root_index_map_; } | 547 RootIndexMap* root_index_map() { return &root_index_map_; } |
518 | 548 |
519 protected: | 549 protected: |
520 class ObjectSerializer : public ObjectVisitor { | 550 class ObjectSerializer : public ObjectVisitor { |
521 public: | 551 public: |
522 ObjectSerializer(Serializer* serializer, | 552 ObjectSerializer(Serializer* serializer, |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
716 Isolate* isolate, ScriptData* cached_data, Handle<String> source); | 746 Isolate* isolate, ScriptData* cached_data, Handle<String> source); |
717 | 747 |
718 static const int kSourceObjectIndex = 0; | 748 static const int kSourceObjectIndex = 0; |
719 static const int kCodeStubsBaseIndex = 1; | 749 static const int kCodeStubsBaseIndex = 1; |
720 | 750 |
721 String* source() const { | 751 String* source() const { |
722 DCHECK(!AllowHeapAllocation::IsAllowed()); | 752 DCHECK(!AllowHeapAllocation::IsAllowed()); |
723 return source_; | 753 return source_; |
724 } | 754 } |
725 | 755 |
726 List<uint32_t>* stub_keys() { return &stub_keys_; } | 756 const List<uint32_t>* stub_keys() const { return &stub_keys_; } |
727 int num_internalized_strings() const { return num_internalized_strings_; } | 757 int num_internalized_strings() const { return num_internalized_strings_; } |
728 | 758 |
729 private: | 759 private: |
730 CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source, | 760 CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source, |
731 Code* main_code) | 761 Code* main_code) |
732 : Serializer(isolate, sink), | 762 : Serializer(isolate, sink), |
733 source_(source), | 763 source_(source), |
734 main_code_(main_code), | 764 main_code_(main_code), |
735 num_internalized_strings_(0) { | 765 num_internalized_strings_(0) { |
736 back_reference_map_.AddSourceString(source); | 766 back_reference_map_.AddSourceString(source); |
(...skipping 16 matching lines...) Expand all Loading... | |
753 | 783 |
754 DisallowHeapAllocation no_gc_; | 784 DisallowHeapAllocation no_gc_; |
755 String* source_; | 785 String* source_; |
756 Code* main_code_; | 786 Code* main_code_; |
757 int num_internalized_strings_; | 787 int num_internalized_strings_; |
758 List<uint32_t> stub_keys_; | 788 List<uint32_t> stub_keys_; |
759 DISALLOW_COPY_AND_ASSIGN(CodeSerializer); | 789 DISALLOW_COPY_AND_ASSIGN(CodeSerializer); |
760 }; | 790 }; |
761 | 791 |
762 | 792 |
793 // Wrapper around reservation sizes and the serialization payload. | |
794 class SnapshotData : public SerializedData { | |
795 public: | |
796 // Used when producing. | |
797 SnapshotData(const SnapshotByteSink& sink, const Serializer& ser); | |
798 | |
799 // Used when consuming. | |
800 explicit SnapshotData(const byte* data, int size) | |
801 : SerializedData(const_cast<byte*>(data), size) { | |
802 CHECK(IsSane()); | |
803 } | |
804 | |
805 virtual Vector<const Reservation> Reservations() const OVERRIDE; | |
806 virtual Vector<const byte> Payload() const OVERRIDE; | |
807 | |
808 Vector<const byte> RawData() const { | |
809 return Vector<const byte>(data_, size_); | |
810 } | |
811 | |
812 private: | |
813 bool IsSane(); | |
814 // The data header consists of int-sized entries: | |
815 // [0] version hash | |
816 // [1] number of reservation size entries | |
817 // [2] payload length | |
818 static const int kCheckSumOffset = 0; | |
819 static const int kReservationsOffset = 1; | |
820 static const int kPayloadLengthOffset = 2; | |
821 static const int kHeaderSize = (kPayloadLengthOffset + 1) * kIntSize; | |
822 }; | |
823 | |
824 | |
763 // Wrapper around ScriptData to provide code-serializer-specific functionality. | 825 // Wrapper around ScriptData to provide code-serializer-specific functionality. |
764 class SerializedCodeData { | 826 class SerializedCodeData : public SerializedData { |
765 public: | 827 public: |
766 // Used by when consuming. | 828 // Used when consuming. |
767 static SerializedCodeData* FromCachedData(ScriptData* cached_data, | 829 static SerializedCodeData* FromCachedData(ScriptData* cached_data, |
768 String* source) { | 830 String* source) { |
769 DisallowHeapAllocation no_gc; | 831 DisallowHeapAllocation no_gc; |
770 SerializedCodeData* scd = new SerializedCodeData(cached_data); | 832 SerializedCodeData* scd = new SerializedCodeData(cached_data); |
771 if (scd->IsSane(source)) return scd; | 833 if (scd->IsSane(source)) return scd; |
772 cached_data->Reject(); | 834 cached_data->Reject(); |
773 delete scd; | 835 delete scd; |
774 return NULL; | 836 return NULL; |
775 } | 837 } |
776 | 838 |
777 // Used when producing. | 839 // Used when producing. |
778 SerializedCodeData(const List<byte>& payload, CodeSerializer* cs); | 840 SerializedCodeData(const List<byte>& payload, const CodeSerializer& cs); |
779 | |
780 ~SerializedCodeData() { | |
781 if (owns_script_data_) DeleteArray<byte>(data_); | |
782 } | |
783 | 841 |
784 // Return ScriptData object and relinquish ownership over it to the caller. | 842 // Return ScriptData object and relinquish ownership over it to the caller. |
785 ScriptData* GetScriptData() { | 843 ScriptData* GetScriptData(); |
786 DCHECK(owns_script_data_); | |
787 ScriptData* result = new ScriptData(data_, size_); | |
788 result->AcquireDataOwnership(); | |
789 return result; | |
790 } | |
791 | 844 |
792 class Reservation { | 845 virtual Vector<const Reservation> Reservations() const OVERRIDE; |
793 public: | 846 virtual Vector<const byte> Payload() const OVERRIDE; |
794 uint32_t chunk_size() const { return ChunkSizeBits::decode(reservation); } | |
795 bool is_last_chunk() const { return IsLastChunkBits::decode(reservation); } | |
796 | 847 |
797 private: | 848 int NumInternalizedStrings() const; |
798 uint32_t reservation; | 849 Vector<const uint32_t> CodeStubKeys() const; |
799 | |
800 DISALLOW_COPY_AND_ASSIGN(Reservation); | |
801 }; | |
802 | |
803 int NumInternalizedStrings() const { | |
804 return GetHeaderValue(kNumInternalizedStringsOffset); | |
805 } | |
806 | |
807 Vector<const Reservation> Reservations() const { | |
808 return Vector<const Reservation>( | |
809 reinterpret_cast<const Reservation*>(data_ + kHeaderSize), | |
810 GetHeaderValue(kReservationsOffset)); | |
811 } | |
812 | |
813 Vector<const uint32_t> CodeStubKeys() const { | |
814 int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; | |
815 const byte* start = data_ + kHeaderSize + reservations_size; | |
816 return Vector<const uint32_t>(reinterpret_cast<const uint32_t*>(start), | |
817 GetHeaderValue(kNumCodeStubKeysOffset)); | |
818 } | |
819 | |
820 const byte* Payload() const { | |
821 int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; | |
822 int code_stubs_size = GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size; | |
823 return data_ + kHeaderSize + reservations_size + code_stubs_size; | |
824 } | |
825 | |
826 int PayloadLength() const { | |
827 int payload_length = GetHeaderValue(kPayloadLengthOffset); | |
828 DCHECK_EQ(data_ + size_, Payload() + payload_length); | |
829 return payload_length; | |
830 } | |
831 | 850 |
832 private: | 851 private: |
833 explicit SerializedCodeData(ScriptData* data) | 852 explicit SerializedCodeData(ScriptData* data) |
834 : data_(const_cast<byte*>(data->data())), | 853 : SerializedData(const_cast<byte*>(data->data()), data->length()) {} |
835 size_(data->length()), | |
836 owns_script_data_(false) {} | |
837 | |
838 void SetHeaderValue(int offset, int value) { | |
839 reinterpret_cast<int*>(data_)[offset] = value; | |
840 } | |
841 | |
842 int GetHeaderValue(int offset) const { | |
843 return reinterpret_cast<const int*>(data_)[offset]; | |
844 } | |
845 | 854 |
846 bool IsSane(String* source); | 855 bool IsSane(String* source); |
847 | 856 |
848 int CheckSum(String* source); | 857 int CheckSum(String* source); |
849 | 858 |
850 // The data header consists of int-sized entries: | 859 // The data header consists of int-sized entries: |
851 // [0] version hash | 860 // [0] version hash |
852 // [1] number of internalized strings | 861 // [1] number of internalized strings |
853 // [2] number of code stub keys | 862 // [2] number of code stub keys |
854 // [3] number of reservation size entries | 863 // [3] number of reservation size entries |
855 // [3] payload length | 864 // [4] payload length |
856 static const int kCheckSumOffset = 0; | 865 static const int kCheckSumOffset = 0; |
857 static const int kNumInternalizedStringsOffset = 1; | 866 static const int kNumInternalizedStringsOffset = 1; |
858 static const int kReservationsOffset = 2; | 867 static const int kReservationsOffset = 2; |
859 static const int kNumCodeStubKeysOffset = 3; | 868 static const int kNumCodeStubKeysOffset = 3; |
860 static const int kPayloadLengthOffset = 4; | 869 static const int kPayloadLengthOffset = 4; |
861 static const int kHeaderSize = (kPayloadLengthOffset + 1) * kIntSize; | 870 static const int kHeaderSize = (kPayloadLengthOffset + 1) * kIntSize; |
862 | |
863 class ChunkSizeBits : public BitField<uint32_t, 0, 31> {}; | |
864 class IsLastChunkBits : public BitField<bool, 31, 1> {}; | |
865 | |
866 byte* data_; | |
867 int size_; | |
868 bool owns_script_data_; | |
869 }; | 871 }; |
870 } } // namespace v8::internal | 872 } } // namespace v8::internal |
871 | 873 |
872 #endif // V8_SERIALIZE_H_ | 874 #endif // V8_SERIALIZE_H_ |
OLD | NEW |