OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #ifndef VM_WEAK_TABLE_H_ | |
6 #define VM_WEAK_TABLE_H_ | |
7 | |
8 #include "vm/globals.h" | |
9 | |
10 #include "platform/assert.h" | |
11 #include "vm/raw_object.h" | |
12 | |
13 namespace dart { | |
14 | |
15 class WeakTable { | |
16 public: | |
17 explicit WeakTable(intptr_t size) : used_(0), count_(0) { | |
18 ASSERT(size >= 0); | |
19 if (size < 8) { | |
20 size = 8; | |
21 } | |
22 data_ = reinterpret_cast<intptr_t*>(calloc(size, kEntrySize * kWordSize)); | |
23 size_ = size; | |
24 } | |
25 | |
26 static WeakTable* NewFrom(WeakTable* original) { | |
27 intptr_t cnt = original->count(); | |
28 intptr_t sz = original->size(); | |
29 intptr_t new_sz = sz; | |
30 | |
31 if (cnt <= (sz / 4)) { | |
32 // Reduce the capacity. | |
siva
2013/06/27 22:11:33
ASSERT(sz > 1);
Ivan Posva
2013/06/27 23:59:12
sz of zero is a legal value.
| |
33 new_sz = sz / 2; | |
34 } else if (cnt > (sz / 2)) { | |
35 // Increase the capacity. | |
36 new_sz = sz * 2; | |
siva
2013/06/27 22:11:33
we should protect against overflows here.
Maybe so
Ivan Posva
2013/06/27 23:59:12
Done.
| |
37 } | |
38 return new WeakTable(new_sz); | |
39 } | |
40 | |
41 intptr_t size() const { return size_; } | |
42 intptr_t used() const { return used_; } | |
43 intptr_t count() const { return count_; } | |
44 | |
45 bool IsValidEntryAt(intptr_t i) { | |
siva
2013/06/27 22:11:33
const
Ivan Posva
2013/06/27 23:59:12
Done.
| |
46 ASSERT(((ValueAt(i) == 0) && | |
47 ((ObjectAt(i) == NULL) || | |
48 (data_[ObjectIndex(i)] == kDeletedEntry))) || | |
49 ((ValueAt(i) != 0) && | |
50 (ObjectAt(i) != NULL) && | |
51 (data_[ObjectIndex(i)] != kDeletedEntry))); | |
52 return (data_[ValueIndex(i)] != 0); | |
53 } | |
54 | |
55 void InvalidateAt(intptr_t i) { | |
56 ASSERT(IsValidEntryAt(i)); | |
57 SetValueAt(i, 0); | |
58 } | |
59 | |
60 RawObject* ObjectAt(intptr_t i) { | |
siva
2013/06/27 22:11:33
const
Here and some more functions below.
Ivan Posva
2013/06/27 23:59:12
Done.
| |
61 return reinterpret_cast<RawObject*>(data_[ObjectIndex(i)]); | |
62 } | |
63 | |
64 intptr_t ValueAt(intptr_t i) { | |
65 return data_[ValueIndex(i)]; | |
66 } | |
67 | |
68 WeakTable* SetValue(RawObject* key, intptr_t val); | |
69 | |
70 intptr_t GetValue(RawObject* key) { | |
71 intptr_t sz = size(); | |
72 intptr_t idx = Hash(key) % sz; | |
73 RawObject* obj = ObjectAt(idx); | |
74 while (obj != NULL) { | |
75 if (obj == key) { | |
76 return ValueAt(idx); | |
77 } | |
78 idx = (idx + 1) % sz; | |
79 obj = ObjectAt(idx); | |
80 } | |
81 ASSERT(ValueAt(idx) == 0); | |
82 return 0; | |
83 } | |
84 | |
85 private: | |
86 enum { | |
87 kObjectOffset = 0, | |
88 kValueOffset, | |
89 kEntrySize, | |
90 }; | |
91 | |
92 static const intptr_t kDeletedEntry = 1; // Equivalent to a tagged NULL. | |
93 | |
94 static intptr_t LimitFor(intptr_t size) { return 3 * (size / 4); } | |
siva
2013/06/27 22:11:33
Use names constants instead of 3, 4 etc. here and
Ivan Posva
2013/06/27 23:59:12
Added a kMinSize and a comment in LimitFor, as 3 a
| |
95 intptr_t limit() const { return LimitFor(size()); } | |
96 | |
97 intptr_t index(intptr_t i) { | |
98 ASSERT(i >= 0); | |
99 ASSERT(i < size()); | |
100 return i * kEntrySize; | |
101 } | |
102 | |
103 void set_used(intptr_t val) { | |
104 ASSERT(val <= limit()); | |
105 used_ = val; | |
106 } | |
107 | |
108 void set_count(intptr_t val) { | |
109 ASSERT(val <= limit()); | |
110 ASSERT(val <= used()); | |
111 count_ = val; | |
112 } | |
113 | |
114 intptr_t ObjectIndex(intptr_t i) { | |
115 return index(i) + kObjectOffset; | |
116 } | |
117 | |
118 intptr_t ValueIndex(intptr_t i) { | |
119 return index(i) + kValueOffset; | |
120 } | |
121 | |
122 void SetObjectAt(intptr_t i, RawObject* key) { | |
123 data_[ObjectIndex(i)] = reinterpret_cast<intptr_t>(key); | |
124 } | |
125 | |
126 void SetValueAt(intptr_t i, intptr_t val) { | |
127 // Setting a value of 0 is equivalent to invalidating the entry. | |
siva
2013/06/27 22:11:33
The comment here states setting a value of 0 is eq
| |
128 if (val == 0) { | |
129 data_[ObjectIndex(i)] = kDeletedEntry; | |
130 set_count(count() - 1); | |
131 } | |
132 data_[ValueIndex(i)] = val; | |
133 } | |
134 | |
135 WeakTable* Rehash(); | |
136 | |
137 static intptr_t Hash(RawObject* key) { | |
138 return reinterpret_cast<intptr_t>(key) >> kObjectAlignmentLog2; | |
139 } | |
140 | |
141 // data_ contains size_ tuples of key/value. | |
142 intptr_t* data_; | |
143 // size_ keeps the number of entries in data_. used_ maintains the number of | |
144 // non-NULL entries and will trigger rehashing if needed. count_ stores the | |
145 // number valid entries, and will determine the size_ after rehashing. | |
146 intptr_t size_; | |
147 intptr_t used_; | |
148 intptr_t count_; | |
siva
2013/06/27 22:11:33
Missing the DISALLOW stuff...
Ivan Posva
2013/06/27 23:59:12
Done.
| |
149 }; | |
150 | |
151 } // namespace dart | |
152 | |
153 #endif // VM_WEAK_TABLE_H_ | |
OLD | NEW |