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

Unified Diff: runtime/vm/weak_table.h

Issue 17992002: - Add a WeakTable to the VM. This is used to remember the (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 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 | « runtime/vm/vm_sources.gypi ('k') | runtime/vm/weak_table.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/weak_table.h
===================================================================
--- runtime/vm/weak_table.h (revision 0)
+++ runtime/vm/weak_table.h (revision 0)
@@ -0,0 +1,163 @@
+// 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<intptr_t*>(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<RawObject*>(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<intptr_t>(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<intptr_t>(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_
« no previous file with comments | « runtime/vm/vm_sources.gypi ('k') | runtime/vm/weak_table.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698