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 1151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1162 for (int i = 0; i < num_maps; i++) { | 1162 for (int i = 0; i < num_maps; i++) { |
1163 // The deserializer will update the skip list. | 1163 // The deserializer will update the skip list. |
1164 AllocationResult allocation = map_space()->AllocateRawUnaligned( | 1164 AllocationResult allocation = map_space()->AllocateRawUnaligned( |
1165 Map::kSize, PagedSpace::IGNORE_SKIP_LIST); | 1165 Map::kSize, PagedSpace::IGNORE_SKIP_LIST); |
1166 HeapObject* free_space = nullptr; | 1166 HeapObject* free_space = nullptr; |
1167 if (allocation.To(&free_space)) { | 1167 if (allocation.To(&free_space)) { |
1168 // Mark with a free list node, in case we have a GC before | 1168 // Mark with a free list node, in case we have a GC before |
1169 // deserializing. | 1169 // deserializing. |
1170 Address free_space_address = free_space->address(); | 1170 Address free_space_address = free_space->address(); |
1171 CreateFillerObjectAt(free_space_address, Map::kSize, | 1171 CreateFillerObjectAt(free_space_address, Map::kSize, |
1172 ClearRecordedSlots::kNo, ClearBlackArea::kNo); | 1172 ClearRecordedSlots::kNo); |
1173 maps->Add(free_space_address); | 1173 maps->Add(free_space_address); |
1174 } else { | 1174 } else { |
1175 perform_gc = true; | 1175 perform_gc = true; |
1176 break; | 1176 break; |
1177 } | 1177 } |
1178 } | 1178 } |
1179 } else if (space == LO_SPACE) { | 1179 } else if (space == LO_SPACE) { |
1180 // Just check that we can allocate during deserialization. | 1180 // Just check that we can allocate during deserialization. |
1181 DCHECK_EQ(1, reservation->length()); | 1181 DCHECK_EQ(1, reservation->length()); |
1182 perform_gc = !CanExpandOldGeneration(reservation->at(0).size); | 1182 perform_gc = !CanExpandOldGeneration(reservation->at(0).size); |
(...skipping 10 matching lines...) Expand all Loading... |
1193 // The deserializer will update the skip list. | 1193 // The deserializer will update the skip list. |
1194 allocation = paged_space(space)->AllocateRawUnaligned( | 1194 allocation = paged_space(space)->AllocateRawUnaligned( |
1195 size, PagedSpace::IGNORE_SKIP_LIST); | 1195 size, PagedSpace::IGNORE_SKIP_LIST); |
1196 } | 1196 } |
1197 HeapObject* free_space = nullptr; | 1197 HeapObject* free_space = nullptr; |
1198 if (allocation.To(&free_space)) { | 1198 if (allocation.To(&free_space)) { |
1199 // Mark with a free list node, in case we have a GC before | 1199 // Mark with a free list node, in case we have a GC before |
1200 // deserializing. | 1200 // deserializing. |
1201 Address free_space_address = free_space->address(); | 1201 Address free_space_address = free_space->address(); |
1202 CreateFillerObjectAt(free_space_address, size, | 1202 CreateFillerObjectAt(free_space_address, size, |
1203 ClearRecordedSlots::kNo, ClearBlackArea::kNo); | 1203 ClearRecordedSlots::kNo); |
1204 DCHECK(space < SerializerDeserializer::kNumberOfPreallocatedSpaces); | 1204 DCHECK(space < SerializerDeserializer::kNumberOfPreallocatedSpaces); |
1205 chunk.start = free_space_address; | 1205 chunk.start = free_space_address; |
1206 chunk.end = free_space_address + size; | 1206 chunk.end = free_space_address + size; |
1207 } else { | 1207 } else { |
1208 perform_gc = true; | 1208 perform_gc = true; |
1209 break; | 1209 break; |
1210 } | 1210 } |
1211 } | 1211 } |
1212 } | 1212 } |
1213 if (perform_gc) { | 1213 if (perform_gc) { |
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2093 HeapObject* obj = nullptr; | 2093 HeapObject* obj = nullptr; |
2094 { | 2094 { |
2095 AllocationAlignment align = double_align ? kDoubleAligned : kWordAligned; | 2095 AllocationAlignment align = double_align ? kDoubleAligned : kWordAligned; |
2096 AllocationResult allocation = AllocateRaw(size, space, align); | 2096 AllocationResult allocation = AllocateRaw(size, space, align); |
2097 if (!allocation.To(&obj)) return allocation; | 2097 if (!allocation.To(&obj)) return allocation; |
2098 } | 2098 } |
2099 #ifdef DEBUG | 2099 #ifdef DEBUG |
2100 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); | 2100 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); |
2101 DCHECK(chunk->owner()->identity() == space); | 2101 DCHECK(chunk->owner()->identity() == space); |
2102 #endif | 2102 #endif |
2103 CreateFillerObjectAt(obj->address(), size, ClearRecordedSlots::kNo, | 2103 CreateFillerObjectAt(obj->address(), size, ClearRecordedSlots::kNo); |
2104 ClearBlackArea::kNo); | |
2105 return obj; | 2104 return obj; |
2106 } | 2105 } |
2107 | 2106 |
2108 | 2107 |
2109 const Heap::StringTypeTable Heap::string_type_table[] = { | 2108 const Heap::StringTypeTable Heap::string_type_table[] = { |
2110 #define STRING_TYPE_ELEMENT(type, size, name, camel_name) \ | 2109 #define STRING_TYPE_ELEMENT(type, size, name, camel_name) \ |
2111 { type, size, k##camel_name##MapRootIndex } \ | 2110 { type, size, k##camel_name##MapRootIndex } \ |
2112 , | 2111 , |
2113 STRING_TYPE_LIST(STRING_TYPE_ELEMENT) | 2112 STRING_TYPE_LIST(STRING_TYPE_ELEMENT) |
2114 #undef STRING_TYPE_ELEMENT | 2113 #undef STRING_TYPE_ELEMENT |
(...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3056 instance->set_osr_loop_nesting_level(0); | 3055 instance->set_osr_loop_nesting_level(0); |
3057 instance->set_bytecode_age(BytecodeArray::kNoAgeBytecodeAge); | 3056 instance->set_bytecode_age(BytecodeArray::kNoAgeBytecodeAge); |
3058 instance->set_constant_pool(constant_pool); | 3057 instance->set_constant_pool(constant_pool); |
3059 instance->set_handler_table(empty_fixed_array()); | 3058 instance->set_handler_table(empty_fixed_array()); |
3060 instance->set_source_position_table(empty_byte_array()); | 3059 instance->set_source_position_table(empty_byte_array()); |
3061 CopyBytes(instance->GetFirstBytecodeAddress(), raw_bytecodes, length); | 3060 CopyBytes(instance->GetFirstBytecodeAddress(), raw_bytecodes, length); |
3062 | 3061 |
3063 return result; | 3062 return result; |
3064 } | 3063 } |
3065 | 3064 |
3066 void Heap::CreateFillerObjectAt(Address addr, int size, ClearRecordedSlots mode, | 3065 void Heap::CreateFillerObjectAt(Address addr, int size, |
3067 ClearBlackArea black_area_mode) { | 3066 ClearRecordedSlots mode) { |
3068 if (size == 0) return; | 3067 if (size == 0) return; |
3069 HeapObject* filler = HeapObject::FromAddress(addr); | 3068 HeapObject* filler = HeapObject::FromAddress(addr); |
3070 if (size == kPointerSize) { | 3069 if (size == kPointerSize) { |
3071 filler->set_map_no_write_barrier( | 3070 filler->set_map_no_write_barrier( |
3072 reinterpret_cast<Map*>(root(kOnePointerFillerMapRootIndex))); | 3071 reinterpret_cast<Map*>(root(kOnePointerFillerMapRootIndex))); |
3073 } else if (size == 2 * kPointerSize) { | 3072 } else if (size == 2 * kPointerSize) { |
3074 filler->set_map_no_write_barrier( | 3073 filler->set_map_no_write_barrier( |
3075 reinterpret_cast<Map*>(root(kTwoPointerFillerMapRootIndex))); | 3074 reinterpret_cast<Map*>(root(kTwoPointerFillerMapRootIndex))); |
3076 } else { | 3075 } else { |
3077 DCHECK_GT(size, 2 * kPointerSize); | 3076 DCHECK_GT(size, 2 * kPointerSize); |
3078 filler->set_map_no_write_barrier( | 3077 filler->set_map_no_write_barrier( |
3079 reinterpret_cast<Map*>(root(kFreeSpaceMapRootIndex))); | 3078 reinterpret_cast<Map*>(root(kFreeSpaceMapRootIndex))); |
3080 FreeSpace::cast(filler)->nobarrier_set_size(size); | 3079 FreeSpace::cast(filler)->nobarrier_set_size(size); |
3081 } | 3080 } |
3082 if (mode == ClearRecordedSlots::kYes) { | 3081 if (mode == ClearRecordedSlots::kYes) { |
3083 ClearRecordedSlotRange(addr, addr + size); | 3082 ClearRecordedSlotRange(addr, addr + size); |
3084 } | 3083 } |
3085 | 3084 |
3086 // If the location where the filler is created is within a black area we have | |
3087 // to clear the mark bits of the filler space. | |
3088 if (black_area_mode == ClearBlackArea::kYes && | |
3089 incremental_marking()->black_allocation() && | |
3090 Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(addr))) { | |
3091 Page* page = Page::FromAddress(addr); | |
3092 page->markbits()->ClearRange(page->AddressToMarkbitIndex(addr), | |
3093 page->AddressToMarkbitIndex(addr + size)); | |
3094 } | |
3095 | |
3096 // At this point, we may be deserializing the heap from a snapshot, and | 3085 // At this point, we may be deserializing the heap from a snapshot, and |
3097 // none of the maps have been created yet and are NULL. | 3086 // none of the maps have been created yet and are NULL. |
3098 DCHECK((filler->map() == NULL && !deserialization_complete_) || | 3087 DCHECK((filler->map() == NULL && !deserialization_complete_) || |
3099 filler->map()->IsMap()); | 3088 filler->map()->IsMap()); |
3100 } | 3089 } |
3101 | 3090 |
3102 | 3091 |
3103 bool Heap::CanMoveObjectStart(HeapObject* object) { | 3092 bool Heap::CanMoveObjectStart(HeapObject* object) { |
3104 if (!FLAG_move_object_start) return false; | 3093 if (!FLAG_move_object_start) return false; |
3105 | 3094 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3160 // a black area. | 3149 // a black area. |
3161 if (!incremental_marking()->black_allocation() || | 3150 if (!incremental_marking()->black_allocation() || |
3162 !Marking::IsBlack(ObjectMarking::MarkBitFrom(new_start))) { | 3151 !Marking::IsBlack(ObjectMarking::MarkBitFrom(new_start))) { |
3163 IncrementalMarking::TransferMark(this, old_start, new_start); | 3152 IncrementalMarking::TransferMark(this, old_start, new_start); |
3164 } | 3153 } |
3165 | 3154 |
3166 // Technically in new space this write might be omitted (except for | 3155 // Technically in new space this write might be omitted (except for |
3167 // debug mode which iterates through the heap), but to play safer | 3156 // debug mode which iterates through the heap), but to play safer |
3168 // we still do it. | 3157 // we still do it. |
3169 CreateFillerObjectAt(old_start, bytes_to_trim, ClearRecordedSlots::kYes); | 3158 CreateFillerObjectAt(old_start, bytes_to_trim, ClearRecordedSlots::kYes); |
| 3159 |
| 3160 // Clear the mark bits of the black area that belongs now to the filler. |
| 3161 // This is an optimization. The sweeper will release black fillers anyway. |
| 3162 if (incremental_marking()->black_allocation() && |
| 3163 Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(old_start))) { |
| 3164 Page* page = Page::FromAddress(old_start); |
| 3165 page->markbits()->ClearRange( |
| 3166 page->AddressToMarkbitIndex(old_start), |
| 3167 page->AddressToMarkbitIndex(old_start + bytes_to_trim)); |
| 3168 } |
| 3169 |
3170 // Initialize header of the trimmed array. Since left trimming is only | 3170 // Initialize header of the trimmed array. Since left trimming is only |
3171 // performed on pages which are not concurrently swept creating a filler | 3171 // performed on pages which are not concurrently swept creating a filler |
3172 // object does not require synchronization. | 3172 // object does not require synchronization. |
3173 DCHECK(CanMoveObjectStart(object)); | 3173 DCHECK(CanMoveObjectStart(object)); |
3174 Object** former_start = HeapObject::RawField(object, 0); | 3174 Object** former_start = HeapObject::RawField(object, 0); |
3175 int new_start_index = elements_to_trim * (element_size / kPointerSize); | 3175 int new_start_index = elements_to_trim * (element_size / kPointerSize); |
3176 former_start[new_start_index] = map; | 3176 former_start[new_start_index] = map; |
3177 former_start[new_start_index + 1] = Smi::FromInt(len - elements_to_trim); | 3177 former_start[new_start_index + 1] = Smi::FromInt(len - elements_to_trim); |
3178 | 3178 |
3179 FixedArrayBase* new_object = | 3179 FixedArrayBase* new_object = |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3231 // Technically in new space this write might be omitted (except for | 3231 // Technically in new space this write might be omitted (except for |
3232 // debug mode which iterates through the heap), but to play safer | 3232 // debug mode which iterates through the heap), but to play safer |
3233 // we still do it. | 3233 // we still do it. |
3234 // We do not create a filler for objects in large object space. | 3234 // We do not create a filler for objects in large object space. |
3235 // TODO(hpayer): We should shrink the large object page if the size | 3235 // TODO(hpayer): We should shrink the large object page if the size |
3236 // of the object changed significantly. | 3236 // of the object changed significantly. |
3237 if (!lo_space()->Contains(object)) { | 3237 if (!lo_space()->Contains(object)) { |
3238 CreateFillerObjectAt(new_end, bytes_to_trim, ClearRecordedSlots::kYes); | 3238 CreateFillerObjectAt(new_end, bytes_to_trim, ClearRecordedSlots::kYes); |
3239 } | 3239 } |
3240 | 3240 |
| 3241 // Clear the mark bits of the black area that belongs now to the filler. |
| 3242 // This is an optimization. The sweeper will release black fillers anyway. |
| 3243 if (incremental_marking()->black_allocation() && |
| 3244 Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(new_end))) { |
| 3245 Page* page = Page::FromAddress(new_end); |
| 3246 page->markbits()->ClearRange( |
| 3247 page->AddressToMarkbitIndex(new_end), |
| 3248 page->AddressToMarkbitIndex(new_end + bytes_to_trim)); |
| 3249 } |
| 3250 |
3241 // Initialize header of the trimmed array. We are storing the new length | 3251 // Initialize header of the trimmed array. We are storing the new length |
3242 // using release store after creating a filler for the left-over space to | 3252 // using release store after creating a filler for the left-over space to |
3243 // avoid races with the sweeper thread. | 3253 // avoid races with the sweeper thread. |
3244 object->synchronized_set_length(len - elements_to_trim); | 3254 object->synchronized_set_length(len - elements_to_trim); |
3245 | 3255 |
3246 // Maintain consistency of live bytes during incremental marking | 3256 // Maintain consistency of live bytes during incremental marking |
3247 AdjustLiveBytes(object, -bytes_to_trim); | 3257 AdjustLiveBytes(object, -bytes_to_trim); |
3248 | 3258 |
3249 // Notify the heap profiler of change in object layout. The array may not be | 3259 // Notify the heap profiler of change in object layout. The array may not be |
3250 // moved during GC, and size has to be adjusted nevertheless. | 3260 // moved during GC, and size has to be adjusted nevertheless. |
(...skipping 3239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6490 } | 6500 } |
6491 | 6501 |
6492 | 6502 |
6493 // static | 6503 // static |
6494 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6504 int Heap::GetStaticVisitorIdForMap(Map* map) { |
6495 return StaticVisitorBase::GetVisitorId(map); | 6505 return StaticVisitorBase::GetVisitorId(map); |
6496 } | 6506 } |
6497 | 6507 |
6498 } // namespace internal | 6508 } // namespace internal |
6499 } // namespace v8 | 6509 } // namespace v8 |
OLD | NEW |