| 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/context-slot-cache.h" | 9 #include "src/ast/context-slot-cache.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 3092 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3103 instance->set_osr_loop_nesting_level(0); | 3103 instance->set_osr_loop_nesting_level(0); |
| 3104 instance->set_bytecode_age(BytecodeArray::kNoAgeBytecodeAge); | 3104 instance->set_bytecode_age(BytecodeArray::kNoAgeBytecodeAge); |
| 3105 instance->set_constant_pool(constant_pool); | 3105 instance->set_constant_pool(constant_pool); |
| 3106 instance->set_handler_table(empty_fixed_array()); | 3106 instance->set_handler_table(empty_fixed_array()); |
| 3107 instance->set_source_position_table(empty_byte_array()); | 3107 instance->set_source_position_table(empty_byte_array()); |
| 3108 CopyBytes(instance->GetFirstBytecodeAddress(), raw_bytecodes, length); | 3108 CopyBytes(instance->GetFirstBytecodeAddress(), raw_bytecodes, length); |
| 3109 | 3109 |
| 3110 return result; | 3110 return result; |
| 3111 } | 3111 } |
| 3112 | 3112 |
| 3113 void Heap::CreateFillerObjectAt(Address addr, int size, | 3113 HeapObject* Heap::CreateFillerObjectAt(Address addr, int size, |
| 3114 ClearRecordedSlots mode) { | 3114 ClearRecordedSlots mode) { |
| 3115 if (size == 0) return; | 3115 if (size == 0) return nullptr; |
| 3116 HeapObject* filler = HeapObject::FromAddress(addr); | 3116 HeapObject* filler = HeapObject::FromAddress(addr); |
| 3117 if (size == kPointerSize) { | 3117 if (size == kPointerSize) { |
| 3118 filler->set_map_no_write_barrier( | 3118 filler->set_map_no_write_barrier( |
| 3119 reinterpret_cast<Map*>(root(kOnePointerFillerMapRootIndex))); | 3119 reinterpret_cast<Map*>(root(kOnePointerFillerMapRootIndex))); |
| 3120 } else if (size == 2 * kPointerSize) { | 3120 } else if (size == 2 * kPointerSize) { |
| 3121 filler->set_map_no_write_barrier( | 3121 filler->set_map_no_write_barrier( |
| 3122 reinterpret_cast<Map*>(root(kTwoPointerFillerMapRootIndex))); | 3122 reinterpret_cast<Map*>(root(kTwoPointerFillerMapRootIndex))); |
| 3123 } else { | 3123 } else { |
| 3124 DCHECK_GT(size, 2 * kPointerSize); | 3124 DCHECK_GT(size, 2 * kPointerSize); |
| 3125 filler->set_map_no_write_barrier( | 3125 filler->set_map_no_write_barrier( |
| 3126 reinterpret_cast<Map*>(root(kFreeSpaceMapRootIndex))); | 3126 reinterpret_cast<Map*>(root(kFreeSpaceMapRootIndex))); |
| 3127 FreeSpace::cast(filler)->nobarrier_set_size(size); | 3127 FreeSpace::cast(filler)->nobarrier_set_size(size); |
| 3128 } | 3128 } |
| 3129 if (mode == ClearRecordedSlots::kYes) { | 3129 if (mode == ClearRecordedSlots::kYes) { |
| 3130 ClearRecordedSlotRange(addr, addr + size); | 3130 ClearRecordedSlotRange(addr, addr + size); |
| 3131 } | 3131 } |
| 3132 | 3132 |
| 3133 // At this point, we may be deserializing the heap from a snapshot, and | 3133 // At this point, we may be deserializing the heap from a snapshot, and |
| 3134 // none of the maps have been created yet and are NULL. | 3134 // none of the maps have been created yet and are NULL. |
| 3135 DCHECK((filler->map() == NULL && !deserialization_complete_) || | 3135 DCHECK((filler->map() == NULL && !deserialization_complete_) || |
| 3136 filler->map()->IsMap()); | 3136 filler->map()->IsMap()); |
| 3137 return filler; |
| 3137 } | 3138 } |
| 3138 | 3139 |
| 3139 | 3140 |
| 3140 bool Heap::CanMoveObjectStart(HeapObject* object) { | 3141 bool Heap::CanMoveObjectStart(HeapObject* object) { |
| 3141 if (!FLAG_move_object_start) return false; | 3142 if (!FLAG_move_object_start) return false; |
| 3142 | 3143 |
| 3143 // Sampling heap profiler may have a reference to the object. | 3144 // Sampling heap profiler may have a reference to the object. |
| 3144 if (isolate()->heap_profiler()->is_sampling_allocations()) return false; | 3145 if (isolate()->heap_profiler()->is_sampling_allocations()) return false; |
| 3145 | 3146 |
| 3146 Address address = object->address(); | 3147 Address address = object->address(); |
| 3147 | 3148 |
| 3148 if (lo_space()->Contains(object)) return false; | 3149 if (lo_space()->Contains(object)) return false; |
| 3149 | 3150 |
| 3150 // We can move the object start if the page was already swept. | 3151 // We can move the object start if the page was already swept. |
| 3151 return Page::FromAddress(address)->SweepingDone(); | 3152 return Page::FromAddress(address)->SweepingDone(); |
| 3152 } | 3153 } |
| 3153 | 3154 |
| 3154 void Heap::AdjustLiveBytes(HeapObject* object, int by) { | 3155 void Heap::AdjustLiveBytes(HeapObject* object, int by) { |
| 3155 // As long as the inspected object is black and we are currently not iterating | 3156 // As long as the inspected object is black and we are currently not iterating |
| 3156 // the heap using HeapIterator, we can update the live byte count. We cannot | 3157 // the heap using HeapIterator, we can update the live byte count. We cannot |
| 3157 // update while using HeapIterator because the iterator is temporarily | 3158 // update while using HeapIterator because the iterator is temporarily |
| 3158 // marking the whole object graph, without updating live bytes. | 3159 // marking the whole object graph, without updating live bytes. |
| 3159 if (lo_space()->Contains(object)) { | 3160 if (lo_space()->Contains(object)) { |
| 3160 lo_space()->AdjustLiveBytes(by); | 3161 lo_space()->AdjustLiveBytes(by); |
| 3161 } else if (!in_heap_iterator() && | 3162 } else if (!in_heap_iterator() && |
| 3162 !mark_compact_collector()->sweeping_in_progress() && | 3163 !mark_compact_collector()->sweeping_in_progress() && |
| 3163 Marking::IsBlack(ObjectMarking::MarkBitFrom(object->address()))) { | 3164 Marking::IsBlack(ObjectMarking::MarkBitFrom(object))) { |
| 3164 DCHECK(MemoryChunk::FromAddress(object->address())->SweepingDone()); | 3165 DCHECK(MemoryChunk::FromAddress(object->address())->SweepingDone()); |
| 3165 MemoryChunk::IncrementLiveBytes(object, by); | 3166 MemoryChunk::IncrementLiveBytes(object, by); |
| 3166 } | 3167 } |
| 3167 } | 3168 } |
| 3168 | 3169 |
| 3169 | 3170 |
| 3170 FixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object, | 3171 FixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object, |
| 3171 int elements_to_trim) { | 3172 int elements_to_trim) { |
| 3172 CHECK_NOT_NULL(object); | 3173 CHECK_NOT_NULL(object); |
| 3173 DCHECK(!object->IsFixedTypedArrayBase()); | 3174 DCHECK(!object->IsFixedTypedArrayBase()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3189 const int len = object->length(); | 3190 const int len = object->length(); |
| 3190 DCHECK(elements_to_trim <= len); | 3191 DCHECK(elements_to_trim <= len); |
| 3191 | 3192 |
| 3192 // Calculate location of new array start. | 3193 // Calculate location of new array start. |
| 3193 Address old_start = object->address(); | 3194 Address old_start = object->address(); |
| 3194 Address new_start = old_start + bytes_to_trim; | 3195 Address new_start = old_start + bytes_to_trim; |
| 3195 | 3196 |
| 3196 // Transfer the mark bits to their new location if the object is not within | 3197 // Transfer the mark bits to their new location if the object is not within |
| 3197 // a black area. | 3198 // a black area. |
| 3198 if (!incremental_marking()->black_allocation() || | 3199 if (!incremental_marking()->black_allocation() || |
| 3199 !Marking::IsBlack(ObjectMarking::MarkBitFrom(new_start))) { | 3200 !Marking::IsBlack( |
| 3200 IncrementalMarking::TransferMark(this, old_start, new_start); | 3201 ObjectMarking::MarkBitFrom(HeapObject::FromAddress(new_start)))) { |
| 3202 IncrementalMarking::TransferMark(this, object, |
| 3203 HeapObject::FromAddress(new_start)); |
| 3201 } | 3204 } |
| 3202 | 3205 |
| 3203 // Technically in new space this write might be omitted (except for | 3206 // Technically in new space this write might be omitted (except for |
| 3204 // debug mode which iterates through the heap), but to play safer | 3207 // debug mode which iterates through the heap), but to play safer |
| 3205 // we still do it. | 3208 // we still do it. |
| 3206 CreateFillerObjectAt(old_start, bytes_to_trim, ClearRecordedSlots::kYes); | 3209 CreateFillerObjectAt(old_start, bytes_to_trim, ClearRecordedSlots::kYes); |
| 3207 | 3210 |
| 3208 // Clear the mark bits of the black area that belongs now to the filler. | 3211 // Clear the mark bits of the black area that belongs now to the filler. |
| 3209 // This is an optimization. The sweeper will release black fillers anyway. | 3212 // This is an optimization. The sweeper will release black fillers anyway. |
| 3210 if (incremental_marking()->black_allocation() && | 3213 if (incremental_marking()->black_allocation() && |
| 3211 Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(old_start))) { | 3214 Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(object))) { |
| 3212 Page* page = Page::FromAddress(old_start); | 3215 Page* page = Page::FromAddress(old_start); |
| 3213 page->markbits()->ClearRange( | 3216 page->markbits()->ClearRange( |
| 3214 page->AddressToMarkbitIndex(old_start), | 3217 page->AddressToMarkbitIndex(old_start), |
| 3215 page->AddressToMarkbitIndex(old_start + bytes_to_trim)); | 3218 page->AddressToMarkbitIndex(old_start + bytes_to_trim)); |
| 3216 } | 3219 } |
| 3217 | 3220 |
| 3218 // Initialize header of the trimmed array. Since left trimming is only | 3221 // Initialize header of the trimmed array. Since left trimming is only |
| 3219 // performed on pages which are not concurrently swept creating a filler | 3222 // performed on pages which are not concurrently swept creating a filler |
| 3220 // object does not require synchronization. | 3223 // object does not require synchronization. |
| 3221 DCHECK(CanMoveObjectStart(object)); | 3224 DCHECK(CanMoveObjectStart(object)); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3276 Address old_end = object->address() + object->Size(); | 3279 Address old_end = object->address() + object->Size(); |
| 3277 Address new_end = old_end - bytes_to_trim; | 3280 Address new_end = old_end - bytes_to_trim; |
| 3278 | 3281 |
| 3279 // Technically in new space this write might be omitted (except for | 3282 // Technically in new space this write might be omitted (except for |
| 3280 // debug mode which iterates through the heap), but to play safer | 3283 // debug mode which iterates through the heap), but to play safer |
| 3281 // we still do it. | 3284 // we still do it. |
| 3282 // We do not create a filler for objects in large object space. | 3285 // We do not create a filler for objects in large object space. |
| 3283 // TODO(hpayer): We should shrink the large object page if the size | 3286 // TODO(hpayer): We should shrink the large object page if the size |
| 3284 // of the object changed significantly. | 3287 // of the object changed significantly. |
| 3285 if (!lo_space()->Contains(object)) { | 3288 if (!lo_space()->Contains(object)) { |
| 3286 CreateFillerObjectAt(new_end, bytes_to_trim, ClearRecordedSlots::kYes); | 3289 HeapObject* filler = |
| 3290 CreateFillerObjectAt(new_end, bytes_to_trim, ClearRecordedSlots::kYes); |
| 3291 DCHECK_NOT_NULL(filler); |
| 3287 // Clear the mark bits of the black area that belongs now to the filler. | 3292 // Clear the mark bits of the black area that belongs now to the filler. |
| 3288 // This is an optimization. The sweeper will release black fillers anyway. | 3293 // This is an optimization. The sweeper will release black fillers anyway. |
| 3289 if (incremental_marking()->black_allocation() && | 3294 if (incremental_marking()->black_allocation() && |
| 3290 Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(new_end))) { | 3295 Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(filler))) { |
| 3291 Page* page = Page::FromAddress(new_end); | 3296 Page* page = Page::FromAddress(new_end); |
| 3292 page->markbits()->ClearRange( | 3297 page->markbits()->ClearRange( |
| 3293 page->AddressToMarkbitIndex(new_end), | 3298 page->AddressToMarkbitIndex(new_end), |
| 3294 page->AddressToMarkbitIndex(new_end + bytes_to_trim)); | 3299 page->AddressToMarkbitIndex(new_end + bytes_to_trim)); |
| 3295 } | 3300 } |
| 3296 } | 3301 } |
| 3297 | 3302 |
| 3298 // Initialize header of the trimmed array. We are storing the new length | 3303 // Initialize header of the trimmed array. We are storing the new length |
| 3299 // using release store after creating a filler for the left-over space to | 3304 // using release store after creating a filler for the left-over space to |
| 3300 // avoid races with the sweeper thread. | 3305 // avoid races with the sweeper thread. |
| (...skipping 3261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6562 } | 6567 } |
| 6563 | 6568 |
| 6564 | 6569 |
| 6565 // static | 6570 // static |
| 6566 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6571 int Heap::GetStaticVisitorIdForMap(Map* map) { |
| 6567 return StaticVisitorBase::GetVisitorId(map); | 6572 return StaticVisitorBase::GetVisitorId(map); |
| 6568 } | 6573 } |
| 6569 | 6574 |
| 6570 } // namespace internal | 6575 } // namespace internal |
| 6571 } // namespace v8 | 6576 } // namespace v8 |
| OLD | NEW |