OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 23 matching lines...) Expand all Loading... | |
34 namespace v8 { | 34 namespace v8 { |
35 namespace internal { | 35 namespace internal { |
36 | 36 |
37 StoreBuffer::StoreBuffer(Heap* heap) | 37 StoreBuffer::StoreBuffer(Heap* heap) |
38 : heap_(heap), | 38 : heap_(heap), |
39 start_(NULL), | 39 start_(NULL), |
40 limit_(NULL), | 40 limit_(NULL), |
41 old_start_(NULL), | 41 old_start_(NULL), |
42 old_limit_(NULL), | 42 old_limit_(NULL), |
43 old_top_(NULL), | 43 old_top_(NULL), |
44 old_reserved_limit_(NULL), | |
44 old_buffer_is_sorted_(false), | 45 old_buffer_is_sorted_(false), |
45 old_buffer_is_filtered_(false), | 46 old_buffer_is_filtered_(false), |
46 during_gc_(false), | 47 during_gc_(false), |
47 store_buffer_rebuilding_enabled_(false), | 48 store_buffer_rebuilding_enabled_(false), |
48 callback_(NULL), | 49 callback_(NULL), |
49 may_move_store_buffer_entries_(true), | 50 may_move_store_buffer_entries_(true), |
50 virtual_memory_(NULL), | 51 virtual_memory_(NULL), |
51 hash_map_1_(NULL), | 52 hash_map_1_(NULL), |
52 hash_map_2_(NULL) { | 53 hash_map_2_(NULL) { |
53 } | 54 } |
54 | 55 |
55 | 56 |
56 void StoreBuffer::Setup() { | 57 void StoreBuffer::Setup() { |
57 virtual_memory_ = new VirtualMemory(kStoreBufferSize * 3); | 58 virtual_memory_ = new VirtualMemory(kStoreBufferSize * 3); |
58 uintptr_t start_as_int = | 59 uintptr_t start_as_int = |
59 reinterpret_cast<uintptr_t>(virtual_memory_->address()); | 60 reinterpret_cast<uintptr_t>(virtual_memory_->address()); |
60 start_ = | 61 start_ = |
61 reinterpret_cast<Address*>(RoundUp(start_as_int, kStoreBufferSize * 2)); | 62 reinterpret_cast<Address*>(RoundUp(start_as_int, kStoreBufferSize * 2)); |
62 limit_ = start_ + (kStoreBufferSize / sizeof(*start_)); | 63 limit_ = start_ + (kStoreBufferSize / kPointerSize); |
63 | 64 |
64 old_top_ = old_start_ = new Address[kOldStoreBufferLength]; | 65 old_virtual_memory_ = |
65 old_limit_ = old_start_ + kOldStoreBufferLength; | 66 new VirtualMemory(kOldStoreBufferLength * kPointerSize); |
67 old_top_ = old_start_ = | |
68 reinterpret_cast<Address*>(old_virtual_memory_->address()); | |
69 // Don't know the alignment requirements of the OS, but it is certainly not | |
70 // less than 0xfff. | |
71 ASSERT((reinterpret_cast<uintptr_t>(old_start_) & 0xfff) == 0); | |
72 int initial_length = kInitialOldStoreBufferLength; | |
73 if (initial_length == 0) initial_length = 1; | |
Michael Starzinger
2011/12/02 13:38:52
Can we change this into ASSERT(initial_length != 0
Erik Corry
2011/12/02 14:07:27
Refactored in a slightly different way.
| |
74 while (initial_length * kPointerSize < OS::CommitPageSize()) { | |
75 initial_length *= 2; | |
76 } | |
77 old_limit_ = old_start_ + initial_length; | |
78 old_reserved_limit_ = old_start_ + kOldStoreBufferLength; | |
79 | |
80 CHECK(old_virtual_memory_->Commit( | |
81 reinterpret_cast<void*>(old_start_), | |
82 (old_limit_ - old_start_) * kPointerSize, | |
83 false)); | |
66 | 84 |
67 ASSERT(reinterpret_cast<Address>(start_) >= virtual_memory_->address()); | 85 ASSERT(reinterpret_cast<Address>(start_) >= virtual_memory_->address()); |
68 ASSERT(reinterpret_cast<Address>(limit_) >= virtual_memory_->address()); | 86 ASSERT(reinterpret_cast<Address>(limit_) >= virtual_memory_->address()); |
69 Address* vm_limit = reinterpret_cast<Address*>( | 87 Address* vm_limit = reinterpret_cast<Address*>( |
70 reinterpret_cast<char*>(virtual_memory_->address()) + | 88 reinterpret_cast<char*>(virtual_memory_->address()) + |
71 virtual_memory_->size()); | 89 virtual_memory_->size()); |
72 ASSERT(start_ <= vm_limit); | 90 ASSERT(start_ <= vm_limit); |
73 ASSERT(limit_ <= vm_limit); | 91 ASSERT(limit_ <= vm_limit); |
74 USE(vm_limit); | 92 USE(vm_limit); |
75 ASSERT((reinterpret_cast<uintptr_t>(limit_) & kStoreBufferOverflowBit) != 0); | 93 ASSERT((reinterpret_cast<uintptr_t>(limit_) & kStoreBufferOverflowBit) != 0); |
76 ASSERT((reinterpret_cast<uintptr_t>(limit_ - 1) & kStoreBufferOverflowBit) == | 94 ASSERT((reinterpret_cast<uintptr_t>(limit_ - 1) & kStoreBufferOverflowBit) == |
77 0); | 95 0); |
78 | 96 |
79 virtual_memory_->Commit(reinterpret_cast<Address>(start_), | 97 CHECK(virtual_memory_->Commit(reinterpret_cast<Address>(start_), |
80 kStoreBufferSize, | 98 kStoreBufferSize, |
81 false); // Not executable. | 99 false)); // Not executable. |
82 heap_->public_set_store_buffer_top(start_); | 100 heap_->public_set_store_buffer_top(start_); |
83 | 101 |
84 hash_map_1_ = new uintptr_t[kHashMapLength]; | 102 hash_map_1_ = new uintptr_t[kHashMapLength]; |
85 hash_map_2_ = new uintptr_t[kHashMapLength]; | 103 hash_map_2_ = new uintptr_t[kHashMapLength]; |
86 | 104 |
87 ZapHashTables(); | 105 ZapHashTables(); |
88 } | 106 } |
89 | 107 |
90 | 108 |
91 void StoreBuffer::TearDown() { | 109 void StoreBuffer::TearDown() { |
92 delete virtual_memory_; | 110 delete virtual_memory_; |
111 delete old_virtual_memory_; | |
93 delete[] hash_map_1_; | 112 delete[] hash_map_1_; |
94 delete[] hash_map_2_; | 113 delete[] hash_map_2_; |
95 delete[] old_start_; | 114 old_start_ = old_top_ = old_limit_ = old_reserved_limit_ = NULL; |
96 old_start_ = old_top_ = old_limit_ = NULL; | |
97 start_ = limit_ = NULL; | 115 start_ = limit_ = NULL; |
98 heap_->public_set_store_buffer_top(start_); | 116 heap_->public_set_store_buffer_top(start_); |
99 } | 117 } |
100 | 118 |
101 | 119 |
102 void StoreBuffer::StoreBufferOverflow(Isolate* isolate) { | 120 void StoreBuffer::StoreBufferOverflow(Isolate* isolate) { |
103 isolate->heap()->store_buffer()->Compact(); | 121 isolate->heap()->store_buffer()->Compact(); |
104 } | 122 } |
105 | 123 |
106 | 124 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
143 if (heap_->InNewSpace(*reinterpret_cast<Object**>(current))) { | 161 if (heap_->InNewSpace(*reinterpret_cast<Object**>(current))) { |
144 *write++ = current; | 162 *write++ = current; |
145 } | 163 } |
146 } | 164 } |
147 previous = current; | 165 previous = current; |
148 } | 166 } |
149 old_top_ = write; | 167 old_top_ = write; |
150 } | 168 } |
151 | 169 |
152 | 170 |
153 void StoreBuffer::HandleFullness() { | 171 void StoreBuffer::EnsureSpace(intptr_t space_needed) { |
172 while (old_limit_ - old_top_ < space_needed && | |
173 old_limit_ < old_reserved_limit_) { | |
174 size_t grow = old_limit_ - old_start_; // Double size. | |
175 CHECK(old_virtual_memory_->Commit( | |
176 reinterpret_cast<void*>(old_limit_), grow * kPointerSize, false)); | |
Michael Starzinger
2011/12/02 13:38:52
Can we put each argument on a separate line like w
Erik Corry
2011/12/02 14:07:27
Done.
| |
177 old_limit_ += grow; | |
178 } | |
179 | |
180 if (old_limit_ - old_top_ >= space_needed) return; | |
181 | |
154 if (old_buffer_is_filtered_) return; | 182 if (old_buffer_is_filtered_) return; |
155 ASSERT(may_move_store_buffer_entries_); | 183 ASSERT(may_move_store_buffer_entries_); |
156 Compact(); | 184 Compact(); |
157 | 185 |
158 old_buffer_is_filtered_ = true; | 186 old_buffer_is_filtered_ = true; |
159 bool page_has_scan_on_scavenge_flag = false; | 187 bool page_has_scan_on_scavenge_flag = false; |
160 | 188 |
161 PointerChunkIterator it(heap_); | 189 PointerChunkIterator it(heap_); |
162 MemoryChunk* chunk; | 190 MemoryChunk* chunk; |
163 while ((chunk = it.next()) != NULL) { | 191 while ((chunk = it.next()) != NULL) { |
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
638 | 666 |
639 void StoreBuffer::Compact() { | 667 void StoreBuffer::Compact() { |
640 Address* top = reinterpret_cast<Address*>(heap_->store_buffer_top()); | 668 Address* top = reinterpret_cast<Address*>(heap_->store_buffer_top()); |
641 | 669 |
642 if (top == start_) return; | 670 if (top == start_) return; |
643 | 671 |
644 // There's no check of the limit in the loop below so we check here for | 672 // There's no check of the limit in the loop below so we check here for |
645 // the worst case (compaction doesn't eliminate any pointers). | 673 // the worst case (compaction doesn't eliminate any pointers). |
646 ASSERT(top <= limit_); | 674 ASSERT(top <= limit_); |
647 heap_->public_set_store_buffer_top(start_); | 675 heap_->public_set_store_buffer_top(start_); |
648 if (top - start_ > old_limit_ - old_top_) { | 676 EnsureSpace(top - start_); |
649 HandleFullness(); | |
650 } | |
651 ASSERT(may_move_store_buffer_entries_); | 677 ASSERT(may_move_store_buffer_entries_); |
652 // Goes through the addresses in the store buffer attempting to remove | 678 // Goes through the addresses in the store buffer attempting to remove |
653 // duplicates. In the interest of speed this is a lossy operation. Some | 679 // duplicates. In the interest of speed this is a lossy operation. Some |
654 // duplicates will remain. We have two hash tables with different hash | 680 // duplicates will remain. We have two hash tables with different hash |
655 // functions to reduce the number of unnecessary clashes. | 681 // functions to reduce the number of unnecessary clashes. |
656 for (Address* current = start_; current < top; current++) { | 682 for (Address* current = start_; current < top; current++) { |
657 ASSERT(!heap_->cell_space()->Contains(*current)); | 683 ASSERT(!heap_->cell_space()->Contains(*current)); |
658 ASSERT(!heap_->code_space()->Contains(*current)); | 684 ASSERT(!heap_->code_space()->Contains(*current)); |
659 ASSERT(!heap_->old_data_space()->Contains(*current)); | 685 ASSERT(!heap_->old_data_space()->Contains(*current)); |
660 uintptr_t int_addr = reinterpret_cast<uintptr_t>(*current); | 686 uintptr_t int_addr = reinterpret_cast<uintptr_t>(*current); |
(...skipping 20 matching lines...) Expand all Loading... | |
681 old_buffer_is_filtered_ = false; | 707 old_buffer_is_filtered_ = false; |
682 *old_top_++ = reinterpret_cast<Address>(int_addr << kPointerSizeLog2); | 708 *old_top_++ = reinterpret_cast<Address>(int_addr << kPointerSizeLog2); |
683 ASSERT(old_top_ <= old_limit_); | 709 ASSERT(old_top_ <= old_limit_); |
684 } | 710 } |
685 heap_->isolate()->counters()->store_buffer_compactions()->Increment(); | 711 heap_->isolate()->counters()->store_buffer_compactions()->Increment(); |
686 CheckForFullBuffer(); | 712 CheckForFullBuffer(); |
687 } | 713 } |
688 | 714 |
689 | 715 |
690 void StoreBuffer::CheckForFullBuffer() { | 716 void StoreBuffer::CheckForFullBuffer() { |
691 if (old_limit_ - old_top_ < kStoreBufferSize * 2) { | 717 EnsureSpace(kStoreBufferSize * 2); |
692 HandleFullness(); | |
693 } | |
694 } | 718 } |
695 | 719 |
696 } } // namespace v8::internal | 720 } } // namespace v8::internal |
OLD | NEW |