Commit b0db0541 authored by ulan's avatar ulan Committed by Commit bot

[heap] Use shared markbits in the concurrent marker.

The concurrent marker now colors objects grey and black using
the atomic markbit operations.

The heap visitor is changed in two ways:
1) It iterates the map pointer of each object.
2) It guards object visitation with a predicate, which is overridden
in the concurrent marker with the result of GreyToBlack transition.

BUG=chromium:694255

Review-Url: https://codereview.chromium.org/2855003004
Cr-Commit-Position: refs/heads/master@{#45099}
parent 3a473122
...@@ -666,7 +666,7 @@ DEFINE_BOOL(age_code, true, ...@@ -666,7 +666,7 @@ DEFINE_BOOL(age_code, true,
DEFINE_BOOL(incremental_marking, true, "use incremental marking") DEFINE_BOOL(incremental_marking, true, "use incremental marking")
DEFINE_BOOL(incremental_marking_wrappers, true, DEFINE_BOOL(incremental_marking_wrappers, true,
"use incremental marking for marking wrappers") "use incremental marking for marking wrappers")
DEFINE_BOOL(concurrent_marking, false, "use concurrent marking") DEFINE_BOOL(concurrent_marking, V8_CONCURRENT_MARKING, "use concurrent marking")
DEFINE_BOOL(trace_concurrent_marking, false, "trace concurrent marking") DEFINE_BOOL(trace_concurrent_marking, false, "trace concurrent marking")
DEFINE_INT(min_progress_during_incremental_marking_finalization, 32, DEFINE_INT(min_progress_during_incremental_marking_finalization, 32,
"keep finalizing incremental marking as long as we discover at " "keep finalizing incremental marking as long as we discover at "
......
...@@ -30,6 +30,11 @@ class ConcurrentMarkingVisitor final ...@@ -30,6 +30,11 @@ class ConcurrentMarkingVisitor final
explicit ConcurrentMarkingVisitor(ConcurrentMarkingDeque* deque) explicit ConcurrentMarkingVisitor(ConcurrentMarkingDeque* deque)
: deque_(deque) {} : deque_(deque) {}
bool ShouldVisit(HeapObject* object) override {
return ObjectMarking::GreyToBlack<MarkBit::AccessMode::ATOMIC>(
object, marking_state(object));
}
void VisitPointers(HeapObject* host, Object** start, Object** end) override { void VisitPointers(HeapObject* host, Object** start, Object** end) override {
for (Object** p = start; p < end; p++) { for (Object** p = start; p < end; p++) {
if (!(*p)->IsHeapObject()) continue; if (!(*p)->IsHeapObject()) continue;
...@@ -68,7 +73,7 @@ class ConcurrentMarkingVisitor final ...@@ -68,7 +73,7 @@ class ConcurrentMarkingVisitor final
// =========================================================================== // ===========================================================================
int VisitCode(Map* map, Code* object) override { int VisitCode(Map* map, Code* object) override {
// TODO(ulan): push the object to the bail-out deque. deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout);
return 0; return 0;
} }
...@@ -77,58 +82,65 @@ class ConcurrentMarkingVisitor final ...@@ -77,58 +82,65 @@ class ConcurrentMarkingVisitor final
// =========================================================================== // ===========================================================================
int VisitBytecodeArray(Map* map, BytecodeArray* object) override { int VisitBytecodeArray(Map* map, BytecodeArray* object) override {
// TODO(ulan): implement iteration of strong fields and push the object to // TODO(ulan): implement iteration of strong fields.
// the bailout deque. deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout);
return 0; return 0;
} }
int VisitJSFunction(Map* map, JSFunction* object) override { int VisitJSFunction(Map* map, JSFunction* object) override {
// TODO(ulan): implement iteration of strong fields and push the object to // TODO(ulan): implement iteration of strong fields.
// the bailout deque. deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout);
return 0; return 0;
} }
int VisitMap(Map* map, Map* object) override { int VisitMap(Map* map, Map* object) override {
// TODO(ulan): implement iteration of strong fields and push the object to // TODO(ulan): implement iteration of strong fields.
// the bailout deque. deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout);
return 0; return 0;
} }
int VisitNativeContext(Map* map, Context* object) override { int VisitNativeContext(Map* map, Context* object) override {
// TODO(ulan): implement iteration of strong fields and push the object to // TODO(ulan): implement iteration of strong fields.
// the bailout deque. deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout);
return 0; return 0;
} }
int VisitSharedFunctionInfo(Map* map, SharedFunctionInfo* object) override { int VisitSharedFunctionInfo(Map* map, SharedFunctionInfo* object) override {
// TODO(ulan): implement iteration of strong fields and push the object to // TODO(ulan): implement iteration of strong fields.
// the bailout deque. deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout);
return 0; return 0;
} }
int VisitTransitionArray(Map* map, TransitionArray* object) override { int VisitTransitionArray(Map* map, TransitionArray* object) override {
// TODO(ulan): implement iteration of strong fields and push the object to // TODO(ulan): implement iteration of strong fields.
// the bailout deque. deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout);
return 0; return 0;
} }
int VisitWeakCell(Map* map, WeakCell* object) override { int VisitWeakCell(Map* map, WeakCell* object) override {
// TODO(ulan): implement iteration of strong fields and push the object to // TODO(ulan): implement iteration of strong fields.
// the bailout deque. deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout);
return 0; return 0;
} }
int VisitJSWeakCollection(Map* map, JSWeakCollection* object) override { int VisitJSWeakCollection(Map* map, JSWeakCollection* object) override {
// TODO(ulan): implement iteration of strong fields and push the object to // TODO(ulan): implement iteration of strong fields.
// the bailout deque. deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout);
return 0; return 0;
} }
void MarkObject(HeapObject* obj) { void MarkObject(HeapObject* object) {
deque_->Push(obj, MarkingThread::kConcurrent, TargetDeque::kShared); if (ObjectMarking::WhiteToGrey<MarkBit::AccessMode::ATOMIC>(
object, marking_state(object))) {
deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kShared);
}
} }
private: private:
MarkingState marking_state(HeapObject* object) const {
return MarkingState::Internal(object);
}
ConcurrentMarkingDeque* deque_; ConcurrentMarkingDeque* deque_;
}; };
...@@ -175,7 +187,7 @@ void ConcurrentMarking::Run() { ...@@ -175,7 +187,7 @@ void ConcurrentMarking::Run() {
TimedScope scope(&time_ms); TimedScope scope(&time_ms);
HeapObject* object; HeapObject* object;
while ((object = deque_->Pop(MarkingThread::kConcurrent)) != nullptr) { while ((object = deque_->Pop(MarkingThread::kConcurrent)) != nullptr) {
bytes_marked += visitor_->IterateBody(object); bytes_marked += visitor_->Visit(object);
} }
} }
if (FLAG_trace_concurrent_marking) { if (FLAG_trace_concurrent_marking) {
......
...@@ -637,8 +637,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSFunctionWeakCode( ...@@ -637,8 +637,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSFunctionWeakCode(
} }
template <typename ResultType, typename ConcreteVisitor> template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::IterateBody( ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(HeapObject* object) {
HeapObject* object) {
Map* map = object->map(); Map* map = object->map();
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())) {
...@@ -669,14 +668,28 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::IterateBody( ...@@ -669,14 +668,28 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::IterateBody(
return ResultType(); return ResultType();
} }
#define VISIT(type) \ template <typename ResultType, typename ConcreteVisitor>
template <typename ResultType, typename ConcreteVisitor> \ void HeapVisitor<ResultType, ConcreteVisitor>::VisitMapPointer(
ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit##type( \ HeapObject* host, HeapObject** map) {
Map* map, type* object) { \ static_cast<ConcreteVisitor*>(this)->VisitPointer(
int size = type::BodyDescriptor::SizeOf(map, object); \ host, reinterpret_cast<Object**>(map));
type::BodyDescriptor::IterateBody(object, size, \ }
static_cast<ConcreteVisitor*>(this)); \
return static_cast<ResultType>(size); \ template <typename ResultType, typename ConcreteVisitor>
bool HeapVisitor<ResultType, ConcreteVisitor>::ShouldVisit(HeapObject* object) {
return true;
}
#define VISIT(type) \
template <typename ResultType, typename ConcreteVisitor> \
ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit##type( \
Map* map, type* object) { \
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this); \
if (!visitor->ShouldVisit(object)) return ResultType(); \
int size = type::BodyDescriptor::SizeOf(map, object); \
visitor->VisitMapPointer(object, object->map_slot()); \
type::BodyDescriptor::IterateBody(object, size, visitor); \
return static_cast<ResultType>(size); \
} }
TYPED_VISITOR_ID_LIST(VISIT) TYPED_VISITOR_ID_LIST(VISIT)
#undef VISIT #undef VISIT
...@@ -684,7 +697,10 @@ TYPED_VISITOR_ID_LIST(VISIT) ...@@ -684,7 +697,10 @@ TYPED_VISITOR_ID_LIST(VISIT)
template <typename ResultType, typename ConcreteVisitor> template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitShortcutCandidate( ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitShortcutCandidate(
Map* map, ConsString* object) { Map* map, ConsString* object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
if (!visitor->ShouldVisit(object)) return ResultType();
int size = ConsString::BodyDescriptor::SizeOf(map, object); int size = ConsString::BodyDescriptor::SizeOf(map, object);
visitor->VisitMapPointer(object, object->map_slot());
ConsString::BodyDescriptor::IterateBody(object, size, ConsString::BodyDescriptor::IterateBody(object, size,
static_cast<ConcreteVisitor*>(this)); static_cast<ConcreteVisitor*>(this));
return static_cast<ResultType>(size); return static_cast<ResultType>(size);
...@@ -693,7 +709,10 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitShortcutCandidate( ...@@ -693,7 +709,10 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitShortcutCandidate(
template <typename ResultType, typename ConcreteVisitor> template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitNativeContext( ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitNativeContext(
Map* map, Context* object) { Map* map, Context* object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
if (!visitor->ShouldVisit(object)) return ResultType();
int size = Context::BodyDescriptor::SizeOf(map, object); int size = Context::BodyDescriptor::SizeOf(map, object);
visitor->VisitMapPointer(object, object->map_slot());
Context::BodyDescriptor::IterateBody(object, size, Context::BodyDescriptor::IterateBody(object, size,
static_cast<ConcreteVisitor*>(this)); static_cast<ConcreteVisitor*>(this));
return static_cast<ResultType>(size); return static_cast<ResultType>(size);
...@@ -702,14 +721,20 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitNativeContext( ...@@ -702,14 +721,20 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitNativeContext(
template <typename ResultType, typename ConcreteVisitor> template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitDataObject( ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitDataObject(
Map* map, HeapObject* object) { Map* map, HeapObject* object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
if (!visitor->ShouldVisit(object)) return ResultType();
int size = map->instance_size(); int size = map->instance_size();
visitor->VisitMapPointer(object, object->map_slot());
return static_cast<ResultType>(size); return static_cast<ResultType>(size);
} }
template <typename ResultType, typename ConcreteVisitor> template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSObjectFast( ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSObjectFast(
Map* map, JSObject* object) { Map* map, JSObject* object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
if (!visitor->ShouldVisit(object)) return ResultType();
int size = JSObject::FastBodyDescriptor::SizeOf(map, object); int size = JSObject::FastBodyDescriptor::SizeOf(map, object);
visitor->VisitMapPointer(object, object->map_slot());
JSObject::FastBodyDescriptor::IterateBody( JSObject::FastBodyDescriptor::IterateBody(
object, size, static_cast<ConcreteVisitor*>(this)); object, size, static_cast<ConcreteVisitor*>(this));
return static_cast<ResultType>(size); return static_cast<ResultType>(size);
...@@ -717,7 +742,10 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSObjectFast( ...@@ -717,7 +742,10 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSObjectFast(
template <typename ResultType, typename ConcreteVisitor> template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSApiObject( ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSApiObject(
Map* map, JSObject* object) { Map* map, JSObject* object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
if (!visitor->ShouldVisit(object)) return ResultType();
int size = JSObject::BodyDescriptor::SizeOf(map, object); int size = JSObject::BodyDescriptor::SizeOf(map, object);
visitor->VisitMapPointer(object, object->map_slot());
JSObject::BodyDescriptor::IterateBody(object, size, JSObject::BodyDescriptor::IterateBody(object, size,
static_cast<ConcreteVisitor*>(this)); static_cast<ConcreteVisitor*>(this));
return static_cast<ResultType>(size); return static_cast<ResultType>(size);
...@@ -725,7 +753,10 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSApiObject( ...@@ -725,7 +753,10 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitJSApiObject(
template <typename ResultType, typename ConcreteVisitor> template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitStruct( ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitStruct(
Map* map, HeapObject* object) { Map* map, HeapObject* object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
if (!visitor->ShouldVisit(object)) return ResultType();
int size = map->instance_size(); int size = map->instance_size();
visitor->VisitMapPointer(object, object->map_slot());
StructBodyDescriptor::IterateBody(object, size, StructBodyDescriptor::IterateBody(object, size,
static_cast<ConcreteVisitor*>(this)); static_cast<ConcreteVisitor*>(this));
return static_cast<ResultType>(size); return static_cast<ResultType>(size);
...@@ -733,6 +764,9 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitStruct( ...@@ -733,6 +764,9 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitStruct(
template <typename ResultType, typename ConcreteVisitor> template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitFreeSpace( ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitFreeSpace(
Map* map, FreeSpace* object) { Map* map, FreeSpace* object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
if (!visitor->ShouldVisit(object)) return ResultType();
visitor->VisitMapPointer(object, object->map_slot());
return static_cast<ResultType>(FreeSpace::cast(object)->size()); return static_cast<ResultType>(FreeSpace::cast(object)->size());
} }
......
...@@ -395,9 +395,16 @@ VisitorDispatchTable<typename StaticMarkingVisitor<StaticVisitor>::Callback> ...@@ -395,9 +395,16 @@ VisitorDispatchTable<typename StaticMarkingVisitor<StaticVisitor>::Callback>
template <typename ResultType, typename ConcreteVisitor> template <typename ResultType, typename ConcreteVisitor>
class HeapVisitor : public ObjectVisitor { class HeapVisitor : public ObjectVisitor {
public: public:
ResultType IterateBody(HeapObject* object); ResultType Visit(HeapObject* object);
protected: protected:
// A guard predicate for visiting the object.
// If it returns false then the default implementations of the Visit*
// functions bailout from iterating the object pointers.
virtual bool ShouldVisit(HeapObject* object);
// A callback for visiting the map pointer in the object header.
virtual void VisitMapPointer(HeapObject* host, HeapObject** map);
#define VISIT(type) virtual ResultType Visit##type(Map* map, type* object); #define VISIT(type) virtual ResultType Visit##type(Map* map, type* object);
TYPED_VISITOR_ID_LIST(VISIT) TYPED_VISITOR_ID_LIST(VISIT)
#undef VISIT #undef VISIT
......
...@@ -1525,6 +1525,9 @@ void HeapObject::set_map_no_write_barrier(Map* value) { ...@@ -1525,6 +1525,9 @@ void HeapObject::set_map_no_write_barrier(Map* value) {
set_map_word(MapWord::FromMap(value)); set_map_word(MapWord::FromMap(value));
} }
HeapObject** HeapObject::map_slot() {
return reinterpret_cast<HeapObject**>(FIELD_ADDR(this, kMapOffset));
}
MapWord HeapObject::map_word() const { MapWord HeapObject::map_word() const {
return MapWord( return MapWord(
......
...@@ -1669,6 +1669,9 @@ class HeapObject: public Object { ...@@ -1669,6 +1669,9 @@ class HeapObject: public Object {
// information. // information.
inline Map* map() const; inline Map* map() const;
inline void set_map(Map* value); inline void set_map(Map* value);
inline HeapObject** map_slot();
// The no-write-barrier version. This is OK if the object is white and in // The no-write-barrier version. This is OK if the object is white and in
// new space, or if the value is an immortal immutable object, like the maps // new space, or if the value is an immortal immutable object, like the maps
// of primitive (non-JS) objects like strings, heap numbers etc. // of primitive (non-JS) objects like strings, heap numbers etc.
......
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