| 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 |