| 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
| 15 // | 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_WRITE_BARRIER_H_ | 28 #ifndef V8_STORE_BUFFER_H_ |
| 29 #define V8_WRITE_BARRIER_H_ | 29 #define V8_STORE_BUFFER_H_ |
| 30 | 30 |
| 31 #include "allocation.h" | 31 #include "allocation.h" |
| 32 #include "checks.h" | 32 #include "checks.h" |
| 33 #include "globals.h" | 33 #include "globals.h" |
| 34 #include "platform.h" | 34 #include "platform.h" |
| 35 #include "v8globals.h" |
| 35 | 36 |
| 36 namespace v8 { | 37 namespace v8 { |
| 37 namespace internal { | 38 namespace internal { |
| 38 | 39 |
| 40 |
| 39 typedef void (*ObjectSlotCallback)(HeapObject** from, HeapObject* to); | 41 typedef void (*ObjectSlotCallback)(HeapObject** from, HeapObject* to); |
| 40 | 42 |
| 43 |
| 41 // Used to implement the write barrier by collecting addresses of pointers | 44 // Used to implement the write barrier by collecting addresses of pointers |
| 42 // between spaces. | 45 // between spaces. |
| 43 class StoreBuffer : public AllStatic { | 46 class StoreBuffer : public AllStatic { |
| 44 public: | 47 public: |
| 45 static inline Address TopAddress(); | 48 static inline Address TopAddress(); |
| 46 | 49 |
| 47 static void Setup(); | 50 static void Setup(); |
| 48 static void TearDown(); | 51 static void TearDown(); |
| 49 | 52 |
| 50 // This is used by the mutator to enter addresses into the store buffer. | 53 // This is used by the mutator to enter addresses into the store buffer. |
| 51 static inline void Mark(Address addr); | 54 static inline void Mark(Address addr); |
| 52 | 55 |
| 53 // This is used by the heap traversal to enter the addresses into the store | 56 // This is used by the heap traversal to enter the addresses into the store |
| 54 // buffer that should still be in the store buffer after GC. It enters | 57 // buffer that should still be in the store buffer after GC. It enters |
| 55 // addresses directly into the old buffer because the GC starts by wiping the | 58 // addresses directly into the old buffer because the GC starts by wiping the |
| 56 // old buffer and thereafter only visits each cell once so there is no need | 59 // old buffer and thereafter only visits each cell once so there is no need |
| 57 // to attempt to remove any dupes. During the first part of a scavenge we | 60 // to attempt to remove any dupes. During the first part of a GC we |
| 58 // are using the store buffer to access the old spaces and at the same time | 61 // are using the store buffer to access the old spaces and at the same time |
| 59 // we are rebuilding the store buffer using this function. There is, however | 62 // we are rebuilding the store buffer using this function. There is, however |
| 60 // no issue of overwriting the buffer we are iterating over, because this | 63 // no issue of overwriting the buffer we are iterating over, because this |
| 61 // stage of the scavenge can only reduce the number of addresses in the store | 64 // stage of the scavenge can only reduce the number of addresses in the store |
| 62 // buffer (some objects are promoted so pointers to them do not need to be in | 65 // buffer (some objects are promoted so pointers to them do not need to be in |
| 63 // the store buffer). The later parts of the scavenge process the promotion | 66 // the store buffer). The later parts of the GC scan the pages that are |
| 64 // queue and they can overflow this buffer, which we must check for. | 67 // exempt from the store buffer and process the promotion queue. These steps |
| 68 // can overflow this buffer. We check for this and on overflow we call the |
| 69 // callback set up with the StoreBufferRebuildScope object. |
| 65 static inline void EnterDirectlyIntoStoreBuffer(Address addr); | 70 static inline void EnterDirectlyIntoStoreBuffer(Address addr); |
| 66 | 71 |
| 67 // Iterates over all pointers that go from old space to new space. It will | 72 // Iterates over all pointers that go from old space to new space. It will |
| 68 // delete the store buffer as it starts so the callback should reenter | 73 // delete the store buffer as it starts so the callback should reenter |
| 69 // surviving old-to-new pointers into the store buffer to rebuild it. | 74 // surviving old-to-new pointers into the store buffer to rebuild it. |
| 70 static void IteratePointersToNewSpace(ObjectSlotCallback callback); | 75 static void IteratePointersToNewSpace(ObjectSlotCallback callback); |
| 71 | 76 |
| 72 static const int kStoreBufferOverflowBit = 1 << 16; | 77 static const int kStoreBufferOverflowBit = 1 << 16; |
| 73 static const int kStoreBufferSize = kStoreBufferOverflowBit; | 78 static const int kStoreBufferSize = kStoreBufferOverflowBit; |
| 74 static const int kStoreBufferLength = kStoreBufferSize / sizeof(Address); | 79 static const int kStoreBufferLength = kStoreBufferSize / sizeof(Address); |
| 75 static const int kOldStoreBufferLength = kStoreBufferLength * 64; | 80 static const int kOldStoreBufferLength = kStoreBufferLength * 64; |
| 76 static const int kHashMapLengthLog2 = 12; | 81 static const int kHashMapLengthLog2 = 12; |
| 77 static const int kHashMapLength = 1 << kHashMapLengthLog2; | 82 static const int kHashMapLength = 1 << kHashMapLengthLog2; |
| 78 | 83 |
| 79 static void Compact(); | 84 static void Compact(); |
| 80 static void GCPrologue(GCType type, GCCallbackFlags flags); | 85 static void GCPrologue(GCType type, GCCallbackFlags flags); |
| 81 static void GCEpilogue(GCType type, GCCallbackFlags flags); | 86 static void GCEpilogue(GCType type, GCCallbackFlags flags); |
| 82 | 87 |
| 88 static Object*** Limit() { return reinterpret_cast<Object***>(old_limit_); } |
| 83 static Object*** Start() { return reinterpret_cast<Object***>(old_start_); } | 89 static Object*** Start() { return reinterpret_cast<Object***>(old_start_); } |
| 84 static Object*** Top() { return reinterpret_cast<Object***>(old_top_); } | 90 static Object*** Top() { return reinterpret_cast<Object***>(old_top_); } |
| 91 static void SetTop(Object*** top) { |
| 92 ASSERT(top >= Start()); |
| 93 ASSERT(top <= Limit()); |
| 94 old_top_ = reinterpret_cast<Address*>(top); |
| 95 } |
| 85 | 96 |
| 86 enum StoreBufferMode { | |
| 87 kStoreBufferFunctional, | |
| 88 kStoreBufferDisabled, | |
| 89 kStoreBufferBeingRebuilt | |
| 90 }; | |
| 91 | |
| 92 static StoreBufferMode store_buffer_mode() { return store_buffer_mode_; } | |
| 93 static inline void set_store_buffer_mode(StoreBufferMode mode); | |
| 94 static bool old_buffer_is_sorted() { return old_buffer_is_sorted_; } | 97 static bool old_buffer_is_sorted() { return old_buffer_is_sorted_; } |
| 98 static bool old_buffer_is_filtered() { return old_buffer_is_filtered_; } |
| 95 | 99 |
| 96 // Goes through the store buffer removing pointers to things that have | 100 // Goes through the store buffer removing pointers to things that have |
| 97 // been promoted. Rebuilds the store buffer completely if it overflowed. | 101 // been promoted. Rebuilds the store buffer completely if it overflowed. |
| 98 static void SortUniq(); | 102 static void SortUniq(); |
| 103 |
| 104 static void HandleFullness(); |
| 99 static void Verify(); | 105 static void Verify(); |
| 100 | 106 |
| 101 static void PrepareForIteration(); | 107 static bool PrepareForIteration(); |
| 102 | 108 |
| 103 #ifdef DEBUG | 109 #ifdef DEBUG |
| 104 static void Clean(); | 110 static void Clean(); |
| 105 // Slow, for asserts only. | 111 // Slow, for asserts only. |
| 106 static bool CellIsInStoreBuffer(Address cell); | 112 static bool CellIsInStoreBuffer(Address cell); |
| 107 #endif | 113 #endif |
| 108 | 114 |
| 109 private: | 115 private: |
| 110 // The store buffer is divided up into a new buffer that is constantly being | 116 // The store buffer is divided up into a new buffer that is constantly being |
| 111 // filled by mutator activity and an old buffer that is filled with the data | 117 // filled by mutator activity and an old buffer that is filled with the data |
| 112 // from the new buffer after compression. | 118 // from the new buffer after compression. |
| 113 static Address* start_; | 119 static Address* start_; |
| 114 static Address* limit_; | 120 static Address* limit_; |
| 115 | 121 |
| 116 static Address* old_start_; | 122 static Address* old_start_; |
| 117 static Address* old_limit_; | 123 static Address* old_limit_; |
| 118 static Address* old_top_; | 124 static Address* old_top_; |
| 119 | 125 |
| 120 static bool old_buffer_is_sorted_; | 126 static bool old_buffer_is_sorted_; |
| 121 static StoreBufferMode store_buffer_mode_; | 127 static bool old_buffer_is_filtered_; |
| 122 static bool during_gc_; | 128 static bool during_gc_; |
| 129 // The garbage collector iterates over many pointers to new space that are not |
| 130 // handled by the store buffer. This flag indicates whether the pointers |
| 131 // found by the callbacks should be added to the store buffer or not. |
| 123 static bool store_buffer_rebuilding_enabled_; | 132 static bool store_buffer_rebuilding_enabled_; |
| 133 static StoreBufferCallback callback_; |
| 124 static bool may_move_store_buffer_entries_; | 134 static bool may_move_store_buffer_entries_; |
| 125 | 135 |
| 126 static VirtualMemory* virtual_memory_; | 136 static VirtualMemory* virtual_memory_; |
| 127 static uintptr_t* hash_map_1_; | 137 static uintptr_t* hash_map_1_; |
| 128 static uintptr_t* hash_map_2_; | 138 static uintptr_t* hash_map_2_; |
| 129 | 139 |
| 130 static void CheckForFullBuffer(); | 140 static void CheckForFullBuffer(); |
| 131 static void Uniq(); | 141 static void Uniq(); |
| 132 static void ZapHashTables(); | 142 static void ZapHashTables(); |
| 133 static bool HashTablesAreZapped(); | 143 static bool HashTablesAreZapped(); |
| 144 static void FilterScanOnScavengeEntries(); |
| 145 static void ExemptPopularPages(int prime_sample_step, int threshold); |
| 134 | 146 |
| 135 friend class StoreBufferRebuildScope; | 147 friend class StoreBufferRebuildScope; |
| 136 friend class DontMoveStoreBufferEntriesScope; | 148 friend class DontMoveStoreBufferEntriesScope; |
| 137 }; | 149 }; |
| 138 | 150 |
| 139 | 151 |
| 140 class StoreBufferRebuildScope { | 152 class StoreBufferRebuildScope { |
| 141 public: | 153 public: |
| 142 StoreBufferRebuildScope() : | 154 explicit StoreBufferRebuildScope(StoreBufferCallback callback) |
| 143 stored_state_(StoreBuffer::store_buffer_rebuilding_enabled_) { | 155 : stored_state_(StoreBuffer::store_buffer_rebuilding_enabled_), |
| 156 stored_callback_(StoreBuffer::callback_) { |
| 144 StoreBuffer::store_buffer_rebuilding_enabled_ = true; | 157 StoreBuffer::store_buffer_rebuilding_enabled_ = true; |
| 158 StoreBuffer::callback_ = callback; |
| 159 (*callback)(NULL, kStoreBufferScanningPageEvent); |
| 145 } | 160 } |
| 146 | 161 |
| 147 ~StoreBufferRebuildScope() { | 162 ~StoreBufferRebuildScope() { |
| 163 StoreBuffer::callback_ = stored_callback_; |
| 148 StoreBuffer::store_buffer_rebuilding_enabled_ = stored_state_; | 164 StoreBuffer::store_buffer_rebuilding_enabled_ = stored_state_; |
| 149 StoreBuffer::CheckForFullBuffer(); | 165 StoreBuffer::CheckForFullBuffer(); |
| 150 } | 166 } |
| 151 | 167 |
| 152 private: | 168 private: |
| 153 bool stored_state_; | 169 bool stored_state_; |
| 170 StoreBufferCallback stored_callback_; |
| 154 }; | 171 }; |
| 155 | 172 |
| 156 | 173 |
| 157 class DontMoveStoreBufferEntriesScope { | 174 class DontMoveStoreBufferEntriesScope { |
| 158 public: | 175 public: |
| 159 DontMoveStoreBufferEntriesScope() : | 176 DontMoveStoreBufferEntriesScope() : |
| 160 stored_state_(StoreBuffer::may_move_store_buffer_entries_) { | 177 stored_state_(StoreBuffer::may_move_store_buffer_entries_) { |
| 161 StoreBuffer::may_move_store_buffer_entries_ = false; | 178 StoreBuffer::may_move_store_buffer_entries_ = false; |
| 162 } | 179 } |
| 163 | 180 |
| 164 ~DontMoveStoreBufferEntriesScope() { | 181 ~DontMoveStoreBufferEntriesScope() { |
| 165 StoreBuffer::may_move_store_buffer_entries_ = stored_state_; | 182 StoreBuffer::may_move_store_buffer_entries_ = stored_state_; |
| 166 } | 183 } |
| 167 | 184 |
| 168 private: | 185 private: |
| 169 bool stored_state_; | 186 bool stored_state_; |
| 170 }; | 187 }; |
| 171 | 188 |
| 172 } } // namespace v8::internal | 189 } } // namespace v8::internal |
| 173 | 190 |
| 174 #endif // V8_WRITE_BARRIER_H_ | 191 #endif // V8_STORE_BUFFER_H_ |
| OLD | NEW |