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/scopeinfo.h" | 9 #include "src/ast/scopeinfo.h" |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 3048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3059 reinterpret_cast<Map*>(root(kTwoPointerFillerMapRootIndex))); | 3059 reinterpret_cast<Map*>(root(kTwoPointerFillerMapRootIndex))); |
3060 } else { | 3060 } else { |
3061 DCHECK_GT(size, 2 * kPointerSize); | 3061 DCHECK_GT(size, 2 * kPointerSize); |
3062 filler->set_map_no_write_barrier( | 3062 filler->set_map_no_write_barrier( |
3063 reinterpret_cast<Map*>(root(kFreeSpaceMapRootIndex))); | 3063 reinterpret_cast<Map*>(root(kFreeSpaceMapRootIndex))); |
3064 FreeSpace::cast(filler)->nobarrier_set_size(size); | 3064 FreeSpace::cast(filler)->nobarrier_set_size(size); |
3065 } | 3065 } |
3066 if (mode == ClearRecordedSlots::kYes) { | 3066 if (mode == ClearRecordedSlots::kYes) { |
3067 ClearRecordedSlotRange(addr, addr + size); | 3067 ClearRecordedSlotRange(addr, addr + size); |
3068 } | 3068 } |
3069 | |
3070 // If the location where the filler is created is within a black area we have | |
3071 // to clear the mark bits of the filler space. | |
3072 if (incremental_marking()->black_allocation() && | |
3073 Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(addr))) { | |
3074 Page* page = Page::FromAddress(addr); | |
3075 page->markbits()->ClearRange(page->AddressToMarkbitIndex(addr), | |
3076 page->AddressToMarkbitIndex(addr + size)); | |
3077 } | |
3078 | |
3079 // At this point, we may be deserializing the heap from a snapshot, and | 3069 // At this point, we may be deserializing the heap from a snapshot, and |
3080 // none of the maps have been created yet and are NULL. | 3070 // none of the maps have been created yet and are NULL. |
3081 DCHECK((filler->map() == NULL && !deserialization_complete_) || | 3071 DCHECK((filler->map() == NULL && !deserialization_complete_) || |
3082 filler->map()->IsMap()); | 3072 filler->map()->IsMap()); |
3083 } | 3073 } |
3084 | 3074 |
3085 | 3075 |
3086 bool Heap::CanMoveObjectStart(HeapObject* object) { | 3076 bool Heap::CanMoveObjectStart(HeapObject* object) { |
3087 if (!FLAG_move_object_start) return false; | 3077 if (!FLAG_move_object_start) return false; |
3088 | 3078 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3139 DCHECK(object->map() != fixed_cow_array_map()); | 3129 DCHECK(object->map() != fixed_cow_array_map()); |
3140 | 3130 |
3141 STATIC_ASSERT(FixedArrayBase::kMapOffset == 0); | 3131 STATIC_ASSERT(FixedArrayBase::kMapOffset == 0); |
3142 STATIC_ASSERT(FixedArrayBase::kLengthOffset == kPointerSize); | 3132 STATIC_ASSERT(FixedArrayBase::kLengthOffset == kPointerSize); |
3143 STATIC_ASSERT(FixedArrayBase::kHeaderSize == 2 * kPointerSize); | 3133 STATIC_ASSERT(FixedArrayBase::kHeaderSize == 2 * kPointerSize); |
3144 | 3134 |
3145 const int len = object->length(); | 3135 const int len = object->length(); |
3146 DCHECK(elements_to_trim <= len); | 3136 DCHECK(elements_to_trim <= len); |
3147 | 3137 |
3148 // Calculate location of new array start. | 3138 // Calculate location of new array start. |
3149 Address old_start = object->address(); | 3139 Address new_start = object->address() + bytes_to_trim; |
3150 Address new_start = old_start + bytes_to_trim; | |
3151 | |
3152 // Transfer the mark bits to their new location if the object is not within | |
3153 // a black area. | |
3154 if (!incremental_marking()->black_allocation() || | |
3155 !Marking::IsBlack(ObjectMarking::MarkBitFrom(new_start))) { | |
3156 IncrementalMarking::TransferMark(this, old_start, new_start); | |
3157 } | |
3158 | 3140 |
3159 // Technically in new space this write might be omitted (except for | 3141 // Technically in new space this write might be omitted (except for |
3160 // debug mode which iterates through the heap), but to play safer | 3142 // debug mode which iterates through the heap), but to play safer |
3161 // we still do it. | 3143 // we still do it. |
3162 CreateFillerObjectAt(old_start, bytes_to_trim, ClearRecordedSlots::kYes); | 3144 CreateFillerObjectAt(object->address(), bytes_to_trim, |
| 3145 ClearRecordedSlots::kYes); |
3163 // Initialize header of the trimmed array. Since left trimming is only | 3146 // Initialize header of the trimmed array. Since left trimming is only |
3164 // performed on pages which are not concurrently swept creating a filler | 3147 // performed on pages which are not concurrently swept creating a filler |
3165 // object does not require synchronization. | 3148 // object does not require synchronization. |
3166 DCHECK(CanMoveObjectStart(object)); | 3149 DCHECK(CanMoveObjectStart(object)); |
3167 Object** former_start = HeapObject::RawField(object, 0); | 3150 Object** former_start = HeapObject::RawField(object, 0); |
3168 int new_start_index = elements_to_trim * (element_size / kPointerSize); | 3151 int new_start_index = elements_to_trim * (element_size / kPointerSize); |
3169 former_start[new_start_index] = map; | 3152 former_start[new_start_index] = map; |
3170 former_start[new_start_index + 1] = Smi::FromInt(len - elements_to_trim); | 3153 former_start[new_start_index + 1] = Smi::FromInt(len - elements_to_trim); |
3171 | |
3172 FixedArrayBase* new_object = | 3154 FixedArrayBase* new_object = |
3173 FixedArrayBase::cast(HeapObject::FromAddress(new_start)); | 3155 FixedArrayBase::cast(HeapObject::FromAddress(new_start)); |
3174 | 3156 |
3175 // Maintain consistency of live bytes during incremental marking | |
3176 AdjustLiveBytes(new_object, -bytes_to_trim, Heap::CONCURRENT_TO_SWEEPER); | |
3177 | |
3178 // Remove recorded slots for the new map and length offset. | 3157 // Remove recorded slots for the new map and length offset. |
3179 ClearRecordedSlot(new_object, HeapObject::RawField(new_object, 0)); | 3158 ClearRecordedSlot(new_object, HeapObject::RawField(new_object, 0)); |
3180 ClearRecordedSlot(new_object, HeapObject::RawField( | 3159 ClearRecordedSlot(new_object, HeapObject::RawField( |
3181 new_object, FixedArrayBase::kLengthOffset)); | 3160 new_object, FixedArrayBase::kLengthOffset)); |
3182 | 3161 |
| 3162 // Maintain consistency of live bytes during incremental marking |
| 3163 IncrementalMarking::TransferMark(this, object->address(), new_start); |
| 3164 AdjustLiveBytes(new_object, -bytes_to_trim, Heap::CONCURRENT_TO_SWEEPER); |
| 3165 |
3183 // Notify the heap profiler of change in object layout. | 3166 // Notify the heap profiler of change in object layout. |
3184 OnMoveEvent(new_object, object, new_object->Size()); | 3167 OnMoveEvent(new_object, object, new_object->Size()); |
3185 return new_object; | 3168 return new_object; |
3186 } | 3169 } |
3187 | 3170 |
3188 | 3171 |
3189 // Force instantiation of templatized method. | 3172 // Force instantiation of templatized method. |
3190 template void Heap::RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>( | 3173 template void Heap::RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>( |
3191 FixedArrayBase*, int); | 3174 FixedArrayBase*, int); |
3192 template void Heap::RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( | 3175 template void Heap::RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( |
(...skipping 994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4187 | 4170 |
4188 void Heap::RegisterReservationsForBlackAllocation(Reservation* reservations) { | 4171 void Heap::RegisterReservationsForBlackAllocation(Reservation* reservations) { |
4189 // TODO(hpayer): We do not have to iterate reservations on black objects | 4172 // TODO(hpayer): We do not have to iterate reservations on black objects |
4190 // for marking. We just have to execute the special visiting side effect | 4173 // for marking. We just have to execute the special visiting side effect |
4191 // code that adds objects to global data structures, e.g. for array buffers. | 4174 // code that adds objects to global data structures, e.g. for array buffers. |
4192 | 4175 |
4193 // Code space, map space, and large object space do not use black pages. | 4176 // Code space, map space, and large object space do not use black pages. |
4194 // Hence we have to color all objects of the reservation first black to avoid | 4177 // Hence we have to color all objects of the reservation first black to avoid |
4195 // unnecessary marking deque load. | 4178 // unnecessary marking deque load. |
4196 if (incremental_marking()->black_allocation()) { | 4179 if (incremental_marking()->black_allocation()) { |
4197 for (int i = OLD_SPACE; i < Serializer::kNumberOfSpaces; i++) { | 4180 for (int i = CODE_SPACE; i < Serializer::kNumberOfSpaces; i++) { |
4198 const Heap::Reservation& res = reservations[i]; | 4181 const Heap::Reservation& res = reservations[i]; |
4199 for (auto& chunk : res) { | 4182 for (auto& chunk : res) { |
4200 Address addr = chunk.start; | 4183 Address addr = chunk.start; |
4201 while (addr < chunk.end) { | 4184 while (addr < chunk.end) { |
4202 HeapObject* obj = HeapObject::FromAddress(addr); | 4185 HeapObject* obj = HeapObject::FromAddress(addr); |
4203 Marking::MarkBlack(ObjectMarking::MarkBitFrom(obj)); | 4186 Marking::MarkBlack(ObjectMarking::MarkBitFrom(obj)); |
| 4187 MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size()); |
4204 addr += obj->Size(); | 4188 addr += obj->Size(); |
4205 } | 4189 } |
4206 } | 4190 } |
4207 } | 4191 } |
4208 for (int i = OLD_SPACE; i < Serializer::kNumberOfSpaces; i++) { | 4192 for (int i = OLD_SPACE; i < Serializer::kNumberOfSpaces; i++) { |
4209 const Heap::Reservation& res = reservations[i]; | 4193 const Heap::Reservation& res = reservations[i]; |
4210 for (auto& chunk : res) { | 4194 for (auto& chunk : res) { |
4211 Address addr = chunk.start; | 4195 Address addr = chunk.start; |
4212 while (addr < chunk.end) { | 4196 while (addr < chunk.end) { |
4213 HeapObject* obj = HeapObject::FromAddress(addr); | 4197 HeapObject* obj = HeapObject::FromAddress(addr); |
(...skipping 2240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6454 } | 6438 } |
6455 | 6439 |
6456 | 6440 |
6457 // static | 6441 // static |
6458 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6442 int Heap::GetStaticVisitorIdForMap(Map* map) { |
6459 return StaticVisitorBase::GetVisitorId(map); | 6443 return StaticVisitorBase::GetVisitorId(map); |
6460 } | 6444 } |
6461 | 6445 |
6462 } // namespace internal | 6446 } // namespace internal |
6463 } // namespace v8 | 6447 } // namespace v8 |
OLD | NEW |