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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/compilation-cache.h" | 9 #include "src/compilation-cache.h" |
10 #include "src/cpu-profiler.h" | 10 #include "src/cpu-profiler.h" |
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
552 class MarkCompactCollector::SweeperTask : public v8::Task { | 552 class MarkCompactCollector::SweeperTask : public v8::Task { |
553 public: | 553 public: |
554 SweeperTask(Heap* heap, PagedSpace* space) | 554 SweeperTask(Heap* heap, PagedSpace* space) |
555 : heap_(heap), space_(space) {} | 555 : heap_(heap), space_(space) {} |
556 | 556 |
557 virtual ~SweeperTask() {} | 557 virtual ~SweeperTask() {} |
558 | 558 |
559 private: | 559 private: |
560 // v8::Task overrides. | 560 // v8::Task overrides. |
561 virtual void Run() V8_OVERRIDE { | 561 virtual void Run() V8_OVERRIDE { |
562 heap_->mark_compact_collector()->SweepInParallel(space_); | 562 heap_->mark_compact_collector()->SweepInParallel(space_, 0); |
563 heap_->mark_compact_collector()->pending_sweeper_jobs_semaphore_.Signal(); | 563 heap_->mark_compact_collector()->pending_sweeper_jobs_semaphore_.Signal(); |
564 } | 564 } |
565 | 565 |
566 Heap* heap_; | 566 Heap* heap_; |
567 PagedSpace* space_; | 567 PagedSpace* space_; |
568 | 568 |
569 DISALLOW_COPY_AND_ASSIGN(SweeperTask); | 569 DISALLOW_COPY_AND_ASSIGN(SweeperTask); |
570 }; | 570 }; |
571 | 571 |
572 | 572 |
(...skipping 2964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3537 } else { | 3537 } else { |
3538 if (FLAG_gc_verbose) { | 3538 if (FLAG_gc_verbose) { |
3539 PrintF("Sweeping 0x%" V8PRIxPTR " during evacuation.\n", | 3539 PrintF("Sweeping 0x%" V8PRIxPTR " during evacuation.\n", |
3540 reinterpret_cast<intptr_t>(p)); | 3540 reinterpret_cast<intptr_t>(p)); |
3541 } | 3541 } |
3542 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3542 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
3543 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); | 3543 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); |
3544 | 3544 |
3545 switch (space->identity()) { | 3545 switch (space->identity()) { |
3546 case OLD_DATA_SPACE: | 3546 case OLD_DATA_SPACE: |
3547 SweepConservatively<SWEEP_SEQUENTIALLY>(space, NULL, p); | 3547 SweepConservatively<SWEEP_ON_MAIN_THREAD>(space, NULL, p); |
3548 break; | 3548 break; |
3549 case OLD_POINTER_SPACE: | 3549 case OLD_POINTER_SPACE: |
3550 SweepPrecisely<SWEEP_AND_VISIT_LIVE_OBJECTS, | 3550 SweepPrecisely<SWEEP_AND_VISIT_LIVE_OBJECTS, |
3551 IGNORE_SKIP_LIST, | 3551 IGNORE_SKIP_LIST, |
3552 IGNORE_FREE_SPACE>( | 3552 IGNORE_FREE_SPACE>( |
3553 space, p, &updating_visitor); | 3553 space, p, &updating_visitor); |
3554 break; | 3554 break; |
3555 case CODE_SPACE: | 3555 case CODE_SPACE: |
3556 if (FLAG_zap_code_space) { | 3556 if (FLAG_zap_code_space) { |
3557 SweepPrecisely<SWEEP_AND_VISIT_LIVE_OBJECTS, | 3557 SweepPrecisely<SWEEP_AND_VISIT_LIVE_OBJECTS, |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3932 USE(live_objects); | 3932 USE(live_objects); |
3933 return block_address + offsets[0] * kPointerSize; | 3933 return block_address + offsets[0] * kPointerSize; |
3934 } | 3934 } |
3935 | 3935 |
3936 | 3936 |
3937 template<MarkCompactCollector::SweepingParallelism mode> | 3937 template<MarkCompactCollector::SweepingParallelism mode> |
3938 static intptr_t Free(PagedSpace* space, | 3938 static intptr_t Free(PagedSpace* space, |
3939 FreeList* free_list, | 3939 FreeList* free_list, |
3940 Address start, | 3940 Address start, |
3941 int size) { | 3941 int size) { |
3942 if (mode == MarkCompactCollector::SWEEP_SEQUENTIALLY) { | 3942 if (mode == MarkCompactCollector::SWEEP_ON_MAIN_THREAD) { |
3943 return space->Free(start, size); | 3943 return space->Free(start, size); |
3944 } else { | 3944 } else { |
3945 return size - free_list->Free(start, size); | 3945 return size - free_list->Free(start, size); |
3946 } | 3946 } |
3947 } | 3947 } |
3948 | 3948 |
3949 | 3949 |
3950 // Force instantiation of templatized SweepConservatively method for | 3950 // Force instantiation of templatized SweepConservatively method for |
3951 // SWEEP_SEQUENTIALLY mode. | 3951 // SWEEP_ON_MAIN_THREAD mode. |
3952 template intptr_t MarkCompactCollector:: | 3952 template intptr_t MarkCompactCollector:: |
3953 SweepConservatively<MarkCompactCollector::SWEEP_SEQUENTIALLY>( | 3953 SweepConservatively<MarkCompactCollector::SWEEP_ON_MAIN_THREAD>( |
3954 PagedSpace*, FreeList*, Page*); | 3954 PagedSpace*, FreeList*, Page*); |
3955 | 3955 |
3956 | 3956 |
3957 // Force instantiation of templatized SweepConservatively method for | 3957 // Force instantiation of templatized SweepConservatively method for |
3958 // SWEEP_IN_PARALLEL mode. | 3958 // SWEEP_IN_PARALLEL mode. |
3959 template intptr_t MarkCompactCollector:: | 3959 template intptr_t MarkCompactCollector:: |
3960 SweepConservatively<MarkCompactCollector::SWEEP_IN_PARALLEL>( | 3960 SweepConservatively<MarkCompactCollector::SWEEP_IN_PARALLEL>( |
3961 PagedSpace*, FreeList*, Page*); | 3961 PagedSpace*, FreeList*, Page*); |
3962 | 3962 |
3963 | 3963 |
3964 // Sweeps a space conservatively. After this has been done the larger free | 3964 // Sweeps a space conservatively. After this has been done the larger free |
3965 // spaces have been put on the free list and the smaller ones have been | 3965 // spaces have been put on the free list and the smaller ones have been |
3966 // ignored and left untouched. A free space is always either ignored or put | 3966 // ignored and left untouched. A free space is always either ignored or put |
3967 // on the free list, never split up into two parts. This is important | 3967 // on the free list, never split up into two parts. This is important |
3968 // because it means that any FreeSpace maps left actually describe a region of | 3968 // because it means that any FreeSpace maps left actually describe a region of |
3969 // memory that can be ignored when scanning. Dead objects other than free | 3969 // memory that can be ignored when scanning. Dead objects other than free |
3970 // spaces will not contain the free space map. | 3970 // spaces will not contain the free space map. |
3971 template<MarkCompactCollector::SweepingParallelism mode> | 3971 template<MarkCompactCollector::SweepingParallelism mode> |
3972 intptr_t MarkCompactCollector::SweepConservatively(PagedSpace* space, | 3972 intptr_t MarkCompactCollector::SweepConservatively(PagedSpace* space, |
3973 FreeList* free_list, | 3973 FreeList* free_list, |
3974 Page* p) { | 3974 Page* p) { |
3975 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); | 3975 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); |
3976 ASSERT((mode == MarkCompactCollector::SWEEP_IN_PARALLEL && | 3976 ASSERT((mode == MarkCompactCollector::SWEEP_IN_PARALLEL && |
3977 free_list != NULL) || | 3977 free_list != NULL) || |
3978 (mode == MarkCompactCollector::SWEEP_SEQUENTIALLY && | 3978 (mode == MarkCompactCollector::SWEEP_ON_MAIN_THREAD && |
3979 free_list == NULL)); | 3979 free_list == NULL)); |
3980 | 3980 |
3981 // When parallel sweeping is active, the page will be marked after | 3981 // When parallel sweeping is active, the page will be marked after |
3982 // sweeping by the main thread. | 3982 // sweeping by the main thread. |
3983 if (mode != MarkCompactCollector::SWEEP_IN_PARALLEL) { | 3983 if (mode == MarkCompactCollector::SWEEP_IN_PARALLEL) { |
3984 p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_FINALIZE); | |
3985 } else { | |
3984 p->MarkSweptConservatively(); | 3986 p->MarkSweptConservatively(); |
3985 } | 3987 } |
3986 | 3988 |
3987 intptr_t freed_bytes = 0; | 3989 intptr_t freed_bytes = 0; |
3990 intptr_t max_freed_bytes = 0; | |
3988 size_t size = 0; | 3991 size_t size = 0; |
3989 | 3992 |
3990 // Skip over all the dead objects at the start of the page and mark them free. | 3993 // Skip over all the dead objects at the start of the page and mark them free. |
3991 Address cell_base = 0; | 3994 Address cell_base = 0; |
3992 MarkBit::CellType* cell = NULL; | 3995 MarkBit::CellType* cell = NULL; |
3993 MarkBitCellIterator it(p); | 3996 MarkBitCellIterator it(p); |
3994 for (; !it.Done(); it.Advance()) { | 3997 for (; !it.Done(); it.Advance()) { |
3995 cell_base = it.CurrentCellBase(); | 3998 cell_base = it.CurrentCellBase(); |
3996 cell = it.CurrentCell(); | 3999 cell = it.CurrentCell(); |
3997 if (*cell != 0) break; | 4000 if (*cell != 0) break; |
3998 } | 4001 } |
3999 | 4002 |
4000 if (it.Done()) { | 4003 if (it.Done()) { |
4001 size = p->area_end() - p->area_start(); | 4004 size = p->area_end() - p->area_start(); |
4002 freed_bytes += Free<mode>(space, free_list, p->area_start(), | 4005 freed_bytes = Free<mode>(space, free_list, p->area_start(), |
4003 static_cast<int>(size)); | 4006 static_cast<int>(size)); |
4007 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | |
4004 ASSERT_EQ(0, p->LiveBytes()); | 4008 ASSERT_EQ(0, p->LiveBytes()); |
4005 return freed_bytes; | 4009 return freed_bytes; |
4006 } | 4010 } |
4007 | 4011 |
4008 // Grow the size of the start-of-page free space a little to get up to the | 4012 // Grow the size of the start-of-page free space a little to get up to the |
4009 // first live object. | 4013 // first live object. |
4010 Address free_end = StartOfLiveObject(cell_base, *cell); | 4014 Address free_end = StartOfLiveObject(cell_base, *cell); |
4011 // Free the first free space. | 4015 // Free the first free space. |
4012 size = free_end - p->area_start(); | 4016 size = free_end - p->area_start(); |
4013 freed_bytes += Free<mode>(space, free_list, p->area_start(), | 4017 freed_bytes = Free<mode>(space, free_list, p->area_start(), |
4014 static_cast<int>(size)); | 4018 static_cast<int>(size)); |
4019 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | |
4015 | 4020 |
4016 // The start of the current free area is represented in undigested form by | 4021 // The start of the current free area is represented in undigested form by |
4017 // the address of the last 32-word section that contained a live object and | 4022 // the address of the last 32-word section that contained a live object and |
4018 // the marking bitmap for that cell, which describes where the live object | 4023 // the marking bitmap for that cell, which describes where the live object |
4019 // started. Unless we find a large free space in the bitmap we will not | 4024 // started. Unless we find a large free space in the bitmap we will not |
4020 // digest this pair into a real address. We start the iteration here at the | 4025 // digest this pair into a real address. We start the iteration here at the |
4021 // first word in the marking bit map that indicates a live object. | 4026 // first word in the marking bit map that indicates a live object. |
4022 Address free_start = cell_base; | 4027 Address free_start = cell_base; |
4023 MarkBit::CellType free_start_cell = *cell; | 4028 MarkBit::CellType free_start_cell = *cell; |
4024 | 4029 |
4025 for (; !it.Done(); it.Advance()) { | 4030 for (; !it.Done(); it.Advance()) { |
4026 cell_base = it.CurrentCellBase(); | 4031 cell_base = it.CurrentCellBase(); |
4027 cell = it.CurrentCell(); | 4032 cell = it.CurrentCell(); |
4028 if (*cell != 0) { | 4033 if (*cell != 0) { |
4029 // We have a live object. Check approximately whether it is more than 32 | 4034 // We have a live object. Check approximately whether it is more than 32 |
4030 // words since the last live object. | 4035 // words since the last live object. |
4031 if (cell_base - free_start > 32 * kPointerSize) { | 4036 if (cell_base - free_start > 32 * kPointerSize) { |
4032 free_start = DigestFreeStart(free_start, free_start_cell); | 4037 free_start = DigestFreeStart(free_start, free_start_cell); |
4033 if (cell_base - free_start > 32 * kPointerSize) { | 4038 if (cell_base - free_start > 32 * kPointerSize) { |
4034 // Now that we know the exact start of the free space it still looks | 4039 // Now that we know the exact start of the free space it still looks |
4035 // like we have a large enough free space to be worth bothering with. | 4040 // like we have a large enough free space to be worth bothering with. |
4036 // so now we need to find the start of the first live object at the | 4041 // so now we need to find the start of the first live object at the |
4037 // end of the free space. | 4042 // end of the free space. |
4038 free_end = StartOfLiveObject(cell_base, *cell); | 4043 free_end = StartOfLiveObject(cell_base, *cell); |
4039 freed_bytes += Free<mode>(space, free_list, free_start, | 4044 freed_bytes = Free<mode>(space, free_list, free_start, |
4040 static_cast<int>(free_end - free_start)); | 4045 static_cast<int>(free_end - free_start)); |
4046 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | |
4041 } | 4047 } |
4042 } | 4048 } |
4043 // Update our undigested record of where the current free area started. | 4049 // Update our undigested record of where the current free area started. |
4044 free_start = cell_base; | 4050 free_start = cell_base; |
4045 free_start_cell = *cell; | 4051 free_start_cell = *cell; |
4046 // Clear marking bits for current cell. | 4052 // Clear marking bits for current cell. |
4047 *cell = 0; | 4053 *cell = 0; |
4048 } | 4054 } |
4049 } | 4055 } |
4050 | 4056 |
4051 // Handle the free space at the end of the page. | 4057 // Handle the free space at the end of the page. |
4052 if (cell_base - free_start > 32 * kPointerSize) { | 4058 if (cell_base - free_start > 32 * kPointerSize) { |
4053 free_start = DigestFreeStart(free_start, free_start_cell); | 4059 free_start = DigestFreeStart(free_start, free_start_cell); |
4054 freed_bytes += Free<mode>(space, free_list, free_start, | 4060 freed_bytes = Free<mode>(space, free_list, free_start, |
4055 static_cast<int>(p->area_end() - free_start)); | 4061 static_cast<int>(p->area_end() - free_start)); |
4062 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | |
4056 } | 4063 } |
4057 | 4064 |
4058 p->ResetLiveBytes(); | 4065 p->ResetLiveBytes(); |
4059 return freed_bytes; | 4066 return max_freed_bytes; |
4060 } | 4067 } |
4061 | 4068 |
4062 | 4069 |
4063 void MarkCompactCollector::SweepInParallel(PagedSpace* space) { | 4070 int MarkCompactCollector::SweepInParallel(PagedSpace* space, |
4071 int required_freed_bytes) { | |
4064 PageIterator it(space); | 4072 PageIterator it(space); |
4065 FreeList* free_list = space == heap()->old_pointer_space() | 4073 FreeList* free_list = space == heap()->old_pointer_space() |
4066 ? free_list_old_pointer_space_.get() | 4074 ? free_list_old_pointer_space_.get() |
4067 : free_list_old_data_space_.get(); | 4075 : free_list_old_data_space_.get(); |
4068 FreeList private_free_list(space); | 4076 FreeList private_free_list(space); |
4077 int max_freed = 0; | |
Jarin
2014/07/10 12:12:20
Nit: you could remove this line and declare the in
| |
4078 int max_freed_overall = 0; | |
4069 while (it.has_next()) { | 4079 while (it.has_next()) { |
4070 Page* p = it.next(); | 4080 Page* p = it.next(); |
4071 | 4081 |
4072 if (p->TryParallelSweeping()) { | 4082 if (p->TryParallelSweeping()) { |
4073 SweepConservatively<SWEEP_IN_PARALLEL>(space, &private_free_list, p); | 4083 max_freed = SweepConservatively<SWEEP_IN_PARALLEL>( |
4084 space, &private_free_list, p); | |
4074 free_list->Concatenate(&private_free_list); | 4085 free_list->Concatenate(&private_free_list); |
4075 p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_FINALIZE); | 4086 if (required_freed_bytes > 0 && max_freed >= required_freed_bytes) { |
4087 return max_freed; | |
4088 } | |
4089 max_freed_overall = Max(max_freed, max_freed_overall); | |
4076 } | 4090 } |
4077 if (p == space->end_of_unswept_pages()) break; | 4091 if (p == space->end_of_unswept_pages()) break; |
4078 } | 4092 } |
4093 return max_freed_overall; | |
4079 } | 4094 } |
4080 | 4095 |
4081 | 4096 |
4082 void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) { | 4097 void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) { |
4083 space->set_is_iterable(sweeper == PRECISE); | 4098 space->set_is_iterable(sweeper == PRECISE); |
4084 space->set_is_swept_concurrently(sweeper == CONCURRENT_CONSERVATIVE); | 4099 space->set_is_swept_concurrently(sweeper == CONCURRENT_CONSERVATIVE); |
4085 space->ClearStats(); | 4100 space->ClearStats(); |
4086 | 4101 |
4087 // We defensively initialize end_of_unswept_pages_ here with the first page | 4102 // We defensively initialize end_of_unswept_pages_ here with the first page |
4088 // of the pages list. | 4103 // of the pages list. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4124 } | 4139 } |
4125 unused_page_present = true; | 4140 unused_page_present = true; |
4126 } | 4141 } |
4127 | 4142 |
4128 switch (sweeper) { | 4143 switch (sweeper) { |
4129 case CONSERVATIVE: { | 4144 case CONSERVATIVE: { |
4130 if (FLAG_gc_verbose) { | 4145 if (FLAG_gc_verbose) { |
4131 PrintF("Sweeping 0x%" V8PRIxPTR " conservatively.\n", | 4146 PrintF("Sweeping 0x%" V8PRIxPTR " conservatively.\n", |
4132 reinterpret_cast<intptr_t>(p)); | 4147 reinterpret_cast<intptr_t>(p)); |
4133 } | 4148 } |
4134 SweepConservatively<SWEEP_SEQUENTIALLY>(space, NULL, p); | 4149 SweepConservatively<SWEEP_ON_MAIN_THREAD>(space, NULL, p); |
4135 pages_swept++; | 4150 pages_swept++; |
4136 break; | 4151 break; |
4137 } | 4152 } |
4138 case CONCURRENT_CONSERVATIVE: | 4153 case CONCURRENT_CONSERVATIVE: |
4139 case PARALLEL_CONSERVATIVE: { | 4154 case PARALLEL_CONSERVATIVE: { |
4140 if (!parallel_sweeping_active) { | 4155 if (!parallel_sweeping_active) { |
4141 if (FLAG_gc_verbose) { | 4156 if (FLAG_gc_verbose) { |
4142 PrintF("Sweeping 0x%" V8PRIxPTR " conservatively.\n", | 4157 PrintF("Sweeping 0x%" V8PRIxPTR " conservatively.\n", |
4143 reinterpret_cast<intptr_t>(p)); | 4158 reinterpret_cast<intptr_t>(p)); |
4144 } | 4159 } |
4145 SweepConservatively<SWEEP_SEQUENTIALLY>(space, NULL, p); | 4160 SweepConservatively<SWEEP_ON_MAIN_THREAD>(space, NULL, p); |
4146 pages_swept++; | 4161 pages_swept++; |
4147 parallel_sweeping_active = true; | 4162 parallel_sweeping_active = true; |
4148 } else { | 4163 } else { |
4149 if (p->scan_on_scavenge()) { | 4164 if (p->scan_on_scavenge()) { |
4150 SweepPrecisely<SWEEP_ONLY, IGNORE_SKIP_LIST, IGNORE_FREE_SPACE>( | 4165 SweepPrecisely<SWEEP_ONLY, IGNORE_SKIP_LIST, IGNORE_FREE_SPACE>( |
4151 space, p, NULL); | 4166 space, p, NULL); |
4152 pages_swept++; | 4167 pages_swept++; |
4153 if (FLAG_gc_verbose) { | 4168 if (FLAG_gc_verbose) { |
4154 PrintF("Sweeping 0x%" V8PRIxPTR | 4169 PrintF("Sweeping 0x%" V8PRIxPTR |
4155 " scan on scavenge page precisely.\n", | 4170 " scan on scavenge page precisely.\n", |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4501 while (buffer != NULL) { | 4516 while (buffer != NULL) { |
4502 SlotsBuffer* next_buffer = buffer->next(); | 4517 SlotsBuffer* next_buffer = buffer->next(); |
4503 DeallocateBuffer(buffer); | 4518 DeallocateBuffer(buffer); |
4504 buffer = next_buffer; | 4519 buffer = next_buffer; |
4505 } | 4520 } |
4506 *buffer_address = NULL; | 4521 *buffer_address = NULL; |
4507 } | 4522 } |
4508 | 4523 |
4509 | 4524 |
4510 } } // namespace v8::internal | 4525 } } // namespace v8::internal |
OLD | NEW |