| 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/hash_map.h" |
| 9 #include "vm/object.h" | 9 #include "vm/object.h" |
| 10 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 void ProgramVisitor::DedupStackMaps() { | 143 void ProgramVisitor::DedupStackMaps() { |
| 144 class DedupStackMapsVisitor : public FunctionVisitor { | 144 class DedupStackMapsVisitor : public FunctionVisitor { |
| 145 public: | 145 public: |
| 146 explicit DedupStackMapsVisitor(Zone* zone) | 146 explicit DedupStackMapsVisitor(Zone* zone) |
| 147 : zone_(zone), | 147 : zone_(zone), |
| 148 canonical_stackmaps_(), | 148 canonical_stackmaps_(), |
| 149 code_(Code::Handle(zone)), | 149 code_(Code::Handle(zone)), |
| 150 stackmaps_(Array::Handle(zone)), | 150 stackmaps_(Array::Handle(zone)), |
| 151 stackmap_(StackMap::Handle(zone)) {} | 151 stackmap_(StackMap::Handle(zone)) {} |
| 152 | 152 |
| 153 void AddStackMap(const StackMap& stackmap) { |
| 154 canonical_stackmaps_.Insert(&StackMap::ZoneHandle(zone_, stackmap.raw())); |
| 155 } |
| 156 |
| 153 void Visit(const Function& function) { | 157 void Visit(const Function& function) { |
| 154 if (!function.HasCode()) { | 158 if (!function.HasCode()) { |
| 155 return; | 159 return; |
| 156 } | 160 } |
| 157 code_ = function.CurrentCode(); | 161 code_ = function.CurrentCode(); |
| 158 stackmaps_ = code_.stackmaps(); | 162 stackmaps_ = code_.stackmaps(); |
| 159 if (stackmaps_.IsNull()) return; | 163 if (stackmaps_.IsNull()) return; |
| 160 for (intptr_t i = 0; i < stackmaps_.Length(); i++) { | 164 for (intptr_t i = 0; i < stackmaps_.Length(); i++) { |
| 161 stackmap_ ^= stackmaps_.At(i); | 165 stackmap_ ^= stackmaps_.At(i); |
| 162 stackmap_ = DedupStackMap(stackmap_); | 166 stackmap_ = DedupStackMap(stackmap_); |
| 163 stackmaps_.SetAt(i, stackmap_); | 167 stackmaps_.SetAt(i, stackmap_); |
| 164 } | 168 } |
| 165 } | 169 } |
| 166 | 170 |
| 167 RawStackMap* DedupStackMap(const StackMap& stackmap) { | 171 RawStackMap* DedupStackMap(const StackMap& stackmap) { |
| 168 const StackMap* canonical_stackmap = | 172 const StackMap* canonical_stackmap = |
| 169 canonical_stackmaps_.LookupValue(&stackmap); | 173 canonical_stackmaps_.LookupValue(&stackmap); |
| 170 if (canonical_stackmap == NULL) { | 174 if (canonical_stackmap == NULL) { |
| 171 canonical_stackmaps_.Insert( | 175 AddStackMap(stackmap); |
| 172 &StackMap::ZoneHandle(zone_, stackmap.raw())); | |
| 173 return stackmap.raw(); | 176 return stackmap.raw(); |
| 174 } else { | 177 } else { |
| 175 return canonical_stackmap->raw(); | 178 return canonical_stackmap->raw(); |
| 176 } | 179 } |
| 177 } | 180 } |
| 178 | 181 |
| 179 private: | 182 private: |
| 180 Zone* zone_; | 183 Zone* zone_; |
| 181 StackMapSet canonical_stackmaps_; | 184 StackMapSet canonical_stackmaps_; |
| 182 Code& code_; | 185 Code& code_; |
| 183 Array& stackmaps_; | 186 Array& stackmaps_; |
| 184 StackMap& stackmap_; | 187 StackMap& stackmap_; |
| 185 }; | 188 }; |
| 186 | 189 |
| 187 DedupStackMapsVisitor visitor(Thread::Current()->zone()); | 190 DedupStackMapsVisitor visitor(Thread::Current()->zone()); |
| 191 if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) { |
| 192 // Prefer existing objects in the VM isolate. |
| 193 const Array& object_table = Object::vm_isolate_snapshot_object_table(); |
| 194 Object& object = Object::Handle(); |
| 195 for (intptr_t i = 0; i < object_table.Length(); i++) { |
| 196 object = object_table.At(i); |
| 197 if (object.IsStackMap()) { |
| 198 visitor.AddStackMap(StackMap::Cast(object)); |
| 199 } |
| 200 } |
| 201 } |
| 188 ProgramVisitor::VisitFunctions(&visitor); | 202 ProgramVisitor::VisitFunctions(&visitor); |
| 189 } | 203 } |
| 190 | 204 |
| 191 class PcDescriptorsKeyValueTrait { | 205 class PcDescriptorsKeyValueTrait { |
| 192 public: | 206 public: |
| 193 // Typedefs needed for the DirectChainedHashMap template. | 207 // Typedefs needed for the DirectChainedHashMap template. |
| 194 typedef const PcDescriptors* Key; | 208 typedef const PcDescriptors* Key; |
| 195 typedef const PcDescriptors* Value; | 209 typedef const PcDescriptors* Value; |
| 196 typedef const PcDescriptors* Pair; | 210 typedef const PcDescriptors* Pair; |
| 197 | 211 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 210 | 224 |
| 211 void ProgramVisitor::DedupPcDescriptors() { | 225 void ProgramVisitor::DedupPcDescriptors() { |
| 212 class DedupPcDescriptorsVisitor : public FunctionVisitor { | 226 class DedupPcDescriptorsVisitor : public FunctionVisitor { |
| 213 public: | 227 public: |
| 214 explicit DedupPcDescriptorsVisitor(Zone* zone) | 228 explicit DedupPcDescriptorsVisitor(Zone* zone) |
| 215 : zone_(zone), | 229 : zone_(zone), |
| 216 canonical_pc_descriptors_(), | 230 canonical_pc_descriptors_(), |
| 217 code_(Code::Handle(zone)), | 231 code_(Code::Handle(zone)), |
| 218 pc_descriptor_(PcDescriptors::Handle(zone)) {} | 232 pc_descriptor_(PcDescriptors::Handle(zone)) {} |
| 219 | 233 |
| 234 void AddPcDescriptor(const PcDescriptors& pc_descriptor) { |
| 235 canonical_pc_descriptors_.Insert( |
| 236 &PcDescriptors::ZoneHandle(zone_, pc_descriptor.raw())); |
| 237 } |
| 238 |
| 220 void Visit(const Function& function) { | 239 void Visit(const Function& function) { |
| 221 if (!function.HasCode()) { | 240 if (!function.HasCode()) { |
| 222 return; | 241 return; |
| 223 } | 242 } |
| 224 code_ = function.CurrentCode(); | 243 code_ = function.CurrentCode(); |
| 225 pc_descriptor_ = code_.pc_descriptors(); | 244 pc_descriptor_ = code_.pc_descriptors(); |
| 226 if (pc_descriptor_.IsNull()) return; | 245 if (pc_descriptor_.IsNull()) return; |
| 227 pc_descriptor_ = DedupPcDescriptor(pc_descriptor_); | 246 pc_descriptor_ = DedupPcDescriptor(pc_descriptor_); |
| 228 code_.set_pc_descriptors(pc_descriptor_); | 247 code_.set_pc_descriptors(pc_descriptor_); |
| 229 } | 248 } |
| 230 | 249 |
| 231 RawPcDescriptors* DedupPcDescriptor(const PcDescriptors& pc_descriptor) { | 250 RawPcDescriptors* DedupPcDescriptor(const PcDescriptors& pc_descriptor) { |
| 232 const PcDescriptors* canonical_pc_descriptor = | 251 const PcDescriptors* canonical_pc_descriptor = |
| 233 canonical_pc_descriptors_.LookupValue(&pc_descriptor); | 252 canonical_pc_descriptors_.LookupValue(&pc_descriptor); |
| 234 if (canonical_pc_descriptor == NULL) { | 253 if (canonical_pc_descriptor == NULL) { |
| 235 canonical_pc_descriptors_.Insert( | 254 AddPcDescriptor(pc_descriptor); |
| 236 &PcDescriptors::ZoneHandle(zone_, pc_descriptor.raw())); | |
| 237 return pc_descriptor.raw(); | 255 return pc_descriptor.raw(); |
| 238 } else { | 256 } else { |
| 239 return canonical_pc_descriptor->raw(); | 257 return canonical_pc_descriptor->raw(); |
| 240 } | 258 } |
| 241 } | 259 } |
| 242 | 260 |
| 243 private: | 261 private: |
| 244 Zone* zone_; | 262 Zone* zone_; |
| 245 PcDescriptorsSet canonical_pc_descriptors_; | 263 PcDescriptorsSet canonical_pc_descriptors_; |
| 246 Code& code_; | 264 Code& code_; |
| 247 PcDescriptors& pc_descriptor_; | 265 PcDescriptors& pc_descriptor_; |
| 248 }; | 266 }; |
| 249 | 267 |
| 250 DedupPcDescriptorsVisitor visitor(Thread::Current()->zone()); | 268 DedupPcDescriptorsVisitor visitor(Thread::Current()->zone()); |
| 269 if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) { |
| 270 // Prefer existing objects in the VM isolate. |
| 271 const Array& object_table = Object::vm_isolate_snapshot_object_table(); |
| 272 Object& object = Object::Handle(); |
| 273 for (intptr_t i = 0; i < object_table.Length(); i++) { |
| 274 object = object_table.At(i); |
| 275 if (object.IsPcDescriptors()) { |
| 276 visitor.AddPcDescriptor(PcDescriptors::Cast(object)); |
| 277 } |
| 278 } |
| 279 } |
| 251 ProgramVisitor::VisitFunctions(&visitor); | 280 ProgramVisitor::VisitFunctions(&visitor); |
| 252 } | 281 } |
| 253 | 282 |
| 254 class TypedDataKeyValueTrait { | 283 class TypedDataKeyValueTrait { |
| 255 public: | 284 public: |
| 256 // Typedefs needed for the DirectChainedHashMap template. | 285 // Typedefs needed for the DirectChainedHashMap template. |
| 257 typedef const TypedData* Key; | 286 typedef const TypedData* Key; |
| 258 typedef const TypedData* Value; | 287 typedef const TypedData* Value; |
| 259 typedef const TypedData* Pair; | 288 typedef const TypedData* Pair; |
| 260 | 289 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 | 383 |
| 355 void ProgramVisitor::DedupCodeSourceMaps() { | 384 void ProgramVisitor::DedupCodeSourceMaps() { |
| 356 class DedupCodeSourceMapsVisitor : public FunctionVisitor { | 385 class DedupCodeSourceMapsVisitor : public FunctionVisitor { |
| 357 public: | 386 public: |
| 358 explicit DedupCodeSourceMapsVisitor(Zone* zone) | 387 explicit DedupCodeSourceMapsVisitor(Zone* zone) |
| 359 : zone_(zone), | 388 : zone_(zone), |
| 360 canonical_code_source_maps_(), | 389 canonical_code_source_maps_(), |
| 361 code_(Code::Handle(zone)), | 390 code_(Code::Handle(zone)), |
| 362 code_source_map_(CodeSourceMap::Handle(zone)) {} | 391 code_source_map_(CodeSourceMap::Handle(zone)) {} |
| 363 | 392 |
| 393 void AddCodeSourceMap(const CodeSourceMap& code_source_map) { |
| 394 canonical_code_source_maps_.Insert( |
| 395 &CodeSourceMap::ZoneHandle(zone_, code_source_map.raw())); |
| 396 } |
| 397 |
| 364 void Visit(const Function& function) { | 398 void Visit(const Function& function) { |
| 365 if (!function.HasCode()) { | 399 if (!function.HasCode()) { |
| 366 return; | 400 return; |
| 367 } | 401 } |
| 368 code_ = function.CurrentCode(); | 402 code_ = function.CurrentCode(); |
| 369 code_source_map_ = code_.code_source_map(); | 403 code_source_map_ = code_.code_source_map(); |
| 370 ASSERT(!code_source_map_.IsNull()); | 404 ASSERT(!code_source_map_.IsNull()); |
| 371 code_source_map_ = DedupCodeSourceMap(code_source_map_); | 405 code_source_map_ = DedupCodeSourceMap(code_source_map_); |
| 372 code_.set_code_source_map(code_source_map_); | 406 code_.set_code_source_map(code_source_map_); |
| 373 } | 407 } |
| 374 | 408 |
| 375 RawCodeSourceMap* DedupCodeSourceMap(const CodeSourceMap& code_source_map) { | 409 RawCodeSourceMap* DedupCodeSourceMap(const CodeSourceMap& code_source_map) { |
| 376 const CodeSourceMap* canonical_code_source_map = | 410 const CodeSourceMap* canonical_code_source_map = |
| 377 canonical_code_source_maps_.LookupValue(&code_source_map); | 411 canonical_code_source_maps_.LookupValue(&code_source_map); |
| 378 if (canonical_code_source_map == NULL) { | 412 if (canonical_code_source_map == NULL) { |
| 379 canonical_code_source_maps_.Insert( | 413 AddCodeSourceMap(code_source_map); |
| 380 &CodeSourceMap::ZoneHandle(zone_, code_source_map.raw())); | |
| 381 return code_source_map.raw(); | 414 return code_source_map.raw(); |
| 382 } else { | 415 } else { |
| 383 return canonical_code_source_map->raw(); | 416 return canonical_code_source_map->raw(); |
| 384 } | 417 } |
| 385 } | 418 } |
| 386 | 419 |
| 387 private: | 420 private: |
| 388 Zone* zone_; | 421 Zone* zone_; |
| 389 CodeSourceMapSet canonical_code_source_maps_; | 422 CodeSourceMapSet canonical_code_source_maps_; |
| 390 Code& code_; | 423 Code& code_; |
| 391 CodeSourceMap& code_source_map_; | 424 CodeSourceMap& code_source_map_; |
| 392 }; | 425 }; |
| 393 | 426 |
| 394 DedupCodeSourceMapsVisitor visitor(Thread::Current()->zone()); | 427 DedupCodeSourceMapsVisitor visitor(Thread::Current()->zone()); |
| 428 if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) { |
| 429 // Prefer existing objects in the VM isolate. |
| 430 const Array& object_table = Object::vm_isolate_snapshot_object_table(); |
| 431 Object& object = Object::Handle(); |
| 432 for (intptr_t i = 0; i < object_table.Length(); i++) { |
| 433 object = object_table.At(i); |
| 434 if (object.IsCodeSourceMap()) { |
| 435 visitor.AddCodeSourceMap(CodeSourceMap::Cast(object)); |
| 436 } |
| 437 } |
| 438 } |
| 395 ProgramVisitor::VisitFunctions(&visitor); | 439 ProgramVisitor::VisitFunctions(&visitor); |
| 396 } | 440 } |
| 397 | 441 |
| 398 class ArrayKeyValueTrait { | 442 class ArrayKeyValueTrait { |
| 399 public: | 443 public: |
| 400 // Typedefs needed for the DirectChainedHashMap template. | 444 // Typedefs needed for the DirectChainedHashMap template. |
| 401 typedef const Array* Key; | 445 typedef const Array* Key; |
| 402 typedef const Array* Value; | 446 typedef const Array* Value; |
| 403 typedef const Array* Pair; | 447 typedef const Array* Pair; |
| 404 | 448 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 static inline intptr_t Hashcode(Key key) { return key->Size(); } | 578 static inline intptr_t Hashcode(Key key) { return key->Size(); } |
| 535 | 579 |
| 536 static inline bool IsKeyEqual(Pair pair, Key key) { | 580 static inline bool IsKeyEqual(Pair pair, Key key) { |
| 537 return pair->Equals(*key); | 581 return pair->Equals(*key); |
| 538 } | 582 } |
| 539 }; | 583 }; |
| 540 | 584 |
| 541 typedef DirectChainedHashMap<InstructionsKeyValueTrait> InstructionsSet; | 585 typedef DirectChainedHashMap<InstructionsKeyValueTrait> InstructionsSet; |
| 542 | 586 |
| 543 void ProgramVisitor::DedupInstructions() { | 587 void ProgramVisitor::DedupInstructions() { |
| 544 class DedupInstructionsVisitor : public FunctionVisitor { | 588 class DedupInstructionsVisitor : public FunctionVisitor, |
| 589 public ObjectVisitor { |
| 545 public: | 590 public: |
| 546 explicit DedupInstructionsVisitor(Zone* zone) | 591 explicit DedupInstructionsVisitor(Zone* zone) |
| 547 : zone_(zone), | 592 : zone_(zone), |
| 548 canonical_instructions_set_(), | 593 canonical_instructions_set_(), |
| 549 code_(Code::Handle(zone)), | 594 code_(Code::Handle(zone)), |
| 550 instructions_(Instructions::Handle(zone)) {} | 595 instructions_(Instructions::Handle(zone)) {} |
| 551 | 596 |
| 597 void VisitObject(RawObject* obj) { |
| 598 if (obj->IsInstructions()) { |
| 599 canonical_instructions_set_.Insert( |
| 600 &Instructions::ZoneHandle(zone_, Instructions::RawCast(obj))); |
| 601 } |
| 602 } |
| 603 |
| 552 void Visit(const Function& function) { | 604 void Visit(const Function& function) { |
| 553 if (!function.HasCode()) { | 605 if (!function.HasCode()) { |
| 554 return; | 606 return; |
| 555 } | 607 } |
| 556 code_ = function.CurrentCode(); | 608 code_ = function.CurrentCode(); |
| 557 instructions_ = code_.instructions(); | 609 instructions_ = code_.instructions(); |
| 558 instructions_ = DedupOneInstructions(instructions_); | 610 instructions_ = DedupOneInstructions(instructions_); |
| 559 code_.SetActiveInstructions(instructions_); | 611 code_.SetActiveInstructions(instructions_); |
| 560 code_.set_instructions(instructions_); | 612 code_.set_instructions(instructions_); |
| 561 function.SetInstructions(code_); // Update cached entry point. | 613 function.SetInstructions(code_); // Update cached entry point. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 574 } | 626 } |
| 575 | 627 |
| 576 private: | 628 private: |
| 577 Zone* zone_; | 629 Zone* zone_; |
| 578 InstructionsSet canonical_instructions_set_; | 630 InstructionsSet canonical_instructions_set_; |
| 579 Code& code_; | 631 Code& code_; |
| 580 Instructions& instructions_; | 632 Instructions& instructions_; |
| 581 }; | 633 }; |
| 582 | 634 |
| 583 DedupInstructionsVisitor visitor(Thread::Current()->zone()); | 635 DedupInstructionsVisitor visitor(Thread::Current()->zone()); |
| 636 if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) { |
| 637 // Prefer existing objects in the VM isolate. |
| 638 Dart::vm_isolate()->heap()->VisitObjectsImagePages(&visitor); |
| 639 } |
| 584 ProgramVisitor::VisitFunctions(&visitor); | 640 ProgramVisitor::VisitFunctions(&visitor); |
| 585 } | 641 } |
| 586 | 642 |
| 587 void ProgramVisitor::Dedup() { | 643 void ProgramVisitor::Dedup() { |
| 588 Thread* thread = Thread::Current(); | 644 Thread* thread = Thread::Current(); |
| 589 StackZone stack_zone(thread); | 645 StackZone stack_zone(thread); |
| 590 HANDLESCOPE(thread); | 646 HANDLESCOPE(thread); |
| 591 | 647 |
| 592 // TODO(rmacnak): Bind static calls whose target has been compiled. Forward | 648 // TODO(rmacnak): Bind static calls whose target has been compiled. Forward |
| 593 // references to disabled code. | 649 // references to disabled code. |
| 594 ShareMegamorphicBuckets(); | 650 ShareMegamorphicBuckets(); |
| 595 DedupStackMaps(); | 651 DedupStackMaps(); |
| 596 DedupPcDescriptors(); | 652 DedupPcDescriptors(); |
| 597 NOT_IN_PRECOMPILED(DedupDeoptEntries()); | 653 NOT_IN_PRECOMPILED(DedupDeoptEntries()); |
| 598 DedupCodeSourceMaps(); | 654 DedupCodeSourceMaps(); |
| 599 DedupLists(); | 655 DedupLists(); |
| 600 | 656 |
| 601 #if defined(PRODUCT) | 657 #if defined(PRODUCT) |
| 602 // Reduces binary size but obfuscates profiler results. | 658 // Reduces binary size but obfuscates profiler results. |
| 603 DedupInstructions(); | 659 DedupInstructions(); |
| 604 #endif | 660 #endif |
| 605 } | 661 } |
| 606 | 662 |
| 607 } // namespace dart | 663 } // namespace dart |
| OLD | NEW |