| Index: src/heap/slot-set.h
|
| diff --git a/src/heap/slot-set.h b/src/heap/slot-set.h
|
| index 6144706f71e3ed34d81693557b4fe87492499619..e55ffe98e60aa88f74c2e886f226f37eb21bab93 100644
|
| --- a/src/heap/slot-set.h
|
| +++ b/src/heap/slot-set.h
|
| @@ -7,10 +7,13 @@
|
|
|
| #include "src/allocation.h"
|
| #include "src/base/bits.h"
|
| +#include "src/utils.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
|
|
| +enum SlotCallbackResult { KEEP_SLOT, REMOVE_SLOT };
|
| +
|
| // Data structure for maintaining a set of slots in a standard (non-large)
|
| // page. The base address of the page must be set with SetPageStart before any
|
| // operation.
|
| @@ -19,8 +22,6 @@ namespace internal {
|
| // Each bucket is a bitmap with a bit corresponding to a single slot offset.
|
| class SlotSet : public Malloced {
|
| public:
|
| - enum CallbackResult { KEEP_SLOT, REMOVE_SLOT };
|
| -
|
| SlotSet() {
|
| for (int i = 0; i < kBuckets; i++) {
|
| bucket[i] = nullptr;
|
| @@ -213,6 +214,124 @@ class SlotSet : public Malloced {
|
| Address page_start_;
|
| };
|
|
|
| +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
|
| +};
|
| +
|
| +// Data structure for maintaining a multiset of typed slots in a page.
|
| +// Typed slots can only appear in Code and JSFunction objects, so
|
| +// the maximum possible offset is limited by the LargePage::kMaxCodePageSize.
|
| +// The implementation is a chain of chunks, where each chunks is an array of
|
| +// encoded (slot type, slot offset) pairs.
|
| +// There is no duplicate detection and we do not expect many duplicates because
|
| +// typed slots contain V8 internal pointers that are not directly exposed to JS.
|
| +class TypedSlotSet {
|
| + public:
|
| + typedef uint32_t TypedSlot;
|
| + static const int kMaxOffset = 1 << 29;
|
| +
|
| + explicit TypedSlotSet(Address page_start) : page_start_(page_start) {
|
| + chunk_ = new Chunk(nullptr, kInitialBufferSize);
|
| + }
|
| +
|
| + ~TypedSlotSet() {
|
| + Chunk* chunk = chunk_;
|
| + while (chunk != nullptr) {
|
| + Chunk* next = chunk->next;
|
| + delete chunk;
|
| + chunk = next;
|
| + }
|
| + }
|
| +
|
| + // The slot offset specifies a slot at address page_start_ + offset.
|
| + void Insert(SlotType type, int offset) {
|
| + TypedSlot slot = ToTypedSlot(type, offset);
|
| + if (!chunk_->AddSlot(slot)) {
|
| + chunk_ = new Chunk(chunk_, NextCapacity(chunk_->capacity));
|
| + bool added = chunk_->AddSlot(slot);
|
| + DCHECK(added);
|
| + USE(added);
|
| + }
|
| + }
|
| +
|
| + // Iterate over all slots in the set and for each slot invoke the callback.
|
| + // If the callback returns REMOVE_SLOT then the slot is removed from the set.
|
| + // Returns the new number of slots.
|
| + //
|
| + // Sample usage:
|
| + // Iterate([](SlotType slot_type, Address slot_address) {
|
| + // if (good(slot_type, slot_address)) return KEEP_SLOT;
|
| + // else return REMOVE_SLOT;
|
| + // });
|
| + template <typename Callback>
|
| + int Iterate(Callback callback) {
|
| + STATIC_ASSERT(NUMBER_OF_SLOT_TYPES < 8);
|
| + const TypedSlot kRemovedSlot = TypeField::encode(NUMBER_OF_SLOT_TYPES);
|
| + Chunk* chunk = chunk_;
|
| + int new_count = 0;
|
| + while (chunk != nullptr) {
|
| + TypedSlot* buffer = chunk->buffer;
|
| + int count = chunk->count;
|
| + for (int i = 0; i < count; i++) {
|
| + TypedSlot slot = buffer[i];
|
| + if (slot != kRemovedSlot) {
|
| + SlotType type = TypeField::decode(slot);
|
| + Address addr = page_start_ + OffsetField::decode(slot);
|
| + if (callback(type, addr) == KEEP_SLOT) {
|
| + new_count++;
|
| + } else {
|
| + buffer[i] = kRemovedSlot;
|
| + }
|
| + }
|
| + }
|
| + chunk = chunk->next;
|
| + }
|
| + return new_count;
|
| + }
|
| +
|
| + private:
|
| + static const int kInitialBufferSize = 100;
|
| + static const int kMaxBufferSize = 16 * KB;
|
| +
|
| + static int NextCapacity(int capacity) {
|
| + return Min(kMaxBufferSize, capacity * 2);
|
| + }
|
| +
|
| + static TypedSlot ToTypedSlot(SlotType type, int offset) {
|
| + return TypeField::encode(type) | OffsetField::encode(offset);
|
| + }
|
| +
|
| + class OffsetField : public BitField<int, 0, 29> {};
|
| + class TypeField : public BitField<SlotType, 29, 3> {};
|
| +
|
| + struct Chunk : Malloced {
|
| + explicit Chunk(Chunk* next_chunk, int capacity)
|
| + : next(next_chunk), count(0), capacity(capacity) {
|
| + buffer = NewArray<TypedSlot>(capacity);
|
| + }
|
| + bool AddSlot(TypedSlot slot) {
|
| + if (count == capacity) return false;
|
| + buffer[count++] = slot;
|
| + return true;
|
| + }
|
| + ~Chunk() { DeleteArray(buffer); }
|
| + Chunk* next;
|
| + int count;
|
| + int capacity;
|
| + TypedSlot* buffer;
|
| + };
|
| +
|
| + Address page_start_;
|
| + Chunk* chunk_;
|
| +};
|
| +
|
| } // namespace internal
|
| } // namespace v8
|
|
|
|
|