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() { ...@@ -2627,16 +2627,21 @@ void MarkCompactCollector::ClearFullMapTransitions() {
while (weak_objects_.transition_arrays.Pop(kMainThread, &array)) { while (weak_objects_.transition_arrays.Pop(kMainThread, &array)) {
int num_transitions = array->number_of_entries(); int num_transitions = array->number_of_entries();
if (num_transitions > 0) { if (num_transitions > 0) {
Map* map = array->GetTarget(0); Map* map;
DCHECK_NOT_NULL(map); // WeakCells aren't cleared yet. // The array might contain "undefined" elements because it's not yet
Map* parent = Map::cast(map->constructor_or_backpointer()); // filled. Allow it.
bool parent_is_alive = non_atomic_marking_state()->IsBlackOrGrey(parent); if (array->GetTargetIfExists(0, isolate(), &map)) {
DescriptorArray* descriptors = DCHECK_NOT_NULL(map); // WeakCells aren't cleared yet.
parent_is_alive ? parent->instance_descriptors() : nullptr; Map* parent = Map::cast(map->constructor_or_backpointer());
bool descriptors_owner_died = bool parent_is_alive =
CompactTransitionArray(parent, array, descriptors); non_atomic_marking_state()->IsBlackOrGrey(parent);
if (descriptors_owner_died) { DescriptorArray* descriptors =
TrimDescriptorArray(parent, 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) { ...@@ -152,6 +152,15 @@ void TransitionArray::SetTarget(int transition_number, Object* value) {
set(ToTargetIndex(transition_number), 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) { int TransitionArray::SearchName(Name* name, int* out_insertion_index) {
DCHECK(name->IsUniqueName()); DCHECK(name->IsUniqueName());
......
...@@ -224,6 +224,8 @@ class TransitionArray : public FixedArray { ...@@ -224,6 +224,8 @@ class TransitionArray : public FixedArray {
inline void SetTarget(int transition_number, Object* target); inline void SetTarget(int transition_number, Object* target);
inline Object* GetRawTarget(int transition_number); inline Object* GetRawTarget(int transition_number);
inline Object** GetTargetSlot(int transition_number); inline Object** GetTargetSlot(int transition_number);
inline bool GetTargetIfExists(int transition_number, Isolate* isolate,
Map** target);
// Required for templatized Search interface. // Required for templatized Search interface.
static const int kNotFound = -1; 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