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