| Index: src/heap/mark-compact.h
|
| diff --git a/src/heap/mark-compact.h b/src/heap/mark-compact.h
|
| index 7c438132b4b7657d3ee80a55004e680d3a8fb45b..a6c0f796ef6836fb7affba8521e0945c40241080 100644
|
| --- a/src/heap/mark-compact.h
|
| +++ b/src/heap/mark-compact.h
|
| @@ -24,6 +24,8 @@ class CodeFlusher;
|
| class MarkCompactCollector;
|
| class MarkingVisitor;
|
| class RootMarkingVisitor;
|
| +class SlotsBuffer;
|
| +class SlotsBufferAllocator;
|
|
|
|
|
| class Marking : public AllStatic {
|
| @@ -258,178 +260,6 @@ class MarkingDeque {
|
| };
|
|
|
|
|
| -class SlotsBufferAllocator {
|
| - public:
|
| - SlotsBuffer* AllocateBuffer(SlotsBuffer* next_buffer);
|
| - void DeallocateBuffer(SlotsBuffer* buffer);
|
| -
|
| - void DeallocateChain(SlotsBuffer** buffer_address);
|
| -};
|
| -
|
| -
|
| -// SlotsBuffer records a sequence of slots that has to be updated
|
| -// after live objects were relocated from evacuation candidates.
|
| -// All slots are either untyped or typed:
|
| -// - Untyped slots are expected to contain a tagged object pointer.
|
| -// They are recorded by an address.
|
| -// - Typed slots are expected to contain an encoded pointer to a heap
|
| -// object where the way of encoding depends on the type of the slot.
|
| -// They are recorded as a pair (SlotType, slot address).
|
| -// We assume that zero-page is never mapped this allows us to distinguish
|
| -// untyped slots from typed slots during iteration by a simple comparison:
|
| -// if element of slots buffer is less than NUMBER_OF_SLOT_TYPES then it
|
| -// is the first element of typed slot's pair.
|
| -class SlotsBuffer {
|
| - public:
|
| - typedef Object** ObjectSlot;
|
| -
|
| - explicit SlotsBuffer(SlotsBuffer* next_buffer)
|
| - : idx_(0), chain_length_(1), next_(next_buffer) {
|
| - if (next_ != NULL) {
|
| - chain_length_ = next_->chain_length_ + 1;
|
| - }
|
| - }
|
| -
|
| - ~SlotsBuffer() {}
|
| -
|
| - void Add(ObjectSlot slot) {
|
| - DCHECK(0 <= idx_ && idx_ < kNumberOfElements);
|
| -#ifdef DEBUG
|
| - if (slot >= reinterpret_cast<ObjectSlot>(NUMBER_OF_SLOT_TYPES)) {
|
| - DCHECK_NOT_NULL(*slot);
|
| - }
|
| -#endif
|
| - slots_[idx_++] = slot;
|
| - }
|
| -
|
| - // Should be used for testing only.
|
| - ObjectSlot Get(intptr_t i) {
|
| - DCHECK(i >= 0 && i < kNumberOfElements);
|
| - return slots_[i];
|
| - }
|
| -
|
| - enum SlotType {
|
| - EMBEDDED_OBJECT_SLOT,
|
| - OBJECT_SLOT,
|
| - RELOCATED_CODE_OBJECT,
|
| - CELL_TARGET_SLOT,
|
| - CODE_TARGET_SLOT,
|
| - CODE_ENTRY_SLOT,
|
| - DEBUG_TARGET_SLOT,
|
| - NUMBER_OF_SLOT_TYPES
|
| - };
|
| -
|
| - static const char* SlotTypeToString(SlotType type) {
|
| - switch (type) {
|
| - case EMBEDDED_OBJECT_SLOT:
|
| - return "EMBEDDED_OBJECT_SLOT";
|
| - case OBJECT_SLOT:
|
| - return "OBJECT_SLOT";
|
| - case RELOCATED_CODE_OBJECT:
|
| - return "RELOCATED_CODE_OBJECT";
|
| - case CELL_TARGET_SLOT:
|
| - return "CELL_TARGET_SLOT";
|
| - case CODE_TARGET_SLOT:
|
| - return "CODE_TARGET_SLOT";
|
| - case CODE_ENTRY_SLOT:
|
| - return "CODE_ENTRY_SLOT";
|
| - case DEBUG_TARGET_SLOT:
|
| - return "DEBUG_TARGET_SLOT";
|
| - case NUMBER_OF_SLOT_TYPES:
|
| - return "NUMBER_OF_SLOT_TYPES";
|
| - }
|
| - return "UNKNOWN SlotType";
|
| - }
|
| -
|
| - void UpdateSlots(Heap* heap);
|
| -
|
| - void UpdateSlotsWithFilter(Heap* heap);
|
| -
|
| - SlotsBuffer* next() { return next_; }
|
| -
|
| - static int SizeOfChain(SlotsBuffer* buffer) {
|
| - if (buffer == NULL) return 0;
|
| - return static_cast<int>(buffer->idx_ +
|
| - (buffer->chain_length_ - 1) * kNumberOfElements);
|
| - }
|
| -
|
| - inline bool IsFull() { return idx_ == kNumberOfElements; }
|
| -
|
| - inline bool HasSpaceForTypedSlot() { return idx_ < kNumberOfElements - 1; }
|
| -
|
| - static void UpdateSlotsRecordedIn(Heap* heap, SlotsBuffer* buffer) {
|
| - while (buffer != NULL) {
|
| - buffer->UpdateSlots(heap);
|
| - buffer = buffer->next();
|
| - }
|
| - }
|
| -
|
| - enum AdditionMode { FAIL_ON_OVERFLOW, IGNORE_OVERFLOW };
|
| -
|
| - static bool ChainLengthThresholdReached(SlotsBuffer* buffer) {
|
| - return buffer != NULL && buffer->chain_length_ >= kChainLengthThreshold;
|
| - }
|
| -
|
| - INLINE(static bool AddToSynchronized(SlotsBufferAllocator* allocator,
|
| - SlotsBuffer** buffer_address,
|
| - base::Mutex* buffer_mutex,
|
| - ObjectSlot slot, AdditionMode mode)) {
|
| - base::LockGuard<base::Mutex> lock_guard(buffer_mutex);
|
| - return AddTo(allocator, buffer_address, slot, mode);
|
| - }
|
| -
|
| - INLINE(static bool AddTo(SlotsBufferAllocator* allocator,
|
| - SlotsBuffer** buffer_address, ObjectSlot slot,
|
| - AdditionMode mode)) {
|
| - SlotsBuffer* buffer = *buffer_address;
|
| - if (buffer == NULL || buffer->IsFull()) {
|
| - if (mode == FAIL_ON_OVERFLOW && ChainLengthThresholdReached(buffer)) {
|
| - allocator->DeallocateChain(buffer_address);
|
| - return false;
|
| - }
|
| - buffer = allocator->AllocateBuffer(buffer);
|
| - *buffer_address = buffer;
|
| - }
|
| - buffer->Add(slot);
|
| - return true;
|
| - }
|
| -
|
| - static bool IsTypedSlot(ObjectSlot slot);
|
| -
|
| - static bool AddToSynchronized(SlotsBufferAllocator* allocator,
|
| - SlotsBuffer** buffer_address,
|
| - base::Mutex* buffer_mutex, SlotType type,
|
| - Address addr, AdditionMode mode);
|
| -
|
| - static bool AddTo(SlotsBufferAllocator* allocator,
|
| - SlotsBuffer** buffer_address, SlotType type, Address addr,
|
| - AdditionMode mode);
|
| -
|
| - // Eliminates all stale entries from the slots buffer, i.e., slots that
|
| - // are not part of live objects anymore. This method must be called after
|
| - // marking, when the whole transitive closure is known and must be called
|
| - // before sweeping when mark bits are still intact.
|
| - static void RemoveInvalidSlots(Heap* heap, SlotsBuffer* buffer);
|
| -
|
| - // Eliminate all slots that are within the given address range.
|
| - static void RemoveObjectSlots(Heap* heap, SlotsBuffer* buffer,
|
| - Address start_slot, Address end_slot);
|
| -
|
| - // Ensures that there are no invalid slots in the chain of slots buffers.
|
| - static void VerifySlots(Heap* heap, SlotsBuffer* buffer);
|
| -
|
| - static const int kNumberOfElements = 1021;
|
| -
|
| - private:
|
| - static const int kChainLengthThreshold = 15;
|
| -
|
| - intptr_t idx_;
|
| - intptr_t chain_length_;
|
| - SlotsBuffer* next_;
|
| - ObjectSlot slots_[kNumberOfElements];
|
| -};
|
| -
|
| -
|
| // CodeFlusher collects candidates for code flushing during marking and
|
| // processes those candidates after marking has completed in order to
|
| // reset those functions referencing code objects that would otherwise
|
| @@ -589,10 +419,11 @@ class MarkCompactCollector {
|
| void RecordRelocSlot(RelocInfo* rinfo, Object* target);
|
| void RecordCodeEntrySlot(HeapObject* object, Address slot, Code* target);
|
| void RecordCodeTargetPatch(Address pc, Code* target);
|
| + void RecordSlot(HeapObject* object, Object** slot, Object* target);
|
| + void ForceRecordSlot(HeapObject* object, Object** slot, Object* target);
|
|
|
| - INLINE(void RecordSlot(
|
| - HeapObject* object, Object** slot, Object* target,
|
| - SlotsBuffer::AdditionMode mode = SlotsBuffer::FAIL_ON_OVERFLOW));
|
| + void UpdateSlots(SlotsBuffer* buffer);
|
| + void UpdateSlotsRecordedIn(SlotsBuffer* buffer);
|
|
|
| void MigrateObject(HeapObject* dst, HeapObject* src, int size,
|
| AllocationSpace to_old_space);
|
| @@ -727,7 +558,7 @@ class MarkCompactCollector {
|
|
|
| bool evacuation_;
|
|
|
| - SlotsBufferAllocator slots_buffer_allocator_;
|
| + SlotsBufferAllocator* slots_buffer_allocator_;
|
|
|
| SlotsBuffer* migration_slots_buffer_;
|
|
|
|
|