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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/base/platform/platform.h" | 9 #include "src/base/platform/platform.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 for (auto& r : res) { | 509 for (auto& r : res) { |
510 reservations_[current_space].Add({r.chunk_size(), NULL, NULL}); | 510 reservations_[current_space].Add({r.chunk_size(), NULL, NULL}); |
511 if (r.is_last()) current_space++; | 511 if (r.is_last()) current_space++; |
512 } | 512 } |
513 DCHECK_EQ(kNumberOfSpaces, current_space); | 513 DCHECK_EQ(kNumberOfSpaces, current_space); |
514 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) current_chunk_[i] = 0; | 514 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) current_chunk_[i] = 0; |
515 } | 515 } |
516 | 516 |
517 | 517 |
518 void Deserializer::FlushICacheForNewCodeObjects() { | 518 void Deserializer::FlushICacheForNewCodeObjects() { |
519 PageIterator it(isolate_->heap()->code_space()); | 519 if (!deserializing_user_code_) { |
520 while (it.has_next()) { | 520 // The entire isolate is newly deserialized. Simply flush all code pages. |
521 Page* p = it.next(); | 521 PageIterator it(isolate_->heap()->code_space()); |
522 CpuFeatures::FlushICache(p->area_start(), p->area_end() - p->area_start()); | 522 while (it.has_next()) { |
| 523 Page* p = it.next(); |
| 524 CpuFeatures::FlushICache(p->area_start(), |
| 525 p->area_end() - p->area_start()); |
| 526 } |
| 527 } |
| 528 for (Code* code : new_code_objects_) { |
| 529 CpuFeatures::FlushICache(code->instruction_start(), |
| 530 code->instruction_size()); |
523 } | 531 } |
524 } | 532 } |
525 | 533 |
526 | 534 |
527 bool Deserializer::ReserveSpace() { | 535 bool Deserializer::ReserveSpace() { |
528 #ifdef DEBUG | 536 #ifdef DEBUG |
529 for (int i = NEW_SPACE; i < kNumberOfSpaces; ++i) { | 537 for (int i = NEW_SPACE; i < kNumberOfSpaces; ++i) { |
530 CHECK(reservations_[i].length() > 0); | 538 CHECK(reservations_[i].length() > 0); |
531 } | 539 } |
532 #endif // DEBUG | 540 #endif // DEBUG |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 // Keep track of the code space start and end pointers in case new | 613 // Keep track of the code space start and end pointers in case new |
606 // code objects were unserialized | 614 // code objects were unserialized |
607 OldSpace* code_space = isolate_->heap()->code_space(); | 615 OldSpace* code_space = isolate_->heap()->code_space(); |
608 Address start_address = code_space->top(); | 616 Address start_address = code_space->top(); |
609 Object* root; | 617 Object* root; |
610 Object* outdated_contexts; | 618 Object* outdated_contexts; |
611 VisitPointer(&root); | 619 VisitPointer(&root); |
612 VisitPointer(&outdated_contexts); | 620 VisitPointer(&outdated_contexts); |
613 DeserializeDeferredObjects(); | 621 DeserializeDeferredObjects(); |
614 | 622 |
615 // There's no code deserialized here. If this assert fires | 623 // There's no code deserialized here. If this assert fires then that's |
616 // then that's changed and logging should be added to notify | 624 // changed and logging should be added to notify the profiler et al of the |
617 // the profiler et al of the new code. | 625 // new code, which also has to be flushed from instruction cache. |
618 CHECK_EQ(start_address, code_space->top()); | 626 CHECK_EQ(start_address, code_space->top()); |
619 CHECK(outdated_contexts->IsFixedArray()); | 627 CHECK(outdated_contexts->IsFixedArray()); |
620 *outdated_contexts_out = | 628 *outdated_contexts_out = |
621 Handle<FixedArray>(FixedArray::cast(outdated_contexts), isolate); | 629 Handle<FixedArray>(FixedArray::cast(outdated_contexts), isolate); |
622 return Handle<Object>(root, isolate); | 630 return Handle<Object>(root, isolate); |
623 } | 631 } |
624 | 632 |
625 | 633 |
626 MaybeHandle<SharedFunctionInfo> Deserializer::DeserializeCode( | 634 MaybeHandle<SharedFunctionInfo> Deserializer::DeserializeCode( |
627 Isolate* isolate) { | 635 Isolate* isolate) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 int space = code & kSpaceMask; | 668 int space = code & kSpaceMask; |
661 DCHECK(space <= kNumberOfSpaces); | 669 DCHECK(space <= kNumberOfSpaces); |
662 DCHECK(code - space == kNewObject); | 670 DCHECK(code - space == kNewObject); |
663 HeapObject* object = GetBackReferencedObject(space); | 671 HeapObject* object = GetBackReferencedObject(space); |
664 int size = source_.GetInt() << kPointerSizeLog2; | 672 int size = source_.GetInt() << kPointerSizeLog2; |
665 Address obj_address = object->address(); | 673 Address obj_address = object->address(); |
666 Object** start = reinterpret_cast<Object**>(obj_address + kPointerSize); | 674 Object** start = reinterpret_cast<Object**>(obj_address + kPointerSize); |
667 Object** end = reinterpret_cast<Object**>(obj_address + size); | 675 Object** end = reinterpret_cast<Object**>(obj_address + size); |
668 bool filled = ReadData(start, end, space, obj_address); | 676 bool filled = ReadData(start, end, space, obj_address); |
669 CHECK(filled); | 677 CHECK(filled); |
670 if (object->IsAllocationSite()) { | 678 DCHECK(CanBeDeferred(object)); |
671 RelinkAllocationSite(AllocationSite::cast(object)); | 679 PostProcessNewObject(object, space); |
672 } | |
673 } | 680 } |
674 } | 681 } |
675 | 682 |
676 | 683 |
677 // Used to insert a deserialized internalized string into the string table. | 684 // Used to insert a deserialized internalized string into the string table. |
678 class StringTableInsertionKey : public HashTableKey { | 685 class StringTableInsertionKey : public HashTableKey { |
679 public: | 686 public: |
680 explicit StringTableInsertionKey(String* string) | 687 explicit StringTableInsertionKey(String* string) |
681 : string_(string), hash_(HashForObject(string)) { | 688 : string_(string), hash_(HashForObject(string)) { |
682 DCHECK(string->IsInternalizedString()); | 689 DCHECK(string->IsInternalizedString()); |
(...skipping 15 matching lines...) Expand all Loading... |
698 | 705 |
699 MUST_USE_RESULT virtual Handle<Object> AsHandle(Isolate* isolate) override { | 706 MUST_USE_RESULT virtual Handle<Object> AsHandle(Isolate* isolate) override { |
700 return handle(string_, isolate); | 707 return handle(string_, isolate); |
701 } | 708 } |
702 | 709 |
703 String* string_; | 710 String* string_; |
704 uint32_t hash_; | 711 uint32_t hash_; |
705 }; | 712 }; |
706 | 713 |
707 | 714 |
708 HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj) { | 715 HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj, int space) { |
709 DCHECK(deserializing_user_code()); | 716 if (deserializing_user_code()) { |
710 if (obj->IsString()) { | 717 if (obj->IsString()) { |
711 String* string = String::cast(obj); | 718 String* string = String::cast(obj); |
712 // Uninitialize hash field as the hash seed may have changed. | 719 // Uninitialize hash field as the hash seed may have changed. |
713 string->set_hash_field(String::kEmptyHashField); | 720 string->set_hash_field(String::kEmptyHashField); |
714 if (string->IsInternalizedString()) { | 721 if (string->IsInternalizedString()) { |
715 DisallowHeapAllocation no_gc; | 722 // Canonicalize the internalized string. If it already exists in the |
716 HandleScope scope(isolate_); | 723 // string table, set it to forward to the existing one. |
717 StringTableInsertionKey key(string); | 724 DisallowHeapAllocation no_gc; |
718 String* canonical = *StringTable::LookupKey(isolate_, &key); | 725 HandleScope scope(isolate_); |
719 string->SetForwardedInternalizedString(canonical); | 726 StringTableInsertionKey key(string); |
720 return canonical; | 727 String* canonical = *StringTable::LookupKey(isolate_, &key); |
| 728 string->SetForwardedInternalizedString(canonical); |
| 729 return canonical; |
| 730 } |
| 731 } else if (obj->IsScript()) { |
| 732 // Assign a new script id to avoid collision. |
| 733 Script::cast(obj)->set_id(isolate_->heap()->NextScriptId()); |
| 734 } else { |
| 735 DCHECK(CanBeDeferred(obj)); |
721 } | 736 } |
722 } else if (obj->IsScript()) { | 737 } |
723 Script::cast(obj)->set_id(isolate_->heap()->NextScriptId()); | 738 if (obj->IsAllocationSite()) { |
724 } else { | 739 DCHECK(obj->IsAllocationSite()); |
725 DCHECK(CanBeDeferred(obj)); | 740 // Allocation sites are present in the snapshot, and must be linked into |
| 741 // a list at deserialization time. |
| 742 AllocationSite* site = AllocationSite::cast(obj); |
| 743 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() |
| 744 // as a (weak) root. If this root is relocated correctly, this becomes |
| 745 // unnecessary. |
| 746 if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { |
| 747 site->set_weak_next(isolate_->heap()->undefined_value()); |
| 748 } else { |
| 749 site->set_weak_next(isolate_->heap()->allocation_sites_list()); |
| 750 } |
| 751 isolate_->heap()->set_allocation_sites_list(site); |
| 752 } else if (obj->IsCode()) { |
| 753 // We flush all code pages after deserializing the startup snapshot. In that |
| 754 // case, we only need to remember code objects in the large object space. |
| 755 // When deserializing user code, remember each individual code object. |
| 756 if (deserializing_user_code() || space == LO_SPACE) { |
| 757 new_code_objects_.Add(Code::cast(obj)); |
| 758 } |
726 } | 759 } |
727 return obj; | 760 return obj; |
728 } | 761 } |
729 | 762 |
730 | 763 |
731 void Deserializer::RelinkAllocationSite(AllocationSite* obj) { | |
732 DCHECK(obj->IsAllocationSite()); | |
733 // Allocation sites are present in the snapshot, and must be linked into | |
734 // a list at deserialization time. | |
735 AllocationSite* site = AllocationSite::cast(obj); | |
736 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() | |
737 // as a (weak) root. If this root is relocated correctly, | |
738 // RelinkAllocationSite() isn't necessary. | |
739 if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { | |
740 site->set_weak_next(isolate_->heap()->undefined_value()); | |
741 } else { | |
742 site->set_weak_next(isolate_->heap()->allocation_sites_list()); | |
743 } | |
744 isolate_->heap()->set_allocation_sites_list(site); | |
745 } | |
746 | |
747 | |
748 HeapObject* Deserializer::GetBackReferencedObject(int space) { | 764 HeapObject* Deserializer::GetBackReferencedObject(int space) { |
749 HeapObject* obj; | 765 HeapObject* obj; |
750 BackReference back_reference(source_.GetInt()); | 766 BackReference back_reference(source_.GetInt()); |
751 if (space == LO_SPACE) { | 767 if (space == LO_SPACE) { |
752 CHECK(back_reference.chunk_index() == 0); | 768 CHECK(back_reference.chunk_index() == 0); |
753 uint32_t index = back_reference.large_object_index(); | 769 uint32_t index = back_reference.large_object_index(); |
754 obj = deserialized_large_objects_[index]; | 770 obj = deserialized_large_objects_[index]; |
755 } else { | 771 } else { |
756 DCHECK(space < kNumberOfPreallocatedSpaces); | 772 DCHECK(space < kNumberOfPreallocatedSpaces); |
757 uint32_t chunk_index = back_reference.chunk_index(); | 773 uint32_t chunk_index = back_reference.chunk_index(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 | 812 |
797 isolate_->heap()->OnAllocationEvent(obj, size); | 813 isolate_->heap()->OnAllocationEvent(obj, size); |
798 Object** current = reinterpret_cast<Object**>(address); | 814 Object** current = reinterpret_cast<Object**>(address); |
799 Object** limit = current + (size >> kPointerSizeLog2); | 815 Object** limit = current + (size >> kPointerSizeLog2); |
800 if (FLAG_log_snapshot_positions) { | 816 if (FLAG_log_snapshot_positions) { |
801 LOG(isolate_, SnapshotPositionEvent(address, source_.position())); | 817 LOG(isolate_, SnapshotPositionEvent(address, source_.position())); |
802 } | 818 } |
803 | 819 |
804 if (ReadData(current, limit, space_number, address)) { | 820 if (ReadData(current, limit, space_number, address)) { |
805 // Only post process if object content has not been deferred. | 821 // Only post process if object content has not been deferred. |
806 if (obj->IsAllocationSite()) { | 822 obj = PostProcessNewObject(obj, space_number); |
807 RelinkAllocationSite(AllocationSite::cast(obj)); | |
808 } | |
809 | |
810 if (deserializing_user_code()) obj = PostProcessNewObject(obj); | |
811 } | 823 } |
812 | 824 |
813 Object* write_back_obj = obj; | 825 Object* write_back_obj = obj; |
814 UnalignedCopy(write_back, &write_back_obj); | 826 UnalignedCopy(write_back, &write_back_obj); |
815 #ifdef DEBUG | 827 #ifdef DEBUG |
816 if (obj->IsCode()) { | 828 if (obj->IsCode()) { |
817 DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE); | 829 DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE); |
818 } else { | 830 } else { |
819 DCHECK(space_number != CODE_SPACE); | 831 DCHECK(space_number != CODE_SPACE); |
820 } | 832 } |
(...skipping 1857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2678 SerializedCodeData* scd = new SerializedCodeData(cached_data); | 2690 SerializedCodeData* scd = new SerializedCodeData(cached_data); |
2679 SanityCheckResult r = scd->SanityCheck(isolate, source); | 2691 SanityCheckResult r = scd->SanityCheck(isolate, source); |
2680 if (r == CHECK_SUCCESS) return scd; | 2692 if (r == CHECK_SUCCESS) return scd; |
2681 cached_data->Reject(); | 2693 cached_data->Reject(); |
2682 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); | 2694 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); |
2683 delete scd; | 2695 delete scd; |
2684 return NULL; | 2696 return NULL; |
2685 } | 2697 } |
2686 } // namespace internal | 2698 } // namespace internal |
2687 } // namespace v8 | 2699 } // namespace v8 |
OLD | NEW |