Replace ad-hoc weakness in prototype transitions with WeakCell.
BUG= Review URL: https://codereview.chromium.org/1163073002 Cr-Commit-Position: refs/heads/master@{#28830}
This commit is contained in:
parent
9c41204048
commit
bfb81fbe0d
@ -2404,11 +2404,10 @@ void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) {
|
||||
const int header = TransitionArray::kProtoTransitionHeaderSize;
|
||||
int new_number_of_transitions = 0;
|
||||
for (int i = 0; i < number_of_transitions; i++) {
|
||||
Object* cached_map = prototype_transitions->get(header + i);
|
||||
if (IsMarked(cached_map)) {
|
||||
Object* cell = prototype_transitions->get(header + i);
|
||||
if (!WeakCell::cast(cell)->cleared()) {
|
||||
if (new_number_of_transitions != i) {
|
||||
prototype_transitions->set(header + new_number_of_transitions,
|
||||
cached_map, SKIP_WRITE_BARRIER);
|
||||
prototype_transitions->set(header + new_number_of_transitions, cell);
|
||||
}
|
||||
new_number_of_transitions++;
|
||||
}
|
||||
|
@ -571,13 +571,8 @@ void StaticMarkingVisitor<StaticVisitor>::MarkTransitionArray(
|
||||
if (!StaticVisitor::MarkObjectWithoutPush(heap, transitions)) return;
|
||||
|
||||
if (transitions->HasPrototypeTransitions()) {
|
||||
// Mark prototype transitions array but do not push it onto marking
|
||||
// stack, this will make references from it weak. We will clean dead
|
||||
// prototype transitions in ClearNonLiveReferences.
|
||||
Object** slot = transitions->GetPrototypeTransitionsSlot();
|
||||
HeapObject* obj = HeapObject::cast(*slot);
|
||||
heap->mark_compact_collector()->RecordSlot(slot, slot, obj);
|
||||
StaticVisitor::MarkObjectWithoutPush(heap, obj);
|
||||
StaticVisitor::VisitPointer(heap,
|
||||
transitions->GetPrototypeTransitionsSlot());
|
||||
}
|
||||
|
||||
int num_transitions = TransitionArray::NumberOfTransitions(transitions);
|
||||
|
@ -233,17 +233,19 @@ bool TransitionArray::CanHaveMoreTransitions(Handle<Map> map) {
|
||||
|
||||
|
||||
// static
|
||||
Handle<Map> TransitionArray::PutPrototypeTransition(Handle<Map> map,
|
||||
Handle<Object> prototype,
|
||||
Handle<Map> target_map) {
|
||||
void TransitionArray::PutPrototypeTransition(Handle<Map> map,
|
||||
Handle<Object> prototype,
|
||||
Handle<Map> target_map) {
|
||||
DCHECK(HeapObject::cast(*prototype)->map()->IsMap());
|
||||
// Don't cache prototype transition if this map is either shared, or a map of
|
||||
// a prototype.
|
||||
if (map->is_prototype_map()) return map;
|
||||
if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map;
|
||||
if (map->is_prototype_map()) return;
|
||||
if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return;
|
||||
|
||||
const int header = kProtoTransitionHeaderSize;
|
||||
|
||||
Handle<WeakCell> target_cell = Map::WeakCellForMap(target_map);
|
||||
|
||||
Handle<FixedArray> cache(GetPrototypeTransitions(*map));
|
||||
int capacity = cache->length() - header;
|
||||
int transitions = NumberOfPrototypeTransitions(*cache) + 1;
|
||||
@ -251,7 +253,7 @@ Handle<Map> TransitionArray::PutPrototypeTransition(Handle<Map> map,
|
||||
if (transitions > capacity) {
|
||||
// Grow array by factor 2 up to MaxCachedPrototypeTransitions.
|
||||
int new_capacity = Min(kMaxCachedPrototypeTransitions, transitions * 2);
|
||||
if (new_capacity == capacity) return map;
|
||||
if (new_capacity == capacity) return;
|
||||
|
||||
cache = FixedArray::CopySize(cache, header + new_capacity);
|
||||
if (capacity < 0) {
|
||||
@ -267,10 +269,8 @@ Handle<Map> TransitionArray::PutPrototypeTransition(Handle<Map> map,
|
||||
int last = NumberOfPrototypeTransitions(*cache);
|
||||
int entry = header + last;
|
||||
|
||||
cache->set(entry, *target_map);
|
||||
cache->set(entry, *target_cell);
|
||||
SetNumberOfPrototypeTransitions(*cache, last + 1);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
@ -281,8 +281,12 @@ Handle<Map> TransitionArray::GetPrototypeTransition(Handle<Map> map,
|
||||
FixedArray* cache = GetPrototypeTransitions(*map);
|
||||
int number_of_transitions = NumberOfPrototypeTransitions(cache);
|
||||
for (int i = 0; i < number_of_transitions; i++) {
|
||||
Map* target = Map::cast(cache->get(kProtoTransitionHeaderSize + i));
|
||||
if (target->prototype() == *prototype) return handle(target);
|
||||
WeakCell* target_cell =
|
||||
WeakCell::cast(cache->get(kProtoTransitionHeaderSize + i));
|
||||
if (!target_cell->cleared() &&
|
||||
Map::cast(target_cell->value())->prototype() == *prototype) {
|
||||
return handle(Map::cast(target_cell->value()));
|
||||
}
|
||||
}
|
||||
return Handle<Map>();
|
||||
}
|
||||
@ -436,8 +440,9 @@ void TransitionArray::TraverseTransitionTreeInternal(Map* map,
|
||||
FixedArray* proto_trans = transitions->GetPrototypeTransitions();
|
||||
for (int i = 0; i < NumberOfPrototypeTransitions(proto_trans); ++i) {
|
||||
int index = TransitionArray::kProtoTransitionHeaderSize + i;
|
||||
TraverseTransitionTreeInternal(Map::cast(proto_trans->get(index)),
|
||||
callback, data);
|
||||
WeakCell* cell = WeakCell::cast(proto_trans->get(index));
|
||||
TraverseTransitionTreeInternal(Map::cast(cell->value()), callback,
|
||||
data);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < transitions->number_of_transitions(); ++i) {
|
||||
|
@ -92,9 +92,8 @@ class TransitionArray: public FixedArray {
|
||||
// 0: finger - index of the first free cell in the cache
|
||||
// 1 + i: target map
|
||||
static const int kMaxCachedPrototypeTransitions = 256;
|
||||
static Handle<Map> PutPrototypeTransition(Handle<Map> map,
|
||||
Handle<Object> prototype,
|
||||
Handle<Map> target_map);
|
||||
static void PutPrototypeTransition(Handle<Map> map, Handle<Object> prototype,
|
||||
Handle<Map> target_map);
|
||||
|
||||
static Handle<Map> GetPrototypeTransition(Handle<Map> map,
|
||||
Handle<Object> prototype);
|
||||
|
@ -2521,7 +2521,8 @@ TEST(PrototypeTransitionClearing) {
|
||||
TransitionArray::GetPrototypeTransitions(baseObject->map());
|
||||
for (int i = initialTransitions; i < initialTransitions + transitions; i++) {
|
||||
int j = TransitionArray::kProtoTransitionHeaderSize + i;
|
||||
CHECK(trans->get(j)->IsMap());
|
||||
CHECK(trans->get(j)->IsWeakCell());
|
||||
CHECK(WeakCell::cast(trans->get(j))->value()->IsMap());
|
||||
}
|
||||
|
||||
// Make sure next prototype is placed on an old-space evacuation candidate.
|
||||
|
Loading…
Reference in New Issue
Block a user