[heap] Fix a map creation data race with concurrent marking.
The race happens when an object transitions to a newly created map. The map initializing stores can be reordered after object->set_map(map), which will cause the concurrent marker to observe inconsistent map. The fix is to use store-release when setting the map pointer and acquire-load when reading the map in the concurrent marker. BUG=chromium:694255 Change-Id: I4fd6bc27dd70ff1a30f56a4cec13310ccdd627c8 Reviewed-on: https://chromium-review.googlesource.com/528118 Reviewed-by: Hannes Payer <hpayer@chromium.org> Commit-Queue: Ulan Degenbaev <ulan@chromium.org> Cr-Commit-Position: refs/heads/master@{#45876}
This commit is contained in:
parent
0aa78b9e5b
commit
d906f81502
@ -498,9 +498,9 @@ class ArrayConcatVisitor {
|
||||
isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
|
||||
Handle<Map> map = JSObject::GetElementsTransitionMap(
|
||||
array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
|
||||
array->set_map(*map);
|
||||
array->set_length(*length);
|
||||
array->set_elements(*storage_fixed_array());
|
||||
array->synchronized_set_map(*map);
|
||||
return array;
|
||||
}
|
||||
|
||||
|
@ -1864,8 +1864,8 @@ Handle<JSGlobalObject> Factory::NewJSGlobalObject(
|
||||
new_map->set_dictionary_map(true);
|
||||
|
||||
// Set up the global object as a normalized object.
|
||||
global->set_map(*new_map);
|
||||
global->set_properties(*dictionary);
|
||||
global->synchronized_set_map(*new_map);
|
||||
|
||||
// Make sure result is a global object with properties in dictionary.
|
||||
DCHECK(global->IsJSGlobalObject() && !global->HasFastProperties());
|
||||
|
@ -266,7 +266,8 @@ void ConcurrentMarking::Run() {
|
||||
if (new_space_top <= addr && addr < new_space_limit) {
|
||||
deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout);
|
||||
} else {
|
||||
bytes_marked += visitor_->Visit(object);
|
||||
Map* map = object->synchronized_map();
|
||||
bytes_marked += visitor_->Visit(map, object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -487,7 +487,12 @@ inline static bool HasSourceCode(Heap* heap, SharedFunctionInfo* info) {
|
||||
|
||||
template <typename ResultType, typename ConcreteVisitor>
|
||||
ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(HeapObject* object) {
|
||||
Map* map = object->map();
|
||||
return Visit(object->map(), object);
|
||||
}
|
||||
|
||||
template <typename ResultType, typename ConcreteVisitor>
|
||||
ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(Map* map,
|
||||
HeapObject* object) {
|
||||
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
|
||||
switch (static_cast<VisitorId>(map->visitor_id())) {
|
||||
#define CASE(type) \
|
||||
|
@ -387,6 +387,7 @@ template <typename ResultType, typename ConcreteVisitor>
|
||||
class HeapVisitor : public ObjectVisitor {
|
||||
public:
|
||||
ResultType Visit(HeapObject* object);
|
||||
ResultType Visit(Map* map, HeapObject* object);
|
||||
|
||||
protected:
|
||||
// A guard predicate for visiting the object.
|
||||
|
@ -3822,7 +3822,7 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
|
||||
CHECK(new_map->is_dictionary_map());
|
||||
|
||||
// Slow-to-slow migration is trivial.
|
||||
object->set_map(*new_map);
|
||||
object->synchronized_set_map(*new_map);
|
||||
} else if (!new_map->is_dictionary_map()) {
|
||||
MigrateFastToFast(object, new_map);
|
||||
if (old_map->is_prototype_map()) {
|
||||
@ -15298,7 +15298,7 @@ void JSObject::SetImmutableProto(Handle<JSObject> object) {
|
||||
if (map->is_immutable_proto()) return;
|
||||
|
||||
Handle<Map> new_map = Map::TransitionToImmutableProto(map);
|
||||
object->set_map(*new_map);
|
||||
object->synchronized_set_map(*new_map);
|
||||
}
|
||||
|
||||
void JSObject::EnsureCanContainElements(Handle<JSObject> object,
|
||||
|
@ -111,7 +111,7 @@ static Handle<Object> CreateArrayLiteralBoilerplate(
|
||||
Context* native_context = isolate->context()->native_context();
|
||||
Object* map =
|
||||
native_context->get(Context::ArrayMapIndex(constant_elements_kind));
|
||||
object->set_map(Map::cast(map));
|
||||
object->synchronized_set_map(Map::cast(map));
|
||||
}
|
||||
|
||||
Handle<FixedArrayBase> copied_elements_values;
|
||||
|
Loading…
Reference in New Issue
Block a user