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

Side by Side Diff: vm/symbols.cc

Issue 12052033: Added macros OBJECT_IMPLEMENTATION and FINAL_OBJECT_IMPLEMENTATION (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 7 years, 11 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 | « vm/stub_code_ia32_test.cc ('k') | no next file » | 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 #include "vm/symbols.h" 5 #include "vm/symbols.h"
6 6
7 #include "vm/handles.h" 7 #include "vm/handles.h"
8 #include "vm/handles_impl.h" 8 #include "vm/handles_impl.h"
9 #include "vm/isolate.h" 9 #include "vm/isolate.h"
10 #include "vm/object.h" 10 #include "vm/object.h"
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 ASSERT((sizeof(names) / sizeof(const char*)) == Symbols::kNullCharId); 58 ASSERT((sizeof(names) / sizeof(const char*)) == Symbols::kNullCharId);
59 ObjectStore* object_store = isolate->object_store(); 59 ObjectStore* object_store = isolate->object_store();
60 Array& symbol_table = Array::Handle(); 60 Array& symbol_table = Array::Handle();
61 61
62 62
63 // First set up all the predefined string symbols. 63 // First set up all the predefined string symbols.
64 for (intptr_t i = 1; i < Symbols::kNullCharId; i++) { 64 for (intptr_t i = 1; i < Symbols::kNullCharId; i++) {
65 // The symbol_table needs to be reloaded as it might have grown in the 65 // The symbol_table needs to be reloaded as it might have grown in the
66 // previous iteration. 66 // previous iteration.
67 symbol_table = object_store->symbol_table(); 67 symbol_table = object_store->symbol_table();
68 String* str = reinterpret_cast<String*>(Dart::AllocateReadOnlyHandle()); 68 String* str = String::ReadOnlyHandle(isolate);
69 *str = OneByteString::New(names[i], Heap::kOld); 69 *str = OneByteString::New(names[i], Heap::kOld);
70 Add(symbol_table, *str); 70 Add(symbol_table, *str);
71 symbol_handles_[i] = str; 71 symbol_handles_[i] = str;
72 } 72 }
73 Object::RegisterSingletonClassNames(); 73 Object::RegisterSingletonClassNames();
74 74
75 // Add Latin1 characters as Symbols, so that Symbols::FromCharCode is fast. 75 // Add Latin1 characters as Symbols, so that Symbols::FromCharCode is fast.
76 for (intptr_t c = 0; c < kNumberOfOneCharCodeSymbols; c++) { 76 for (intptr_t c = 0; c < kNumberOfOneCharCodeSymbols; c++) {
77 // The symbol_table needs to be reloaded as it might have grown in the 77 // The symbol_table needs to be reloaded as it might have grown in the
78 // previous iteration. 78 // previous iteration.
79 symbol_table = object_store->symbol_table(); 79 symbol_table = object_store->symbol_table();
80 intptr_t idx = (kNullCharId + c); 80 intptr_t idx = (kNullCharId + c);
81 ASSERT(idx < kMaxPredefinedId); 81 ASSERT(idx < kMaxPredefinedId);
82 ASSERT(Utf::IsLatin1(c)); 82 ASSERT(Utf::IsLatin1(c));
83 uint8_t ch = static_cast<uint8_t>(c); 83 uint8_t ch = static_cast<uint8_t>(c);
84 String* str = reinterpret_cast<String*>(Dart::AllocateReadOnlyHandle()); 84 String* str = String::ReadOnlyHandle(isolate);
85 *str = OneByteString::New(&ch, 1, Heap::kOld); 85 *str = OneByteString::New(&ch, 1, Heap::kOld);
86 Add(symbol_table, *str); 86 Add(symbol_table, *str);
87 predefined_[c] = str->raw(); 87 predefined_[c] = str->raw();
88 symbol_handles_[idx] = str; 88 symbol_handles_[idx] = str;
89 } 89 }
90 } 90 }
91 91
92 92
93 void Symbols::SetupSymbolTable(Isolate* isolate) { 93 void Symbols::SetupSymbolTable(Isolate* isolate) {
94 ASSERT(isolate != NULL); 94 ASSERT(isolate != NULL);
95 95
96 // Setup the symbol table used within the String class. 96 // Setup the symbol table used within the String class.
97 const int initial_size = (isolate == Dart::vm_isolate()) ? 97 const int initial_size = (isolate == Dart::vm_isolate()) ?
98 kInitialVMIsolateSymtabSize : kInitialSymtabSize; 98 kInitialVMIsolateSymtabSize : kInitialSymtabSize;
99 const Array& array = Array::Handle(Array::New(initial_size + 1)); 99 const Array& array = Array::Handle(Array::New(initial_size + 1));
100 100
101 // Last element contains the count of used slots. 101 // Last element contains the count of used slots.
102 array.SetAt(initial_size, Smi::Handle(Smi::New(0))); 102 array.SetAt(initial_size, Smi::Handle(Smi::New(0)));
103 isolate->object_store()->set_symbol_table(array); 103 isolate->object_store()->set_symbol_table(array);
104 } 104 }
105 105
106 106
107 intptr_t Symbols::Size(Isolate* isolate) { 107 intptr_t Symbols::Size(Isolate* isolate) {
108 ASSERT(isolate != NULL); 108 ASSERT(isolate != NULL);
109 Array& symbol_table = Array::Handle(isolate, 109 Array& symbol_table = Array::Handle(isolate,
110 isolate->object_store()->symbol_table()); 110 isolate->object_store()->symbol_table());
111 intptr_t table_size_index = symbol_table.Length() - 1; 111 intptr_t table_size_index = symbol_table.Length() - 1;
112 dart::Smi& used = Smi::Handle(); 112 dart::Smi& used = Smi::Handle();
113 used |= symbol_table.At(table_size_index); 113 used ^= symbol_table.At(table_size_index);
114 return used.Value(); 114 return used.Value();
115 } 115 }
116 116
117 117
118 void Symbols::Add(const Array& symbol_table, const String& str) { 118 void Symbols::Add(const Array& symbol_table, const String& str) {
119 // Should only be run by the vm isolate. 119 // Should only be run by the vm isolate.
120 ASSERT(Isolate::Current() == Dart::vm_isolate()); 120 ASSERT(Isolate::Current() == Dart::vm_isolate());
121 intptr_t hash = str.Hash(); 121 intptr_t hash = str.Hash();
122 intptr_t index = FindIndex(symbol_table, str, 0, str.Length(), hash); 122 intptr_t index = FindIndex(symbol_table, str, 0, str.Length(), hash);
123 ASSERT(symbol_table.At(index) == String::null()); 123 ASSERT(symbol_table.At(index) == String::null());
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 Isolate* isolate = Isolate::Current(); 175 Isolate* isolate = Isolate::Current();
176 String& symbol = String::Handle(isolate, String::null()); 176 String& symbol = String::Handle(isolate, String::null());
177 Array& symbol_table = Array::Handle(isolate, Array::null()); 177 Array& symbol_table = Array::Handle(isolate, Array::null());
178 178
179 // Calculate the String hash for this sequence of characters. 179 // Calculate the String hash for this sequence of characters.
180 intptr_t hash = String::Hash(characters, len); 180 intptr_t hash = String::Hash(characters, len);
181 181
182 // First check if a symbol exists in the vm isolate for these characters. 182 // First check if a symbol exists in the vm isolate for these characters.
183 symbol_table = Dart::vm_isolate()->object_store()->symbol_table(); 183 symbol_table = Dart::vm_isolate()->object_store()->symbol_table();
184 intptr_t index = FindIndex(symbol_table, characters, len, hash); 184 intptr_t index = FindIndex(symbol_table, characters, len, hash);
185 symbol |= symbol_table.At(index); 185 symbol ^= symbol_table.At(index);
186 if (symbol.IsNull()) { 186 if (symbol.IsNull()) {
187 // Now try in the symbol table of the current isolate. 187 // Now try in the symbol table of the current isolate.
188 symbol_table = isolate->object_store()->symbol_table(); 188 symbol_table = isolate->object_store()->symbol_table();
189 index = FindIndex(symbol_table, characters, len, hash); 189 index = FindIndex(symbol_table, characters, len, hash);
190 // Since we leave enough room in the table to guarantee, that we find an 190 // Since we leave enough room in the table to guarantee, that we find an
191 // empty spot, index is the insertion point if symbol is null. 191 // empty spot, index is the insertion point if symbol is null.
192 symbol |= symbol_table.At(index); 192 symbol ^= symbol_table.At(index);
193 if (symbol.IsNull()) { 193 if (symbol.IsNull()) {
194 // Allocate new result string. 194 // Allocate new result string.
195 symbol = (*new_string)(characters, len, Heap::kOld); 195 symbol = (*new_string)(characters, len, Heap::kOld);
196 symbol.SetHash(hash); // Remember the calculated hash value. 196 symbol.SetHash(hash); // Remember the calculated hash value.
197 InsertIntoSymbolTable(symbol_table, symbol, index); 197 InsertIntoSymbolTable(symbol_table, symbol, index);
198 } 198 }
199 } 199 }
200 ASSERT(symbol.IsSymbol()); 200 ASSERT(symbol.IsSymbol());
201 return symbol.raw(); 201 return symbol.raw();
202 } 202 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 String& symbol = String::Handle(isolate, String::null()); 236 String& symbol = String::Handle(isolate, String::null());
237 Array& symbol_table = Array::Handle(isolate, Array::null()); 237 Array& symbol_table = Array::Handle(isolate, Array::null());
238 238
239 // Calculate the String hash for this sequence of characters. 239 // Calculate the String hash for this sequence of characters.
240 intptr_t hash = (begin_index == 0 && len == str.Length()) ? str.Hash() : 240 intptr_t hash = (begin_index == 0 && len == str.Length()) ? str.Hash() :
241 String::Hash(str, begin_index, len); 241 String::Hash(str, begin_index, len);
242 242
243 // First check if a symbol exists in the vm isolate for these characters. 243 // First check if a symbol exists in the vm isolate for these characters.
244 symbol_table = Dart::vm_isolate()->object_store()->symbol_table(); 244 symbol_table = Dart::vm_isolate()->object_store()->symbol_table();
245 intptr_t index = FindIndex(symbol_table, str, begin_index, len, hash); 245 intptr_t index = FindIndex(symbol_table, str, begin_index, len, hash);
246 symbol |= symbol_table.At(index); 246 symbol ^= symbol_table.At(index);
247 if (symbol.IsNull()) { 247 if (symbol.IsNull()) {
248 // Now try in the symbol table of the current isolate. 248 // Now try in the symbol table of the current isolate.
249 symbol_table = isolate->object_store()->symbol_table(); 249 symbol_table = isolate->object_store()->symbol_table();
250 index = FindIndex(symbol_table, str, begin_index, len, hash); 250 index = FindIndex(symbol_table, str, begin_index, len, hash);
251 // Since we leave enough room in the table to guarantee, that we find an 251 // Since we leave enough room in the table to guarantee, that we find an
252 // empty spot, index is the insertion point if symbol is null. 252 // empty spot, index is the insertion point if symbol is null.
253 symbol |= symbol_table.At(index); 253 symbol ^= symbol_table.At(index);
254 if (symbol.IsNull()) { 254 if (symbol.IsNull()) {
255 if (str.IsOld() && begin_index == 0 && len == str.Length()) { 255 if (str.IsOld() && begin_index == 0 && len == str.Length()) {
256 // Reuse the incoming str as the symbol value. 256 // Reuse the incoming str as the symbol value.
257 symbol = str.raw(); 257 symbol = str.raw();
258 } else { 258 } else {
259 // Allocate a copy in old space. 259 // Allocate a copy in old space.
260 symbol = String::SubString(str, begin_index, len, Heap::kOld); 260 symbol = String::SubString(str, begin_index, len, Heap::kOld);
261 symbol.SetHash(hash); 261 symbol.SetHash(hash);
262 } 262 }
263 InsertIntoSymbolTable(symbol_table, symbol, index); 263 InsertIntoSymbolTable(symbol_table, symbol, index);
(...skipping 14 matching lines...) Expand all
278 278
279 void Symbols::DumpStats() { 279 void Symbols::DumpStats() {
280 if (FLAG_dump_symbol_stats) { 280 if (FLAG_dump_symbol_stats) {
281 intptr_t table_size = 0; 281 intptr_t table_size = 0;
282 dart::Smi& used = Smi::Handle(); 282 dart::Smi& used = Smi::Handle();
283 Array& symbol_table = Array::Handle(Array::null()); 283 Array& symbol_table = Array::Handle(Array::null());
284 284
285 // First dump VM symbol table stats. 285 // First dump VM symbol table stats.
286 symbol_table = Dart::vm_isolate()->object_store()->symbol_table(); 286 symbol_table = Dart::vm_isolate()->object_store()->symbol_table();
287 table_size = symbol_table.Length() - 1; 287 table_size = symbol_table.Length() - 1;
288 used |= symbol_table.At(table_size); 288 used ^= symbol_table.At(table_size);
289 OS::Print("VM Isolate: Number of symbols : %"Pd"\n", used.Value()); 289 OS::Print("VM Isolate: Number of symbols : %"Pd"\n", used.Value());
290 OS::Print("VM Isolate: Symbol table capacity : %"Pd"\n", table_size); 290 OS::Print("VM Isolate: Symbol table capacity : %"Pd"\n", table_size);
291 291
292 // Now dump regular isolate symbol table stats. 292 // Now dump regular isolate symbol table stats.
293 symbol_table = Isolate::Current()->object_store()->symbol_table(); 293 symbol_table = Isolate::Current()->object_store()->symbol_table();
294 table_size = symbol_table.Length() - 1; 294 table_size = symbol_table.Length() - 1;
295 used |= symbol_table.At(table_size); 295 used ^= symbol_table.At(table_size);
296 OS::Print("Isolate: Number of symbols : %"Pd"\n", used.Value()); 296 OS::Print("Isolate: Number of symbols : %"Pd"\n", used.Value());
297 OS::Print("Isolate: Symbol table capacity : %"Pd"\n", table_size); 297 OS::Print("Isolate: Symbol table capacity : %"Pd"\n", table_size);
298 298
299 // Dump overall collision and growth counts. 299 // Dump overall collision and growth counts.
300 OS::Print("Number of symbol table grows = %"Pd"\n", num_of_grows_); 300 OS::Print("Number of symbol table grows = %"Pd"\n", num_of_grows_);
301 OS::Print("Collision counts on add and lookup :\n"); 301 OS::Print("Collision counts on add and lookup :\n");
302 intptr_t i = 0; 302 intptr_t i = 0;
303 for (i = 0; i < (kMaxCollisionBuckets - 1); i++) { 303 for (i = 0; i < (kMaxCollisionBuckets - 1); i++) {
304 OS::Print(" %"Pd" collisions => %"Pd"\n", i, collision_count_[i]); 304 OS::Print(" %"Pd" collisions => %"Pd"\n", i, collision_count_[i]);
305 } 305 }
306 OS::Print(" > %"Pd" collisions => %"Pd"\n", i, collision_count_[i]); 306 OS::Print(" > %"Pd" collisions => %"Pd"\n", i, collision_count_[i]);
307 } 307 }
308 } 308 }
309 309
310 310
311 void Symbols::GrowSymbolTable(const Array& symbol_table) { 311 void Symbols::GrowSymbolTable(const Array& symbol_table) {
312 // TODO(iposva): Avoid exponential growth. 312 // TODO(iposva): Avoid exponential growth.
313 num_of_grows_ += 1; 313 num_of_grows_ += 1;
314 intptr_t table_size = symbol_table.Length() - 1; 314 intptr_t table_size = symbol_table.Length() - 1;
315 intptr_t new_table_size = table_size * 2; 315 intptr_t new_table_size = table_size * 2;
316 Array& new_symbol_table = Array::Handle(Array::New(new_table_size + 1)); 316 Array& new_symbol_table = Array::Handle(Array::New(new_table_size + 1));
317 // Copy all elements from the original symbol table to the newly allocated 317 // Copy all elements from the original symbol table to the newly allocated
318 // array. 318 // array.
319 String& element = String::Handle(); 319 String& element = String::Handle();
320 dart::Object& new_element = Object::Handle(); 320 dart::Object& new_element = Object::Handle();
321 for (intptr_t i = 0; i < table_size; i++) { 321 for (intptr_t i = 0; i < table_size; i++) {
322 element |= symbol_table.At(i); 322 element ^= symbol_table.At(i);
323 if (!element.IsNull()) { 323 if (!element.IsNull()) {
324 intptr_t hash = element.Hash(); 324 intptr_t hash = element.Hash();
325 intptr_t index = hash % new_table_size; 325 intptr_t index = hash % new_table_size;
326 new_element = new_symbol_table.At(index); 326 new_element = new_symbol_table.At(index);
327 intptr_t num_collisions = 0; 327 intptr_t num_collisions = 0;
328 while (!new_element.IsNull()) { 328 while (!new_element.IsNull()) {
329 index = (index + 1) % new_table_size; // Move to next element. 329 index = (index + 1) % new_table_size; // Move to next element.
330 new_element = new_symbol_table.At(index); 330 new_element = new_symbol_table.At(index);
331 num_collisions += 1; 331 num_collisions += 1;
332 } 332 }
(...skipping 14 matching lines...) Expand all
347 } 347 }
348 348
349 349
350 void Symbols::InsertIntoSymbolTable(const Array& symbol_table, 350 void Symbols::InsertIntoSymbolTable(const Array& symbol_table,
351 const String& symbol, 351 const String& symbol,
352 intptr_t index) { 352 intptr_t index) {
353 intptr_t table_size = symbol_table.Length() - 1; 353 intptr_t table_size = symbol_table.Length() - 1;
354 symbol.SetCanonical(); // Mark object as being canonical. 354 symbol.SetCanonical(); // Mark object as being canonical.
355 symbol_table.SetAt(index, symbol); // Remember the new symbol. 355 symbol_table.SetAt(index, symbol); // Remember the new symbol.
356 dart::Smi& used = Smi::Handle(); 356 dart::Smi& used = Smi::Handle();
357 used |= symbol_table.At(table_size); 357 used ^= symbol_table.At(table_size);
358 intptr_t used_elements = used.Value() + 1; // One more element added. 358 intptr_t used_elements = used.Value() + 1; // One more element added.
359 used = Smi::New(used_elements); 359 used = Smi::New(used_elements);
360 symbol_table.SetAt(table_size, used); // Update used count. 360 symbol_table.SetAt(table_size, used); // Update used count.
361 361
362 // Rehash if symbol_table is 75% full. 362 // Rehash if symbol_table is 75% full.
363 if (used_elements > ((table_size / 4) * 3)) { 363 if (used_elements > ((table_size / 4) * 3)) {
364 GrowSymbolTable(symbol_table); 364 GrowSymbolTable(symbol_table);
365 } 365 }
366 } 366 }
367 367
368 368
369 template<typename T> 369 template<typename T>
370 intptr_t Symbols::FindIndex(const Array& symbol_table, 370 intptr_t Symbols::FindIndex(const Array& symbol_table,
371 const T* characters, 371 const T* characters,
372 intptr_t len, 372 intptr_t len,
373 intptr_t hash) { 373 intptr_t hash) {
374 // Last element of the array is the number of used elements. 374 // Last element of the array is the number of used elements.
375 intptr_t table_size = symbol_table.Length() - 1; 375 intptr_t table_size = symbol_table.Length() - 1;
376 intptr_t index = hash % table_size; 376 intptr_t index = hash % table_size;
377 intptr_t num_collisions = 0; 377 intptr_t num_collisions = 0;
378 378
379 String& symbol = String::Handle(); 379 String& symbol = String::Handle();
380 symbol |= symbol_table.At(index); 380 symbol ^= symbol_table.At(index);
381 while (!symbol.IsNull() && !symbol.Equals(characters, len)) { 381 while (!symbol.IsNull() && !symbol.Equals(characters, len)) {
382 index = (index + 1) % table_size; // Move to next element. 382 index = (index + 1) % table_size; // Move to next element.
383 symbol |= symbol_table.At(index); 383 symbol ^= symbol_table.At(index);
384 num_collisions += 1; 384 num_collisions += 1;
385 } 385 }
386 if (FLAG_dump_symbol_stats) { 386 if (FLAG_dump_symbol_stats) {
387 if (num_collisions >= kMaxCollisionBuckets) { 387 if (num_collisions >= kMaxCollisionBuckets) {
388 num_collisions = (kMaxCollisionBuckets - 1); 388 num_collisions = (kMaxCollisionBuckets - 1);
389 } 389 }
390 collision_count_[num_collisions] += 1; 390 collision_count_[num_collisions] += 1;
391 } 391 }
392 return index; // Index of symbol if found or slot into which to add symbol. 392 return index; // Index of symbol if found or slot into which to add symbol.
393 } 393 }
(...skipping 17 matching lines...) Expand all
411 const String& str, 411 const String& str,
412 intptr_t begin_index, 412 intptr_t begin_index,
413 intptr_t len, 413 intptr_t len,
414 intptr_t hash) { 414 intptr_t hash) {
415 // Last element of the array is the number of used elements. 415 // Last element of the array is the number of used elements.
416 intptr_t table_size = symbol_table.Length() - 1; 416 intptr_t table_size = symbol_table.Length() - 1;
417 intptr_t index = hash % table_size; 417 intptr_t index = hash % table_size;
418 intptr_t num_collisions = 0; 418 intptr_t num_collisions = 0;
419 419
420 String& symbol = String::Handle(); 420 String& symbol = String::Handle();
421 symbol |= symbol_table.At(index); 421 symbol ^= symbol_table.At(index);
422 while (!symbol.IsNull() && !symbol.Equals(str, begin_index, len)) { 422 while (!symbol.IsNull() && !symbol.Equals(str, begin_index, len)) {
423 index = (index + 1) % table_size; // Move to next element. 423 index = (index + 1) % table_size; // Move to next element.
424 symbol |= symbol_table.At(index); 424 symbol ^= symbol_table.At(index);
425 num_collisions += 1; 425 num_collisions += 1;
426 } 426 }
427 if (FLAG_dump_symbol_stats) { 427 if (FLAG_dump_symbol_stats) {
428 if (num_collisions >= kMaxCollisionBuckets) { 428 if (num_collisions >= kMaxCollisionBuckets) {
429 num_collisions = (kMaxCollisionBuckets - 1); 429 num_collisions = (kMaxCollisionBuckets - 1);
430 } 430 }
431 collision_count_[num_collisions] += 1; 431 collision_count_[num_collisions] += 1;
432 } 432 }
433 return index; // Index of symbol if found or slot into which to add symbol. 433 return index; // Index of symbol if found or slot into which to add symbol.
434 } 434 }
(...skipping 12 matching lines...) Expand all
447 RawObject* Symbols::GetVMSymbol(intptr_t object_id) { 447 RawObject* Symbols::GetVMSymbol(intptr_t object_id) {
448 ASSERT(IsVMSymbolId(object_id)); 448 ASSERT(IsVMSymbolId(object_id));
449 intptr_t i = (object_id - kMaxPredefinedObjectIds); 449 intptr_t i = (object_id - kMaxPredefinedObjectIds);
450 if ((i > kIllegal) && (i < Symbols::kMaxPredefinedId)) { 450 if ((i > kIllegal) && (i < Symbols::kMaxPredefinedId)) {
451 return symbol_handles_[i]->raw(); 451 return symbol_handles_[i]->raw();
452 } 452 }
453 return Object::null(); 453 return Object::null();
454 } 454 }
455 455
456 } // namespace dart 456 } // namespace dart
OLDNEW
« no previous file with comments | « vm/stub_code_ia32_test.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698