Commit d82e8f37 authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[heap] Fix iterating uninitialized TransitionArrays.

This pattern seems to reoccur in the code:

Handle<TransitionArray> array = TransitionArray::Allocate(...);
<something that causes allocation>
// Fill up the array
array->set(...);

If the allocation causes GC, we try to iterate the TransitionArrray
in MarkCompactCollector::ClearFullMapTransitions, and that crashes because it
expects the TransitionArray to contain handlers (not undefined).

This bug is present e.g., in TransitionAccessor::EnsureHasFullTransition.

BUG=v8:7308

Change-Id: I306204fc27d62041801427c466c82d1d9df1bf0c
Reviewed-on: https://chromium-review.googlesource.com/997493
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52386}
parent a9f5dd30
......@@ -2627,16 +2627,21 @@ void MarkCompactCollector::ClearFullMapTransitions() {
while (weak_objects_.transition_arrays.Pop(kMainThread, &array)) {
int num_transitions = array->number_of_entries();
if (num_transitions > 0) {
Map* map = array->GetTarget(0);
DCHECK_NOT_NULL(map); // WeakCells aren't cleared yet.
Map* parent = Map::cast(map->constructor_or_backpointer());
bool parent_is_alive = non_atomic_marking_state()->IsBlackOrGrey(parent);
DescriptorArray* descriptors =
parent_is_alive ? parent->instance_descriptors() : nullptr;
bool descriptors_owner_died =
CompactTransitionArray(parent, array, descriptors);
if (descriptors_owner_died) {
TrimDescriptorArray(parent, descriptors);
Map* map;
// The array might contain "undefined" elements because it's not yet
// filled. Allow it.
if (array->GetTargetIfExists(0, isolate(), &map)) {
DCHECK_NOT_NULL(map); // WeakCells aren't cleared yet.
Map* parent = Map::cast(map->constructor_or_backpointer());
bool parent_is_alive =
non_atomic_marking_state()->IsBlackOrGrey(parent);
DescriptorArray* descriptors =
parent_is_alive ? parent->instance_descriptors() : nullptr;
bool descriptors_owner_died =
CompactTransitionArray(parent, array, descriptors);
if (descriptors_owner_died) {
TrimDescriptorArray(parent, descriptors);
}
}
}
}
......
......@@ -152,6 +152,15 @@ void TransitionArray::SetTarget(int transition_number, Object* value) {
set(ToTargetIndex(transition_number), value);
}
bool TransitionArray::GetTargetIfExists(int transition_number, Isolate* isolate,
Map** target) {
Object* raw = GetRawTarget(transition_number);
if (raw->IsUndefined(isolate)) {
return false;
}
*target = TransitionsAccessor::GetTargetFromRaw(raw);
return true;
}
int TransitionArray::SearchName(Name* name, int* out_insertion_index) {
DCHECK(name->IsUniqueName());
......
......@@ -224,6 +224,8 @@ class TransitionArray : public FixedArray {
inline void SetTarget(int transition_number, Object* target);
inline Object* GetRawTarget(int transition_number);
inline Object** GetTargetSlot(int transition_number);
inline bool GetTargetIfExists(int transition_number, Isolate* isolate,
Map** target);
// Required for templatized Search interface.
static const int kNotFound = -1;
......
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