Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Unified Diff: runtime/vm/hash_table.h

Issue 428273002: Handle-like interface for HashTable. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | runtime/vm/hash_table_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/hash_table.h
===================================================================
--- runtime/vm/hash_table.h (revision 38793)
+++ runtime/vm/hash_table.h (working copy)
@@ -43,17 +43,22 @@
//
// The classes all wrap an Array handle, and metods like HashSet::Insert can
// trigger growth into a new RawArray, updating the handle. Debug mode asserts
-// that 'Release' was called to get the final RawArray before destruction.
+// that 'Release' was called once to access the final array before destruction.
//
// Example use:
-// typedef UnorderedHashMap<FooTraits> ResolvedNamesMap;
+// typedef UnorderedHashMap<FooTraits> FooMap;
// ...
-// ResolvedNamesMap cache(Array::Handle(resolved_names()));
+// FooMap cache(get_foo_cache());
// cache.UpdateOrInsert(name0, obj0);
// cache.UpdateOrInsert(name1, obj1);
// ...
-// StorePointer(&raw_ptr()->resolved_names_, cache.Release());
+// set_foo_cache(cache.Release());
//
+// If you *know* that no mutating operations were called, you can optimize:
+// ...
+// obj ^= cache.GetOrNull(name);
+// ASSERT(cache.Release().raw() == get_foo_cache());
+//
// TODO(koda): When exposing these to Dart code, document and assert that
// KeyTraits methods must not run Dart code (since the C++ code doesn't check
// for concurrent modification).
@@ -79,17 +84,25 @@
class HashTable : public ValueObject {
public:
typedef KeyTraits Traits;
- explicit HashTable(Array& data) : data_(data) {}
+ // Uses 'isolate' for handle allocation. 'Release' must be called at the end
+ // to obtain the final table after potential growth/shrinkage.
+ HashTable(Isolate* isolate, RawArray* data)
+ : isolate_(isolate), data_(&Array::Handle(isolate_, data)) {}
+ // Like above, except uses current isolate.
+ explicit HashTable(RawArray* data)
+ : isolate_(Isolate::Current()), data_(&Array::Handle(isolate_, data)) {}
- RawArray* Release() {
- ASSERT(!data_.IsNull());
- RawArray* array = data_.raw();
- data_ = Array::null();
- return array;
+ Array& Release() {
+ ASSERT(data_ != NULL);
+ Array* result = data_;
+ // Ensure that no methods are called after 'Release'.
+ data_ = NULL;
+ return *result;
}
~HashTable() {
- ASSERT(data_.IsNull());
+ // Ensure that 'Release' was called.
+ ASSERT(data_ == NULL);
}
// Returns a backing storage size such that 'num_occupied' distinct keys can
@@ -103,12 +116,12 @@
// Initializes an empty table.
void Initialize() const {
- ASSERT(data_.Length() >= ArrayLengthForNumOccupied(0));
- Smi& zero = Smi::Handle(Smi::New(0));
- data_.SetAt(kOccupiedEntriesIndex, zero);
- data_.SetAt(kDeletedEntriesIndex, zero);
- for (intptr_t i = kHeaderSize; i < data_.Length(); ++i) {
- data_.SetAt(i, Object::sentinel());
+ ASSERT(data_->Length() >= ArrayLengthForNumOccupied(0));
+ Smi& zero = Smi::Handle(isolate(), Smi::New(0));
+ data_->SetAt(kOccupiedEntriesIndex, zero);
+ data_->SetAt(kDeletedEntriesIndex, zero);
+ for (intptr_t i = kHeaderSize; i < data_->Length(); ++i) {
+ data_->SetAt(i, Object::sentinel());
}
}
@@ -124,7 +137,7 @@
ASSERT(NumOccupied() < NumEntries());
// TODO(koda): Add salt.
intptr_t probe = static_cast<uword>(KeyTraits::Hash(key)) % NumEntries();
- Object& obj = Object::Handle();
+ Object& obj = Object::Handle(isolate());
// TODO(koda): Consider quadratic probing.
for (; ; probe = (probe + 1) % NumEntries()) {
if (IsUnused(probe)) {
@@ -151,7 +164,7 @@
ASSERT(entry != NULL);
ASSERT(NumOccupied() < NumEntries());
intptr_t probe = static_cast<uword>(KeyTraits::Hash(key)) % NumEntries();
- Object& obj = Object::Handle();
+ Object& obj = Object::Handle(isolate());
intptr_t deleted = -1;
// TODO(koda): Consider quadratic probing.
for (; ; probe = (probe + 1) % NumEntries()) {
@@ -205,14 +218,14 @@
}
RawObject* GetPayload(intptr_t entry, intptr_t component) const {
ASSERT(IsOccupied(entry));
- return data_.At(PayloadIndex(entry, component));
+ return data_->At(PayloadIndex(entry, component));
}
void UpdatePayload(intptr_t entry,
intptr_t component,
const Object& value) const {
ASSERT(IsOccupied(entry));
ASSERT(0 <= component && component < kPayloadSize);
- data_.SetAt(PayloadIndex(entry, component), value);
+ data_->SetAt(PayloadIndex(entry, component), value);
}
// Deletes both the key and payload of the specified entry.
void DeleteEntry(intptr_t entry) const {
@@ -225,7 +238,7 @@
AdjustSmiValueAt(kDeletedEntriesIndex, 1);
}
intptr_t NumEntries() const {
- return (data_.Length() - kFirstKeyIndex) / kEntrySize;
+ return (data_->Length() - kFirstKeyIndex) / kEntrySize;
}
intptr_t NumUnused() const {
return NumEntries() - NumOccupied() - NumDeleted();
@@ -256,29 +269,34 @@
}
RawObject* InternalGetKey(intptr_t entry) const {
- return data_.At(KeyIndex(entry));
+ return data_->At(KeyIndex(entry));
}
void InternalSetKey(intptr_t entry, const Object& key) const {
- data_.SetAt(KeyIndex(entry), key);
+ data_->SetAt(KeyIndex(entry), key);
}
intptr_t GetSmiValueAt(intptr_t index) const {
- ASSERT(Object::Handle(data_.At(index)).IsSmi());
- return Smi::Value(Smi::RawCast(data_.At(index)));
+ ASSERT(Object::Handle(isolate(), data_->At(index)).IsSmi());
+ return Smi::Value(Smi::RawCast(data_->At(index)));
}
void SetSmiValueAt(intptr_t index, intptr_t value) const {
- const Smi& smi = Smi::Handle(Smi::New(value));
- data_.SetAt(index, smi);
+ const Smi& smi = Smi::Handle(isolate(), Smi::New(value));
+ data_->SetAt(index, smi);
}
void AdjustSmiValueAt(intptr_t index, intptr_t delta) const {
SetSmiValueAt(index, (GetSmiValueAt(index) + delta));
}
- Array& data_;
+ Isolate* isolate() const { return isolate_; }
+ Isolate* isolate_;
+ // This is a pointer rather than a reference, to enable Release nulling it,
+ // preventing post-Release modification.
+ Array* data_;
+
friend class HashTables;
};
@@ -289,7 +307,9 @@
public:
typedef HashTable<KeyTraits, kUserPayloadSize, 0> BaseTable;
static const intptr_t kPayloadSize = kUserPayloadSize;
- explicit UnorderedHashTable(Array& data) : BaseTable(data) {}
+ explicit UnorderedHashTable(RawArray* data) : BaseTable(data) {}
+ UnorderedHashTable(Isolate* isolate, RawArray* data)
+ : BaseTable(isolate, data) {}
// Note: Does not check for concurrent modification.
class Iterator {
public:
@@ -326,7 +346,9 @@
typedef HashTable<KeyTraits, kUserPayloadSize + 1, 1> BaseTable;
static const intptr_t kPayloadSize = kUserPayloadSize;
static const intptr_t kNextEnumIndex = BaseTable::kMetaDataIndex;
- explicit EnumIndexHashTable(Array& data) : BaseTable(data) {}
+ EnumIndexHashTable(Isolate* isolate, RawArray* data)
+ : BaseTable(isolate, data) {}
+ explicit EnumIndexHashTable(RawArray* data) : BaseTable(data) {}
// Note: Does not check for concurrent modification.
class Iterator {
public:
@@ -369,8 +391,8 @@
void InsertKey(intptr_t entry, const Object& key) const {
BaseTable::InsertKey(entry, key);
- const Smi& next_enum_index =
- Smi::Handle(Smi::New(BaseTable::GetSmiValueAt(kNextEnumIndex)));
+ const Smi& next_enum_index = Smi::Handle(BaseTable::isolate(),
+ Smi::New(BaseTable::GetSmiValueAt(kNextEnumIndex)));
BaseTable::UpdatePayload(entry, kPayloadSize, next_enum_index);
// TODO(koda): Handle possible Smi overflow from repeated insert/delete.
BaseTable::AdjustSmiValueAt(kNextEnumIndex, 1);
@@ -386,10 +408,10 @@
template<typename Table>
static RawArray* New(intptr_t initial_capacity,
Heap::Space space = Heap::kNew) {
- Table table(Array::Handle(Array::New(
- Table::ArrayLengthForNumOccupied(initial_capacity), space)));
+ Table table(Array::New(
+ Table::ArrayLengthForNumOccupied(initial_capacity), space));
table.Initialize();
- return table.Release();
+ return table.Release().raw();
}
// Clears 'to' and inserts all elements from 'from', in iteration order.
@@ -425,11 +447,11 @@
}
double target = (low + high) / 2.0;
intptr_t new_capacity = (1 + table.NumOccupied()) / target;
- Table new_table(Array::Handle(New<Table>(
+ Table new_table(New<Table>(
new_capacity,
- table.data_.IsOld() ? Heap::kOld : Heap::kNew)));
+ table.data_->IsOld() ? Heap::kOld : Heap::kNew));
Copy(table, new_table);
- table.data_ = new_table.Release();
+ *table.data_ = new_table.Release().raw();
}
// Serializes a table by concatenating its entries as an array.
@@ -459,7 +481,8 @@
template<typename BaseIterTable>
class HashMap : public BaseIterTable {
public:
- explicit HashMap(Array& data) : BaseIterTable(data) {}
+ explicit HashMap(RawArray* data) : BaseIterTable(data) {}
+ HashMap(Isolate* isolate, RawArray* data) : BaseIterTable(isolate, data) {}
template<typename Key>
RawObject* GetOrNull(const Key& key, bool* present = NULL) const {
intptr_t entry = BaseIterTable::FindKey(key);
@@ -506,7 +529,7 @@
EnsureCapacity();
intptr_t entry = -1;
if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) {
- Object& new_key = Object::Handle(
+ Object& new_key = Object::Handle(BaseIterTable::isolate(),
BaseIterTable::BaseTable::Traits::NewKey(key));
BaseIterTable::InsertKey(entry, new_key);
BaseIterTable::UpdatePayload(entry, 0, value_if_absent);
@@ -539,7 +562,8 @@
class UnorderedHashMap : public HashMap<UnorderedHashTable<KeyTraits, 1> > {
public:
typedef HashMap<UnorderedHashTable<KeyTraits, 1> > BaseMap;
- explicit UnorderedHashMap(Array& data) : BaseMap(data) {}
+ explicit UnorderedHashMap(RawArray* data) : BaseMap(data) {}
+ UnorderedHashMap(Isolate* isolate, RawArray* data) : BaseMap(isolate, data) {}
};
@@ -547,14 +571,16 @@
class EnumIndexHashMap : public HashMap<EnumIndexHashTable<KeyTraits, 1> > {
public:
typedef HashMap<EnumIndexHashTable<KeyTraits, 1> > BaseMap;
- explicit EnumIndexHashMap(Array& data) : BaseMap(data) {}
+ explicit EnumIndexHashMap(RawArray* data) : BaseMap(data) {}
+ EnumIndexHashMap(Isolate* isolate, RawArray* data) : BaseMap(isolate, data) {}
};
template<typename BaseIterTable>
class HashSet : public BaseIterTable {
public:
- explicit HashSet(Array& data) : BaseIterTable(data) {}
+ explicit HashSet(RawArray* data) : BaseIterTable(data) {}
+ HashSet(Isolate* isolate, RawArray* data) : BaseIterTable(isolate, data) {}
bool Insert(const Object& key) {
EnsureCapacity();
intptr_t entry = -1;
@@ -584,7 +610,7 @@
EnsureCapacity();
intptr_t entry = -1;
if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) {
- Object& new_key = Object::Handle(
+ Object& new_key = Object::Handle(BaseIterTable::isolate(),
BaseIterTable::BaseTable::Traits::NewKey(key));
BaseIterTable::InsertKey(entry, new_key);
return new_key.raw();
@@ -625,7 +651,8 @@
class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > {
public:
typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet;
- explicit UnorderedHashSet(Array& data) : BaseSet(data) {}
+ explicit UnorderedHashSet(RawArray* data) : BaseSet(data) {}
+ UnorderedHashSet(Isolate* isolate, RawArray* data) : BaseSet(isolate, data) {}
};
@@ -633,7 +660,8 @@
class EnumIndexHashSet : public HashSet<EnumIndexHashTable<KeyTraits, 0> > {
public:
typedef HashSet<EnumIndexHashTable<KeyTraits, 0> > BaseSet;
- explicit EnumIndexHashSet(Array& data) : BaseSet(data) {}
+ explicit EnumIndexHashSet(RawArray* data) : BaseSet(data) {}
+ EnumIndexHashSet(Isolate* isolate, RawArray* data) : BaseSet(isolate, data) {}
};
} // namespace dart
« no previous file with comments | « no previous file | runtime/vm/hash_table_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698