diff --git a/runtime/lib/expando_patch.dart b/runtime/lib/expando_patch.dart index 5de84c42a7a..d6145358874 100644 --- a/runtime/lib/expando_patch.dart +++ b/runtime/lib/expando_patch.dart @@ -3,135 +3,61 @@ // BSD-style license that can be found in the LICENSE file. patch class Expando { - /* patch */ Expando([this.name]) - : _data = new List(_minSize), - _used = 0; - - static const _minSize = 8; - static final _deletedEntry = new _WeakProperty(null, null); + /* patch */ Expando([this.name]) : _data = new List(); /* patch */ T operator[](Object object) { _checkType(object); - - var mask = _size - 1; - var idx = object.hashCode & mask; - var wp = _data[idx]; - - while (wp != null) { - if (identical(wp.key, object)) { - return wp.value; - } else if (wp.key == null) { - // This entry has been cleared by the GC. - _data[idx] = _deletedEntry; + var doCompact = false; + var result = null; + for (int i = 0; i < _data.length; ++i) { + var key = _data[i].key; + if (identical(key, object)) { + result = _data[i].value; + break; + } + if (key == null) { + doCompact = true; + _data[i] = null; } - idx = (idx + 1) & mask; - wp = _data[idx]; } - - return null; + if (doCompact) { + _data = _data.where((e) => (e != null)).toList(); + } + return result; } /* patch */ void operator[]=(Object object, T value) { _checkType(object); - - var mask = _size - 1; - var idx = object.hashCode & mask; - var empty_idx = -1; - var wp = _data[idx]; - - while (wp != null) { - if (identical(wp.key, object)) { - if (value != null) { - // Update the associated value. - wp.value = value; - } else { - // Mark the entry as deleted. - _data[idx] = _deletedEntry; - } - return; - } else if ((empty_idx < 0) && identical(wp, _deletedEntry)) { - empty_idx = idx; // Insert at this location if not found. - } else if (wp.key == null) { - // This entry has been cleared by the GC. - _data[idx] = _deletedEntry; - if (empty_idx < 0) { - empty_idx = idx; // Insert at this location if not found. - } + var doCompact = false; + int i = 0; + for (; i < _data.length; ++i) { + var key = _data[i].key; + if (identical(key, object)) { + break; } - idx = (idx + 1) & mask; - wp = _data[idx]; - } - - if (value == null) { - // Not entering a null value. We just needed to make sure to clear an - // existing value if it existed. - return; - } - - if (empty_idx >= 0) { - // We will be reusing the empty slot below. - _used--; - idx = empty_idx; - } - - if (_used < _limit) { - _data[idx] = new _WeakProperty(object, value); - _used++; - return; - } - - // Grow/reallocate if too many slots have been used. - _rehash(); - this[object] = value; // Recursively add the value. - } - - _rehash() { - // Determine the population count of the map to allocate an appropriately - // sized map below. - var count = 0; - var old_data = _data; - var len = old_data.length; - for (var i = 0; i < len; i++) { - var entry = old_data[i]; - if ((entry != null) && (entry.key != null)) { - // Only count non-cleared entries. - count++; + if (key == null) { + doCompact = true; + _data[i] = null; } } - - var new_size = _size; - if (count <= (new_size >> 2)) { - new_size = new_size >> 1; - } else if (count > (new_size >> 1)) { - new_size = new_size << 1; + if (i != _data.length && value == null) { + doCompact = true; + _data[i] = null; + } else if (i != _data.length) { + _data[i].value = value; + } else { + _data.add(new _WeakProperty(object, value)); } - new_size = (new_size < _minSize) ? _minSize : new_size; - - // Reset the mappings to empty so that we can just add the existing - // valid entries. - _data = new List(new_size); - _used = 0; - - for (var i = 0; i < old_data.length; i++) { - var entry = old_data[i]; - if ((entry != null) && (entry.key != null)) { - this[entry.key] = entry.value; - } + if (doCompact) { + _data = _data.where((e) => (e != null)).toList(); } } static _checkType(object) { - if ((object == null) || - (object is bool) || - (object is num) || - (object is String)) { + if (object == null || object is bool || object is num || object is String) { throw new ArgumentError(object); } } - get _size => _data.length; - get _limit => (3 * (_size ~/ 4)); - List _data; - int _used; // Number of used (active and deleted) slots. } diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc index d9b0c6529da..a4a3faf3584 100644 --- a/runtime/lib/object.cc +++ b/runtime/lib/object.cc @@ -5,7 +5,6 @@ #include "vm/bootstrap_natives.h" #include "vm/exceptions.h" -#include "vm/heap.h" #include "vm/native_entry.h" #include "vm/object.h" #include "vm/stack_frame.h" @@ -22,22 +21,6 @@ DEFINE_NATIVE_ENTRY(Object_cid, 1) { } -DEFINE_NATIVE_ENTRY(Object_getHash, 1) { - const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0)); - Heap* heap = isolate->heap(); - return Smi::New(heap->GetHash(instance.raw())); -} - - -DEFINE_NATIVE_ENTRY(Object_setHash, 2) { - const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0)); - GET_NON_NULL_NATIVE_ARGUMENT(Smi, hash, arguments->NativeArgAt(1)); - Heap* heap = isolate->heap(); - heap->SetHash(instance.raw(), hash.Value()); - return Object::null(); -} - - DEFINE_NATIVE_ENTRY(Object_toString, 1) { const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0)); const char* c_str = instance.ToCString(); diff --git a/runtime/lib/object_patch.dart b/runtime/lib/object_patch.dart index 8ef62a93a9f..72b158ab08b 100644 --- a/runtime/lib/object_patch.dart +++ b/runtime/lib/object_patch.dart @@ -4,26 +4,20 @@ patch class Object { - // Helpers used to implement hashCode. If a hashCode is used, we remember it - // in a weak table in the VM. A new hashCode value is calculated using a + // Helpers used to implement hashCode. If a hashCode is used we remember it + // using an Expando object. A new hashCode value is calculated using a Random // number generator. - static final _hashCodeRnd = new Random(); - - static _getHash(obj) native "Object_getHash"; - static _setHash(obj, hash) native "Object_setHash"; + static Expando _hashCodeExp = new Expando("Object.hashCode"); + static Random _hashCodeRnd = new Random(); /* patch */ int get hashCode { if (this == null) { return 2011; // The year Dart was announced and a prime. } - var result = _getHash(this); - if (result == 0) { - // We want the hash to be a Smi value greater than 0. - result = _hashCodeRnd.nextInt(0x40000000); - while (result == 0) { - result = _hashCodeRnd.nextInt(0x40000000); - } - _setHash(this, result); + var result = _hashCodeExp[this]; + if (result == null) { + result = _hashCodeRnd.nextInt(0x40000000); // Stay in Smi range. + _hashCodeExp[this] = result; } return result; } diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h index 2dae0c42c50..29b92533ac7 100644 --- a/runtime/vm/bootstrap_natives.h +++ b/runtime/vm/bootstrap_natives.h @@ -13,8 +13,6 @@ namespace dart { // List of bootstrap native entry points used in the core dart library. #define BOOTSTRAP_NATIVE_LIST(V) \ - V(Object_getHash, 1) \ - V(Object_setHash, 2) \ V(Object_toString, 1) \ V(Object_noSuchMethod, 6) \ V(Object_runtimeType, 1) \ diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc index b7ae253b911..509f422cd9e 100644 --- a/runtime/vm/gc_marker.cc +++ b/runtime/vm/gc_marker.cc @@ -379,21 +379,18 @@ void GCMarker::ProcessWeakProperty(RawWeakProperty* raw_weak, } -void GCMarker::ProcessWeakTables(PageSpace* page_space) { - for (int sel = 0; - sel < Heap::kNumWeakSelectors; - sel++) { - WeakTable* table = heap_->GetWeakTable( - Heap::kOld, static_cast(sel)); - intptr_t size = table->size(); - for (intptr_t i = 0; i < size; i++) { - if (table->IsValidEntryAt(i)) { - RawObject* raw_obj = table->ObjectAt(i); - ASSERT(raw_obj->IsHeapObject()); - if (!raw_obj->IsMarked()) { - table->InvalidateAt(i); - } - } +void GCMarker::ProcessPeerReferents(PageSpace* page_space) { + PageSpace::PeerTable* peer_table = page_space->GetPeerTable(); + PageSpace::PeerTable::iterator it = peer_table->begin(); + while (it != peer_table->end()) { + RawObject* raw_obj = it->first; + ASSERT(raw_obj->IsHeapObject()); + if (raw_obj->IsMarked()) { + // The object has survived. Do nothing. + ++it; + } else { + // The object has become garbage. Remove its record. + peer_table->erase(it++); } } } @@ -411,7 +408,7 @@ void GCMarker::MarkObjects(Isolate* isolate, MarkingWeakVisitor mark_weak; IterateWeakRoots(isolate, &mark_weak, invoke_api_callbacks); mark.Finalize(); - ProcessWeakTables(page_space); + ProcessPeerReferents(page_space); Epilogue(isolate, invoke_api_callbacks); } diff --git a/runtime/vm/gc_marker.h b/runtime/vm/gc_marker.h index 36c899c9375..576a7ad1a93 100644 --- a/runtime/vm/gc_marker.h +++ b/runtime/vm/gc_marker.h @@ -41,7 +41,7 @@ class GCMarker : public ValueObject { void IterateWeakReferences(Isolate* isolate, MarkingVisitor* visitor); void DrainMarkingStack(Isolate* isolate, MarkingVisitor* visitor); void ProcessWeakProperty(RawWeakProperty* raw_weak, MarkingVisitor* visitor); - void ProcessWeakTables(PageSpace* page_space); + void ProcessPeerReferents(PageSpace* page_space); Heap* heap_; diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc index 54222fba53f..5dcc4b9be01 100644 --- a/runtime/vm/heap.cc +++ b/runtime/vm/heap.cc @@ -19,7 +19,6 @@ #include "vm/stack_frame.h" #include "vm/verifier.h" #include "vm/virtual_memory.h" -#include "vm/weak_table.h" namespace dart { @@ -36,13 +35,7 @@ DEFINE_FLAG(int, old_gen_heap_size, Heap::kHeapSizeInMB, "old gen heap size in MB," "e.g: --old_gen_heap_size=1024 allocates a 1024MB old gen heap"); - Heap::Heap() : read_only_(false), gc_in_progress_(false) { - for (int sel = 0; - sel < kNumWeakSelectors; - sel++) { - new_weak_tables_[sel] = new WeakTable(0); - old_weak_tables_[sel] = new WeakTable(0); - } +Heap::Heap() : read_only_(false), gc_in_progress_(false) { new_space_ = new Scavenger(this, (FLAG_new_gen_heap_size * MB), kNewObjectAlignmentOffset); @@ -367,36 +360,30 @@ const char* Heap::GCReasonToString(GCReason gc_reason) { } -int64_t Heap::PeerCount() const { - return new_weak_tables_[kPeers]->count() + old_weak_tables_[kPeers]->count(); -} - - -int64_t Heap::HashCount() const { - return - new_weak_tables_[kHashes]->count() + old_weak_tables_[kHashes]->count(); -} - - -intptr_t Heap::GetWeakEntry(RawObject* raw_obj, WeakSelector sel) const { +void Heap::SetPeer(RawObject* raw_obj, void* peer) { if (raw_obj->IsNewObject()) { - return new_weak_tables_[sel]->GetValue(raw_obj); - } - ASSERT(raw_obj->IsOldObject()); - return old_weak_tables_[sel]->GetValue(raw_obj); -} - - -void Heap::SetWeakEntry(RawObject* raw_obj, WeakSelector sel, intptr_t val) { - if (raw_obj->IsNewObject()) { - new_weak_tables_[sel] = new_weak_tables_[sel]->SetValue(raw_obj, val); + new_space_->SetPeer(raw_obj, peer); } else { ASSERT(raw_obj->IsOldObject()); - old_weak_tables_[sel] = old_weak_tables_[sel]->SetValue(raw_obj, val); + old_space_->SetPeer(raw_obj, peer); } } +void* Heap::GetPeer(RawObject* raw_obj) { + if (raw_obj->IsNewObject()) { + return new_space_->GetPeer(raw_obj); + } + ASSERT(raw_obj->IsOldObject()); + return old_space_->GetPeer(raw_obj); +} + + +int64_t Heap::PeerCount() const { + return new_space_->PeerCount() + old_space_->PeerCount(); +} + + void Heap::RecordBeforeGC(Space space, GCReason reason) { ASSERT(!gc_in_progress_); gc_in_progress_ = true; diff --git a/runtime/vm/heap.h b/runtime/vm/heap.h index 6dd44192735..359efeae276 100644 --- a/runtime/vm/heap.h +++ b/runtime/vm/heap.h @@ -11,7 +11,6 @@ #include "vm/globals.h" #include "vm/pages.h" #include "vm/scavenger.h" -#include "vm/weak_table.h" namespace dart { @@ -34,12 +33,6 @@ class Heap { kCode, }; - enum WeakSelector { - kPeers = 0, - kHashes, - kNumWeakSelectors - }; - enum ApiCallbacks { kIgnoreApiCallbacks, kInvokeApiCallbacks @@ -175,45 +168,17 @@ class Heap { static const char* GCReasonToString(GCReason gc_reason); - // Associate a peer with an object. A non-existent peer is equal to NULL. - void SetPeer(RawObject* raw_obj, void* peer) { - SetWeakEntry(raw_obj, kPeers, reinterpret_cast(peer)); - } - void* GetPeer(RawObject* raw_obj) const { - return reinterpret_cast(GetWeakEntry(raw_obj, kPeers)); - } + // Associates a peer with an object. If an object has a peer, it is + // replaced. A value of NULL disassociate an object from its peer. + void SetPeer(RawObject* raw_obj, void* peer); + + // Retrieves the peer associated with an object. Returns NULL if + // there is no association. + void* GetPeer(RawObject* raw_obj); + + // Returns the number of objects with a peer. int64_t PeerCount() const; - // Associate an identity hashCode with an object. An non-existent hashCode - // is equal to 0. - void SetHash(RawObject* raw_obj, intptr_t hash) { - SetWeakEntry(raw_obj, kHashes, hash); - } - intptr_t GetHash(RawObject* raw_obj) const { - return GetWeakEntry(raw_obj, kHashes); - } - int64_t HashCount() const; - - // Used by the GC algorithms to propagate weak entries. - intptr_t GetWeakEntry(RawObject* raw_obj, WeakSelector sel) const; - void SetWeakEntry(RawObject* raw_obj, WeakSelector sel, intptr_t val); - - WeakTable* GetWeakTable(Space space, WeakSelector selector) const { - if (space == kNew) { - return new_weak_tables_[selector]; - } - ASSERT(space ==kOld); - return old_weak_tables_[selector]; - } - void SetWeakTable(Space space, WeakSelector selector, WeakTable* value) { - if (space == kNew) { - new_weak_tables_[selector] = value; - } else { - ASSERT(space == kOld); - old_weak_tables_[selector] = value; - } - } - // Stats collection. void RecordTime(int id, int64_t micros) { ASSERT((id >= 0) && (id < GCStats::kDataEntries)); @@ -281,9 +246,6 @@ class Heap { Scavenger* new_space_; PageSpace* old_space_; - WeakTable* new_weak_tables_[kNumWeakSelectors]; - WeakTable* old_weak_tables_[kNumWeakSelectors]; - // GC stats collection. GCStats stats_; diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc index 2e82fcdfde4..d8522bb9ab1 100644 --- a/runtime/vm/pages.cc +++ b/runtime/vm/pages.cc @@ -321,6 +321,26 @@ void PageSpace::VisitObjects(ObjectVisitor* visitor) const { } +void PageSpace::SetPeer(RawObject* raw_obj, void* peer) { + if (peer == NULL) { + peer_table_.erase(raw_obj); + } else { + peer_table_[raw_obj] = peer; + } +} + + +void* PageSpace::GetPeer(RawObject* raw_obj) { + PeerTable::iterator it = peer_table_.find(raw_obj); + return (it == peer_table_.end()) ? NULL : it->second; +} + + +int64_t PageSpace::PeerCount() const { + return static_cast(peer_table_.size()); +} + + void PageSpace::VisitObjectPointers(ObjectPointerVisitor* visitor) const { HeapPage* page = pages_; while (page != NULL) { diff --git a/runtime/vm/pages.h b/runtime/vm/pages.h index c29121b9e3e..4a61de07bec 100644 --- a/runtime/vm/pages.h +++ b/runtime/vm/pages.h @@ -5,6 +5,8 @@ #ifndef VM_PAGES_H_ #define VM_PAGES_H_ +#include + #include "vm/freelist.h" #include "vm/globals.h" #include "vm/virtual_memory.h" @@ -203,6 +205,16 @@ class PageSpace { void WriteProtect(bool read_only); + typedef std::map PeerTable; + + void SetPeer(RawObject* raw_obj, void* peer); + + void* GetPeer(RawObject* raw_obj); + + int64_t PeerCount() const; + + PeerTable* GetPeerTable() { return &peer_table_; } + private: // Ids for time and data records in Heap::GCStats. enum { @@ -241,6 +253,8 @@ class PageSpace { HeapPage* pages_tail_; HeapPage* large_pages_; + PeerTable peer_table_; + // Various sizes being tracked for this generation. intptr_t max_capacity_; intptr_t capacity_; diff --git a/runtime/vm/scavenger.cc b/runtime/vm/scavenger.cc index 65c0d066a32..81aae4d8736 100644 --- a/runtime/vm/scavenger.cc +++ b/runtime/vm/scavenger.cc @@ -16,7 +16,6 @@ #include "vm/store_buffer.h" #include "vm/verifier.h" #include "vm/visitor.h" -#include "vm/weak_table.h" namespace dart { @@ -557,31 +556,19 @@ uword Scavenger::ProcessWeakProperty(RawWeakProperty* raw_weak, } -void Scavenger::ProcessWeakTables() { - for (int sel = 0; - sel < Heap::kNumWeakSelectors; - sel++) { - WeakTable* table = heap_->GetWeakTable( - Heap::kNew, static_cast(sel)); - intptr_t size = table->size(); - heap_->SetWeakTable(Heap::kNew, - static_cast(sel), - WeakTable::NewFrom(table)); - for (intptr_t i = 0; i < size; i++) { - if (table->IsValidEntryAt(i)) { - RawObject* raw_obj = table->ObjectAt(i); - ASSERT(raw_obj->IsHeapObject()); - uword raw_addr = RawObject::ToAddr(raw_obj); - uword header = *reinterpret_cast(raw_addr); - if (IsForwarding(header)) { - // The object has survived. Preserve its record. - uword new_addr = ForwardedAddr(header); - raw_obj = RawObject::FromAddr(new_addr); - heap_->SetWeakEntry(raw_obj, - static_cast(sel), - table->ValueAt(i)); - } - } +void Scavenger::ProcessPeerReferents() { + PeerTable prev; + std::swap(prev, peer_table_); + for (PeerTable::iterator it = prev.begin(); it != prev.end(); ++it) { + RawObject* raw_obj = it->first; + ASSERT(raw_obj->IsHeapObject()); + uword raw_addr = RawObject::ToAddr(raw_obj); + uword header = *reinterpret_cast(raw_addr); + if (IsForwarding(header)) { + // The object has survived. Preserve its record. + uword new_addr = ForwardedAddr(header); + raw_obj = RawObject::FromAddr(new_addr); + heap_->SetPeer(raw_obj, it->second); } } } @@ -638,7 +625,7 @@ void Scavenger::Scavenge(bool invoke_api_callbacks) { ScavengerWeakVisitor weak_visitor(this); IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); visitor.Finalize(); - ProcessWeakTables(); + ProcessPeerReferents(); int64_t end = OS::GetCurrentTimeMicros(); heap_->RecordTime(kProcessToSpace, middle - start); heap_->RecordTime(kIterateWeaks, end - middle); @@ -662,4 +649,23 @@ void Scavenger::WriteProtect(bool read_only) { } +void Scavenger::SetPeer(RawObject* raw_obj, void* peer) { + if (peer == NULL) { + peer_table_.erase(raw_obj); + } else { + peer_table_[raw_obj] = peer; + } +} + + +void* Scavenger::GetPeer(RawObject* raw_obj) { + PeerTable::iterator it = peer_table_.find(raw_obj); + return (it == peer_table_.end()) ? NULL : it->second; +} + + +int64_t Scavenger::PeerCount() const { + return static_cast(peer_table_.size()); +} + } // namespace dart diff --git a/runtime/vm/scavenger.h b/runtime/vm/scavenger.h index 2ff0033355f..0ce70d6e30d 100644 --- a/runtime/vm/scavenger.h +++ b/runtime/vm/scavenger.h @@ -5,6 +5,8 @@ #ifndef VM_SCAVENGER_H_ #define VM_SCAVENGER_H_ +#include + #include "platform/assert.h" #include "platform/utils.h" #include "vm/flags.h" @@ -87,6 +89,12 @@ class Scavenger { void WriteProtect(bool read_only); + void SetPeer(RawObject* raw_obj, void* peer); + + void* GetPeer(RawObject* raw_obj); + + int64_t PeerCount() const; + private: // Ids for time and data records in Heap::GCStats. enum { @@ -137,7 +145,7 @@ class Scavenger { return end_ < to_->end(); } - void ProcessWeakTables(); + void ProcessPeerReferents(); VirtualMemory* space_; MemoryRegion* to_; @@ -145,6 +153,9 @@ class Scavenger { Heap* heap_; + typedef std::map PeerTable; + PeerTable peer_table_; + // Current allocation top and end. These values are being accessed directly // from generated code. uword top_; diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi index 0c9fdcb09cc..1d6ec2992f4 100644 --- a/runtime/vm/vm_sources.gypi +++ b/runtime/vm/vm_sources.gypi @@ -335,8 +335,6 @@ 'visitor.h', 'vtune.cc', 'vtune.h', - 'weak_table.cc', - 'weak_table.h', 'zone.cc', 'zone.h', 'zone_test.cc', diff --git a/runtime/vm/weak_table.cc b/runtime/vm/weak_table.cc deleted file mode 100644 index 416a747d9d7..00000000000 --- a/runtime/vm/weak_table.cc +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "vm/weak_table.h" - -#include "platform/assert.h" -#include "vm/raw_object.h" - -namespace dart { - -WeakTable* WeakTable::SetValue(RawObject* key, intptr_t val) { - intptr_t sz = size(); - intptr_t idx = Hash(key) % sz; - intptr_t empty_idx = -1; - RawObject* obj = ObjectAt(idx); - - while (obj != NULL) { - if (obj == key) { - SetValueAt(idx, val); - return this; - } else if ((empty_idx < 0) && - (reinterpret_cast(obj) == kDeletedEntry)) { - empty_idx = idx; // Insert at this location if not found. - } - idx = (idx + 1) % sz; - obj = ObjectAt(idx); - } - - if (val == 0) { - // Do not enter an invalid value. Associating 0 with a key deletes it from - // this weak table above in SetValueAt. If the key was not present in the - // weak table we are done. - return this; - } - - if (empty_idx >= 0) { - // We will be reusing a slot below. - set_used(used() - 1); - idx = empty_idx; - } - - ASSERT(!IsValidEntryAt(idx)); - // Set the key and value. - SetObjectAt(idx, key); - SetValueAt(idx, val); - // Update the counts. - set_used(used() + 1); - set_count(count() + 1); - - // Rehash if needed to ensure that there are empty slots available. - if (used_ >= limit()) { - return Rehash(); - } - return this; -} - - -WeakTable* WeakTable::Rehash() { - intptr_t sz = size(); - WeakTable* result = NewFrom(this); - - for (intptr_t i = 0; i < sz; i++) { - if (IsValidEntryAt(i)) { - WeakTable* temp = result->SetValue(ObjectAt(i), ValueAt(i)); - ASSERT(temp == result); - } - } - return result; -} - -} // namespace dart diff --git a/runtime/vm/weak_table.h b/runtime/vm/weak_table.h deleted file mode 100644 index 3aa4dee007e..00000000000 --- a/runtime/vm/weak_table.h +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef VM_WEAK_TABLE_H_ -#define VM_WEAK_TABLE_H_ - -#include "vm/globals.h" - -#include "platform/assert.h" -#include "vm/raw_object.h" - -namespace dart { - -class WeakTable { - public: - explicit WeakTable(intptr_t size) : used_(0), count_(0) { - ASSERT(size >= 0); - if (size < kMinSize) { - size = kMinSize; - } - data_ = reinterpret_cast(calloc(size, kEntrySize * kWordSize)); - size_ = size; - } - - static WeakTable* NewFrom(WeakTable* original) { - intptr_t cnt = original->count(); - intptr_t sz = original->size(); - intptr_t new_sz = sz; - - if (cnt <= (sz / 4)) { - // Reduce the capacity. - new_sz = sz / 2; - } else if (cnt > (sz / 2)) { - // Increase the capacity. - new_sz = sz * 2; - if (new_sz < sz) { - FATAL("Reached impossible state of having more weak table entries" - " than memory available for heap objects."); - } - } - return new WeakTable(new_sz); - } - - intptr_t size() const { return size_; } - intptr_t used() const { return used_; } - intptr_t count() const { return count_; } - - bool IsValidEntryAt(intptr_t i) const { - ASSERT(((ValueAt(i) == 0) && - ((ObjectAt(i) == NULL) || - (data_[ObjectIndex(i)] == kDeletedEntry))) || - ((ValueAt(i) != 0) && - (ObjectAt(i) != NULL) && - (data_[ObjectIndex(i)] != kDeletedEntry))); - return (data_[ValueIndex(i)] != 0); - } - - void InvalidateAt(intptr_t i) { - ASSERT(IsValidEntryAt(i)); - SetValueAt(i, 0); - } - - RawObject* ObjectAt(intptr_t i) const { - return reinterpret_cast(data_[ObjectIndex(i)]); - } - - intptr_t ValueAt(intptr_t i) const { - return data_[ValueIndex(i)]; - } - - WeakTable* SetValue(RawObject* key, intptr_t val); - - intptr_t GetValue(RawObject* key) const { - intptr_t sz = size(); - intptr_t idx = Hash(key) % sz; - RawObject* obj = ObjectAt(idx); - while (obj != NULL) { - if (obj == key) { - return ValueAt(idx); - } - idx = (idx + 1) % sz; - obj = ObjectAt(idx); - } - ASSERT(ValueAt(idx) == 0); - return 0; - } - - private: - enum { - kObjectOffset = 0, - kValueOffset, - kEntrySize, - }; - - static const intptr_t kDeletedEntry = 1; // Equivalent to a tagged NULL. - static const intptr_t kMinSize = 8; - - static intptr_t LimitFor(intptr_t size) { - // Maintain a maximum of 75% fill rate. - return 3 * (size / 4); - } - intptr_t limit() const { return LimitFor(size()); } - - intptr_t index(intptr_t i) const { - ASSERT(i >= 0); - ASSERT(i < size()); - return i * kEntrySize; - } - - void set_used(intptr_t val) { - ASSERT(val <= limit()); - used_ = val; - } - - void set_count(intptr_t val) { - ASSERT(val <= limit()); - ASSERT(val <= used()); - count_ = val; - } - - intptr_t ObjectIndex(intptr_t i) const { - return index(i) + kObjectOffset; - } - - intptr_t ValueIndex(intptr_t i) const { - return index(i) + kValueOffset; - } - - void SetObjectAt(intptr_t i, RawObject* key) { - data_[ObjectIndex(i)] = reinterpret_cast(key); - } - - void SetValueAt(intptr_t i, intptr_t val) { - // Setting a value of 0 is equivalent to invalidating the entry. - if (val == 0) { - data_[ObjectIndex(i)] = kDeletedEntry; - set_count(count() - 1); - } - data_[ValueIndex(i)] = val; - } - - WeakTable* Rehash(); - - static intptr_t Hash(RawObject* key) { - return reinterpret_cast(key) >> kObjectAlignmentLog2; - } - - // data_ contains size_ tuples of key/value. - intptr_t* data_; - // size_ keeps the number of entries in data_. used_ maintains the number of - // non-NULL entries and will trigger rehashing if needed. count_ stores the - // number valid entries, and will determine the size_ after rehashing. - intptr_t size_; - intptr_t used_; - intptr_t count_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(WeakTable); -}; - -} // namespace dart - -#endif // VM_WEAK_TABLE_H_