| 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/heap/heap.h" | 5 #include "src/heap/heap.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/ast/scopeinfo.h" | 9 #include "src/ast/scopeinfo.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 memory_reducer_(nullptr), | 143 memory_reducer_(nullptr), |
| 144 object_stats_(nullptr), | 144 object_stats_(nullptr), |
| 145 scavenge_job_(nullptr), | 145 scavenge_job_(nullptr), |
| 146 idle_scavenge_observer_(nullptr), | 146 idle_scavenge_observer_(nullptr), |
| 147 full_codegen_bytes_generated_(0), | 147 full_codegen_bytes_generated_(0), |
| 148 crankshaft_codegen_bytes_generated_(0), | 148 crankshaft_codegen_bytes_generated_(0), |
| 149 new_space_allocation_counter_(0), | 149 new_space_allocation_counter_(0), |
| 150 old_generation_allocation_counter_(0), | 150 old_generation_allocation_counter_(0), |
| 151 old_generation_size_at_last_gc_(0), | 151 old_generation_size_at_last_gc_(0), |
| 152 gcs_since_last_deopt_(0), | 152 gcs_since_last_deopt_(0), |
| 153 allocation_sites_scratchpad_length_(0), | 153 global_pretenuring_feedback_(nullptr), |
| 154 ring_buffer_full_(false), | 154 ring_buffer_full_(false), |
| 155 ring_buffer_end_(0), | 155 ring_buffer_end_(0), |
| 156 promotion_queue_(this), | 156 promotion_queue_(this), |
| 157 configured_(false), | 157 configured_(false), |
| 158 current_gc_flags_(Heap::kNoGCFlags), | 158 current_gc_flags_(Heap::kNoGCFlags), |
| 159 current_gc_callback_flags_(GCCallbackFlags::kNoGCCallbackFlags), | 159 current_gc_callback_flags_(GCCallbackFlags::kNoGCCallbackFlags), |
| 160 external_string_table_(this), | 160 external_string_table_(this), |
| 161 chunks_queued_for_free_(NULL), | 161 chunks_queued_for_free_(NULL), |
| 162 concurrent_unmapping_tasks_active_(0), | 162 concurrent_unmapping_tasks_active_(0), |
| 163 pending_unmapping_tasks_semaphore_(0), | 163 pending_unmapping_tasks_semaphore_(0), |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 | 501 |
| 502 void Heap::RepairFreeListsAfterDeserialization() { | 502 void Heap::RepairFreeListsAfterDeserialization() { |
| 503 PagedSpaces spaces(this); | 503 PagedSpaces spaces(this); |
| 504 for (PagedSpace* space = spaces.next(); space != NULL; | 504 for (PagedSpace* space = spaces.next(); space != NULL; |
| 505 space = spaces.next()) { | 505 space = spaces.next()) { |
| 506 space->RepairFreeListsAfterDeserialization(); | 506 space->RepairFreeListsAfterDeserialization(); |
| 507 } | 507 } |
| 508 } | 508 } |
| 509 | 509 |
| 510 | 510 |
| 511 bool Heap::ProcessPretenuringFeedback() { | 511 void Heap::MergeAllocationSitePretenuringFeedback( |
| 512 const HashMap& local_pretenuring_feedback) { |
| 513 AllocationSite* site = nullptr; |
| 514 for (HashMap::Entry* local_entry = local_pretenuring_feedback.Start(); |
| 515 local_entry != nullptr; |
| 516 local_entry = local_pretenuring_feedback.Next(local_entry)) { |
| 517 site = reinterpret_cast<AllocationSite*>(local_entry->key); |
| 518 MapWord map_word = site->map_word(); |
| 519 if (map_word.IsForwardingAddress()) { |
| 520 site = AllocationSite::cast(map_word.ToForwardingAddress()); |
| 521 } |
| 522 DCHECK(site->IsAllocationSite()); |
| 523 int value = |
| 524 static_cast<int>(reinterpret_cast<intptr_t>(local_entry->value)); |
| 525 DCHECK_GT(value, 0); |
| 526 |
| 527 { |
| 528 // TODO(mlippautz): For parallel processing we need synchronization here. |
| 529 if (site->IncrementMementoFoundCount(value)) { |
| 530 global_pretenuring_feedback_->LookupOrInsert( |
| 531 site, static_cast<uint32_t>(bit_cast<uintptr_t>(site))); |
| 532 } |
| 533 } |
| 534 } |
| 535 } |
| 536 |
| 537 |
| 538 class Heap::PretenuringScope { |
| 539 public: |
| 540 explicit PretenuringScope(Heap* heap) : heap_(heap) { |
| 541 heap_->global_pretenuring_feedback_ = |
| 542 new HashMap(HashMap::PointersMatch, kInitialFeedbackCapacity); |
| 543 } |
| 544 |
| 545 ~PretenuringScope() { |
| 546 delete heap_->global_pretenuring_feedback_; |
| 547 heap_->global_pretenuring_feedback_ = nullptr; |
| 548 } |
| 549 |
| 550 private: |
| 551 Heap* heap_; |
| 552 }; |
| 553 |
| 554 |
| 555 void Heap::ProcessPretenuringFeedback() { |
| 512 bool trigger_deoptimization = false; | 556 bool trigger_deoptimization = false; |
| 513 if (FLAG_allocation_site_pretenuring) { | 557 if (FLAG_allocation_site_pretenuring) { |
| 514 int tenure_decisions = 0; | 558 int tenure_decisions = 0; |
| 515 int dont_tenure_decisions = 0; | 559 int dont_tenure_decisions = 0; |
| 516 int allocation_mementos_found = 0; | 560 int allocation_mementos_found = 0; |
| 517 int allocation_sites = 0; | 561 int allocation_sites = 0; |
| 518 int active_allocation_sites = 0; | 562 int active_allocation_sites = 0; |
| 519 | 563 |
| 520 // If the scratchpad overflowed, we have to iterate over the allocation | 564 AllocationSite* site = nullptr; |
| 521 // sites list. | 565 |
| 522 // TODO(hpayer): We iterate over the whole list of allocation sites when | 566 // Step 1: Digest feedback for recorded allocation sites. |
| 523 // we grew to the maximum semi-space size to deopt maybe tenured | 567 bool maximum_size_scavenge = MaximumSizeScavenge(); |
| 524 // allocation sites. We could hold the maybe tenured allocation sites | 568 for (HashMap::Entry* e = global_pretenuring_feedback_->Start(); |
| 525 // in a seperate data structure if this is a performance problem. | 569 e != nullptr; e = global_pretenuring_feedback_->Next(e)) { |
| 570 site = reinterpret_cast<AllocationSite*>(e->key); |
| 571 int found_count = site->memento_found_count(); |
| 572 // The fact that we have an entry in the storage means that we've found |
| 573 // the site at least once. |
| 574 DCHECK_GT(found_count, 0); |
| 575 DCHECK(site->IsAllocationSite()); |
| 576 allocation_sites++; |
| 577 active_allocation_sites++; |
| 578 allocation_mementos_found += found_count; |
| 579 if (site->DigestPretenuringFeedback(maximum_size_scavenge)) { |
| 580 trigger_deoptimization = true; |
| 581 } |
| 582 if (site->GetPretenureMode() == TENURED) { |
| 583 tenure_decisions++; |
| 584 } else { |
| 585 dont_tenure_decisions++; |
| 586 } |
| 587 } |
| 588 |
| 589 // Step 2: Deopt maybe tenured allocation sites if necessary. |
| 526 bool deopt_maybe_tenured = DeoptMaybeTenuredAllocationSites(); | 590 bool deopt_maybe_tenured = DeoptMaybeTenuredAllocationSites(); |
| 527 bool use_scratchpad = | 591 if (deopt_maybe_tenured) { |
| 528 allocation_sites_scratchpad_length_ < kAllocationSiteScratchpadSize && | 592 Object* list_element = allocation_sites_list(); |
| 529 !deopt_maybe_tenured; | 593 while (list_element->IsAllocationSite()) { |
| 530 | 594 site = AllocationSite::cast(list_element); |
| 531 int i = 0; | 595 DCHECK(site->IsAllocationSite()); |
| 532 Object* list_element = allocation_sites_list(); | 596 allocation_sites++; |
| 533 bool maximum_size_scavenge = MaximumSizeScavenge(); | 597 if (site->IsMaybeTenure()) { |
| 534 while (use_scratchpad ? i < allocation_sites_scratchpad_length_ | 598 site->set_deopt_dependent_code(true); |
| 535 : list_element->IsAllocationSite()) { | |
| 536 AllocationSite* site = | |
| 537 use_scratchpad | |
| 538 ? AllocationSite::cast(allocation_sites_scratchpad()->get(i)) | |
| 539 : AllocationSite::cast(list_element); | |
| 540 allocation_mementos_found += site->memento_found_count(); | |
| 541 if (site->memento_found_count() > 0) { | |
| 542 active_allocation_sites++; | |
| 543 if (site->DigestPretenuringFeedback(maximum_size_scavenge)) { | |
| 544 trigger_deoptimization = true; | 599 trigger_deoptimization = true; |
| 545 } | 600 } |
| 546 if (site->GetPretenureMode() == TENURED) { | |
| 547 tenure_decisions++; | |
| 548 } else { | |
| 549 dont_tenure_decisions++; | |
| 550 } | |
| 551 allocation_sites++; | |
| 552 } | |
| 553 | |
| 554 if (deopt_maybe_tenured && site->IsMaybeTenure()) { | |
| 555 site->set_deopt_dependent_code(true); | |
| 556 trigger_deoptimization = true; | |
| 557 } | |
| 558 | |
| 559 if (use_scratchpad) { | |
| 560 i++; | |
| 561 } else { | |
| 562 list_element = site->weak_next(); | 601 list_element = site->weak_next(); |
| 563 } | 602 } |
| 564 } | 603 } |
| 565 | 604 |
| 566 if (trigger_deoptimization) { | 605 if (trigger_deoptimization) { |
| 567 isolate_->stack_guard()->RequestDeoptMarkedAllocationSites(); | 606 isolate_->stack_guard()->RequestDeoptMarkedAllocationSites(); |
| 568 } | 607 } |
| 569 | 608 |
| 570 FlushAllocationSitesScratchpad(); | |
| 571 | |
| 572 if (FLAG_trace_pretenuring_statistics && | 609 if (FLAG_trace_pretenuring_statistics && |
| 573 (allocation_mementos_found > 0 || tenure_decisions > 0 || | 610 (allocation_mementos_found > 0 || tenure_decisions > 0 || |
| 574 dont_tenure_decisions > 0)) { | 611 dont_tenure_decisions > 0)) { |
| 575 PrintF( | 612 PrintIsolate(isolate(), |
| 576 "GC: (mode, #visited allocation sites, #active allocation sites, " | 613 "pretenuring: deopt_maybe_tenured=%d visited_sites=%d " |
| 577 "#mementos, #tenure decisions, #donttenure decisions) " | 614 "active_sites=%d " |
| 578 "(%s, %d, %d, %d, %d, %d)\n", | 615 "mementos=%d tenured=%d not_tenured=%d\n", |
| 579 use_scratchpad ? "use scratchpad" : "use list", allocation_sites, | 616 deopt_maybe_tenured ? 1 : 0, allocation_sites, |
| 580 active_allocation_sites, allocation_mementos_found, tenure_decisions, | 617 active_allocation_sites, allocation_mementos_found, |
| 581 dont_tenure_decisions); | 618 tenure_decisions, dont_tenure_decisions); |
| 582 } | 619 } |
| 583 } | 620 } |
| 584 return trigger_deoptimization; | |
| 585 } | 621 } |
| 586 | 622 |
| 587 | 623 |
| 588 void Heap::DeoptMarkedAllocationSites() { | 624 void Heap::DeoptMarkedAllocationSites() { |
| 589 // TODO(hpayer): If iterating over the allocation sites list becomes a | 625 // TODO(hpayer): If iterating over the allocation sites list becomes a |
| 590 // performance issue, use a cache heap data structure instead (similar to the | 626 // performance issue, use a cache data structure in heap instead. |
| 591 // allocation sites scratchpad). | |
| 592 Object* list_element = allocation_sites_list(); | 627 Object* list_element = allocation_sites_list(); |
| 593 while (list_element->IsAllocationSite()) { | 628 while (list_element->IsAllocationSite()) { |
| 594 AllocationSite* site = AllocationSite::cast(list_element); | 629 AllocationSite* site = AllocationSite::cast(list_element); |
| 595 if (site->deopt_dependent_code()) { | 630 if (site->deopt_dependent_code()) { |
| 596 site->dependent_code()->MarkCodeForDeoptimization( | 631 site->dependent_code()->MarkCodeForDeoptimization( |
| 597 isolate_, DependentCode::kAllocationSiteTenuringChangedGroup); | 632 isolate_, DependentCode::kAllocationSiteTenuringChangedGroup); |
| 598 site->set_deopt_dependent_code(false); | 633 site->set_deopt_dependent_code(false); |
| 599 } | 634 } |
| 600 list_element = site->weak_next(); | 635 list_element = site->weak_next(); |
| 601 } | 636 } |
| (...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1255 | 1290 |
| 1256 int start_new_space_size = Heap::new_space()->SizeAsInt(); | 1291 int start_new_space_size = Heap::new_space()->SizeAsInt(); |
| 1257 | 1292 |
| 1258 if (IsHighSurvivalRate()) { | 1293 if (IsHighSurvivalRate()) { |
| 1259 // We speed up the incremental marker if it is running so that it | 1294 // We speed up the incremental marker if it is running so that it |
| 1260 // does not fall behind the rate of promotion, which would cause a | 1295 // does not fall behind the rate of promotion, which would cause a |
| 1261 // constantly growing old space. | 1296 // constantly growing old space. |
| 1262 incremental_marking()->NotifyOfHighPromotionRate(); | 1297 incremental_marking()->NotifyOfHighPromotionRate(); |
| 1263 } | 1298 } |
| 1264 | 1299 |
| 1265 if (collector == MARK_COMPACTOR) { | 1300 { |
| 1266 UpdateOldGenerationAllocationCounter(); | 1301 Heap::PretenuringScope pretenuring_scope(this); |
| 1267 // Perform mark-sweep with optional compaction. | 1302 |
| 1268 MarkCompact(); | 1303 if (collector == MARK_COMPACTOR) { |
| 1269 old_gen_exhausted_ = false; | 1304 UpdateOldGenerationAllocationCounter(); |
| 1270 old_generation_size_configured_ = true; | 1305 // Perform mark-sweep with optional compaction. |
| 1271 // This should be updated before PostGarbageCollectionProcessing, which can | 1306 MarkCompact(); |
| 1272 // cause another GC. Take into account the objects promoted during GC. | 1307 old_gen_exhausted_ = false; |
| 1273 old_generation_allocation_counter_ += | 1308 old_generation_size_configured_ = true; |
| 1274 static_cast<size_t>(promoted_objects_size_); | 1309 // This should be updated before PostGarbageCollectionProcessing, which |
| 1275 old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects(); | 1310 // can cause another GC. Take into account the objects promoted during GC. |
| 1276 } else { | 1311 old_generation_allocation_counter_ += |
| 1277 Scavenge(); | 1312 static_cast<size_t>(promoted_objects_size_); |
| 1313 old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects(); |
| 1314 } else { |
| 1315 Scavenge(); |
| 1316 } |
| 1317 |
| 1318 ProcessPretenuringFeedback(); |
| 1278 } | 1319 } |
| 1279 | 1320 |
| 1280 ProcessPretenuringFeedback(); | |
| 1281 UpdateSurvivalStatistics(start_new_space_size); | 1321 UpdateSurvivalStatistics(start_new_space_size); |
| 1282 ConfigureInitialOldGenerationSize(); | 1322 ConfigureInitialOldGenerationSize(); |
| 1283 | 1323 |
| 1284 isolate_->counters()->objs_since_last_young()->Set(0); | 1324 isolate_->counters()->objs_since_last_young()->Set(0); |
| 1285 | 1325 |
| 1286 if (collector != SCAVENGER) { | 1326 if (collector != SCAVENGER) { |
| 1287 // Callbacks that fire after this point might trigger nested GCs and | 1327 // Callbacks that fire after this point might trigger nested GCs and |
| 1288 // restart incremental marking, the assertion can't be moved down. | 1328 // restart incremental marking, the assertion can't be moved down. |
| 1289 DCHECK(incremental_marking()->IsStopped()); | 1329 DCHECK(incremental_marking()->IsStopped()); |
| 1290 | 1330 |
| (...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1823 void Heap::ResetAllAllocationSitesDependentCode(PretenureFlag flag) { | 1863 void Heap::ResetAllAllocationSitesDependentCode(PretenureFlag flag) { |
| 1824 DisallowHeapAllocation no_allocation_scope; | 1864 DisallowHeapAllocation no_allocation_scope; |
| 1825 Object* cur = allocation_sites_list(); | 1865 Object* cur = allocation_sites_list(); |
| 1826 bool marked = false; | 1866 bool marked = false; |
| 1827 while (cur->IsAllocationSite()) { | 1867 while (cur->IsAllocationSite()) { |
| 1828 AllocationSite* casted = AllocationSite::cast(cur); | 1868 AllocationSite* casted = AllocationSite::cast(cur); |
| 1829 if (casted->GetPretenureMode() == flag) { | 1869 if (casted->GetPretenureMode() == flag) { |
| 1830 casted->ResetPretenureDecision(); | 1870 casted->ResetPretenureDecision(); |
| 1831 casted->set_deopt_dependent_code(true); | 1871 casted->set_deopt_dependent_code(true); |
| 1832 marked = true; | 1872 marked = true; |
| 1873 RemoveAllocationSitePretenuringFeedback(casted); |
| 1833 } | 1874 } |
| 1834 cur = casted->weak_next(); | 1875 cur = casted->weak_next(); |
| 1835 } | 1876 } |
| 1836 if (marked) isolate_->stack_guard()->RequestDeoptMarkedAllocationSites(); | 1877 if (marked) isolate_->stack_guard()->RequestDeoptMarkedAllocationSites(); |
| 1837 } | 1878 } |
| 1838 | 1879 |
| 1839 | 1880 |
| 1840 void Heap::EvaluateOldSpaceLocalPretenuring( | 1881 void Heap::EvaluateOldSpaceLocalPretenuring( |
| 1841 uint64_t size_of_objects_before_gc) { | 1882 uint64_t size_of_objects_before_gc) { |
| 1842 uint64_t size_of_objects_after_gc = SizeOfObjects(); | 1883 uint64_t size_of_objects_after_gc = SizeOfObjects(); |
| (...skipping 985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2828 | 2869 |
| 2829 set_weak_stack_trace_list(Smi::FromInt(0)); | 2870 set_weak_stack_trace_list(Smi::FromInt(0)); |
| 2830 | 2871 |
| 2831 set_noscript_shared_function_infos(Smi::FromInt(0)); | 2872 set_noscript_shared_function_infos(Smi::FromInt(0)); |
| 2832 | 2873 |
| 2833 // Will be filled in by Interpreter::Initialize(). | 2874 // Will be filled in by Interpreter::Initialize(). |
| 2834 set_interpreter_table( | 2875 set_interpreter_table( |
| 2835 *interpreter::Interpreter::CreateUninitializedInterpreterTable( | 2876 *interpreter::Interpreter::CreateUninitializedInterpreterTable( |
| 2836 isolate())); | 2877 isolate())); |
| 2837 | 2878 |
| 2838 set_allocation_sites_scratchpad( | |
| 2839 *factory->NewFixedArray(kAllocationSiteScratchpadSize, TENURED)); | |
| 2840 InitializeAllocationSitesScratchpad(); | |
| 2841 | |
| 2842 // Initialize keyed lookup cache. | 2879 // Initialize keyed lookup cache. |
| 2843 isolate_->keyed_lookup_cache()->Clear(); | 2880 isolate_->keyed_lookup_cache()->Clear(); |
| 2844 | 2881 |
| 2845 // Initialize context slot cache. | 2882 // Initialize context slot cache. |
| 2846 isolate_->context_slot_cache()->Clear(); | 2883 isolate_->context_slot_cache()->Clear(); |
| 2847 | 2884 |
| 2848 // Initialize descriptor cache. | 2885 // Initialize descriptor cache. |
| 2849 isolate_->descriptor_lookup_cache()->Clear(); | 2886 isolate_->descriptor_lookup_cache()->Clear(); |
| 2850 | 2887 |
| 2851 // Initialize compilation cache. | 2888 // Initialize compilation cache. |
| 2852 isolate_->compilation_cache()->Clear(); | 2889 isolate_->compilation_cache()->Clear(); |
| 2853 } | 2890 } |
| 2854 | 2891 |
| 2855 | 2892 |
| 2856 bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) { | 2893 bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) { |
| 2857 switch (root_index) { | 2894 switch (root_index) { |
| 2858 case kStoreBufferTopRootIndex: | 2895 case kStoreBufferTopRootIndex: |
| 2859 case kNumberStringCacheRootIndex: | 2896 case kNumberStringCacheRootIndex: |
| 2860 case kInstanceofCacheFunctionRootIndex: | 2897 case kInstanceofCacheFunctionRootIndex: |
| 2861 case kInstanceofCacheMapRootIndex: | 2898 case kInstanceofCacheMapRootIndex: |
| 2862 case kInstanceofCacheAnswerRootIndex: | 2899 case kInstanceofCacheAnswerRootIndex: |
| 2863 case kCodeStubsRootIndex: | 2900 case kCodeStubsRootIndex: |
| 2864 case kNonMonomorphicCacheRootIndex: | 2901 case kNonMonomorphicCacheRootIndex: |
| 2865 case kPolymorphicCodeCacheRootIndex: | 2902 case kPolymorphicCodeCacheRootIndex: |
| 2866 case kEmptyScriptRootIndex: | 2903 case kEmptyScriptRootIndex: |
| 2867 case kSymbolRegistryRootIndex: | 2904 case kSymbolRegistryRootIndex: |
| 2868 case kScriptListRootIndex: | 2905 case kScriptListRootIndex: |
| 2869 case kMaterializedObjectsRootIndex: | 2906 case kMaterializedObjectsRootIndex: |
| 2870 case kAllocationSitesScratchpadRootIndex: | |
| 2871 case kMicrotaskQueueRootIndex: | 2907 case kMicrotaskQueueRootIndex: |
| 2872 case kDetachedContextsRootIndex: | 2908 case kDetachedContextsRootIndex: |
| 2873 case kWeakObjectToCodeTableRootIndex: | 2909 case kWeakObjectToCodeTableRootIndex: |
| 2874 case kRetainedMapsRootIndex: | 2910 case kRetainedMapsRootIndex: |
| 2875 case kNoScriptSharedFunctionInfosRootIndex: | 2911 case kNoScriptSharedFunctionInfosRootIndex: |
| 2876 case kWeakStackTraceListRootIndex: | 2912 case kWeakStackTraceListRootIndex: |
| 2877 // Smi values | 2913 // Smi values |
| 2878 #define SMI_ENTRY(type, name, Name) case k##Name##RootIndex: | 2914 #define SMI_ENTRY(type, name, Name) case k##Name##RootIndex: |
| 2879 SMI_ROOT_LIST(SMI_ENTRY) | 2915 SMI_ROOT_LIST(SMI_ENTRY) |
| 2880 #undef SMI_ENTRY | 2916 #undef SMI_ENTRY |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2909 | 2945 |
| 2910 void Heap::FlushNumberStringCache() { | 2946 void Heap::FlushNumberStringCache() { |
| 2911 // Flush the number to string cache. | 2947 // Flush the number to string cache. |
| 2912 int len = number_string_cache()->length(); | 2948 int len = number_string_cache()->length(); |
| 2913 for (int i = 0; i < len; i++) { | 2949 for (int i = 0; i < len; i++) { |
| 2914 number_string_cache()->set_undefined(i); | 2950 number_string_cache()->set_undefined(i); |
| 2915 } | 2951 } |
| 2916 } | 2952 } |
| 2917 | 2953 |
| 2918 | 2954 |
| 2919 void Heap::FlushAllocationSitesScratchpad() { | |
| 2920 for (int i = 0; i < allocation_sites_scratchpad_length_; i++) { | |
| 2921 allocation_sites_scratchpad()->set_undefined(i); | |
| 2922 } | |
| 2923 allocation_sites_scratchpad_length_ = 0; | |
| 2924 } | |
| 2925 | |
| 2926 | |
| 2927 void Heap::InitializeAllocationSitesScratchpad() { | |
| 2928 DCHECK(allocation_sites_scratchpad()->length() == | |
| 2929 kAllocationSiteScratchpadSize); | |
| 2930 for (int i = 0; i < kAllocationSiteScratchpadSize; i++) { | |
| 2931 allocation_sites_scratchpad()->set_undefined(i); | |
| 2932 } | |
| 2933 } | |
| 2934 | |
| 2935 | |
| 2936 void Heap::AddAllocationSiteToScratchpad(AllocationSite* site, | |
| 2937 ScratchpadSlotMode mode) { | |
| 2938 if (allocation_sites_scratchpad_length_ < kAllocationSiteScratchpadSize) { | |
| 2939 // We cannot use the normal write-barrier because slots need to be | |
| 2940 // recorded with non-incremental marking as well. We have to explicitly | |
| 2941 // record the slot to take evacuation candidates into account. | |
| 2942 allocation_sites_scratchpad()->set(allocation_sites_scratchpad_length_, | |
| 2943 site, SKIP_WRITE_BARRIER); | |
| 2944 Object** slot = allocation_sites_scratchpad()->RawFieldOfElementAt( | |
| 2945 allocation_sites_scratchpad_length_); | |
| 2946 | |
| 2947 if (mode == RECORD_SCRATCHPAD_SLOT) { | |
| 2948 // We need to allow slots buffer overflow here since the evacuation | |
| 2949 // candidates are not part of the global list of old space pages and | |
| 2950 // releasing an evacuation candidate due to a slots buffer overflow | |
| 2951 // results in lost pages. | |
| 2952 mark_compact_collector()->ForceRecordSlot(allocation_sites_scratchpad(), | |
| 2953 slot, *slot); | |
| 2954 } | |
| 2955 allocation_sites_scratchpad_length_++; | |
| 2956 } | |
| 2957 } | |
| 2958 | |
| 2959 | |
| 2960 | |
| 2961 Map* Heap::MapForFixedTypedArray(ExternalArrayType array_type) { | 2955 Map* Heap::MapForFixedTypedArray(ExternalArrayType array_type) { |
| 2962 return Map::cast(roots_[RootIndexForFixedTypedArray(array_type)]); | 2956 return Map::cast(roots_[RootIndexForFixedTypedArray(array_type)]); |
| 2963 } | 2957 } |
| 2964 | 2958 |
| 2965 | 2959 |
| 2966 Heap::RootListIndex Heap::RootIndexForFixedTypedArray( | 2960 Heap::RootListIndex Heap::RootIndexForFixedTypedArray( |
| 2967 ExternalArrayType array_type) { | 2961 ExternalArrayType array_type) { |
| 2968 switch (array_type) { | 2962 switch (array_type) { |
| 2969 #define ARRAY_TYPE_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \ | 2963 #define ARRAY_TYPE_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \ |
| 2970 case kExternal##Type##Array: \ | 2964 case kExternal##Type##Array: \ |
| (...skipping 3264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6235 } | 6229 } |
| 6236 | 6230 |
| 6237 | 6231 |
| 6238 // static | 6232 // static |
| 6239 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6233 int Heap::GetStaticVisitorIdForMap(Map* map) { |
| 6240 return StaticVisitorBase::GetVisitorId(map); | 6234 return StaticVisitorBase::GetVisitorId(map); |
| 6241 } | 6235 } |
| 6242 | 6236 |
| 6243 } // namespace internal | 6237 } // namespace internal |
| 6244 } // namespace v8 | 6238 } // namespace v8 |
| OLD | NEW |