Index: src/close-table.h |
diff --git a/src/close-table.h b/src/close-table.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7b966c80d65a7d39da9aacf779026907e69eca94 |
--- /dev/null |
+++ b/src/close-table.h |
@@ -0,0 +1,142 @@ |
+#ifndef CLOSE_TABLE_H |
+#define CLOSE_TABLE_H |
+ |
+#include "objects.h" |
+ |
+namespace v8 { |
+namespace internal { |
+ |
+// TODO(adamk): Merge this into objects.h once development is done |
+ |
+// Based on Tyler Close's "Deterministic Hash Table" as described |
+// by Jason Orendorff at |
+// https://wiki.mozilla.org/User:Jorend/Deterministic_hash_tables |
+// |
+// Memory layout: |
+// [0]: bucket count |
+// [1]: element count |
+// [2]: deleted element count |
+// [3]: "hash table", an array of length NumberOfBuckets() entry numbers |
+// followed by "data table", an array of length NumberOfBuckets() * |
+// kLoadFactor entries |
+template<int entrysize> |
+class CloseTable: public FixedArray { |
+ public: |
+ MUST_USE_RESULT static MaybeObject* Allocate(Heap* heap, int capacity); |
+ |
+ MUST_USE_RESULT MaybeObject* EnsureCapacity(int num_to_add); |
+ |
+ static CloseTable* cast(Object* obj) { |
+ ASSERT(obj->IsFixedArray()); // TODO(adamk): Make a map for this |
+ return reinterpret_cast<CloseTable*>(obj); |
+ } |
+ |
+ int FindEntry(Object* key); |
+ |
+ Object* KeyAt(int entry) { return get(EntryToIndex(entry)); } |
+ Object* ChainAt(int entry) { return get(EntryToIndex(entry) + kChainOffset); } |
+ |
+ int NumberOfElements() { |
+ return Smi::cast(get(kNumberOfElementsIndex))->value(); |
+ } |
+ void SetNumberOfElements(int num) { |
+ set(kNumberOfElementsIndex, Smi::FromInt(num)); |
+ } |
+ int NumberOfDeletedElements() { |
+ return Smi::cast(get(kNumberOfDeletedElementsIndex))->value(); |
+ } |
+ void SetNumberOfDeletedElements(int num) { |
+ set(kNumberOfDeletedElementsIndex, Smi::FromInt(num)); |
+ } |
+ |
+ int NumberOfBuckets() { |
+ return Smi::cast(get(kNumberOfBucketsIndex))->value(); |
+ } |
+ |
+ void SetNumberOfBuckets(int num) { |
+ set(kNumberOfBucketsIndex, Smi::FromInt(num)); |
+ } |
+ |
+ void ElementAdded() { |
+ SetNumberOfElements(NumberOfElements() + 1); |
+ } |
+ |
+ void ElementRemoved() { |
+ SetNumberOfElements(NumberOfElements() - 1); |
+ SetNumberOfDeletedElements(NumberOfDeletedElements() + 1); |
+ } |
+ |
+ int Capacity() { |
+ return NumberOfBuckets() * kLoadFactor; |
+ } |
+ |
+ int DataTableStartIndex() { |
+ return kHashTableStartIndex + NumberOfBuckets(); |
+ } |
+ |
+ int EntryToIndex(int entry) { |
+ return DataTableStartIndex() + (entry * kEntrySize); |
+ } |
+ |
+ MUST_USE_RESULT MaybeObject* Shrink(); |
+ MUST_USE_RESULT MaybeObject* Rehash(CloseTable* new_table); |
+ |
+ static const int kNotFound = -1; |
+ |
+ private: |
+ friend class CloseTableSet; |
+ friend class CloseTableMap; |
+ |
+ // Should be 8.0 / 3.0 but making it a double is complicated |
+ static const int kLoadFactor = 2; |
+ |
+ static const int kNumberOfBucketsIndex = 0; |
+ static const int kNumberOfElementsIndex = kNumberOfBucketsIndex + 1; |
+ static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1; |
+ static const int kHashTableStartIndex = kNumberOfDeletedElementsIndex + 1; |
+ |
+ static const int kEntrySize = entrysize + 1; |
+ static const int kChainOffset = entrysize; |
+}; |
+ |
+ |
+class CloseTableSet: public CloseTable<1> { |
+ public: |
+ static CloseTableSet* cast(Object* obj) { |
+ ASSERT(obj->IsFixedArray()); // TODO(adamk): Make a map for this |
+ return reinterpret_cast<CloseTableSet*>(obj); |
+ } |
+ |
+ bool Contains(Object* key); |
+ static Handle<CloseTableSet> Add(Handle<CloseTableSet> table, Handle<Object> key); |
+ static Handle<CloseTableSet> Remove(Handle<CloseTableSet> table, Handle<Object> key); |
+ static Handle<CloseTableSet> EnsureCapacity(Handle<CloseTableSet> table, int num_to_add); |
+ static Handle<CloseTableSet> Shrink(Handle<CloseTableSet>); |
+}; |
+ |
+ |
+class CloseTableMap: public CloseTable<2> { |
+ public: |
+ static CloseTableMap* cast(Object* obj) { |
+ ASSERT(obj->IsFixedArray()); // TODO(adamk): Make a map for this |
+ return reinterpret_cast<CloseTableMap*>(obj); |
+ } |
+ |
+ Object* Lookup(Object* key); |
+ static Handle<CloseTableMap> Put(Handle<CloseTableMap> table, Handle<Object> key, Handle<Object> value); |
+ static Handle<CloseTableMap> EnsureCapacity(Handle<CloseTableMap> table, int num_to_add); |
+ static Handle<CloseTableMap> Shrink(Handle<CloseTableMap>); |
+ |
+ private: |
+ Object* ValueAt(int entry) { |
+ return get(EntryToIndex(entry) + kValueOffset); |
+ } |
+ |
+ static const int kValueOffset = 1; |
+}; |
+ |
+ |
+} // namespace internal |
+} // namespace v8 |
+ |
+#endif //CLOSE_TABLE_H |