OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 13625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13636 void Map::AddDependentCode(Handle<Map> map, | 13636 void Map::AddDependentCode(Handle<Map> map, |
13637 DependentCode::DependencyGroup group, | 13637 DependentCode::DependencyGroup group, |
13638 Handle<Code> code) { | 13638 Handle<Code> code) { |
13639 Handle<WeakCell> cell = Code::WeakCellFor(code); | 13639 Handle<WeakCell> cell = Code::WeakCellFor(code); |
13640 Handle<DependentCode> codes = DependentCode::InsertWeakCode( | 13640 Handle<DependentCode> codes = DependentCode::InsertWeakCode( |
13641 Handle<DependentCode>(map->dependent_code()), group, cell); | 13641 Handle<DependentCode>(map->dependent_code()), group, cell); |
13642 if (*codes != map->dependent_code()) map->set_dependent_code(*codes); | 13642 if (*codes != map->dependent_code()) map->set_dependent_code(*codes); |
13643 } | 13643 } |
13644 | 13644 |
13645 | 13645 |
13646 DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) { | |
13647 Recompute(entries); | |
13648 } | |
13649 | |
13650 | |
13651 void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) { | |
13652 start_indexes_[0] = 0; | |
13653 for (int g = 1; g <= kGroupCount; g++) { | |
13654 int count = entries->number_of_entries(static_cast<DependencyGroup>(g - 1)); | |
13655 start_indexes_[g] = start_indexes_[g - 1] + count; | |
13656 } | |
13657 } | |
13658 | |
13659 | |
13660 Handle<DependentCode> DependentCode::InsertCompilationDependencies( | 13646 Handle<DependentCode> DependentCode::InsertCompilationDependencies( |
13661 Handle<DependentCode> entries, DependencyGroup group, | 13647 Handle<DependentCode> entries, DependencyGroup group, |
13662 Handle<Foreign> info) { | 13648 Handle<Foreign> info) { |
13663 return Insert(entries, group, info); | 13649 return Insert(entries, group, info); |
13664 } | 13650 } |
13665 | 13651 |
13666 | 13652 |
13667 Handle<DependentCode> DependentCode::InsertWeakCode( | 13653 Handle<DependentCode> DependentCode::InsertWeakCode( |
13668 Handle<DependentCode> entries, DependencyGroup group, | 13654 Handle<DependentCode> entries, DependencyGroup group, |
13669 Handle<WeakCell> code_cell) { | 13655 Handle<WeakCell> code_cell) { |
13670 return Insert(entries, group, code_cell); | 13656 return Insert(entries, group, code_cell); |
13671 } | 13657 } |
13672 | 13658 |
13673 | 13659 |
13674 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries, | 13660 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries, |
13675 DependencyGroup group, | 13661 DependencyGroup group, |
13676 Handle<Object> object) { | 13662 Handle<Object> object) { |
13677 GroupStartIndexes starts(*entries); | 13663 if (entries->length() == 0 || entries->group() > group) { |
13678 int start = starts.at(group); | 13664 // There is no such group. |
13679 int end = starts.at(group + 1); | 13665 return DependentCode::New(group, object, entries); |
13680 int number_of_entries = starts.number_of_entries(); | 13666 } |
| 13667 if (entries->group() < group) { |
| 13668 // The group comes later in the list. |
| 13669 Handle<DependentCode> old_next(entries->next_link()); |
| 13670 Handle<DependentCode> new_next = Insert(old_next, group, object); |
| 13671 if (!old_next.is_identical_to(new_next)) { |
| 13672 entries->set_next_link(*new_next); |
| 13673 } |
| 13674 return entries; |
| 13675 } |
| 13676 DCHECK_EQ(group, entries->group()); |
| 13677 int count = entries->count(); |
13681 // Check for existing entry to avoid duplicates. | 13678 // Check for existing entry to avoid duplicates. |
13682 for (int i = start; i < end; i++) { | 13679 for (int i = 0; i < count; i++) { |
13683 if (entries->object_at(i) == *object) return entries; | 13680 if (entries->object_at(i) == *object) return entries; |
13684 } | 13681 } |
13685 if (entries->length() < kCodesStartIndex + number_of_entries + 1) { | 13682 if (entries->length() < kCodesStartIndex + count + 1) { |
13686 entries = EnsureSpace(entries); | 13683 entries = EnsureSpace(entries); |
13687 // The number of codes can change after Compact and GC. | 13684 // Count could have changed, reload it. |
13688 starts.Recompute(*entries); | 13685 count = entries->count(); |
13689 start = starts.at(group); | |
13690 end = starts.at(group + 1); | |
13691 } | 13686 } |
| 13687 entries->set_object_at(count, *object); |
| 13688 entries->set_count(count + 1); |
| 13689 return entries; |
| 13690 } |
13692 | 13691 |
13693 entries->ExtendGroup(group); | 13692 |
13694 entries->set_object_at(end, *object); | 13693 Handle<DependentCode> DependentCode::New(DependencyGroup group, |
13695 entries->set_number_of_entries(group, end + 1 - start); | 13694 Handle<Object> object, |
13696 return entries; | 13695 Handle<DependentCode> next) { |
| 13696 Isolate* isolate = next->GetIsolate(); |
| 13697 Handle<DependentCode> result = Handle<DependentCode>::cast( |
| 13698 isolate->factory()->NewFixedArray(kCodesStartIndex + 1, TENURED)); |
| 13699 result->set_next_link(*next); |
| 13700 result->set_flags(GroupField::encode(group) | CountField::encode(1)); |
| 13701 result->set_object_at(0, *object); |
| 13702 return result; |
13697 } | 13703 } |
13698 | 13704 |
13699 | 13705 |
13700 Handle<DependentCode> DependentCode::EnsureSpace( | 13706 Handle<DependentCode> DependentCode::EnsureSpace( |
13701 Handle<DependentCode> entries) { | 13707 Handle<DependentCode> entries) { |
| 13708 if (entries->Compact()) return entries; |
13702 Isolate* isolate = entries->GetIsolate(); | 13709 Isolate* isolate = entries->GetIsolate(); |
13703 if (entries->length() == 0) { | 13710 int capacity = kCodesStartIndex + DependentCode::Grow(entries->count()); |
13704 entries = Handle<DependentCode>::cast( | |
13705 isolate->factory()->NewFixedArray(kCodesStartIndex + 1, TENURED)); | |
13706 for (int g = 0; g < kGroupCount; g++) { | |
13707 entries->set_number_of_entries(static_cast<DependencyGroup>(g), 0); | |
13708 } | |
13709 return entries; | |
13710 } | |
13711 if (entries->Compact()) return entries; | |
13712 GroupStartIndexes starts(*entries); | |
13713 int capacity = | |
13714 kCodesStartIndex + DependentCode::Grow(starts.number_of_entries()); | |
13715 int grow_by = capacity - entries->length(); | 13711 int grow_by = capacity - entries->length(); |
13716 return Handle<DependentCode>::cast( | 13712 return Handle<DependentCode>::cast( |
13717 isolate->factory()->CopyFixedArrayAndGrow(entries, grow_by, TENURED)); | 13713 isolate->factory()->CopyFixedArrayAndGrow(entries, grow_by, TENURED)); |
13718 } | 13714 } |
13719 | 13715 |
13720 | 13716 |
13721 bool DependentCode::Compact() { | 13717 bool DependentCode::Compact() { |
13722 GroupStartIndexes starts(this); | 13718 int old_count = count(); |
13723 int n = 0; | 13719 int new_count = 0; |
13724 for (int g = 0; g < kGroupCount; g++) { | 13720 for (int i = 0; i < old_count; i++) { |
13725 int start = starts.at(g); | 13721 Object* obj = object_at(i); |
13726 int end = starts.at(g + 1); | 13722 if (!obj->IsWeakCell() || !WeakCell::cast(obj)->cleared()) { |
13727 int count = 0; | 13723 if (i != new_count) { |
13728 DCHECK(start >= n); | 13724 copy(i, new_count); |
13729 for (int i = start; i < end; i++) { | |
13730 Object* obj = object_at(i); | |
13731 if (!obj->IsWeakCell() || !WeakCell::cast(obj)->cleared()) { | |
13732 if (i != n + count) { | |
13733 copy(i, n + count); | |
13734 } | |
13735 count++; | |
13736 } | 13725 } |
| 13726 new_count++; |
13737 } | 13727 } |
13738 if (count != end - start) { | |
13739 set_number_of_entries(static_cast<DependencyGroup>(g), count); | |
13740 } | |
13741 n += count; | |
13742 } | 13728 } |
13743 return n < starts.number_of_entries(); | 13729 set_count(new_count); |
| 13730 for (int i = new_count; i < old_count; i++) { |
| 13731 clear_at(i); |
| 13732 } |
| 13733 return new_count < old_count; |
13744 } | 13734 } |
13745 | 13735 |
13746 | 13736 |
13747 void DependentCode::UpdateToFinishedCode(DependencyGroup group, Foreign* info, | 13737 void DependentCode::UpdateToFinishedCode(DependencyGroup group, Foreign* info, |
13748 WeakCell* code_cell) { | 13738 WeakCell* code_cell) { |
| 13739 if (this->length() == 0 || this->group() > group) { |
| 13740 // There is no such group. |
| 13741 return; |
| 13742 } |
| 13743 if (this->group() < group) { |
| 13744 // The group comes later in the list. |
| 13745 next_link()->UpdateToFinishedCode(group, info, code_cell); |
| 13746 return; |
| 13747 } |
| 13748 DCHECK_EQ(group, this->group()); |
13749 DisallowHeapAllocation no_gc; | 13749 DisallowHeapAllocation no_gc; |
13750 GroupStartIndexes starts(this); | 13750 int count = this->count(); |
13751 int start = starts.at(group); | 13751 for (int i = 0; i < count; i++) { |
13752 int end = starts.at(group + 1); | |
13753 for (int i = start; i < end; i++) { | |
13754 if (object_at(i) == info) { | 13752 if (object_at(i) == info) { |
13755 set_object_at(i, code_cell); | 13753 set_object_at(i, code_cell); |
13756 break; | 13754 break; |
13757 } | 13755 } |
13758 } | 13756 } |
13759 | |
13760 #ifdef DEBUG | 13757 #ifdef DEBUG |
13761 for (int i = start; i < end; i++) { | 13758 for (int i = 0; i < count; i++) { |
13762 DCHECK(object_at(i) != info); | 13759 DCHECK(object_at(i) != info); |
13763 } | 13760 } |
13764 #endif | 13761 #endif |
13765 } | 13762 } |
13766 | 13763 |
13767 | 13764 |
13768 void DependentCode::RemoveCompilationDependencies( | 13765 void DependentCode::RemoveCompilationDependencies( |
13769 DependentCode::DependencyGroup group, Foreign* info) { | 13766 DependentCode::DependencyGroup group, Foreign* info) { |
| 13767 if (this->length() == 0 || this->group() > group) { |
| 13768 // There is no such group. |
| 13769 return; |
| 13770 } |
| 13771 if (this->group() < group) { |
| 13772 // The group comes later in the list. |
| 13773 next_link()->RemoveCompilationDependencies(group, info); |
| 13774 return; |
| 13775 } |
| 13776 DCHECK_EQ(group, this->group()); |
13770 DisallowHeapAllocation no_allocation; | 13777 DisallowHeapAllocation no_allocation; |
13771 GroupStartIndexes starts(this); | 13778 int old_count = count(); |
13772 int start = starts.at(group); | |
13773 int end = starts.at(group + 1); | |
13774 // Find compilation info wrapper. | 13779 // Find compilation info wrapper. |
13775 int info_pos = -1; | 13780 int info_pos = -1; |
13776 for (int i = start; i < end; i++) { | 13781 for (int i = 0; i < old_count; i++) { |
13777 if (object_at(i) == info) { | 13782 if (object_at(i) == info) { |
13778 info_pos = i; | 13783 info_pos = i; |
13779 break; | 13784 break; |
13780 } | 13785 } |
13781 } | 13786 } |
13782 if (info_pos == -1) return; // Not found. | 13787 if (info_pos == -1) return; // Not found. |
13783 int gap = info_pos; | 13788 // Use the last code to fill the gap. |
13784 // Use the last of each group to fill the gap in the previous group. | 13789 if (info_pos < old_count - 1) { |
13785 for (int i = group; i < kGroupCount; i++) { | 13790 copy(old_count - 1, info_pos); |
13786 int last_of_group = starts.at(i + 1) - 1; | |
13787 DCHECK(last_of_group >= gap); | |
13788 if (last_of_group == gap) continue; | |
13789 copy(last_of_group, gap); | |
13790 gap = last_of_group; | |
13791 } | 13791 } |
13792 DCHECK(gap == starts.number_of_entries() - 1); | 13792 clear_at(old_count - 1); |
13793 clear_at(gap); // Clear last gap. | 13793 set_count(old_count - 1); |
13794 set_number_of_entries(group, end - start - 1); | |
13795 | 13794 |
13796 #ifdef DEBUG | 13795 #ifdef DEBUG |
13797 for (int i = start; i < end - 1; i++) { | 13796 for (int i = 0; i < old_count - 1; i++) { |
13798 DCHECK(object_at(i) != info); | 13797 DCHECK(object_at(i) != info); |
13799 } | 13798 } |
13800 #endif | 13799 #endif |
13801 } | 13800 } |
13802 | 13801 |
13803 | 13802 |
13804 bool DependentCode::Contains(DependencyGroup group, WeakCell* code_cell) { | 13803 bool DependentCode::Contains(DependencyGroup group, WeakCell* code_cell) { |
13805 GroupStartIndexes starts(this); | 13804 if (this->length() == 0 || this->group() > group) { |
13806 int start = starts.at(group); | 13805 // There is no such group. |
13807 int end = starts.at(group + 1); | 13806 return false; |
13808 for (int i = start; i < end; i++) { | 13807 } |
| 13808 if (this->group() < group) { |
| 13809 // The group comes later in the list. |
| 13810 return next_link()->Contains(group, code_cell); |
| 13811 } |
| 13812 DCHECK_EQ(group, this->group()); |
| 13813 int count = this->count(); |
| 13814 for (int i = 0; i < count; i++) { |
13809 if (object_at(i) == code_cell) return true; | 13815 if (object_at(i) == code_cell) return true; |
13810 } | 13816 } |
13811 return false; | 13817 return false; |
13812 } | 13818 } |
13813 | 13819 |
13814 | 13820 |
| 13821 bool DependentCode::IsEmpty(DependencyGroup group) { |
| 13822 if (this->length() == 0 || this->group() > group) { |
| 13823 // There is no such group. |
| 13824 return true; |
| 13825 } |
| 13826 if (this->group() < group) { |
| 13827 // The group comes later in the list. |
| 13828 return next_link()->IsEmpty(group); |
| 13829 } |
| 13830 DCHECK_EQ(group, this->group()); |
| 13831 return count() == 0; |
| 13832 } |
| 13833 |
| 13834 |
13815 bool DependentCode::MarkCodeForDeoptimization( | 13835 bool DependentCode::MarkCodeForDeoptimization( |
13816 Isolate* isolate, | 13836 Isolate* isolate, |
13817 DependentCode::DependencyGroup group) { | 13837 DependentCode::DependencyGroup group) { |
| 13838 if (this->length() == 0 || this->group() > group) { |
| 13839 // There is no such group. |
| 13840 return false; |
| 13841 } |
| 13842 if (this->group() < group) { |
| 13843 // The group comes later in the list. |
| 13844 return next_link()->MarkCodeForDeoptimization(isolate, group); |
| 13845 } |
| 13846 DCHECK_EQ(group, this->group()); |
13818 DisallowHeapAllocation no_allocation_scope; | 13847 DisallowHeapAllocation no_allocation_scope; |
13819 DependentCode::GroupStartIndexes starts(this); | |
13820 int start = starts.at(group); | |
13821 int end = starts.at(group + 1); | |
13822 int code_entries = starts.number_of_entries(); | |
13823 if (start == end) return false; | |
13824 | |
13825 // Mark all the code that needs to be deoptimized. | 13848 // Mark all the code that needs to be deoptimized. |
13826 bool marked = false; | 13849 bool marked = false; |
13827 bool invalidate_embedded_objects = group == kWeakCodeGroup; | 13850 bool invalidate_embedded_objects = group == kWeakCodeGroup; |
13828 for (int i = start; i < end; i++) { | 13851 int count = this->count(); |
| 13852 for (int i = 0; i < count; i++) { |
13829 Object* obj = object_at(i); | 13853 Object* obj = object_at(i); |
13830 if (obj->IsWeakCell()) { | 13854 if (obj->IsWeakCell()) { |
13831 WeakCell* cell = WeakCell::cast(obj); | 13855 WeakCell* cell = WeakCell::cast(obj); |
13832 if (cell->cleared()) continue; | 13856 if (cell->cleared()) continue; |
13833 Code* code = Code::cast(cell->value()); | 13857 Code* code = Code::cast(cell->value()); |
13834 if (!code->marked_for_deoptimization()) { | 13858 if (!code->marked_for_deoptimization()) { |
13835 SetMarkedForDeoptimization(code, group); | 13859 SetMarkedForDeoptimization(code, group); |
13836 if (invalidate_embedded_objects) { | 13860 if (invalidate_embedded_objects) { |
13837 code->InvalidateEmbeddedObjects(); | 13861 code->InvalidateEmbeddedObjects(); |
13838 } | 13862 } |
13839 marked = true; | 13863 marked = true; |
13840 } | 13864 } |
13841 } else { | 13865 } else { |
13842 DCHECK(obj->IsForeign()); | 13866 DCHECK(obj->IsForeign()); |
13843 CompilationDependencies* info = | 13867 CompilationDependencies* info = |
13844 reinterpret_cast<CompilationDependencies*>( | 13868 reinterpret_cast<CompilationDependencies*>( |
13845 Foreign::cast(obj)->foreign_address()); | 13869 Foreign::cast(obj)->foreign_address()); |
13846 info->Abort(); | 13870 info->Abort(); |
13847 } | 13871 } |
13848 } | 13872 } |
13849 // Compact the array by moving all subsequent groups to fill in the new holes. | 13873 for (int i = 0; i < count; i++) { |
13850 for (int src = end, dst = start; src < code_entries; src++, dst++) { | |
13851 copy(src, dst); | |
13852 } | |
13853 // Now the holes are at the end of the array, zap them for heap-verifier. | |
13854 int removed = end - start; | |
13855 for (int i = code_entries - removed; i < code_entries; i++) { | |
13856 clear_at(i); | 13874 clear_at(i); |
13857 } | 13875 } |
13858 set_number_of_entries(group, 0); | 13876 set_count(0); |
13859 return marked; | 13877 return marked; |
13860 } | 13878 } |
13861 | 13879 |
13862 | 13880 |
13863 void DependentCode::DeoptimizeDependentCodeGroup( | 13881 void DependentCode::DeoptimizeDependentCodeGroup( |
13864 Isolate* isolate, | 13882 Isolate* isolate, |
13865 DependentCode::DependencyGroup group) { | 13883 DependentCode::DependencyGroup group) { |
13866 DCHECK(AllowCodeDependencyChange::IsAllowed()); | 13884 DCHECK(AllowCodeDependencyChange::IsAllowed()); |
13867 DisallowHeapAllocation no_allocation_scope; | 13885 DisallowHeapAllocation no_allocation_scope; |
13868 bool marked = MarkCodeForDeoptimization(isolate, group); | 13886 bool marked = MarkCodeForDeoptimization(isolate, group); |
(...skipping 4032 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17901 if (cell->value() != *new_value) { | 17919 if (cell->value() != *new_value) { |
17902 cell->set_value(*new_value); | 17920 cell->set_value(*new_value); |
17903 Isolate* isolate = cell->GetIsolate(); | 17921 Isolate* isolate = cell->GetIsolate(); |
17904 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17922 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17905 isolate, DependentCode::kPropertyCellChangedGroup); | 17923 isolate, DependentCode::kPropertyCellChangedGroup); |
17906 } | 17924 } |
17907 } | 17925 } |
17908 | 17926 |
17909 } // namespace internal | 17927 } // namespace internal |
17910 } // namespace v8 | 17928 } // namespace v8 |
OLD | NEW |