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

Side by Side Diff: runtime/vm/weak_table.h

Issue 18826007: Reland r24563 and r24564 with fixes cumbersome API leading to leaks. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/vm_sources.gypi ('k') | runtime/vm/weak_table.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #ifndef VM_WEAK_TABLE_H_ 5 #ifndef VM_WEAK_TABLE_H_
6 #define VM_WEAK_TABLE_H_ 6 #define VM_WEAK_TABLE_H_
7 7
8 #include "vm/globals.h" 8 #include "vm/globals.h"
9 9
10 #include "platform/assert.h" 10 #include "platform/assert.h"
11 #include "vm/raw_object.h" 11 #include "vm/raw_object.h"
12 12
13 namespace dart { 13 namespace dart {
14 14
15 class WeakTable { 15 class WeakTable {
16 public: 16 public:
17 WeakTable() : size_(kMinSize), used_(0), count_(0) {
18 ASSERT(Utils::IsPowerOfTwo(size_));
19 data_ = reinterpret_cast<intptr_t*>(calloc(size_, kEntrySize * kWordSize));
20 }
17 explicit WeakTable(intptr_t size) : used_(0), count_(0) { 21 explicit WeakTable(intptr_t size) : used_(0), count_(0) {
18 ASSERT(size >= 0); 22 ASSERT(size >= 0);
23 ASSERT(Utils::IsPowerOfTwo(kMinSize));
19 if (size < kMinSize) { 24 if (size < kMinSize) {
20 size = kMinSize; 25 size = kMinSize;
21 } 26 }
22 data_ = reinterpret_cast<intptr_t*>(calloc(size, kEntrySize * kWordSize)); 27 // Get a max size that avoids overflows.
28 const intptr_t kMaxSize =
29 (kIntptrOne << (kBitsPerWord - 2)) / (kEntrySize * kWordSize);
30 ASSERT(Utils::IsPowerOfTwo(kMaxSize));
31 if (size > kMaxSize) {
32 size = kMaxSize;
33 }
23 size_ = size; 34 size_ = size;
35 ASSERT(Utils::IsPowerOfTwo(size_));
36 data_ = reinterpret_cast<intptr_t*>(calloc(size_, kEntrySize * kWordSize));
37 }
38
39 ~WeakTable() {
40 free(data_);
24 } 41 }
25 42
26 static WeakTable* NewFrom(WeakTable* original) { 43 static WeakTable* NewFrom(WeakTable* original) {
27 intptr_t cnt = original->count(); 44 return new WeakTable(SizeFor(original->count(), original->size()));
28 intptr_t sz = original->size();
29 intptr_t new_sz = sz;
30
31 if (cnt <= (sz / 4)) {
32 // Reduce the capacity.
33 new_sz = sz / 2;
34 } else if (cnt > (sz / 2)) {
35 // Increase the capacity.
36 new_sz = sz * 2;
37 if (new_sz < sz) {
38 FATAL("Reached impossible state of having more weak table entries"
39 " than memory available for heap objects.");
40 }
41 }
42 return new WeakTable(new_sz);
43 } 45 }
44 46
45 intptr_t size() const { return size_; } 47 intptr_t size() const { return size_; }
46 intptr_t used() const { return used_; } 48 intptr_t used() const { return used_; }
47 intptr_t count() const { return count_; } 49 intptr_t count() const { return count_; }
48 50
49 bool IsValidEntryAt(intptr_t i) const { 51 bool IsValidEntryAt(intptr_t i) const {
50 ASSERT(((ValueAt(i) == 0) && 52 ASSERT(((ValueAt(i) == 0) &&
51 ((ObjectAt(i) == NULL) || 53 ((ObjectAt(i) == NULL) ||
52 (data_[ObjectIndex(i)] == kDeletedEntry))) || 54 (data_[ObjectIndex(i)] == kDeletedEntry))) ||
53 ((ValueAt(i) != 0) && 55 ((ValueAt(i) != 0) &&
54 (ObjectAt(i) != NULL) && 56 (ObjectAt(i) != NULL) &&
55 (data_[ObjectIndex(i)] != kDeletedEntry))); 57 (data_[ObjectIndex(i)] != kDeletedEntry)));
56 return (data_[ValueIndex(i)] != 0); 58 return (data_[ValueIndex(i)] != 0);
57 } 59 }
58 60
59 void InvalidateAt(intptr_t i) { 61 void InvalidateAt(intptr_t i) {
60 ASSERT(IsValidEntryAt(i)); 62 ASSERT(IsValidEntryAt(i));
61 SetValueAt(i, 0); 63 SetValueAt(i, 0);
62 } 64 }
63 65
64 RawObject* ObjectAt(intptr_t i) const { 66 RawObject* ObjectAt(intptr_t i) const {
67 ASSERT(i >= 0);
68 ASSERT(i < size());
65 return reinterpret_cast<RawObject*>(data_[ObjectIndex(i)]); 69 return reinterpret_cast<RawObject*>(data_[ObjectIndex(i)]);
66 } 70 }
67 71
68 intptr_t ValueAt(intptr_t i) const { 72 intptr_t ValueAt(intptr_t i) const {
73 ASSERT(i >= 0);
74 ASSERT(i < size());
69 return data_[ValueIndex(i)]; 75 return data_[ValueIndex(i)];
70 } 76 }
71 77
72 WeakTable* SetValue(RawObject* key, intptr_t val); 78 void SetValue(RawObject* key, intptr_t val);
73 79
74 intptr_t GetValue(RawObject* key) const { 80 intptr_t GetValue(RawObject* key) const {
75 intptr_t sz = size(); 81 intptr_t mask = size() - 1;
76 intptr_t idx = Hash(key) % sz; 82 intptr_t idx = Hash(key) & mask;
77 RawObject* obj = ObjectAt(idx); 83 RawObject* obj = ObjectAt(idx);
78 while (obj != NULL) { 84 while (obj != NULL) {
79 if (obj == key) { 85 if (obj == key) {
80 return ValueAt(idx); 86 return ValueAt(idx);
81 } 87 }
82 idx = (idx + 1) % sz; 88 idx = (idx + 1) & mask;
83 obj = ObjectAt(idx); 89 obj = ObjectAt(idx);
84 } 90 }
85 ASSERT(ValueAt(idx) == 0); 91 ASSERT(ValueAt(idx) == 0);
86 return 0; 92 return 0;
87 } 93 }
88 94
89 private: 95 private:
90 enum { 96 enum {
91 kObjectOffset = 0, 97 kObjectOffset = 0,
92 kValueOffset, 98 kValueOffset,
93 kEntrySize, 99 kEntrySize,
94 }; 100 };
95 101
96 static const intptr_t kDeletedEntry = 1; // Equivalent to a tagged NULL. 102 static const intptr_t kDeletedEntry = 1; // Equivalent to a tagged NULL.
97 static const intptr_t kMinSize = 8; 103 static const intptr_t kMinSize = 8;
98 104
105 static intptr_t SizeFor(intptr_t count, intptr_t size);
99 static intptr_t LimitFor(intptr_t size) { 106 static intptr_t LimitFor(intptr_t size) {
100 // Maintain a maximum of 75% fill rate. 107 // Maintain a maximum of 75% fill rate.
101 return 3 * (size / 4); 108 return 3 * (size / 4);
102 } 109 }
103 intptr_t limit() const { return LimitFor(size()); } 110 intptr_t limit() const { return LimitFor(size()); }
104 111
105 intptr_t index(intptr_t i) const { 112 intptr_t index(intptr_t i) const {
106 ASSERT(i >= 0);
107 ASSERT(i < size());
108 return i * kEntrySize; 113 return i * kEntrySize;
109 } 114 }
110 115
111 void set_used(intptr_t val) { 116 void set_used(intptr_t val) {
112 ASSERT(val <= limit()); 117 ASSERT(val <= limit());
113 used_ = val; 118 used_ = val;
114 } 119 }
115 120
116 void set_count(intptr_t val) { 121 void set_count(intptr_t val) {
117 ASSERT(val <= limit()); 122 ASSERT(val <= limit());
118 ASSERT(val <= used()); 123 ASSERT(val <= used());
119 count_ = val; 124 count_ = val;
120 } 125 }
121 126
122 intptr_t ObjectIndex(intptr_t i) const { 127 intptr_t ObjectIndex(intptr_t i) const {
123 return index(i) + kObjectOffset; 128 return index(i) + kObjectOffset;
124 } 129 }
125 130
126 intptr_t ValueIndex(intptr_t i) const { 131 intptr_t ValueIndex(intptr_t i) const {
127 return index(i) + kValueOffset; 132 return index(i) + kValueOffset;
128 } 133 }
129 134
130 void SetObjectAt(intptr_t i, RawObject* key) { 135 void SetObjectAt(intptr_t i, RawObject* key) {
136 ASSERT(i >= 0);
137 ASSERT(i < size());
131 data_[ObjectIndex(i)] = reinterpret_cast<intptr_t>(key); 138 data_[ObjectIndex(i)] = reinterpret_cast<intptr_t>(key);
132 } 139 }
133 140
134 void SetValueAt(intptr_t i, intptr_t val) { 141 void SetValueAt(intptr_t i, intptr_t val) {
142 ASSERT(i >= 0);
143 ASSERT(i < size());
135 // Setting a value of 0 is equivalent to invalidating the entry. 144 // Setting a value of 0 is equivalent to invalidating the entry.
136 if (val == 0) { 145 if (val == 0) {
137 data_[ObjectIndex(i)] = kDeletedEntry; 146 data_[ObjectIndex(i)] = kDeletedEntry;
138 set_count(count() - 1); 147 set_count(count() - 1);
139 } 148 }
140 data_[ValueIndex(i)] = val; 149 data_[ValueIndex(i)] = val;
141 } 150 }
142 151
143 WeakTable* Rehash(); 152 void Rehash();
144 153
145 static intptr_t Hash(RawObject* key) { 154 static intptr_t Hash(RawObject* key) {
146 return reinterpret_cast<intptr_t>(key) >> kObjectAlignmentLog2; 155 return reinterpret_cast<intptr_t>(key) >> kObjectAlignmentLog2;
147 } 156 }
148 157
149 // data_ contains size_ tuples of key/value. 158 // data_ contains size_ tuples of key/value.
150 intptr_t* data_; 159 intptr_t* data_;
151 // size_ keeps the number of entries in data_. used_ maintains the number of 160 // size_ keeps the number of entries in data_. used_ maintains the number of
152 // non-NULL entries and will trigger rehashing if needed. count_ stores the 161 // non-NULL entries and will trigger rehashing if needed. count_ stores the
153 // number valid entries, and will determine the size_ after rehashing. 162 // number valid entries, and will determine the size_ after rehashing.
154 intptr_t size_; 163 intptr_t size_;
155 intptr_t used_; 164 intptr_t used_;
156 intptr_t count_; 165 intptr_t count_;
157 166
158 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakTable); 167 DISALLOW_COPY_AND_ASSIGN(WeakTable);
159 }; 168 };
160 169
161 } // namespace dart 170 } // namespace dart
162 171
163 #endif // VM_WEAK_TABLE_H_ 172 #endif // VM_WEAK_TABLE_H_
OLDNEW
« 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