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

Side by Side Diff: test/cctest/test-identity-map.cc

Issue 1105693002: Implement IdentityMap<V>, a robust, GC-safe object-identity HashMap. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 7 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
« no previous file with comments | « test/cctest/cctest.gyp ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/v8.h"
6
7 #include "src/heap/identity-map.h"
8 #include "src/zone.h"
9
10 #include "test/cctest/cctest.h"
11
12 namespace v8 {
13 namespace internal {
14
15 // Helper for testing. A "friend" of the IdentityMapBase class, it is able to
16 // "move" objects to simulate GC for testing the internals of the map.
17 class IdentityMapTester : public HandleAndZoneScope {
18 public:
19 IdentityMap<void*> map;
20
21 IdentityMapTester() : map(heap(), main_zone()) {}
22
23 Heap* heap() { return isolate()->heap(); }
24 Isolate* isolate() { return main_isolate(); }
25
26 void TestGetFind(Handle<Object> key1, void* val1, Handle<Object> key2,
27 void* val2) {
28 CHECK_NULL(map.Find(key1));
29 CHECK_NULL(map.Find(key2));
30
31 // Set {key1} the first time.
32 void** entry = map.Get(key1);
33 CHECK_NOT_NULL(entry);
34 *entry = val1;
35
36 for (int i = 0; i < 3; i++) { // Get and find {key1} K times.
37 {
38 void** nentry = map.Get(key1);
39 CHECK_EQ(entry, nentry);
40 CHECK_EQ(val1, *nentry);
41 CHECK_NULL(map.Find(key2));
42 }
43 {
44 void** nentry = map.Find(key1);
45 CHECK_EQ(entry, nentry);
46 CHECK_EQ(val1, *nentry);
47 CHECK_NULL(map.Find(key2));
48 }
49 }
50
51 // Set {key2} the first time.
52 void** entry2 = map.Get(key2);
53 CHECK_NOT_NULL(entry2);
54 *entry2 = val2;
55
56 for (int i = 0; i < 3; i++) { // Get and find {key1} and {key2} K times.
57 {
58 void** nentry = map.Get(key2);
59 CHECK_EQ(entry2, nentry);
60 CHECK_EQ(val2, *nentry);
61 }
62 {
63 void** nentry = map.Find(key2);
64 CHECK_EQ(entry2, nentry);
65 CHECK_EQ(val2, *nentry);
66 }
67 {
68 void** nentry = map.Find(key1);
69 CHECK_EQ(val1, *nentry);
70 }
71 }
72 }
73
74 Handle<Smi> smi(int value) {
75 return Handle<Smi>(Smi::FromInt(value), isolate());
76 }
77
78 Handle<Object> num(double value) {
79 return isolate()->factory()->NewNumber(value);
80 }
81
82 void SimulateGCByIncrementingSmisBy(int shift) {
83 for (int i = 0; i < map.size_; i++) {
84 if (map.keys_[i]->IsSmi()) {
85 map.keys_[i] = Smi::FromInt(Smi::cast(map.keys_[i])->value() + shift);
86 }
87 }
88 map.gc_counter_ = -1;
89 }
90
91 void CheckFind(Handle<Object> key, void* value) {
92 void** entry = map.Find(key);
93 CHECK_NOT_NULL(entry);
94 CHECK_EQ(value, *entry);
95 }
96
97 void CheckGet(Handle<Object> key, void* value) {
98 void** entry = map.Get(key);
99 CHECK_NOT_NULL(entry);
100 CHECK_EQ(value, *entry);
101 }
102
103 void PrintMap() {
104 PrintF("{\n");
105 for (int i = 0; i < map.size_; i++) {
106 PrintF(" %3d: %p => %p\n", i, reinterpret_cast<void*>(map.keys_[i]),
107 reinterpret_cast<void*>(map.values_[i]));
108 }
109 PrintF("}\n");
110 }
111
112 void Resize() { map.Resize(); }
113
114 void Rehash() { map.Rehash(); }
115 };
116
117
118 TEST(Find_smi_not_found) {
119 IdentityMapTester t;
120 for (int i = 0; i < 100; i++) {
121 CHECK_NULL(t.map.Find(t.smi(i)));
122 }
123 }
124
125
126 TEST(Find_num_not_found) {
127 IdentityMapTester t;
128 for (int i = 0; i < 100; i++) {
129 CHECK_NULL(t.map.Find(t.num(i + 0.2)));
130 }
131 }
132
133
134 TEST(GetFind_smi_13) {
135 IdentityMapTester t;
136 t.TestGetFind(t.smi(13), t.isolate(), t.smi(17), t.heap());
137 }
138
139
140 TEST(GetFind_num_13) {
141 IdentityMapTester t;
142 t.TestGetFind(t.num(13.1), t.isolate(), t.num(17.1), t.heap());
143 }
144
145
146 TEST(GetFind_smi_17m) {
147 const int kInterval = 17;
148 const int kShift = 1099;
149 IdentityMapTester t;
150
151 for (int i = 1; i < 100; i += kInterval) {
152 t.map.Set(t.smi(i), reinterpret_cast<void*>(i + kShift));
153 }
154
155 for (int i = 1; i < 100; i += kInterval) {
156 t.CheckFind(t.smi(i), reinterpret_cast<void*>(i + kShift));
157 }
158
159 for (int i = 1; i < 100; i += kInterval) {
160 t.CheckGet(t.smi(i), reinterpret_cast<void*>(i + kShift));
161 }
162
163 for (int i = 1; i < 100; i++) {
164 void** entry = t.map.Find(t.smi(i));
165 if ((i % kInterval) != 1) {
166 CHECK_NULL(entry);
167 } else {
168 CHECK_NOT_NULL(entry);
169 CHECK_EQ(reinterpret_cast<void*>(i + kShift), *entry);
170 }
171 }
172 }
173
174
175 TEST(GetFind_num_1000) {
176 const int kPrime = 137;
177 IdentityMapTester t;
178 int val1;
179 int val2;
180
181 for (int i = 1; i < 1000; i++) {
182 t.TestGetFind(t.smi(i * kPrime), &val1, t.smi(i * kPrime + 1), &val2);
183 }
184 }
185
186
187 TEST(GetFind_smi_gc) {
188 const int kKey = 33;
189 const int kShift = 1211;
190 IdentityMapTester t;
191
192 t.map.Set(t.smi(kKey), &t);
193 t.SimulateGCByIncrementingSmisBy(kShift);
194 t.CheckFind(t.smi(kKey + kShift), &t);
195 t.CheckGet(t.smi(kKey + kShift), &t);
196 }
197
198
199 TEST(GetFind_smi_gc2) {
200 int kKey1 = 1;
201 int kKey2 = 33;
202 const int kShift = 1211;
203 IdentityMapTester t;
204
205 t.map.Set(t.smi(kKey1), &kKey1);
206 t.map.Set(t.smi(kKey2), &kKey2);
207 t.SimulateGCByIncrementingSmisBy(kShift);
208 t.CheckFind(t.smi(kKey1 + kShift), &kKey1);
209 t.CheckGet(t.smi(kKey1 + kShift), &kKey1);
210 t.CheckFind(t.smi(kKey2 + kShift), &kKey2);
211 t.CheckGet(t.smi(kKey2 + kShift), &kKey2);
212 }
213
214
215 TEST(GetFind_smi_gc_n) {
216 const int kShift = 12011;
217 IdentityMapTester t;
218 int keys[12] = {1, 2, 7, 8, 15, 23,
219 1 + 32, 2 + 32, 7 + 32, 8 + 32, 15 + 32, 23 + 32};
220 // Initialize the map first.
221 for (size_t i = 0; i < arraysize(keys); i += 2) {
222 t.TestGetFind(t.smi(keys[i]), &keys[i], t.smi(keys[i + 1]), &keys[i + 1]);
223 }
224 // Check the above initialization.
225 for (size_t i = 0; i < arraysize(keys); i++) {
226 t.CheckFind(t.smi(keys[i]), &keys[i]);
227 }
228 // Simulate a GC by "moving" the smis in the internal keys array.
229 t.SimulateGCByIncrementingSmisBy(kShift);
230 // Check that searching for the incremented smis finds the same values.
231 for (size_t i = 0; i < arraysize(keys); i++) {
232 t.CheckFind(t.smi(keys[i] + kShift), &keys[i]);
233 }
234 // Check that searching for the incremented smis gets the same values.
235 for (size_t i = 0; i < arraysize(keys); i++) {
236 t.CheckGet(t.smi(keys[i] + kShift), &keys[i]);
237 }
238 }
239
240
241 TEST(GetFind_smi_num_gc_n) {
242 const int kShift = 12019;
243 IdentityMapTester t;
244 int smi_keys[] = {1, 2, 7, 15, 23};
245 Handle<Object> num_keys[] = {t.num(1.1), t.num(2.2), t.num(3.3), t.num(4.4),
246 t.num(5.5), t.num(6.6), t.num(7.7), t.num(8.8),
247 t.num(9.9), t.num(10.1)};
248 // Initialize the map first.
249 for (size_t i = 0; i < arraysize(smi_keys); i++) {
250 t.map.Set(t.smi(smi_keys[i]), &smi_keys[i]);
251 }
252 for (size_t i = 0; i < arraysize(num_keys); i++) {
253 t.map.Set(num_keys[i], &num_keys[i]);
254 }
255 // Check the above initialization.
256 for (size_t i = 0; i < arraysize(smi_keys); i++) {
257 t.CheckFind(t.smi(smi_keys[i]), &smi_keys[i]);
258 }
259 for (size_t i = 0; i < arraysize(num_keys); i++) {
260 t.CheckFind(num_keys[i], &num_keys[i]);
261 }
262
263 // Simulate a GC by moving SMIs.
264 // Ironically the SMIs "move", but the heap numbers don't!
265 t.SimulateGCByIncrementingSmisBy(kShift);
266
267 // Check that searching for the incremented smis finds the same values.
268 for (size_t i = 0; i < arraysize(smi_keys); i++) {
269 t.CheckFind(t.smi(smi_keys[i] + kShift), &smi_keys[i]);
270 t.CheckGet(t.smi(smi_keys[i] + kShift), &smi_keys[i]);
271 }
272
273 // Check that searching for the numbers finds the same values.
274 for (size_t i = 0; i < arraysize(num_keys); i++) {
275 t.CheckFind(num_keys[i], &num_keys[i]);
276 t.CheckGet(num_keys[i], &num_keys[i]);
277 }
278 }
279
280
281 void CollisionTest(int stride, bool rehash = false, bool resize = false) {
282 for (int load = 15; load <= 120; load = load * 2) {
283 IdentityMapTester t;
284
285 { // Add entries to the map.
286 HandleScope scope(t.isolate());
287 int next = 1;
288 for (int i = 0; i < load; i++) {
289 t.map.Set(t.smi(next), reinterpret_cast<void*>(next));
290 t.CheckFind(t.smi(next), reinterpret_cast<void*>(next));
291 next = next + stride;
292 }
293 }
294 if (resize) t.Resize(); // Explicit resize (internal method).
295 if (rehash) t.Rehash(); // Explicit rehash (internal method).
296 { // Check find and get.
297 HandleScope scope(t.isolate());
298 int next = 1;
299 for (int i = 0; i < load; i++) {
300 t.CheckFind(t.smi(next), reinterpret_cast<void*>(next));
301 t.CheckGet(t.smi(next), reinterpret_cast<void*>(next));
302 next = next + stride;
303 }
304 }
305 }
306 }
307
308
309 TEST(Collisions_1) { CollisionTest(1); }
310 TEST(Collisions_2) { CollisionTest(2); }
311 TEST(Collisions_3) { CollisionTest(3); }
312 TEST(Collisions_5) { CollisionTest(5); }
313 TEST(Collisions_7) { CollisionTest(7); }
314 TEST(Resize) { CollisionTest(9, false, true); }
315 TEST(Rehash) { CollisionTest(11, true, false); }
316
317
318 TEST(ExplicitGC) {
319 IdentityMapTester t;
320 Handle<Object> num_keys[] = {t.num(2.1), t.num(2.4), t.num(3.3), t.num(4.3),
321 t.num(7.5), t.num(6.4), t.num(7.3), t.num(8.3),
322 t.num(8.9), t.num(10.4)};
323
324 // Insert some objects that should be in new space.
325 for (size_t i = 0; i < arraysize(num_keys); i++) {
326 t.map.Set(num_keys[i], &num_keys[i]);
327 }
328
329 // Do an explicit, real GC.
330 t.heap()->CollectGarbage(i::NEW_SPACE);
331
332 // Check that searching for the numbers finds the same values.
333 for (size_t i = 0; i < arraysize(num_keys); i++) {
334 t.CheckFind(num_keys[i], &num_keys[i]);
335 t.CheckGet(num_keys[i], &num_keys[i]);
336 }
337 }
338 }
339 }
OLDNEW
« no previous file with comments | « test/cctest/cctest.gyp ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698