Chromium Code Reviews| 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 DCHECK_LE(this->group(), group); | |
|
Igor Sheludko
2015/11/20 12:35:32
I think this check is redundant, given that we hav
ulan
2015/11/23 09:01:11
Removed, the length is dchecked when accessing the
| |
| 13740 if (this->group() < group) { | |
| 13741 // The group comes later in the list. | |
| 13742 next_link()->UpdateToFinishedCode(group, info, code_cell); | |
| 13743 return; | |
| 13744 } | |
| 13745 DCHECK_EQ(group, this->group()); | |
| 13749 DisallowHeapAllocation no_gc; | 13746 DisallowHeapAllocation no_gc; |
| 13750 GroupStartIndexes starts(this); | 13747 int count = this->count(); |
| 13751 int start = starts.at(group); | 13748 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) { | 13749 if (object_at(i) == info) { |
| 13755 set_object_at(i, code_cell); | 13750 set_object_at(i, code_cell); |
| 13756 break; | 13751 break; |
| 13757 } | 13752 } |
| 13758 } | 13753 } |
| 13759 | |
| 13760 #ifdef DEBUG | 13754 #ifdef DEBUG |
| 13761 for (int i = start; i < end; i++) { | 13755 for (int i = 0; i < count; i++) { |
| 13762 DCHECK(object_at(i) != info); | 13756 DCHECK(object_at(i) != info); |
| 13763 } | 13757 } |
| 13764 #endif | 13758 #endif |
| 13765 } | 13759 } |
| 13766 | 13760 |
| 13767 | 13761 |
| 13768 void DependentCode::RemoveCompilationDependencies( | 13762 void DependentCode::RemoveCompilationDependencies( |
| 13769 DependentCode::DependencyGroup group, Foreign* info) { | 13763 DependentCode::DependencyGroup group, Foreign* info) { |
| 13764 DCHECK_LE(this->group(), group); | |
|
Igor Sheludko
2015/11/20 12:35:32
Ditto.
ulan
2015/11/23 09:01:11
Done.
| |
| 13765 if (this->group() < group) { | |
| 13766 // The group comes later in the list. | |
| 13767 next_link()->RemoveCompilationDependencies(group, info); | |
| 13768 return; | |
| 13769 } | |
| 13770 DCHECK_EQ(group, this->group()); | |
| 13770 DisallowHeapAllocation no_allocation; | 13771 DisallowHeapAllocation no_allocation; |
| 13771 GroupStartIndexes starts(this); | 13772 int old_count = count(); |
| 13772 int start = starts.at(group); | |
| 13773 int end = starts.at(group + 1); | |
| 13774 // Find compilation info wrapper. | 13773 // Find compilation info wrapper. |
| 13775 int info_pos = -1; | 13774 int info_pos = -1; |
| 13776 for (int i = start; i < end; i++) { | 13775 for (int i = 0; i < old_count; i++) { |
| 13777 if (object_at(i) == info) { | 13776 if (object_at(i) == info) { |
| 13778 info_pos = i; | 13777 info_pos = i; |
| 13779 break; | 13778 break; |
| 13780 } | 13779 } |
| 13781 } | 13780 } |
| 13782 if (info_pos == -1) return; // Not found. | 13781 if (info_pos == -1) return; // Not found. |
| 13783 int gap = info_pos; | 13782 // Use the last code to fill the gap. |
| 13784 // Use the last of each group to fill the gap in the previous group. | 13783 if (info_pos < old_count - 1) { |
| 13785 for (int i = group; i < kGroupCount; i++) { | 13784 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 } | 13785 } |
| 13792 DCHECK(gap == starts.number_of_entries() - 1); | 13786 clear_at(old_count - 1); |
| 13793 clear_at(gap); // Clear last gap. | 13787 set_count(old_count - 1); |
| 13794 set_number_of_entries(group, end - start - 1); | |
| 13795 | 13788 |
| 13796 #ifdef DEBUG | 13789 #ifdef DEBUG |
| 13797 for (int i = start; i < end - 1; i++) { | 13790 for (int i = 0; i < old_count - 1; i++) { |
| 13798 DCHECK(object_at(i) != info); | 13791 DCHECK(object_at(i) != info); |
| 13799 } | 13792 } |
| 13800 #endif | 13793 #endif |
| 13801 } | 13794 } |
| 13802 | 13795 |
| 13803 | 13796 |
| 13804 bool DependentCode::Contains(DependencyGroup group, WeakCell* code_cell) { | 13797 bool DependentCode::Contains(DependencyGroup group, WeakCell* code_cell) { |
| 13805 GroupStartIndexes starts(this); | 13798 if (this->length() == 0 || this->group() > group) { |
| 13806 int start = starts.at(group); | 13799 // There is no such group. |
| 13807 int end = starts.at(group + 1); | 13800 return false; |
| 13808 for (int i = start; i < end; i++) { | 13801 } |
| 13802 if (this->group() < group) { | |
| 13803 // The group comes later in the list. | |
| 13804 return next_link()->Contains(group, code_cell); | |
| 13805 } | |
| 13806 DCHECK_EQ(group, this->group()); | |
| 13807 int count = this->count(); | |
| 13808 for (int i = 0; i < count; i++) { | |
| 13809 if (object_at(i) == code_cell) return true; | 13809 if (object_at(i) == code_cell) return true; |
| 13810 } | 13810 } |
| 13811 return false; | 13811 return false; |
| 13812 } | 13812 } |
| 13813 | 13813 |
| 13814 | 13814 |
| 13815 bool DependentCode::IsEmpty(DependencyGroup group) { | |
| 13816 if (this->length() == 0 || this->group() > group) { | |
| 13817 // There is no such group. | |
| 13818 return true; | |
| 13819 } | |
| 13820 if (this->group() < group) { | |
| 13821 // The group comes later in the list. | |
| 13822 return next_link()->IsEmpty(group); | |
| 13823 } | |
| 13824 DCHECK_EQ(group, this->group()); | |
| 13825 return count() == 0; | |
| 13826 } | |
| 13827 | |
| 13828 | |
| 13815 bool DependentCode::MarkCodeForDeoptimization( | 13829 bool DependentCode::MarkCodeForDeoptimization( |
| 13816 Isolate* isolate, | 13830 Isolate* isolate, |
| 13817 DependentCode::DependencyGroup group) { | 13831 DependentCode::DependencyGroup group) { |
| 13832 if (this->length() == 0 || this->group() > group) { | |
| 13833 // There is no such group. | |
| 13834 return false; | |
| 13835 } | |
| 13836 if (this->group() < group) { | |
| 13837 // The group comes later in the list. | |
| 13838 return next_link()->MarkCodeForDeoptimization(isolate, group); | |
| 13839 } | |
| 13840 DCHECK_EQ(group, this->group()); | |
| 13818 DisallowHeapAllocation no_allocation_scope; | 13841 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. | 13842 // Mark all the code that needs to be deoptimized. |
| 13826 bool marked = false; | 13843 bool marked = false; |
| 13827 bool invalidate_embedded_objects = group == kWeakCodeGroup; | 13844 bool invalidate_embedded_objects = group == kWeakCodeGroup; |
| 13828 for (int i = start; i < end; i++) { | 13845 int count = this->count(); |
| 13846 for (int i = 0; i < count; i++) { | |
| 13829 Object* obj = object_at(i); | 13847 Object* obj = object_at(i); |
| 13830 if (obj->IsWeakCell()) { | 13848 if (obj->IsWeakCell()) { |
| 13831 WeakCell* cell = WeakCell::cast(obj); | 13849 WeakCell* cell = WeakCell::cast(obj); |
| 13832 if (cell->cleared()) continue; | 13850 if (cell->cleared()) continue; |
| 13833 Code* code = Code::cast(cell->value()); | 13851 Code* code = Code::cast(cell->value()); |
| 13834 if (!code->marked_for_deoptimization()) { | 13852 if (!code->marked_for_deoptimization()) { |
| 13835 SetMarkedForDeoptimization(code, group); | 13853 SetMarkedForDeoptimization(code, group); |
| 13836 if (invalidate_embedded_objects) { | 13854 if (invalidate_embedded_objects) { |
| 13837 code->InvalidateEmbeddedObjects(); | 13855 code->InvalidateEmbeddedObjects(); |
| 13838 } | 13856 } |
| 13839 marked = true; | 13857 marked = true; |
| 13840 } | 13858 } |
| 13841 } else { | 13859 } else { |
| 13842 DCHECK(obj->IsForeign()); | 13860 DCHECK(obj->IsForeign()); |
| 13843 CompilationDependencies* info = | 13861 CompilationDependencies* info = |
| 13844 reinterpret_cast<CompilationDependencies*>( | 13862 reinterpret_cast<CompilationDependencies*>( |
| 13845 Foreign::cast(obj)->foreign_address()); | 13863 Foreign::cast(obj)->foreign_address()); |
| 13846 info->Abort(); | 13864 info->Abort(); |
| 13847 } | 13865 } |
| 13848 } | 13866 } |
| 13849 // Compact the array by moving all subsequent groups to fill in the new holes. | 13867 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); | 13868 clear_at(i); |
| 13857 } | 13869 } |
| 13858 set_number_of_entries(group, 0); | 13870 set_count(0); |
| 13859 return marked; | 13871 return marked; |
| 13860 } | 13872 } |
| 13861 | 13873 |
| 13862 | 13874 |
| 13863 void DependentCode::DeoptimizeDependentCodeGroup( | 13875 void DependentCode::DeoptimizeDependentCodeGroup( |
| 13864 Isolate* isolate, | 13876 Isolate* isolate, |
| 13865 DependentCode::DependencyGroup group) { | 13877 DependentCode::DependencyGroup group) { |
| 13866 DCHECK(AllowCodeDependencyChange::IsAllowed()); | 13878 DCHECK(AllowCodeDependencyChange::IsAllowed()); |
| 13867 DisallowHeapAllocation no_allocation_scope; | 13879 DisallowHeapAllocation no_allocation_scope; |
| 13868 bool marked = MarkCodeForDeoptimization(isolate, group); | 13880 bool marked = MarkCodeForDeoptimization(isolate, group); |
| (...skipping 4032 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 17901 if (cell->value() != *new_value) { | 17913 if (cell->value() != *new_value) { |
| 17902 cell->set_value(*new_value); | 17914 cell->set_value(*new_value); |
| 17903 Isolate* isolate = cell->GetIsolate(); | 17915 Isolate* isolate = cell->GetIsolate(); |
| 17904 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17916 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 17905 isolate, DependentCode::kPropertyCellChangedGroup); | 17917 isolate, DependentCode::kPropertyCellChangedGroup); |
| 17906 } | 17918 } |
| 17907 } | 17919 } |
| 17908 | 17920 |
| 17909 } // namespace internal | 17921 } // namespace internal |
| 17910 } // namespace v8 | 17922 } // namespace v8 |
| OLD | NEW |