| 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 | 
|---|