| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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/program_visitor.h" | 5 #include "vm/program_visitor.h" |
| 6 | 6 |
| 7 #include "vm/deopt_instructions.h" | 7 #include "vm/deopt_instructions.h" |
| 8 #include "vm/hash_map.h" |
| 8 #include "vm/object.h" | 9 #include "vm/object.h" |
| 9 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
| 10 #include "vm/hash_map.h" | |
| 11 #include "vm/symbols.h" | 11 #include "vm/symbols.h" |
| 12 | 12 |
| 13 namespace dart { | 13 namespace dart { |
| 14 | 14 |
| 15 void ProgramVisitor::VisitClasses(ClassVisitor* visitor) { | 15 void ProgramVisitor::VisitClasses(ClassVisitor* visitor) { |
| 16 Thread* thread = Thread::Current(); | 16 Thread* thread = Thread::Current(); |
| 17 Isolate* isolate = thread->isolate(); | 17 Isolate* isolate = thread->isolate(); |
| 18 Zone* zone = thread->zone(); | 18 Zone* zone = thread->zone(); |
| 19 GrowableObjectArray& libraries = | 19 GrowableObjectArray& libraries = |
| 20 GrowableObjectArray::Handle(zone, isolate->object_store()->libraries()); | 20 GrowableObjectArray::Handle(zone, isolate->object_store()->libraries()); |
| 21 Library& lib = Library::Handle(zone); | 21 Library& lib = Library::Handle(zone); |
| 22 Class& cls = Class::Handle(zone); | 22 Class& cls = Class::Handle(zone); |
| 23 | 23 |
| 24 for (intptr_t i = 0; i < libraries.Length(); i++) { | 24 for (intptr_t i = 0; i < libraries.Length(); i++) { |
| 25 lib ^= libraries.At(i); | 25 lib ^= libraries.At(i); |
| 26 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); | 26 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); |
| 27 while (it.HasNext()) { | 27 while (it.HasNext()) { |
| 28 cls = it.GetNextClass(); | 28 cls = it.GetNextClass(); |
| 29 if (cls.IsDynamicClass()) { | 29 if (cls.IsDynamicClass()) { |
| 30 continue; // class 'dynamic' is in the read-only VM isolate. | 30 continue; // class 'dynamic' is in the read-only VM isolate. |
| 31 } | 31 } |
| 32 visitor->Visit(cls); | 32 visitor->Visit(cls); |
| 33 } | 33 } |
| 34 } | 34 } |
| 35 } | 35 } |
| 36 | 36 |
| 37 | |
| 38 void ProgramVisitor::VisitFunctions(FunctionVisitor* visitor) { | 37 void ProgramVisitor::VisitFunctions(FunctionVisitor* visitor) { |
| 39 Thread* thread = Thread::Current(); | 38 Thread* thread = Thread::Current(); |
| 40 Isolate* isolate = thread->isolate(); | 39 Isolate* isolate = thread->isolate(); |
| 41 Zone* zone = thread->zone(); | 40 Zone* zone = thread->zone(); |
| 42 GrowableObjectArray& libraries = | 41 GrowableObjectArray& libraries = |
| 43 GrowableObjectArray::Handle(zone, isolate->object_store()->libraries()); | 42 GrowableObjectArray::Handle(zone, isolate->object_store()->libraries()); |
| 44 Library& lib = Library::Handle(zone); | 43 Library& lib = Library::Handle(zone); |
| 45 Class& cls = Class::Handle(zone); | 44 Class& cls = Class::Handle(zone); |
| 46 Array& functions = Array::Handle(zone); | 45 Array& functions = Array::Handle(zone); |
| 47 Array& fields = Array::Handle(zone); | 46 Array& fields = Array::Handle(zone); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 } | 87 } |
| 89 } | 88 } |
| 90 closures = isolate->object_store()->closure_functions(); | 89 closures = isolate->object_store()->closure_functions(); |
| 91 for (intptr_t j = 0; j < closures.Length(); j++) { | 90 for (intptr_t j = 0; j < closures.Length(); j++) { |
| 92 function ^= closures.At(j); | 91 function ^= closures.At(j); |
| 93 visitor->Visit(function); | 92 visitor->Visit(function); |
| 94 ASSERT(!function.HasImplicitClosureFunction()); | 93 ASSERT(!function.HasImplicitClosureFunction()); |
| 95 } | 94 } |
| 96 } | 95 } |
| 97 | 96 |
| 98 | |
| 99 void ProgramVisitor::ShareMegamorphicBuckets() { | 97 void ProgramVisitor::ShareMegamorphicBuckets() { |
| 100 Thread* thread = Thread::Current(); | 98 Thread* thread = Thread::Current(); |
| 101 Isolate* isolate = thread->isolate(); | 99 Isolate* isolate = thread->isolate(); |
| 102 Zone* zone = thread->zone(); | 100 Zone* zone = thread->zone(); |
| 103 | 101 |
| 104 const GrowableObjectArray& table = GrowableObjectArray::Handle( | 102 const GrowableObjectArray& table = GrowableObjectArray::Handle( |
| 105 zone, isolate->object_store()->megamorphic_cache_table()); | 103 zone, isolate->object_store()->megamorphic_cache_table()); |
| 106 if (table.IsNull()) return; | 104 if (table.IsNull()) return; |
| 107 MegamorphicCache& cache = MegamorphicCache::Handle(zone); | 105 MegamorphicCache& cache = MegamorphicCache::Handle(zone); |
| 108 | 106 |
| 109 const intptr_t capacity = 1; | 107 const intptr_t capacity = 1; |
| 110 const Array& buckets = Array::Handle( | 108 const Array& buckets = Array::Handle( |
| 111 zone, Array::New(MegamorphicCache::kEntryLength * capacity, Heap::kOld)); | 109 zone, Array::New(MegamorphicCache::kEntryLength * capacity, Heap::kOld)); |
| 112 const Function& handler = | 110 const Function& handler = |
| 113 Function::Handle(zone, MegamorphicCacheTable::miss_handler(isolate)); | 111 Function::Handle(zone, MegamorphicCacheTable::miss_handler(isolate)); |
| 114 MegamorphicCache::SetEntry(buckets, 0, MegamorphicCache::smi_illegal_cid(), | 112 MegamorphicCache::SetEntry(buckets, 0, MegamorphicCache::smi_illegal_cid(), |
| 115 handler); | 113 handler); |
| 116 | 114 |
| 117 for (intptr_t i = 0; i < table.Length(); i++) { | 115 for (intptr_t i = 0; i < table.Length(); i++) { |
| 118 cache ^= table.At(i); | 116 cache ^= table.At(i); |
| 119 cache.set_buckets(buckets); | 117 cache.set_buckets(buckets); |
| 120 cache.set_mask(capacity - 1); | 118 cache.set_mask(capacity - 1); |
| 121 cache.set_filled_entry_count(0); | 119 cache.set_filled_entry_count(0); |
| 122 } | 120 } |
| 123 } | 121 } |
| 124 | 122 |
| 125 | |
| 126 class StackMapKeyValueTrait { | 123 class StackMapKeyValueTrait { |
| 127 public: | 124 public: |
| 128 // Typedefs needed for the DirectChainedHashMap template. | 125 // Typedefs needed for the DirectChainedHashMap template. |
| 129 typedef const StackMap* Key; | 126 typedef const StackMap* Key; |
| 130 typedef const StackMap* Value; | 127 typedef const StackMap* Value; |
| 131 typedef const StackMap* Pair; | 128 typedef const StackMap* Pair; |
| 132 | 129 |
| 133 static Key KeyOf(Pair kv) { return kv; } | 130 static Key KeyOf(Pair kv) { return kv; } |
| 134 | 131 |
| 135 static Value ValueOf(Pair kv) { return kv; } | 132 static Value ValueOf(Pair kv) { return kv; } |
| 136 | 133 |
| 137 static inline intptr_t Hashcode(Key key) { return key->PcOffset(); } | 134 static inline intptr_t Hashcode(Key key) { return key->PcOffset(); } |
| 138 | 135 |
| 139 static inline bool IsKeyEqual(Pair pair, Key key) { | 136 static inline bool IsKeyEqual(Pair pair, Key key) { |
| 140 return pair->Equals(*key); | 137 return pair->Equals(*key); |
| 141 } | 138 } |
| 142 }; | 139 }; |
| 143 | 140 |
| 144 typedef DirectChainedHashMap<StackMapKeyValueTrait> StackMapSet; | 141 typedef DirectChainedHashMap<StackMapKeyValueTrait> StackMapSet; |
| 145 | 142 |
| 146 | |
| 147 void ProgramVisitor::DedupStackMaps() { | 143 void ProgramVisitor::DedupStackMaps() { |
| 148 class DedupStackMapsVisitor : public FunctionVisitor { | 144 class DedupStackMapsVisitor : public FunctionVisitor { |
| 149 public: | 145 public: |
| 150 explicit DedupStackMapsVisitor(Zone* zone) | 146 explicit DedupStackMapsVisitor(Zone* zone) |
| 151 : zone_(zone), | 147 : zone_(zone), |
| 152 canonical_stackmaps_(), | 148 canonical_stackmaps_(), |
| 153 code_(Code::Handle(zone)), | 149 code_(Code::Handle(zone)), |
| 154 stackmaps_(Array::Handle(zone)), | 150 stackmaps_(Array::Handle(zone)), |
| 155 stackmap_(StackMap::Handle(zone)) {} | 151 stackmap_(StackMap::Handle(zone)) {} |
| 156 | 152 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 185 StackMapSet canonical_stackmaps_; | 181 StackMapSet canonical_stackmaps_; |
| 186 Code& code_; | 182 Code& code_; |
| 187 Array& stackmaps_; | 183 Array& stackmaps_; |
| 188 StackMap& stackmap_; | 184 StackMap& stackmap_; |
| 189 }; | 185 }; |
| 190 | 186 |
| 191 DedupStackMapsVisitor visitor(Thread::Current()->zone()); | 187 DedupStackMapsVisitor visitor(Thread::Current()->zone()); |
| 192 ProgramVisitor::VisitFunctions(&visitor); | 188 ProgramVisitor::VisitFunctions(&visitor); |
| 193 } | 189 } |
| 194 | 190 |
| 195 | |
| 196 class PcDescriptorsKeyValueTrait { | 191 class PcDescriptorsKeyValueTrait { |
| 197 public: | 192 public: |
| 198 // Typedefs needed for the DirectChainedHashMap template. | 193 // Typedefs needed for the DirectChainedHashMap template. |
| 199 typedef const PcDescriptors* Key; | 194 typedef const PcDescriptors* Key; |
| 200 typedef const PcDescriptors* Value; | 195 typedef const PcDescriptors* Value; |
| 201 typedef const PcDescriptors* Pair; | 196 typedef const PcDescriptors* Pair; |
| 202 | 197 |
| 203 static Key KeyOf(Pair kv) { return kv; } | 198 static Key KeyOf(Pair kv) { return kv; } |
| 204 | 199 |
| 205 static Value ValueOf(Pair kv) { return kv; } | 200 static Value ValueOf(Pair kv) { return kv; } |
| 206 | 201 |
| 207 static inline intptr_t Hashcode(Key key) { return key->Length(); } | 202 static inline intptr_t Hashcode(Key key) { return key->Length(); } |
| 208 | 203 |
| 209 static inline bool IsKeyEqual(Pair pair, Key key) { | 204 static inline bool IsKeyEqual(Pair pair, Key key) { |
| 210 return pair->Equals(*key); | 205 return pair->Equals(*key); |
| 211 } | 206 } |
| 212 }; | 207 }; |
| 213 | 208 |
| 214 typedef DirectChainedHashMap<PcDescriptorsKeyValueTrait> PcDescriptorsSet; | 209 typedef DirectChainedHashMap<PcDescriptorsKeyValueTrait> PcDescriptorsSet; |
| 215 | 210 |
| 216 | |
| 217 void ProgramVisitor::DedupPcDescriptors() { | 211 void ProgramVisitor::DedupPcDescriptors() { |
| 218 class DedupPcDescriptorsVisitor : public FunctionVisitor { | 212 class DedupPcDescriptorsVisitor : public FunctionVisitor { |
| 219 public: | 213 public: |
| 220 explicit DedupPcDescriptorsVisitor(Zone* zone) | 214 explicit DedupPcDescriptorsVisitor(Zone* zone) |
| 221 : zone_(zone), | 215 : zone_(zone), |
| 222 canonical_pc_descriptors_(), | 216 canonical_pc_descriptors_(), |
| 223 code_(Code::Handle(zone)), | 217 code_(Code::Handle(zone)), |
| 224 pc_descriptor_(PcDescriptors::Handle(zone)) {} | 218 pc_descriptor_(PcDescriptors::Handle(zone)) {} |
| 225 | 219 |
| 226 void Visit(const Function& function) { | 220 void Visit(const Function& function) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 250 Zone* zone_; | 244 Zone* zone_; |
| 251 PcDescriptorsSet canonical_pc_descriptors_; | 245 PcDescriptorsSet canonical_pc_descriptors_; |
| 252 Code& code_; | 246 Code& code_; |
| 253 PcDescriptors& pc_descriptor_; | 247 PcDescriptors& pc_descriptor_; |
| 254 }; | 248 }; |
| 255 | 249 |
| 256 DedupPcDescriptorsVisitor visitor(Thread::Current()->zone()); | 250 DedupPcDescriptorsVisitor visitor(Thread::Current()->zone()); |
| 257 ProgramVisitor::VisitFunctions(&visitor); | 251 ProgramVisitor::VisitFunctions(&visitor); |
| 258 } | 252 } |
| 259 | 253 |
| 260 | |
| 261 class TypedDataKeyValueTrait { | 254 class TypedDataKeyValueTrait { |
| 262 public: | 255 public: |
| 263 // Typedefs needed for the DirectChainedHashMap template. | 256 // Typedefs needed for the DirectChainedHashMap template. |
| 264 typedef const TypedData* Key; | 257 typedef const TypedData* Key; |
| 265 typedef const TypedData* Value; | 258 typedef const TypedData* Value; |
| 266 typedef const TypedData* Pair; | 259 typedef const TypedData* Pair; |
| 267 | 260 |
| 268 static Key KeyOf(Pair kv) { return kv; } | 261 static Key KeyOf(Pair kv) { return kv; } |
| 269 | 262 |
| 270 static Value ValueOf(Pair kv) { return kv; } | 263 static Value ValueOf(Pair kv) { return kv; } |
| 271 | 264 |
| 272 static inline intptr_t Hashcode(Key key) { | 265 static inline intptr_t Hashcode(Key key) { |
| 273 return key->ComputeCanonicalTableHash(); | 266 return key->ComputeCanonicalTableHash(); |
| 274 } | 267 } |
| 275 | 268 |
| 276 static inline bool IsKeyEqual(Pair pair, Key key) { | 269 static inline bool IsKeyEqual(Pair pair, Key key) { |
| 277 return pair->CanonicalizeEquals(*key); | 270 return pair->CanonicalizeEquals(*key); |
| 278 } | 271 } |
| 279 }; | 272 }; |
| 280 | 273 |
| 281 typedef DirectChainedHashMap<TypedDataKeyValueTrait> TypedDataSet; | 274 typedef DirectChainedHashMap<TypedDataKeyValueTrait> TypedDataSet; |
| 282 | 275 |
| 283 | |
| 284 #if !defined(DART_PRECOMPILED_RUNTIME) | 276 #if !defined(DART_PRECOMPILED_RUNTIME) |
| 285 void ProgramVisitor::DedupDeoptEntries() { | 277 void ProgramVisitor::DedupDeoptEntries() { |
| 286 class DedupDeoptEntriesVisitor : public FunctionVisitor { | 278 class DedupDeoptEntriesVisitor : public FunctionVisitor { |
| 287 public: | 279 public: |
| 288 explicit DedupDeoptEntriesVisitor(Zone* zone) | 280 explicit DedupDeoptEntriesVisitor(Zone* zone) |
| 289 : zone_(zone), | 281 : zone_(zone), |
| 290 canonical_deopt_entries_(), | 282 canonical_deopt_entries_(), |
| 291 code_(Code::Handle(zone)), | 283 code_(Code::Handle(zone)), |
| 292 deopt_table_(Array::Handle(zone)), | 284 deopt_table_(Array::Handle(zone)), |
| 293 deopt_entry_(TypedData::Handle(zone)), | 285 deopt_entry_(TypedData::Handle(zone)), |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 TypedData& deopt_entry_; | 325 TypedData& deopt_entry_; |
| 334 Smi& offset_; | 326 Smi& offset_; |
| 335 Smi& reason_and_flags_; | 327 Smi& reason_and_flags_; |
| 336 }; | 328 }; |
| 337 | 329 |
| 338 DedupDeoptEntriesVisitor visitor(Thread::Current()->zone()); | 330 DedupDeoptEntriesVisitor visitor(Thread::Current()->zone()); |
| 339 ProgramVisitor::VisitFunctions(&visitor); | 331 ProgramVisitor::VisitFunctions(&visitor); |
| 340 } | 332 } |
| 341 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 333 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
| 342 | 334 |
| 343 | |
| 344 class CodeSourceMapKeyValueTrait { | 335 class CodeSourceMapKeyValueTrait { |
| 345 public: | 336 public: |
| 346 // Typedefs needed for the DirectChainedHashMap template. | 337 // Typedefs needed for the DirectChainedHashMap template. |
| 347 typedef const CodeSourceMap* Key; | 338 typedef const CodeSourceMap* Key; |
| 348 typedef const CodeSourceMap* Value; | 339 typedef const CodeSourceMap* Value; |
| 349 typedef const CodeSourceMap* Pair; | 340 typedef const CodeSourceMap* Pair; |
| 350 | 341 |
| 351 static Key KeyOf(Pair kv) { return kv; } | 342 static Key KeyOf(Pair kv) { return kv; } |
| 352 | 343 |
| 353 static Value ValueOf(Pair kv) { return kv; } | 344 static Value ValueOf(Pair kv) { return kv; } |
| 354 | 345 |
| 355 static inline intptr_t Hashcode(Key key) { return key->Length(); } | 346 static inline intptr_t Hashcode(Key key) { return key->Length(); } |
| 356 | 347 |
| 357 static inline bool IsKeyEqual(Pair pair, Key key) { | 348 static inline bool IsKeyEqual(Pair pair, Key key) { |
| 358 return pair->Equals(*key); | 349 return pair->Equals(*key); |
| 359 } | 350 } |
| 360 }; | 351 }; |
| 361 | 352 |
| 362 typedef DirectChainedHashMap<CodeSourceMapKeyValueTrait> CodeSourceMapSet; | 353 typedef DirectChainedHashMap<CodeSourceMapKeyValueTrait> CodeSourceMapSet; |
| 363 | 354 |
| 364 | |
| 365 void ProgramVisitor::DedupCodeSourceMaps() { | 355 void ProgramVisitor::DedupCodeSourceMaps() { |
| 366 class DedupCodeSourceMapsVisitor : public FunctionVisitor { | 356 class DedupCodeSourceMapsVisitor : public FunctionVisitor { |
| 367 public: | 357 public: |
| 368 explicit DedupCodeSourceMapsVisitor(Zone* zone) | 358 explicit DedupCodeSourceMapsVisitor(Zone* zone) |
| 369 : zone_(zone), | 359 : zone_(zone), |
| 370 canonical_code_source_maps_(), | 360 canonical_code_source_maps_(), |
| 371 code_(Code::Handle(zone)), | 361 code_(Code::Handle(zone)), |
| 372 code_source_map_(CodeSourceMap::Handle(zone)) {} | 362 code_source_map_(CodeSourceMap::Handle(zone)) {} |
| 373 | 363 |
| 374 void Visit(const Function& function) { | 364 void Visit(const Function& function) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 398 Zone* zone_; | 388 Zone* zone_; |
| 399 CodeSourceMapSet canonical_code_source_maps_; | 389 CodeSourceMapSet canonical_code_source_maps_; |
| 400 Code& code_; | 390 Code& code_; |
| 401 CodeSourceMap& code_source_map_; | 391 CodeSourceMap& code_source_map_; |
| 402 }; | 392 }; |
| 403 | 393 |
| 404 DedupCodeSourceMapsVisitor visitor(Thread::Current()->zone()); | 394 DedupCodeSourceMapsVisitor visitor(Thread::Current()->zone()); |
| 405 ProgramVisitor::VisitFunctions(&visitor); | 395 ProgramVisitor::VisitFunctions(&visitor); |
| 406 } | 396 } |
| 407 | 397 |
| 408 | |
| 409 class ArrayKeyValueTrait { | 398 class ArrayKeyValueTrait { |
| 410 public: | 399 public: |
| 411 // Typedefs needed for the DirectChainedHashMap template. | 400 // Typedefs needed for the DirectChainedHashMap template. |
| 412 typedef const Array* Key; | 401 typedef const Array* Key; |
| 413 typedef const Array* Value; | 402 typedef const Array* Value; |
| 414 typedef const Array* Pair; | 403 typedef const Array* Pair; |
| 415 | 404 |
| 416 static Key KeyOf(Pair kv) { return kv; } | 405 static Key KeyOf(Pair kv) { return kv; } |
| 417 | 406 |
| 418 static Value ValueOf(Pair kv) { return kv; } | 407 static Value ValueOf(Pair kv) { return kv; } |
| 419 | 408 |
| 420 static inline intptr_t Hashcode(Key key) { return key->Length(); } | 409 static inline intptr_t Hashcode(Key key) { return key->Length(); } |
| 421 | 410 |
| 422 static inline bool IsKeyEqual(Pair pair, Key key) { | 411 static inline bool IsKeyEqual(Pair pair, Key key) { |
| 423 if (pair->Length() != key->Length()) { | 412 if (pair->Length() != key->Length()) { |
| 424 return false; | 413 return false; |
| 425 } | 414 } |
| 426 for (intptr_t i = 0; i < pair->Length(); i++) { | 415 for (intptr_t i = 0; i < pair->Length(); i++) { |
| 427 if (pair->At(i) != key->At(i)) { | 416 if (pair->At(i) != key->At(i)) { |
| 428 return false; | 417 return false; |
| 429 } | 418 } |
| 430 } | 419 } |
| 431 return true; | 420 return true; |
| 432 } | 421 } |
| 433 }; | 422 }; |
| 434 | 423 |
| 435 typedef DirectChainedHashMap<ArrayKeyValueTrait> ArraySet; | 424 typedef DirectChainedHashMap<ArrayKeyValueTrait> ArraySet; |
| 436 | 425 |
| 437 | |
| 438 void ProgramVisitor::DedupLists() { | 426 void ProgramVisitor::DedupLists() { |
| 439 class DedupListsVisitor : public FunctionVisitor { | 427 class DedupListsVisitor : public FunctionVisitor { |
| 440 public: | 428 public: |
| 441 explicit DedupListsVisitor(Zone* zone) | 429 explicit DedupListsVisitor(Zone* zone) |
| 442 : zone_(zone), | 430 : zone_(zone), |
| 443 canonical_lists_(), | 431 canonical_lists_(), |
| 444 code_(Code::Handle(zone)), | 432 code_(Code::Handle(zone)), |
| 445 list_(Array::Handle(zone)) {} | 433 list_(Array::Handle(zone)) {} |
| 446 | 434 |
| 447 void Visit(const Function& function) { | 435 void Visit(const Function& function) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 Zone* zone_; | 513 Zone* zone_; |
| 526 ArraySet canonical_lists_; | 514 ArraySet canonical_lists_; |
| 527 Code& code_; | 515 Code& code_; |
| 528 Array& list_; | 516 Array& list_; |
| 529 }; | 517 }; |
| 530 | 518 |
| 531 DedupListsVisitor visitor(Thread::Current()->zone()); | 519 DedupListsVisitor visitor(Thread::Current()->zone()); |
| 532 ProgramVisitor::VisitFunctions(&visitor); | 520 ProgramVisitor::VisitFunctions(&visitor); |
| 533 } | 521 } |
| 534 | 522 |
| 535 | |
| 536 class InstructionsKeyValueTrait { | 523 class InstructionsKeyValueTrait { |
| 537 public: | 524 public: |
| 538 // Typedefs needed for the DirectChainedHashMap template. | 525 // Typedefs needed for the DirectChainedHashMap template. |
| 539 typedef const Instructions* Key; | 526 typedef const Instructions* Key; |
| 540 typedef const Instructions* Value; | 527 typedef const Instructions* Value; |
| 541 typedef const Instructions* Pair; | 528 typedef const Instructions* Pair; |
| 542 | 529 |
| 543 static Key KeyOf(Pair kv) { return kv; } | 530 static Key KeyOf(Pair kv) { return kv; } |
| 544 | 531 |
| 545 static Value ValueOf(Pair kv) { return kv; } | 532 static Value ValueOf(Pair kv) { return kv; } |
| 546 | 533 |
| 547 static inline intptr_t Hashcode(Key key) { return key->Size(); } | 534 static inline intptr_t Hashcode(Key key) { return key->Size(); } |
| 548 | 535 |
| 549 static inline bool IsKeyEqual(Pair pair, Key key) { | 536 static inline bool IsKeyEqual(Pair pair, Key key) { |
| 550 return pair->Equals(*key); | 537 return pair->Equals(*key); |
| 551 } | 538 } |
| 552 }; | 539 }; |
| 553 | 540 |
| 554 typedef DirectChainedHashMap<InstructionsKeyValueTrait> InstructionsSet; | 541 typedef DirectChainedHashMap<InstructionsKeyValueTrait> InstructionsSet; |
| 555 | 542 |
| 556 | |
| 557 void ProgramVisitor::DedupInstructions() { | 543 void ProgramVisitor::DedupInstructions() { |
| 558 class DedupInstructionsVisitor : public FunctionVisitor { | 544 class DedupInstructionsVisitor : public FunctionVisitor { |
| 559 public: | 545 public: |
| 560 explicit DedupInstructionsVisitor(Zone* zone) | 546 explicit DedupInstructionsVisitor(Zone* zone) |
| 561 : zone_(zone), | 547 : zone_(zone), |
| 562 canonical_instructions_set_(), | 548 canonical_instructions_set_(), |
| 563 code_(Code::Handle(zone)), | 549 code_(Code::Handle(zone)), |
| 564 instructions_(Instructions::Handle(zone)) {} | 550 instructions_(Instructions::Handle(zone)) {} |
| 565 | 551 |
| 566 void Visit(const Function& function) { | 552 void Visit(const Function& function) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 591 Zone* zone_; | 577 Zone* zone_; |
| 592 InstructionsSet canonical_instructions_set_; | 578 InstructionsSet canonical_instructions_set_; |
| 593 Code& code_; | 579 Code& code_; |
| 594 Instructions& instructions_; | 580 Instructions& instructions_; |
| 595 }; | 581 }; |
| 596 | 582 |
| 597 DedupInstructionsVisitor visitor(Thread::Current()->zone()); | 583 DedupInstructionsVisitor visitor(Thread::Current()->zone()); |
| 598 ProgramVisitor::VisitFunctions(&visitor); | 584 ProgramVisitor::VisitFunctions(&visitor); |
| 599 } | 585 } |
| 600 | 586 |
| 601 | |
| 602 void ProgramVisitor::Dedup() { | 587 void ProgramVisitor::Dedup() { |
| 603 Thread* thread = Thread::Current(); | 588 Thread* thread = Thread::Current(); |
| 604 StackZone stack_zone(thread); | 589 StackZone stack_zone(thread); |
| 605 HANDLESCOPE(thread); | 590 HANDLESCOPE(thread); |
| 606 | 591 |
| 607 // TODO(rmacnak): Bind static calls whose target has been compiled. Forward | 592 // TODO(rmacnak): Bind static calls whose target has been compiled. Forward |
| 608 // references to disabled code. | 593 // references to disabled code. |
| 609 ShareMegamorphicBuckets(); | 594 ShareMegamorphicBuckets(); |
| 610 DedupStackMaps(); | 595 DedupStackMaps(); |
| 611 DedupPcDescriptors(); | 596 DedupPcDescriptors(); |
| 612 NOT_IN_PRECOMPILED(DedupDeoptEntries()); | 597 NOT_IN_PRECOMPILED(DedupDeoptEntries()); |
| 613 DedupCodeSourceMaps(); | 598 DedupCodeSourceMaps(); |
| 614 DedupLists(); | 599 DedupLists(); |
| 615 | 600 |
| 616 if (!FLAG_profiler) { | 601 if (!FLAG_profiler) { |
| 617 // Reduces binary size but obfuscates profiler results. | 602 // Reduces binary size but obfuscates profiler results. |
| 618 DedupInstructions(); | 603 DedupInstructions(); |
| 619 } | 604 } |
| 620 } | 605 } |
| 621 | 606 |
| 622 } // namespace dart | 607 } // namespace dart |
| OLD | NEW |