Commit 112e089c authored by hpayer@chromium.org's avatar hpayer@chromium.org

Move ClearNonLiveReferences and friends into the gc.

BUG=
R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/440063002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22864 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 70e7a119
...@@ -2580,11 +2580,121 @@ void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map, ...@@ -2580,11 +2580,121 @@ void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map,
bool current_is_alive = map_mark.Get(); bool current_is_alive = map_mark.Get();
bool parent_is_alive = Marking::MarkBitFrom(parent).Get(); bool parent_is_alive = Marking::MarkBitFrom(parent).Get();
if (!current_is_alive && parent_is_alive) { if (!current_is_alive && parent_is_alive) {
parent->ClearNonLiveTransitions(heap()); ClearMapTransitions(parent);
} }
} }
// Clear a possible back pointer in case the transition leads to a dead map.
// Return true in case a back pointer has been cleared and false otherwise.
bool MarkCompactCollector::ClearMapBackPointer(Map* target) {
if (Marking::MarkBitFrom(target).Get()) return false;
target->SetBackPointer(heap_->undefined_value(), SKIP_WRITE_BARRIER);
return true;
}
void MarkCompactCollector::ClearMapTransitions(Map* map) {
// If there are no transitions to be cleared, return.
// TODO(verwaest) Should be an assert, otherwise back pointers are not
// properly cleared.
if (!map->HasTransitionArray()) return;
TransitionArray* t = map->transitions();
int transition_index = 0;
DescriptorArray* descriptors = map->instance_descriptors();
bool descriptors_owner_died = false;
// Compact all live descriptors to the left.
for (int i = 0; i < t->number_of_transitions(); ++i) {
Map* target = t->GetTarget(i);
if (ClearMapBackPointer(target)) {
if (target->instance_descriptors() == descriptors) {
descriptors_owner_died = true;
}
} else {
if (i != transition_index) {
Name* key = t->GetKey(i);
t->SetKey(transition_index, key);
Object** key_slot = t->GetKeySlot(transition_index);
RecordSlot(key_slot, key_slot, key);
// Target slots do not need to be recorded since maps are not compacted.
t->SetTarget(transition_index, t->GetTarget(i));
}
transition_index++;
}
}
// If there are no transitions to be cleared, return.
// TODO(verwaest) Should be an assert, otherwise back pointers are not
// properly cleared.
if (transition_index == t->number_of_transitions()) return;
int number_of_own_descriptors = map->NumberOfOwnDescriptors();
if (descriptors_owner_died) {
if (number_of_own_descriptors > 0) {
TrimDescriptorArray(map, descriptors, number_of_own_descriptors);
DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors);
map->set_owns_descriptors(true);
} else {
DCHECK(descriptors == heap_->empty_descriptor_array());
}
}
// Note that we never eliminate a transition array, though we might right-trim
// such that number_of_transitions() == 0. If this assumption changes,
// TransitionArray::CopyInsert() will need to deal with the case that a
// transition array disappeared during GC.
int trim = t->number_of_transitions() - transition_index;
if (trim > 0) {
heap_->RightTrimFixedArray<Heap::FROM_GC>(
t, t->IsSimpleTransition() ? trim
: trim * TransitionArray::kTransitionSize);
}
DCHECK(map->HasTransitionArray());
}
void MarkCompactCollector::TrimDescriptorArray(Map* map,
DescriptorArray* descriptors,
int number_of_own_descriptors) {
int number_of_descriptors = descriptors->number_of_descriptors_storage();
int to_trim = number_of_descriptors - number_of_own_descriptors;
if (to_trim == 0) return;
heap_->RightTrimFixedArray<Heap::FROM_GC>(
descriptors, to_trim * DescriptorArray::kDescriptorSize);
descriptors->SetNumberOfDescriptors(number_of_own_descriptors);
if (descriptors->HasEnumCache()) TrimEnumCache(map, descriptors);
descriptors->Sort();
}
void MarkCompactCollector::TrimEnumCache(Map* map,
DescriptorArray* descriptors) {
int live_enum = map->EnumLength();
if (live_enum == kInvalidEnumCacheSentinel) {
live_enum = map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM);
}
if (live_enum == 0) return descriptors->ClearEnumCache();
FixedArray* enum_cache = descriptors->GetEnumCache();
int to_trim = enum_cache->length() - live_enum;
if (to_trim <= 0) return;
heap_->RightTrimFixedArray<Heap::FROM_GC>(descriptors->GetEnumCache(),
to_trim);
if (!descriptors->HasEnumIndicesCache()) return;
FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache();
heap_->RightTrimFixedArray<Heap::FROM_GC>(enum_indices_cache, to_trim);
}
void MarkCompactCollector::ClearDependentICList(Object* head) { void MarkCompactCollector::ClearDependentICList(Object* head) {
Object* current = head; Object* current = head;
Object* undefined = heap()->undefined_value(); Object* undefined = heap()->undefined_value();
......
...@@ -811,6 +811,11 @@ class MarkCompactCollector { ...@@ -811,6 +811,11 @@ class MarkCompactCollector {
void ClearNonLiveReferences(); void ClearNonLiveReferences();
void ClearNonLivePrototypeTransitions(Map* map); void ClearNonLivePrototypeTransitions(Map* map);
void ClearNonLiveMapTransitions(Map* map, MarkBit map_mark); void ClearNonLiveMapTransitions(Map* map, MarkBit map_mark);
void ClearMapTransitions(Map* map);
bool ClearMapBackPointer(Map* map);
void TrimDescriptorArray(Map* map, DescriptorArray* descriptors,
int number_of_own_descriptors);
void TrimEnumCache(Map* map, DescriptorArray* descriptors);
void ClearDependentCode(DependentCode* dependent_code); void ClearDependentCode(DependentCode* dependent_code);
void ClearDependentICList(Object* head); void ClearDependentICList(Object* head);
......
...@@ -9533,119 +9533,6 @@ void String::PrintOn(FILE* file) { ...@@ -9533,119 +9533,6 @@ void String::PrintOn(FILE* file) {
} }
static void TrimEnumCache(Heap* heap, Map* map, DescriptorArray* descriptors) {
int live_enum = map->EnumLength();
if (live_enum == kInvalidEnumCacheSentinel) {
live_enum = map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM);
}
if (live_enum == 0) return descriptors->ClearEnumCache();
FixedArray* enum_cache = descriptors->GetEnumCache();
int to_trim = enum_cache->length() - live_enum;
if (to_trim <= 0) return;
heap->RightTrimFixedArray<Heap::FROM_GC>(
descriptors->GetEnumCache(), to_trim);
if (!descriptors->HasEnumIndicesCache()) return;
FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache();
heap->RightTrimFixedArray<Heap::FROM_GC>(enum_indices_cache, to_trim);
}
static void TrimDescriptorArray(Heap* heap,
Map* map,
DescriptorArray* descriptors,
int number_of_own_descriptors) {
int number_of_descriptors = descriptors->number_of_descriptors_storage();
int to_trim = number_of_descriptors - number_of_own_descriptors;
if (to_trim == 0) return;
heap->RightTrimFixedArray<Heap::FROM_GC>(
descriptors, to_trim * DescriptorArray::kDescriptorSize);
descriptors->SetNumberOfDescriptors(number_of_own_descriptors);
if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors);
descriptors->Sort();
}
// Clear a possible back pointer in case the transition leads to a dead map.
// Return true in case a back pointer has been cleared and false otherwise.
static bool ClearBackPointer(Heap* heap, Map* target) {
if (Marking::MarkBitFrom(target).Get()) return false;
target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
return true;
}
// TODO(mstarzinger): This method should be moved into MarkCompactCollector,
// because it cannot be called from outside the GC and we already have methods
// depending on the transitions layout in the GC anyways.
void Map::ClearNonLiveTransitions(Heap* heap) {
// If there are no transitions to be cleared, return.
// TODO(verwaest) Should be an assert, otherwise back pointers are not
// properly cleared.
if (!HasTransitionArray()) return;
TransitionArray* t = transitions();
MarkCompactCollector* collector = heap->mark_compact_collector();
int transition_index = 0;
DescriptorArray* descriptors = instance_descriptors();
bool descriptors_owner_died = false;
// Compact all live descriptors to the left.
for (int i = 0; i < t->number_of_transitions(); ++i) {
Map* target = t->GetTarget(i);
if (ClearBackPointer(heap, target)) {
if (target->instance_descriptors() == descriptors) {
descriptors_owner_died = true;
}
} else {
if (i != transition_index) {
Name* key = t->GetKey(i);
t->SetKey(transition_index, key);
Object** key_slot = t->GetKeySlot(transition_index);
collector->RecordSlot(key_slot, key_slot, key);
// Target slots do not need to be recorded since maps are not compacted.
t->SetTarget(transition_index, t->GetTarget(i));
}
transition_index++;
}
}
// If there are no transitions to be cleared, return.
// TODO(verwaest) Should be an assert, otherwise back pointers are not
// properly cleared.
if (transition_index == t->number_of_transitions()) return;
int number_of_own_descriptors = NumberOfOwnDescriptors();
if (descriptors_owner_died) {
if (number_of_own_descriptors > 0) {
TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors);
DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors);
set_owns_descriptors(true);
} else {
DCHECK(descriptors == GetHeap()->empty_descriptor_array());
}
}
// Note that we never eliminate a transition array, though we might right-trim
// such that number_of_transitions() == 0. If this assumption changes,
// TransitionArray::CopyInsert() will need to deal with the case that a
// transition array disappeared during GC.
int trim = t->number_of_transitions() - transition_index;
if (trim > 0) {
heap->RightTrimFixedArray<Heap::FROM_GC>(t, t->IsSimpleTransition()
? trim : trim * TransitionArray::kTransitionSize);
}
DCHECK(HasTransitionArray());
}
int Map::Hash() { int Map::Hash() {
// For performance reasons we only hash the 3 most variable fields of a map: // For performance reasons we only hash the 3 most variable fields of a map:
// constructor, prototype and bit_field2. // constructor, prototype and bit_field2.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment