Commit 8a5382b7 authored by ulan's avatar ulan Committed by Commit bot

[heap] Slot snapshot for visiting JSObjects in concurrent marker.

The mutator can convert a pointer slot of a JSObject to an unboxed
double slot. To make it we safe for the concurrent marker, we require
synchronization using the object markbits.

The concurrent marker visits the JSObject as follows:
- save snapshot of object slot addresses and values.
- visit the snapshot only after successful transition of the object
  from grey to black.

Before an unsafe layout change the mutator colors the object black
and visits it using the bailout marking deque.

BUG=chromium:694255

Review-Url: https://codereview.chromium.org/2876553002
Cr-Commit-Position: refs/heads/master@{#45254}
parent 9acc66cd
......@@ -22,6 +22,27 @@
namespace v8 {
namespace internal {
// Helper class for storing in-object slot addresses and values.
class SlotSnapshot {
public:
SlotSnapshot() : number_of_slots_(0) {}
int number_of_slots() const { return number_of_slots_; }
Object** slot(int i) const { return snapshot_[i].first; }
Object* value(int i) const { return snapshot_[i].second; }
void clear() { number_of_slots_ = 0; }
void add(Object** slot, Object* value) {
snapshot_[number_of_slots_].first = slot;
snapshot_[number_of_slots_].second = value;
++number_of_slots_;
}
private:
static const int kMaxSnapshotSize = JSObject::kMaxInstanceSize / kPointerSize;
int number_of_slots_;
std::pair<Object**, Object*> snapshot_[kMaxSnapshotSize];
DISALLOW_COPY_AND_ASSIGN(SlotSnapshot);
};
class ConcurrentMarkingVisitor final
: public HeapVisitor<int, ConcurrentMarkingVisitor> {
public:
......@@ -44,13 +65,24 @@ class ConcurrentMarkingVisitor final
}
}
void VisitPointersInSnapshot(const SlotSnapshot& snapshot) {
for (int i = 0; i < snapshot.number_of_slots(); i++) {
Object* object = snapshot.value(i);
if (!object->IsHeapObject()) continue;
MarkObject(HeapObject::cast(object));
}
}
// ===========================================================================
// JS object =================================================================
// ===========================================================================
int VisitJSObject(Map* map, JSObject* object) override {
// TODO(ulan): impement snapshot iteration.
return BaseClass::VisitJSObject(map, object);
int size = JSObject::BodyDescriptor::SizeOf(map, object);
const SlotSnapshot& snapshot = MakeSlotSnapshot(map, object, size);
if (!ShouldVisit(object)) return 0;
VisitPointersInSnapshot(snapshot);
return size;
}
int VisitJSObjectFast(Map* map, JSObject* object) override {
......@@ -139,11 +171,41 @@ class ConcurrentMarkingVisitor final
}
private:
// Helper class for collecting in-object slot addresses and values.
class SlotSnapshottingVisitor final : public ObjectVisitor {
public:
explicit SlotSnapshottingVisitor(SlotSnapshot* slot_snapshot)
: slot_snapshot_(slot_snapshot) {
slot_snapshot_->clear();
}
void VisitPointers(HeapObject* host, Object** start,
Object** end) override {
for (Object** p = start; p < end; p++) {
Object* object = reinterpret_cast<Object*>(
base::NoBarrier_Load(reinterpret_cast<const base::AtomicWord*>(p)));
slot_snapshot_->add(p, object);
}
}
private:
SlotSnapshot* slot_snapshot_;
};
const SlotSnapshot& MakeSlotSnapshot(Map* map, HeapObject* object, int size) {
SlotSnapshottingVisitor visitor(&slot_snapshot_);
visitor.VisitPointer(object,
reinterpret_cast<Object**>(object->map_slot()));
JSObject::BodyDescriptor::IterateBody(object, size, &visitor);
return slot_snapshot_;
}
MarkingState marking_state(HeapObject* object) const {
return MarkingState::Internal(object);
}
ConcurrentMarkingDeque* deque_;
SlotSnapshot slot_snapshot_;
};
class ConcurrentMarking::Task : public CancelableTask {
......
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