Commit d906f815 authored by Ulan Degenbaev's avatar Ulan Degenbaev Committed by Commit Bot

[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/528118Reviewed-by: 's avatarHannes Payer <hpayer@chromium.org>
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45876}
parent 0aa78b9e
...@@ -498,9 +498,9 @@ class ArrayConcatVisitor { ...@@ -498,9 +498,9 @@ class ArrayConcatVisitor {
isolate_->factory()->NewNumber(static_cast<double>(index_offset_)); isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
Handle<Map> map = JSObject::GetElementsTransitionMap( Handle<Map> map = JSObject::GetElementsTransitionMap(
array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS); array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
array->set_map(*map);
array->set_length(*length); array->set_length(*length);
array->set_elements(*storage_fixed_array()); array->set_elements(*storage_fixed_array());
array->synchronized_set_map(*map);
return array; return array;
} }
......
...@@ -1864,8 +1864,8 @@ Handle<JSGlobalObject> Factory::NewJSGlobalObject( ...@@ -1864,8 +1864,8 @@ Handle<JSGlobalObject> Factory::NewJSGlobalObject(
new_map->set_dictionary_map(true); new_map->set_dictionary_map(true);
// Set up the global object as a normalized object. // Set up the global object as a normalized object.
global->set_map(*new_map);
global->set_properties(*dictionary); global->set_properties(*dictionary);
global->synchronized_set_map(*new_map);
// Make sure result is a global object with properties in dictionary. // Make sure result is a global object with properties in dictionary.
DCHECK(global->IsJSGlobalObject() && !global->HasFastProperties()); DCHECK(global->IsJSGlobalObject() && !global->HasFastProperties());
......
...@@ -266,7 +266,8 @@ void ConcurrentMarking::Run() { ...@@ -266,7 +266,8 @@ void ConcurrentMarking::Run() {
if (new_space_top <= addr && addr < new_space_limit) { if (new_space_top <= addr && addr < new_space_limit) {
deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout); deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout);
} else { } 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) { ...@@ -487,7 +487,12 @@ inline static bool HasSourceCode(Heap* heap, SharedFunctionInfo* info) {
template <typename ResultType, typename ConcreteVisitor> template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(HeapObject* object) { 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); ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
switch (static_cast<VisitorId>(map->visitor_id())) { switch (static_cast<VisitorId>(map->visitor_id())) {
#define CASE(type) \ #define CASE(type) \
......
...@@ -387,6 +387,7 @@ template <typename ResultType, typename ConcreteVisitor> ...@@ -387,6 +387,7 @@ template <typename ResultType, typename ConcreteVisitor>
class HeapVisitor : public ObjectVisitor { class HeapVisitor : public ObjectVisitor {
public: public:
ResultType Visit(HeapObject* object); ResultType Visit(HeapObject* object);
ResultType Visit(Map* map, HeapObject* object);
protected: protected:
// A guard predicate for visiting the object. // A guard predicate for visiting the object.
......
...@@ -3822,7 +3822,7 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, ...@@ -3822,7 +3822,7 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
CHECK(new_map->is_dictionary_map()); CHECK(new_map->is_dictionary_map());
// Slow-to-slow migration is trivial. // Slow-to-slow migration is trivial.
object->set_map(*new_map); object->synchronized_set_map(*new_map);
} else if (!new_map->is_dictionary_map()) { } else if (!new_map->is_dictionary_map()) {
MigrateFastToFast(object, new_map); MigrateFastToFast(object, new_map);
if (old_map->is_prototype_map()) { if (old_map->is_prototype_map()) {
...@@ -15298,7 +15298,7 @@ void JSObject::SetImmutableProto(Handle<JSObject> object) { ...@@ -15298,7 +15298,7 @@ void JSObject::SetImmutableProto(Handle<JSObject> object) {
if (map->is_immutable_proto()) return; if (map->is_immutable_proto()) return;
Handle<Map> new_map = Map::TransitionToImmutableProto(map); Handle<Map> new_map = Map::TransitionToImmutableProto(map);
object->set_map(*new_map); object->synchronized_set_map(*new_map);
} }
void JSObject::EnsureCanContainElements(Handle<JSObject> object, void JSObject::EnsureCanContainElements(Handle<JSObject> object,
......
...@@ -111,7 +111,7 @@ static Handle<Object> CreateArrayLiteralBoilerplate( ...@@ -111,7 +111,7 @@ static Handle<Object> CreateArrayLiteralBoilerplate(
Context* native_context = isolate->context()->native_context(); Context* native_context = isolate->context()->native_context();
Object* map = Object* map =
native_context->get(Context::ArrayMapIndex(constant_elements_kind)); 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; Handle<FixedArrayBase> copied_elements_values;
......
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