OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "Config.h" | 5 #include "Config.h" |
6 #include "RecordInfo.h" | 6 #include "RecordInfo.h" |
7 #include "clang/Sema/Sema.h" | 7 #include "clang/Sema/Sema.h" |
8 | 8 |
9 using namespace clang; | 9 using namespace clang; |
10 using std::string; | 10 using std::string; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 if (!tmpl_type) | 100 if (!tmpl_type) |
101 return 0; | 101 return 0; |
102 | 102 |
103 TemplateDecl* tmpl_decl = tmpl_type->getTemplateName().getAsTemplateDecl(); | 103 TemplateDecl* tmpl_decl = tmpl_type->getTemplateName().getAsTemplateDecl(); |
104 if (!tmpl_decl) | 104 if (!tmpl_decl) |
105 return 0; | 105 return 0; |
106 | 106 |
107 return dyn_cast_or_null<CXXRecordDecl>(tmpl_decl->getTemplatedDecl()); | 107 return dyn_cast_or_null<CXXRecordDecl>(tmpl_decl->getTemplatedDecl()); |
108 } | 108 } |
109 | 109 |
| 110 const Type* RecordInfo::GetPersistentArgumentType(bool& has_persistent_name) { |
| 111 has_persistent_name = |
| 112 Config::IsPersistent(name()) || Config::IsCrossThreadPersistent(name()); |
| 113 if (!has_persistent_name) |
| 114 return nullptr; |
| 115 |
| 116 // "Persistent" could refer to v8::Persistent, check the name space. |
| 117 if (!IsInBlinkNamespace()) |
| 118 return nullptr; |
| 119 |
| 120 TemplateArgs args; |
| 121 if (!GetTemplateArgs(1, &args)) |
| 122 return nullptr; |
| 123 return args[0]; |
| 124 } |
| 125 |
| 126 bool RecordInfo::IsInBlinkNamespace() { |
| 127 NamespaceDecl* ns = dyn_cast<NamespaceDecl>(record()->getDeclContext()); |
| 128 return ns && ns->getName() == "blink"; |
| 129 } |
| 130 |
110 void RecordInfo::walkBases() { | 131 void RecordInfo::walkBases() { |
111 // This traversal is akin to CXXRecordDecl::forallBases()'s, | 132 // This traversal is akin to CXXRecordDecl::forallBases()'s, |
112 // but without stepping over dependent bases -- these might also | 133 // but without stepping over dependent bases -- these might also |
113 // have a "GC base name", so are to be included and considered. | 134 // have a "GC base name", so are to be included and considered. |
114 SmallVector<const CXXRecordDecl*, 8> queue; | 135 SmallVector<const CXXRecordDecl*, 8> queue; |
115 | 136 |
116 const CXXRecordDecl* base_record = record(); | 137 const CXXRecordDecl* base_record = record(); |
117 while (true) { | 138 while (true) { |
118 for (const auto& it : base_record->bases()) { | 139 for (const auto& it : base_record->bases()) { |
119 const RecordType* type = it.getType()->getAs<RecordType>(); | 140 const RecordType* type = it.getType()->getAs<RecordType>(); |
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 // identifiable reason for it being true is the presence | 528 // identifiable reason for it being true is the presence |
508 // of a safely ignorable class as a direct base, | 529 // of a safely ignorable class as a direct base, |
509 // or we're processing such an 'ignorable' class, then it does | 530 // or we're processing such an 'ignorable' class, then it does |
510 // not need finalization. | 531 // not need finalization. |
511 does_need_finalization_ = | 532 does_need_finalization_ = |
512 record_->hasNonTrivialDestructor() ? kTrue : kFalse; | 533 record_->hasNonTrivialDestructor() ? kTrue : kFalse; |
513 if (!does_need_finalization_) | 534 if (!does_need_finalization_) |
514 return does_need_finalization_; | 535 return does_need_finalization_; |
515 | 536 |
516 CXXDestructorDecl* dtor = record_->getDestructor(); | 537 CXXDestructorDecl* dtor = record_->getDestructor(); |
517 if (dtor && dtor->isUserProvided()) | 538 if (dtor && dtor->isUserProvided()) { |
518 return does_need_finalization_; | 539 return does_need_finalization_; |
| 540 } |
519 for (Fields::iterator it = GetFields().begin(); | 541 for (Fields::iterator it = GetFields().begin(); |
520 it != GetFields().end(); | 542 it != GetFields().end(); |
521 ++it) { | 543 ++it) { |
522 if (it->second.edge()->NeedsFinalization()) | 544 if (it->second.edge()->NeedsFinalization()) { |
523 return does_need_finalization_; | 545 return does_need_finalization_; |
| 546 } |
524 } | 547 } |
525 | 548 |
526 for (Bases::iterator it = GetBases().begin(); | 549 for (Bases::iterator it = GetBases().begin(); |
527 it != GetBases().end(); | 550 it != GetBases().end(); |
528 ++it) { | 551 ++it) { |
529 if (it->second.info()->NeedsFinalization()) | 552 if (it->second.info()->NeedsFinalization()) { |
530 return does_need_finalization_; | 553 return does_need_finalization_; |
| 554 } |
531 } | 555 } |
532 // Destructor was non-trivial due to bases with destructors that | 556 // Destructor was non-trivial due to bases with destructors that |
533 // can be safely ignored. Hence, no need for finalization. | 557 // can be safely ignored. Hence, no need for finalization. |
534 does_need_finalization_ = kFalse; | 558 does_need_finalization_ = kFalse; |
535 } | 559 } |
536 return does_need_finalization_; | 560 return does_need_finalization_; |
537 } | 561 } |
538 | 562 |
539 // A class needs tracing if: | 563 // A class needs tracing if: |
540 // - it is allocated on the managed heap, | 564 // - it is allocated on the managed heap, |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 return new Member(ptr); | 672 return new Member(ptr); |
649 return 0; | 673 return 0; |
650 } | 674 } |
651 | 675 |
652 if (Config::IsWeakMember(info->name()) && info->GetTemplateArgs(1, &args)) { | 676 if (Config::IsWeakMember(info->name()) && info->GetTemplateArgs(1, &args)) { |
653 if (Edge* ptr = CreateEdge(args[0])) | 677 if (Edge* ptr = CreateEdge(args[0])) |
654 return new WeakMember(ptr); | 678 return new WeakMember(ptr); |
655 return 0; | 679 return 0; |
656 } | 680 } |
657 | 681 |
658 bool is_persistent = Config::IsPersistent(info->name()); | 682 bool has_persistent_name = false; |
659 if (is_persistent || Config::IsCrossThreadPersistent(info->name())) { | 683 if (const Type* arg_type = |
660 // Persistent might refer to v8::Persistent, so check the name space. | 684 info->GetPersistentArgumentType(has_persistent_name)) { |
661 // TODO: Consider using a more canonical identification than names. | 685 if (Edge* ptr = CreateEdge(arg_type)) { |
662 NamespaceDecl* ns = | 686 if (Config::IsPersistent(info->name())) |
663 dyn_cast<NamespaceDecl>(info->record()->getDeclContext()); | |
664 if (!ns || ns->getName() != "blink") | |
665 return 0; | |
666 if (!info->GetTemplateArgs(1, &args)) | |
667 return 0; | |
668 if (Edge* ptr = CreateEdge(args[0])) { | |
669 if (is_persistent) | |
670 return new Persistent(ptr); | 687 return new Persistent(ptr); |
671 else | 688 else |
672 return new CrossThreadPersistent(ptr); | 689 return new CrossThreadPersistent(ptr); |
673 } | 690 } |
674 return 0; | 691 return nullptr; |
| 692 } else if (has_persistent_name) { |
| 693 // Other Persistent type names are not relevant, like v8::Persistent<>. |
| 694 return nullptr; |
675 } | 695 } |
676 | 696 |
677 if (Config::IsGCCollection(info->name()) || | 697 if (Config::IsGCCollection(info->name()) || |
678 Config::IsWTFCollection(info->name())) { | 698 Config::IsWTFCollection(info->name())) { |
679 bool is_root = Config::IsPersistentGCCollection(info->name()); | 699 bool is_root = Config::IsPersistentGCCollection(info->name()); |
680 bool on_heap = is_root || info->IsHeapAllocatedCollection(); | 700 bool on_heap = is_root || info->IsHeapAllocatedCollection(); |
681 size_t count = Config::CollectionDimension(info->name()); | 701 size_t count = Config::CollectionDimension(info->name()); |
682 if (!info->GetTemplateArgs(count, &args)) | 702 if (!info->GetTemplateArgs(count, &args)) |
683 return 0; | 703 return 0; |
684 Collection* edge = new Collection(info, on_heap, is_root); | 704 Collection* edge = new Collection(info, on_heap, is_root); |
685 for (TemplateArgs::iterator it = args.begin(); it != args.end(); ++it) { | 705 for (TemplateArgs::iterator it = args.begin(); it != args.end(); ++it) { |
686 if (Edge* member = CreateEdge(*it)) { | 706 if (Edge* member = CreateEdge(*it)) { |
687 edge->members().push_back(member); | 707 edge->members().push_back(member); |
688 } | 708 } |
689 // TODO: Handle the case where we fail to create an edge (eg, if the | 709 // TODO: Handle the case where we fail to create an edge (eg, if the |
690 // argument is a primitive type or just not fully known yet). | 710 // argument is a primitive type or just not fully known yet). |
691 } | 711 } |
692 return edge; | 712 return edge; |
693 } | 713 } |
694 | 714 |
695 return new Value(info); | 715 return new Value(info); |
696 } | 716 } |
OLD | NEW |