| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 last_idle_notification_gc_count_init_(false), | 143 last_idle_notification_gc_count_init_(false), |
| 144 mark_sweeps_since_idle_round_started_(0), | 144 mark_sweeps_since_idle_round_started_(0), |
| 145 gc_count_at_last_idle_gc_(0), | 145 gc_count_at_last_idle_gc_(0), |
| 146 scavenges_since_last_idle_round_(kIdleScavengeThreshold), | 146 scavenges_since_last_idle_round_(kIdleScavengeThreshold), |
| 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 gcs_since_last_deopt_(0), | 149 gcs_since_last_deopt_(0), |
| 150 #ifdef VERIFY_HEAP | 150 #ifdef VERIFY_HEAP |
| 151 no_weak_object_verification_scope_depth_(0), | 151 no_weak_object_verification_scope_depth_(0), |
| 152 #endif | 152 #endif |
| 153 allocation_sites_scratchpad_length(0), | 153 allocation_sites_scratchpad_length_(0), |
| 154 promotion_queue_(this), | 154 promotion_queue_(this), |
| 155 configured_(false), | 155 configured_(false), |
| 156 external_string_table_(this), | 156 external_string_table_(this), |
| 157 chunks_queued_for_free_(NULL), | 157 chunks_queued_for_free_(NULL), |
| 158 relocation_mutex_(NULL) { | 158 relocation_mutex_(NULL) { |
| 159 // Allow build-time customization of the max semispace size. Building | 159 // Allow build-time customization of the max semispace size. Building |
| 160 // V8 with snapshots and a non-default max semispace size is much | 160 // V8 with snapshots and a non-default max semispace size is much |
| 161 // easier if you can define it as part of the build environment. | 161 // easier if you can define it as part of the build environment. |
| 162 #if defined(V8_MAX_SEMISPACE_SIZE) | 162 #if defined(V8_MAX_SEMISPACE_SIZE) |
| 163 max_semispace_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; | 163 max_semispace_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 if (FLAG_allocation_site_pretenuring) { | 509 if (FLAG_allocation_site_pretenuring) { |
| 510 int tenure_decisions = 0; | 510 int tenure_decisions = 0; |
| 511 int dont_tenure_decisions = 0; | 511 int dont_tenure_decisions = 0; |
| 512 int allocation_mementos_found = 0; | 512 int allocation_mementos_found = 0; |
| 513 int allocation_sites = 0; | 513 int allocation_sites = 0; |
| 514 int active_allocation_sites = 0; | 514 int active_allocation_sites = 0; |
| 515 | 515 |
| 516 // If the scratchpad overflowed, we have to iterate over the allocation | 516 // If the scratchpad overflowed, we have to iterate over the allocation |
| 517 // sites list. | 517 // sites list. |
| 518 bool use_scratchpad = | 518 bool use_scratchpad = |
| 519 allocation_sites_scratchpad_length < kAllocationSiteScratchpadSize; | 519 allocation_sites_scratchpad_length_ < kAllocationSiteScratchpadSize; |
| 520 | 520 |
| 521 int i = 0; | 521 int i = 0; |
| 522 Object* list_element = allocation_sites_list(); | 522 Object* list_element = allocation_sites_list(); |
| 523 bool trigger_deoptimization = false; | 523 bool trigger_deoptimization = false; |
| 524 while (use_scratchpad ? | 524 while (use_scratchpad ? |
| 525 i < allocation_sites_scratchpad_length : | 525 i < allocation_sites_scratchpad_length_ : |
| 526 list_element->IsAllocationSite()) { | 526 list_element->IsAllocationSite()) { |
| 527 AllocationSite* site = use_scratchpad ? | 527 AllocationSite* site = use_scratchpad ? |
| 528 allocation_sites_scratchpad[i] : AllocationSite::cast(list_element); | 528 AllocationSite::cast(allocation_sites_scratchpad()->get(i)) : |
| 529 AllocationSite::cast(list_element); |
| 529 allocation_mementos_found += site->memento_found_count(); | 530 allocation_mementos_found += site->memento_found_count(); |
| 530 if (site->memento_found_count() > 0) { | 531 if (site->memento_found_count() > 0) { |
| 531 active_allocation_sites++; | 532 active_allocation_sites++; |
| 532 } | 533 } |
| 533 if (site->DigestPretenuringFeedback()) trigger_deoptimization = true; | 534 if (site->DigestPretenuringFeedback()) trigger_deoptimization = true; |
| 534 if (site->GetPretenureMode() == TENURED) { | 535 if (site->GetPretenureMode() == TENURED) { |
| 535 tenure_decisions++; | 536 tenure_decisions++; |
| 536 } else { | 537 } else { |
| 537 dont_tenure_decisions++; | 538 dont_tenure_decisions++; |
| 538 } | 539 } |
| 539 allocation_sites++; | 540 allocation_sites++; |
| 540 if (use_scratchpad) { | 541 if (use_scratchpad) { |
| 541 i++; | 542 i++; |
| 542 } else { | 543 } else { |
| 543 list_element = site->weak_next(); | 544 list_element = site->weak_next(); |
| 544 } | 545 } |
| 545 } | 546 } |
| 546 | 547 |
| 547 if (trigger_deoptimization) isolate_->stack_guard()->DeoptMarkedCode(); | 548 if (trigger_deoptimization) isolate_->stack_guard()->DeoptMarkedCode(); |
| 548 | 549 |
| 549 allocation_sites_scratchpad_length = 0; | 550 FlushAllocationSitesScratchpad(); |
| 550 | 551 |
| 551 // TODO(mvstanton): Pretenure decisions are only made once for an allocation | 552 if (FLAG_trace_pretenuring_statistics && |
| 552 // site. Find a sane way to decide about revisiting the decision later. | |
| 553 | |
| 554 if (FLAG_trace_track_allocation_sites && | |
| 555 (allocation_mementos_found > 0 || | 553 (allocation_mementos_found > 0 || |
| 556 tenure_decisions > 0 || | 554 tenure_decisions > 0 || |
| 557 dont_tenure_decisions > 0)) { | 555 dont_tenure_decisions > 0)) { |
| 558 PrintF("GC: (mode, #visited allocation sites, #active allocation sites, " | 556 PrintF("GC: (mode, #visited allocation sites, #active allocation sites, " |
| 559 "#mementos, #tenure decisions, #donttenure decisions) " | 557 "#mementos, #tenure decisions, #donttenure decisions) " |
| 560 "(%s, %d, %d, %d, %d, %d)\n", | 558 "(%s, %d, %d, %d, %d, %d)\n", |
| 561 use_scratchpad ? "use scratchpad" : "use list", | 559 use_scratchpad ? "use scratchpad" : "use list", |
| 562 allocation_sites, | 560 allocation_sites, |
| 563 active_allocation_sites, | 561 active_allocation_sites, |
| 564 allocation_mementos_found, | 562 allocation_mementos_found, |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 // The optimizing compiler may be unnecessarily holding on to memory. | 730 // The optimizing compiler may be unnecessarily holding on to memory. |
| 733 DisallowHeapAllocation no_recursive_gc; | 731 DisallowHeapAllocation no_recursive_gc; |
| 734 isolate()->optimizing_compiler_thread()->Flush(); | 732 isolate()->optimizing_compiler_thread()->Flush(); |
| 735 } | 733 } |
| 736 mark_compact_collector()->SetFlags(kMakeHeapIterableMask | | 734 mark_compact_collector()->SetFlags(kMakeHeapIterableMask | |
| 737 kReduceMemoryFootprintMask); | 735 kReduceMemoryFootprintMask); |
| 738 isolate_->compilation_cache()->Clear(); | 736 isolate_->compilation_cache()->Clear(); |
| 739 const int kMaxNumberOfAttempts = 7; | 737 const int kMaxNumberOfAttempts = 7; |
| 740 const int kMinNumberOfAttempts = 2; | 738 const int kMinNumberOfAttempts = 2; |
| 741 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { | 739 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { |
| 742 if (!CollectGarbage(OLD_POINTER_SPACE, MARK_COMPACTOR, gc_reason, NULL) && | 740 if (!CollectGarbage(MARK_COMPACTOR, gc_reason, NULL) && |
| 743 attempt + 1 >= kMinNumberOfAttempts) { | 741 attempt + 1 >= kMinNumberOfAttempts) { |
| 744 break; | 742 break; |
| 745 } | 743 } |
| 746 } | 744 } |
| 747 mark_compact_collector()->SetFlags(kNoGCFlags); | 745 mark_compact_collector()->SetFlags(kNoGCFlags); |
| 748 new_space_.Shrink(); | 746 new_space_.Shrink(); |
| 749 UncommitFromSpace(); | 747 UncommitFromSpace(); |
| 750 incremental_marking()->UncommitMarkingDeque(); | 748 incremental_marking()->UncommitMarkingDeque(); |
| 751 } | 749 } |
| 752 | 750 |
| 753 | 751 |
| 754 bool Heap::CollectGarbage(AllocationSpace space, | 752 bool Heap::CollectGarbage(GarbageCollector collector, |
| 755 GarbageCollector collector, | |
| 756 const char* gc_reason, | 753 const char* gc_reason, |
| 757 const char* collector_reason, | 754 const char* collector_reason, |
| 758 const v8::GCCallbackFlags gc_callback_flags) { | 755 const v8::GCCallbackFlags gc_callback_flags) { |
| 759 // The VM is in the GC state until exiting this function. | 756 // The VM is in the GC state until exiting this function. |
| 760 VMState<GC> state(isolate_); | 757 VMState<GC> state(isolate_); |
| 761 | 758 |
| 762 #ifdef DEBUG | 759 #ifdef DEBUG |
| 763 // Reset the allocation timeout to the GC interval, but make sure to | 760 // Reset the allocation timeout to the GC interval, but make sure to |
| 764 // allow at least a few allocations after a collection. The reason | 761 // allow at least a few allocations after a collection. The reason |
| 765 // for this is that we have a lot of allocation sequences and we | 762 // for this is that we have a lot of allocation sequences and we |
| 766 // assume that a garbage collection will allow the subsequent | 763 // assume that a garbage collection will allow the subsequent |
| 767 // allocation attempts to go through. | 764 // allocation attempts to go through. |
| 768 allocation_timeout_ = Max(6, FLAG_gc_interval); | 765 allocation_timeout_ = Max(6, FLAG_gc_interval); |
| 769 #endif | 766 #endif |
| 770 | 767 |
| 768 // There may be an allocation memento behind every object in new space. |
| 769 // If we evacuate a not full new space or if we are on the last page of |
| 770 // the new space, then there may be uninitialized memory behind the top |
| 771 // pointer of the new space page. We store a filler object there to |
| 772 // identify the unused space. |
| 773 Address from_top = new_space_.top(); |
| 774 Address from_limit = new_space_.limit(); |
| 775 if (from_top < from_limit) { |
| 776 int remaining_in_page = static_cast<int>(from_limit - from_top); |
| 777 CreateFillerObjectAt(from_top, remaining_in_page); |
| 778 } |
| 779 |
| 771 if (collector == SCAVENGER && !incremental_marking()->IsStopped()) { | 780 if (collector == SCAVENGER && !incremental_marking()->IsStopped()) { |
| 772 if (FLAG_trace_incremental_marking) { | 781 if (FLAG_trace_incremental_marking) { |
| 773 PrintF("[IncrementalMarking] Scavenge during marking.\n"); | 782 PrintF("[IncrementalMarking] Scavenge during marking.\n"); |
| 774 } | 783 } |
| 775 } | 784 } |
| 776 | 785 |
| 777 if (collector == MARK_COMPACTOR && | 786 if (collector == MARK_COMPACTOR && |
| 778 !mark_compact_collector()->abort_incremental_marking() && | 787 !mark_compact_collector()->abort_incremental_marking() && |
| 779 !incremental_marking()->IsStopped() && | 788 !incremental_marking()->IsStopped() && |
| 780 !incremental_marking()->should_hurry() && | 789 !incremental_marking()->should_hurry() && |
| (...skipping 2509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3290 set_observed_symbol(Symbol::cast(obj)); | 3299 set_observed_symbol(Symbol::cast(obj)); |
| 3291 | 3300 |
| 3292 { MaybeObject* maybe_obj = AllocateFixedArray(0, TENURED); | 3301 { MaybeObject* maybe_obj = AllocateFixedArray(0, TENURED); |
| 3293 if (!maybe_obj->ToObject(&obj)) return false; | 3302 if (!maybe_obj->ToObject(&obj)) return false; |
| 3294 } | 3303 } |
| 3295 set_materialized_objects(FixedArray::cast(obj)); | 3304 set_materialized_objects(FixedArray::cast(obj)); |
| 3296 | 3305 |
| 3297 // Handling of script id generation is in Factory::NewScript. | 3306 // Handling of script id generation is in Factory::NewScript. |
| 3298 set_last_script_id(Smi::FromInt(v8::Script::kNoScriptId)); | 3307 set_last_script_id(Smi::FromInt(v8::Script::kNoScriptId)); |
| 3299 | 3308 |
| 3309 { MaybeObject* maybe_obj = AllocateAllocationSitesScratchpad(); |
| 3310 if (!maybe_obj->ToObject(&obj)) return false; |
| 3311 } |
| 3312 set_allocation_sites_scratchpad(FixedArray::cast(obj)); |
| 3313 InitializeAllocationSitesScratchpad(); |
| 3314 |
| 3300 // Initialize keyed lookup cache. | 3315 // Initialize keyed lookup cache. |
| 3301 isolate_->keyed_lookup_cache()->Clear(); | 3316 isolate_->keyed_lookup_cache()->Clear(); |
| 3302 | 3317 |
| 3303 // Initialize context slot cache. | 3318 // Initialize context slot cache. |
| 3304 isolate_->context_slot_cache()->Clear(); | 3319 isolate_->context_slot_cache()->Clear(); |
| 3305 | 3320 |
| 3306 // Initialize descriptor cache. | 3321 // Initialize descriptor cache. |
| 3307 isolate_->descriptor_lookup_cache()->Clear(); | 3322 isolate_->descriptor_lookup_cache()->Clear(); |
| 3308 | 3323 |
| 3309 // Initialize compilation cache. | 3324 // Initialize compilation cache. |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3579 | 3594 |
| 3580 MaybeObject* Heap::Uint32ToString(uint32_t value, | 3595 MaybeObject* Heap::Uint32ToString(uint32_t value, |
| 3581 bool check_number_string_cache) { | 3596 bool check_number_string_cache) { |
| 3582 Object* number; | 3597 Object* number; |
| 3583 MaybeObject* maybe = NumberFromUint32(value); | 3598 MaybeObject* maybe = NumberFromUint32(value); |
| 3584 if (!maybe->To<Object>(&number)) return maybe; | 3599 if (!maybe->To<Object>(&number)) return maybe; |
| 3585 return NumberToString(number, check_number_string_cache); | 3600 return NumberToString(number, check_number_string_cache); |
| 3586 } | 3601 } |
| 3587 | 3602 |
| 3588 | 3603 |
| 3604 MaybeObject* Heap::AllocateAllocationSitesScratchpad() { |
| 3605 MaybeObject* maybe_obj = |
| 3606 AllocateFixedArray(kAllocationSiteScratchpadSize, TENURED); |
| 3607 return maybe_obj; |
| 3608 } |
| 3609 |
| 3610 |
| 3611 void Heap::FlushAllocationSitesScratchpad() { |
| 3612 for (int i = 0; i < allocation_sites_scratchpad_length_; i++) { |
| 3613 allocation_sites_scratchpad()->set_undefined(i); |
| 3614 } |
| 3615 allocation_sites_scratchpad_length_ = 0; |
| 3616 } |
| 3617 |
| 3618 |
| 3619 void Heap::InitializeAllocationSitesScratchpad() { |
| 3620 ASSERT(allocation_sites_scratchpad()->length() == |
| 3621 kAllocationSiteScratchpadSize); |
| 3622 for (int i = 0; i < kAllocationSiteScratchpadSize; i++) { |
| 3623 allocation_sites_scratchpad()->set_undefined(i); |
| 3624 } |
| 3625 } |
| 3626 |
| 3627 |
| 3628 void Heap::AddAllocationSiteToScratchpad(AllocationSite* site) { |
| 3629 if (allocation_sites_scratchpad_length_ < kAllocationSiteScratchpadSize) { |
| 3630 allocation_sites_scratchpad()->set( |
| 3631 allocation_sites_scratchpad_length_, site); |
| 3632 allocation_sites_scratchpad_length_++; |
| 3633 } |
| 3634 } |
| 3635 |
| 3636 |
| 3589 Map* Heap::MapForExternalArrayType(ExternalArrayType array_type) { | 3637 Map* Heap::MapForExternalArrayType(ExternalArrayType array_type) { |
| 3590 return Map::cast(roots_[RootIndexForExternalArrayType(array_type)]); | 3638 return Map::cast(roots_[RootIndexForExternalArrayType(array_type)]); |
| 3591 } | 3639 } |
| 3592 | 3640 |
| 3593 | 3641 |
| 3594 Heap::RootListIndex Heap::RootIndexForExternalArrayType( | 3642 Heap::RootListIndex Heap::RootIndexForExternalArrayType( |
| 3595 ExternalArrayType array_type) { | 3643 ExternalArrayType array_type) { |
| 3596 switch (array_type) { | 3644 switch (array_type) { |
| 3597 #define ARRAY_TYPE_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \ | 3645 #define ARRAY_TYPE_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \ |
| 3598 case kExternal##Type##Array: \ | 3646 case kExternal##Type##Array: \ |
| (...skipping 4060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7659 static_cast<int>(object_sizes_last_time_[index])); | 7707 static_cast<int>(object_sizes_last_time_[index])); |
| 7660 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 7708 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 7661 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 7709 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 7662 | 7710 |
| 7663 OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 7711 OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 7664 OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 7712 OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 7665 ClearObjectStats(); | 7713 ClearObjectStats(); |
| 7666 } | 7714 } |
| 7667 | 7715 |
| 7668 } } // namespace v8::internal | 7716 } } // namespace v8::internal |
| OLD | NEW |