Chromium Code Reviews| 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 |