OLD | NEW |
(Empty) | |
| 1 #ifndef CLOSE_TABLE_H |
| 2 #define CLOSE_TABLE_H |
| 3 |
| 4 #include "objects.h" |
| 5 |
| 6 namespace v8 { |
| 7 namespace internal { |
| 8 |
| 9 // TODO(adamk): Merge this into objects.h once development is done |
| 10 |
| 11 // Based on Tyler Close's "Deterministic Hash Table" as described |
| 12 // by Jason Orendorff at |
| 13 // https://wiki.mozilla.org/User:Jorend/Deterministic_hash_tables |
| 14 // |
| 15 // Memory layout: |
| 16 // [0]: bucket count |
| 17 // [1]: element count |
| 18 // [2]: deleted element count |
| 19 // [3]: "hash table", an array of length NumberOfBuckets() entry numbers |
| 20 // followed by "data table", an array of length NumberOfBuckets() * |
| 21 // kLoadFactor entries |
| 22 template<int entrysize> |
| 23 class CloseTable: public FixedArray { |
| 24 public: |
| 25 MUST_USE_RESULT static MaybeObject* Allocate(Heap* heap, int capacity); |
| 26 |
| 27 MUST_USE_RESULT MaybeObject* EnsureCapacity(int num_to_add); |
| 28 |
| 29 static CloseTable* cast(Object* obj) { |
| 30 ASSERT(obj->IsFixedArray()); // TODO(adamk): Make a map for this |
| 31 return reinterpret_cast<CloseTable*>(obj); |
| 32 } |
| 33 |
| 34 int FindEntry(Object* key); |
| 35 |
| 36 Object* KeyAt(int entry) { return get(EntryToIndex(entry)); } |
| 37 Object* ChainAt(int entry) { return get(EntryToIndex(entry) + kChainOffset); } |
| 38 |
| 39 int NumberOfElements() { |
| 40 return Smi::cast(get(kNumberOfElementsIndex))->value(); |
| 41 } |
| 42 void SetNumberOfElements(int num) { |
| 43 set(kNumberOfElementsIndex, Smi::FromInt(num)); |
| 44 } |
| 45 int NumberOfDeletedElements() { |
| 46 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value(); |
| 47 } |
| 48 void SetNumberOfDeletedElements(int num) { |
| 49 set(kNumberOfDeletedElementsIndex, Smi::FromInt(num)); |
| 50 } |
| 51 |
| 52 int NumberOfBuckets() { |
| 53 return Smi::cast(get(kNumberOfBucketsIndex))->value(); |
| 54 } |
| 55 |
| 56 void SetNumberOfBuckets(int num) { |
| 57 set(kNumberOfBucketsIndex, Smi::FromInt(num)); |
| 58 } |
| 59 |
| 60 void ElementAdded() { |
| 61 SetNumberOfElements(NumberOfElements() + 1); |
| 62 } |
| 63 |
| 64 void ElementRemoved() { |
| 65 SetNumberOfElements(NumberOfElements() - 1); |
| 66 SetNumberOfDeletedElements(NumberOfDeletedElements() + 1); |
| 67 } |
| 68 |
| 69 int Capacity() { |
| 70 return NumberOfBuckets() * kLoadFactor; |
| 71 } |
| 72 |
| 73 int DataTableStartIndex() { |
| 74 return kHashTableStartIndex + NumberOfBuckets(); |
| 75 } |
| 76 |
| 77 int EntryToIndex(int entry) { |
| 78 return DataTableStartIndex() + (entry * kEntrySize); |
| 79 } |
| 80 |
| 81 MUST_USE_RESULT MaybeObject* Shrink(); |
| 82 MUST_USE_RESULT MaybeObject* Rehash(CloseTable* new_table); |
| 83 |
| 84 static const int kNotFound = -1; |
| 85 |
| 86 private: |
| 87 friend class CloseTableSet; |
| 88 friend class CloseTableMap; |
| 89 |
| 90 // Should be 8.0 / 3.0 but making it a double is complicated |
| 91 static const int kLoadFactor = 2; |
| 92 |
| 93 static const int kNumberOfBucketsIndex = 0; |
| 94 static const int kNumberOfElementsIndex = kNumberOfBucketsIndex + 1; |
| 95 static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1; |
| 96 static const int kHashTableStartIndex = kNumberOfDeletedElementsIndex + 1; |
| 97 |
| 98 static const int kEntrySize = entrysize + 1; |
| 99 static const int kChainOffset = entrysize; |
| 100 }; |
| 101 |
| 102 |
| 103 class CloseTableSet: public CloseTable<1> { |
| 104 public: |
| 105 static CloseTableSet* cast(Object* obj) { |
| 106 ASSERT(obj->IsFixedArray()); // TODO(adamk): Make a map for this |
| 107 return reinterpret_cast<CloseTableSet*>(obj); |
| 108 } |
| 109 |
| 110 bool Contains(Object* key); |
| 111 static Handle<CloseTableSet> Add(Handle<CloseTableSet> table, Handle<Object> k
ey); |
| 112 static Handle<CloseTableSet> Remove(Handle<CloseTableSet> table, Handle<Object
> key); |
| 113 static Handle<CloseTableSet> EnsureCapacity(Handle<CloseTableSet> table, int n
um_to_add); |
| 114 static Handle<CloseTableSet> Shrink(Handle<CloseTableSet>); |
| 115 }; |
| 116 |
| 117 |
| 118 class CloseTableMap: public CloseTable<2> { |
| 119 public: |
| 120 static CloseTableMap* cast(Object* obj) { |
| 121 ASSERT(obj->IsFixedArray()); // TODO(adamk): Make a map for this |
| 122 return reinterpret_cast<CloseTableMap*>(obj); |
| 123 } |
| 124 |
| 125 Object* Lookup(Object* key); |
| 126 static Handle<CloseTableMap> Put(Handle<CloseTableMap> table, Handle<Object> k
ey, Handle<Object> value); |
| 127 static Handle<CloseTableMap> EnsureCapacity(Handle<CloseTableMap> table, int n
um_to_add); |
| 128 static Handle<CloseTableMap> Shrink(Handle<CloseTableMap>); |
| 129 |
| 130 private: |
| 131 Object* ValueAt(int entry) { |
| 132 return get(EntryToIndex(entry) + kValueOffset); |
| 133 } |
| 134 |
| 135 static const int kValueOffset = 1; |
| 136 }; |
| 137 |
| 138 |
| 139 } // namespace internal |
| 140 } // namespace v8 |
| 141 |
| 142 #endif //CLOSE_TABLE_H |
OLD | NEW |