| 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/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
| (...skipping 3047 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3058 reinterpret_cast<Map*>(root(kFreeSpaceMapRootIndex))); | 3058 reinterpret_cast<Map*>(root(kFreeSpaceMapRootIndex))); |
| 3059 FreeSpace::cast(filler)->nobarrier_set_size(size); | 3059 FreeSpace::cast(filler)->nobarrier_set_size(size); |
| 3060 } | 3060 } |
| 3061 // At this point, we may be deserializing the heap from a snapshot, and | 3061 // At this point, we may be deserializing the heap from a snapshot, and |
| 3062 // none of the maps have been created yet and are NULL. | 3062 // none of the maps have been created yet and are NULL. |
| 3063 DCHECK((filler->map() == NULL && !deserialization_complete_) || | 3063 DCHECK((filler->map() == NULL && !deserialization_complete_) || |
| 3064 filler->map()->IsMap()); | 3064 filler->map()->IsMap()); |
| 3065 } | 3065 } |
| 3066 | 3066 |
| 3067 | 3067 |
| 3068 bool Heap::CanMoveObjectStart(HeapObject* object) { | |
| 3069 if (!FLAG_move_object_start) return false; | |
| 3070 | |
| 3071 Address address = object->address(); | |
| 3072 | |
| 3073 if (lo_space()->Contains(object)) return false; | |
| 3074 | |
| 3075 Page* page = Page::FromAddress(address); | |
| 3076 // We can move the object start if: | |
| 3077 // (1) the object is not in old space, | |
| 3078 // (2) the page of the object was already swept, | |
| 3079 // (3) the page was already concurrently swept. This case is an optimization | |
| 3080 // for concurrent sweeping. The WasSwept predicate for concurrently swept | |
| 3081 // pages is set after sweeping all pages. | |
| 3082 return !InOldSpace(address) || page->WasSwept() || page->SweepingCompleted(); | |
| 3083 } | |
| 3084 | |
| 3085 | |
| 3086 void Heap::AdjustLiveBytes(HeapObject* object, int by, InvocationMode mode) { | 3068 void Heap::AdjustLiveBytes(HeapObject* object, int by, InvocationMode mode) { |
| 3087 if (incremental_marking()->IsMarking() && | 3069 if (incremental_marking()->IsMarking() && |
| 3088 Marking::IsBlack(Marking::MarkBitFrom(object->address()))) { | 3070 Marking::IsBlack(Marking::MarkBitFrom(object->address()))) { |
| 3089 if (mode == SEQUENTIAL_TO_SWEEPER) { | 3071 if (mode == SEQUENTIAL_TO_SWEEPER) { |
| 3090 MemoryChunk::IncrementLiveBytesFromGC(object, by); | 3072 MemoryChunk::IncrementLiveBytesFromGC(object, by); |
| 3091 } else { | 3073 } else { |
| 3092 MemoryChunk::IncrementLiveBytesFromMutator(object, by); | 3074 MemoryChunk::IncrementLiveBytesFromMutator(object, by); |
| 3093 } | 3075 } |
| 3094 } | 3076 } |
| 3095 } | 3077 } |
| 3096 | 3078 |
| 3097 | 3079 |
| 3098 FixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object, | |
| 3099 int elements_to_trim) { | |
| 3100 DCHECK(!object->IsFixedTypedArrayBase()); | |
| 3101 const int element_size = object->IsFixedArray() ? kPointerSize : kDoubleSize; | |
| 3102 const int bytes_to_trim = elements_to_trim * element_size; | |
| 3103 Map* map = object->map(); | |
| 3104 | |
| 3105 // For now this trick is only applied to objects in new and paged space. | |
| 3106 // In large object space the object's start must coincide with chunk | |
| 3107 // and thus the trick is just not applicable. | |
| 3108 DCHECK(!lo_space()->Contains(object)); | |
| 3109 DCHECK(object->map() != fixed_cow_array_map()); | |
| 3110 | |
| 3111 STATIC_ASSERT(FixedArrayBase::kMapOffset == 0); | |
| 3112 STATIC_ASSERT(FixedArrayBase::kLengthOffset == kPointerSize); | |
| 3113 STATIC_ASSERT(FixedArrayBase::kHeaderSize == 2 * kPointerSize); | |
| 3114 | |
| 3115 const int len = object->length(); | |
| 3116 DCHECK(elements_to_trim <= len); | |
| 3117 | |
| 3118 // Calculate location of new array start. | |
| 3119 Address new_start = object->address() + bytes_to_trim; | |
| 3120 | |
| 3121 // Technically in new space this write might be omitted (except for | |
| 3122 // debug mode which iterates through the heap), but to play safer | |
| 3123 // we still do it. | |
| 3124 CreateFillerObjectAt(object->address(), bytes_to_trim); | |
| 3125 | |
| 3126 // Initialize header of the trimmed array. Since left trimming is only | |
| 3127 // performed on pages which are not concurrently swept creating a filler | |
| 3128 // object does not require synchronization. | |
| 3129 DCHECK(CanMoveObjectStart(object)); | |
| 3130 Object** former_start = HeapObject::RawField(object, 0); | |
| 3131 int new_start_index = elements_to_trim * (element_size / kPointerSize); | |
| 3132 former_start[new_start_index] = map; | |
| 3133 former_start[new_start_index + 1] = Smi::FromInt(len - elements_to_trim); | |
| 3134 FixedArrayBase* new_object = | |
| 3135 FixedArrayBase::cast(HeapObject::FromAddress(new_start)); | |
| 3136 | |
| 3137 // Maintain consistency of live bytes during incremental marking | |
| 3138 Marking::TransferMark(this, object->address(), new_start); | |
| 3139 AdjustLiveBytes(new_object, -bytes_to_trim, Heap::CONCURRENT_TO_SWEEPER); | |
| 3140 | |
| 3141 // Notify the heap profiler of change in object layout. | |
| 3142 OnMoveEvent(new_object, object, new_object->Size()); | |
| 3143 return new_object; | |
| 3144 } | |
| 3145 | |
| 3146 | |
| 3147 // Force instantiation of templatized method. | 3080 // Force instantiation of templatized method. |
| 3148 template void Heap::RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>( | 3081 template void Heap::RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>( |
| 3149 FixedArrayBase*, int); | 3082 FixedArrayBase*, int); |
| 3150 template void Heap::RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( | 3083 template void Heap::RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( |
| 3151 FixedArrayBase*, int); | 3084 FixedArrayBase*, int); |
| 3152 | 3085 |
| 3153 | 3086 |
| 3154 template<Heap::InvocationMode mode> | 3087 template<Heap::InvocationMode mode> |
| 3155 void Heap::RightTrimFixedArray(FixedArrayBase* object, int elements_to_trim) { | 3088 void Heap::RightTrimFixedArray(FixedArrayBase* object, int elements_to_trim) { |
| 3156 const int len = object->length(); | 3089 const int len = object->length(); |
| (...skipping 3004 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6161 } | 6094 } |
| 6162 | 6095 |
| 6163 | 6096 |
| 6164 // static | 6097 // static |
| 6165 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6098 int Heap::GetStaticVisitorIdForMap(Map* map) { |
| 6166 return StaticVisitorBase::GetVisitorId(map); | 6099 return StaticVisitorBase::GetVisitorId(map); |
| 6167 } | 6100 } |
| 6168 | 6101 |
| 6169 } // namespace internal | 6102 } // namespace internal |
| 6170 } // namespace v8 | 6103 } // namespace v8 |
| OLD | NEW |