Commit 8d1ad4b8 authored by Ulan Degenbaev's avatar Ulan Degenbaev Committed by Commit Bot

[heap] Remove adhoc weakness in TransitionArray.

Currently transition array targets have conditional weakness depending
on the type of the target. Map targets are weak and all other targets
are strong. This patch wraps maps in transitions arrays in weak cells,
which allows us to treat all elements of transition arrays strongly.

Conditional weakness is unsafe for concurrent marking because the
condition can change during marking.

Bug: chromium:694255
Change-Id: I64e5d0699698fc7c1758f3fbc52da43014c247af
Reviewed-on: https://chromium-review.googlesource.com/641271
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48034}
parent c87f8954
......@@ -215,11 +215,12 @@ class ConcurrentMarkingVisitor final
}
int VisitTransitionArray(Map* map, TransitionArray* array) {
if (marking_state_.IsGrey(array)) {
// TODO(ulan): process transition arrays.
bailout_.Push(array);
}
return 0;
if (!ShouldVisit(array)) return 0;
VisitMapPointer(array, array->map_slot());
int size = TransitionArray::BodyDescriptor::SizeOf(map, array);
TransitionArray::BodyDescriptor::IterateBody(array, size, this);
weak_objects_->transition_arrays.Push(task_id_, array);
return size;
}
int VisitWeakCell(Map* map, WeakCell* object) {
......
......@@ -2878,12 +2878,8 @@ bool MarkCompactCollector::CompactTransitionArray(
RecordSlot(transitions, key_slot, key);
Object* raw_target = transitions->GetRawTarget(i);
transitions->SetTarget(transition_index, raw_target);
// Maps are not compacted, but for cached handlers the target slot
// must be recorded.
if (!raw_target->IsMap()) {
Object** target_slot = transitions->GetTargetSlot(transition_index);
RecordSlot(transitions, target_slot, raw_target);
}
Object** target_slot = transitions->GetTargetSlot(transition_index);
RecordSlot(transitions, target_slot, raw_target);
}
transition_index++;
}
......
......@@ -194,23 +194,10 @@ template <typename ConcreteVisitor>
int MarkingVisitor<ConcreteVisitor>::VisitTransitionArray(
Map* map, TransitionArray* array) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
// Visit strong references.
if (array->HasPrototypeTransitions()) {
visitor->VisitPointer(array, array->GetPrototypeTransitionsSlot());
}
int num_transitions = array->number_of_entries();
for (int i = 0; i < num_transitions; ++i) {
visitor->VisitPointer(array, array->GetKeySlot(i));
// A TransitionArray can hold maps or (transitioning StoreIC) handlers.
// Maps have custom weak handling; handlers (which in turn weakly point
// to maps) are marked strongly for now, and will be cleared during
// compaction when the maps they refer to are dead.
if (!array->GetRawTarget(i)->IsMap()) {
visitor->VisitPointer(array, array->GetTargetSlot(i));
}
}
int size = TransitionArray::BodyDescriptor::SizeOf(map, array);
TransitionArray::BodyDescriptor::IterateBody(array, size, visitor);
collector_->AddTransitionArray(array);
return TransitionArray::BodyDescriptor::SizeOf(map, array);
return size;
}
template <typename ConcreteVisitor>
......
......@@ -119,8 +119,9 @@ PropertyDetails TransitionsAccessor::GetTargetDetails(Name* name, Map* target) {
// static
Map* TransitionsAccessor::GetTargetFromRaw(Object* raw) {
if (raw->IsMap()) return Map::cast(raw);
if (raw->IsTuple3()) {
if (raw->IsWeakCell()) {
return Map::cast(WeakCell::cast(raw)->value());
} else if (raw->IsTuple3()) {
return Map::cast(StoreHandler::GetTuple3TransitionCell(raw)->value());
} else {
DCHECK(raw->IsFixedArray());
......@@ -162,6 +163,7 @@ Map* TransitionsAccessor::GetTarget(int transition_number) {
}
void TransitionArray::SetTarget(int transition_number, Object* value) {
DCHECK(!value->IsMap());
DCHECK(transition_number < number_of_transitions());
set(ToTargetIndex(transition_number), value);
}
......
......@@ -68,12 +68,14 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target,
SimpleTransitionFlag flag) {
DCHECK(!map_handle_.is_null());
Isolate* isolate = map_->GetIsolate();
Handle<WeakCell> weak_cell_with_target = Map::WeakCellForMap(target);
Reload();
target->SetBackPointer(map_);
// If the map doesn't have any transitions at all yet, install the new one.
if (encoding() == kUninitialized) {
if (flag == SIMPLE_PROPERTY_TRANSITION) {
ReplaceTransitions(*Map::WeakCellForMap(target));
ReplaceTransitions(*weak_cell_with_target);
return;
}
// If the flag requires a full TransitionArray, allocate one.
......@@ -94,7 +96,7 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target,
if (flag == SIMPLE_PROPERTY_TRANSITION && key->Equals(*name) &&
old_details.kind() == new_details.kind() &&
old_details.attributes() == new_details.attributes()) {
ReplaceTransitions(*Map::WeakCellForMap(target));
ReplaceTransitions(*weak_cell_with_target);
return;
}
// Otherwise allocate a full TransitionArray with slack for a new entry.
......@@ -103,10 +105,8 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target,
Reload();
simple_transition = GetSimpleTransition();
if (simple_transition != nullptr) {
Object* value = raw_transitions_->IsWeakCell()
? WeakCell::cast(raw_transitions_)->value()
: raw_transitions_;
result->Set(0, GetSimpleTransitionKey(simple_transition), value);
result->Set(0, GetSimpleTransitionKey(simple_transition),
raw_transitions_);
} else {
result->SetNumberOfTransitions(0);
}
......@@ -138,7 +138,7 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target,
&insertion_index);
// If an existing entry was found, overwrite it and return.
if (index != kNotFound) {
array->SetTarget(index, *target);
array->SetTarget(index, *weak_cell_with_target);
return;
}
......@@ -154,7 +154,7 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target,
array->SetTarget(index, array->GetRawTarget(index - 1));
}
array->SetKey(index, *name);
array->SetTarget(index, *target);
array->SetTarget(index, *weak_cell_with_target);
SLOW_DCHECK(array->IsSortedNoDuplicates());
return;
}
......@@ -202,7 +202,7 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target,
for (int i = 0; i < insertion_index; ++i) {
result->Set(i, array->GetKey(i), array->GetRawTarget(i));
}
result->Set(insertion_index, *name, *target);
result->Set(insertion_index, *name, *weak_cell_with_target);
for (int i = insertion_index; i < number_of_transitions; ++i) {
result->Set(i + 1, array->GetKey(i), array->GetRawTarget(i));
}
......@@ -456,6 +456,7 @@ void TransitionsAccessor::PutPrototypeTransition(Handle<Object> prototype,
int entry = header + last;
Handle<WeakCell> target_cell = Map::WeakCellForMap(target_map);
Reload(); // Reload after possible GC.
cache->set(entry, *target_cell);
TransitionArray::SetNumberOfPrototypeTransitions(*cache, last + 1);
}
......@@ -553,18 +554,19 @@ void TransitionsAccessor::EnsureHasFullTransitionArray() {
int nof = encoding() == kUninitialized ? 0 : 1;
Handle<TransitionArray> result =
TransitionArray::Allocate(map_->GetIsolate(), nof);
DisallowHeapAllocation no_gc;
Reload(); // Reload after possible GC.
if (nof == 1) {
Map* target = GetSimpleTransition();
if (target == nullptr) {
if (encoding() == kUninitialized) {
// If allocation caused GC and cleared the target, trim the new array.
result->Shrink(TransitionArray::ToKeyIndex(0));
result->SetNumberOfTransitions(0);
} else {
// Otherwise populate the new array.
Name* key = GetSimpleTransitionKey(target);
result->Set(0, key, target);
Handle<Map> target(GetSimpleTransition());
Handle<WeakCell> weak_cell_with_target = Map::WeakCellForMap(target);
Reload(); // Reload after possible GC.
Name* key = GetSimpleTransitionKey(*target);
result->Set(0, key, *weak_cell_with_target);
}
}
ReplaceTransitions(*result);
......
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