summaryrefslogtreecommitdiff
path: root/deps/v8/src/objects/transitions.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/objects/transitions.cc')
-rw-r--r--deps/v8/src/objects/transitions.cc31
1 files changed, 26 insertions, 5 deletions
diff --git a/deps/v8/src/objects/transitions.cc b/deps/v8/src/objects/transitions.cc
index 12190cf9ad..22a7a741da 100644
--- a/deps/v8/src/objects/transitions.cc
+++ b/deps/v8/src/objects/transitions.cc
@@ -371,13 +371,14 @@ Handle<WeakFixedArray> TransitionArray::GrowPrototypeTransitionArray(
new_capacity = std::min({kMaxCachedPrototypeTransitions, new_capacity});
DCHECK_GT(new_capacity, capacity);
int grow_by = new_capacity - capacity;
- array = isolate->factory()->CopyWeakFixedArrayAndGrow(array, grow_by);
+ Handle<WeakFixedArray> new_array =
+ isolate->factory()->CopyWeakFixedArrayAndGrow(array, grow_by);
if (capacity < 0) {
// There was no prototype transitions array before, so the size
// couldn't be copied. Initialize it explicitly.
- SetNumberOfPrototypeTransitions(*array, 0);
+ SetNumberOfPrototypeTransitions(*new_array, 0);
}
- return array;
+ return new_array;
}
// static
@@ -397,15 +398,33 @@ void TransitionsAccessor::PutPrototypeTransition(Isolate* isolate,
int capacity = cache->length() - header;
int transitions = TransitionArray::NumberOfPrototypeTransitions(*cache) + 1;
- base::SharedMutexGuard<base::kExclusive> scope(
- isolate->full_transition_array_access());
+ // We're not using a MutexGuard for {full_transition_array_access}, because
+ // we'll need to release it before growing the transition array (if needed),
+ // in order to avoid deadlock if a background thread is waiting for the shared
+ // mutex outside of a safepoint. And after growing the array, we'll need to
+ // re-lock it.
+ base::SharedMutex* transition_array_mutex =
+ isolate->full_transition_array_access();
+ transition_array_mutex->LockExclusive();
if (transitions > capacity) {
// Grow the array if compacting it doesn't free space.
if (!TransitionArray::CompactPrototypeTransitionArray(isolate, *cache)) {
+ transition_array_mutex->UnlockExclusive();
if (capacity == TransitionArray::kMaxCachedPrototypeTransitions) return;
+
+ // GrowPrototypeTransitionArray can allocate, so it shouldn't hold the
+ // exclusive lock on {full_transition_array_access} mutex, since
+ // background threads could be waiting for the shared lock (outside of a
+ // safe point). This is not an issue, because GrowPrototypeTransitionArray
+ // doesn't actually modify in place the array, but instead return a new
+ // array.
+ transition_array_mutex->LockShared();
cache = TransitionArray::GrowPrototypeTransitionArray(
cache, 2 * transitions, isolate);
+ transition_array_mutex->UnlockShared();
+
+ transition_array_mutex->LockExclusive();
SetPrototypeTransitions(isolate, map, cache);
}
}
@@ -416,6 +435,8 @@ void TransitionsAccessor::PutPrototypeTransition(Isolate* isolate,
cache->Set(entry, HeapObjectReference::Weak(*target_map));
TransitionArray::SetNumberOfPrototypeTransitions(*cache, last + 1);
+
+ transition_array_mutex->UnlockExclusive();
}
// static