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

Side by Side Diff: tools/clang/blink_gc_plugin/RecordInfo.cpp

Issue 827693004: Blink GC plugin: improve handling of type dependent bases. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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
OLDNEW
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 7
8 using namespace clang; 8 using namespace clang;
9 using std::string; 9 using std::string;
10 10
11 RecordInfo::RecordInfo(CXXRecordDecl* record, RecordCache* cache) 11 RecordInfo::RecordInfo(CXXRecordDecl* record, RecordCache* cache)
12 : cache_(cache), 12 : cache_(cache),
13 record_(record), 13 record_(record),
14 name_(record->getName()), 14 name_(record->getName()),
15 fields_need_tracing_(TracingStatus::Unknown()), 15 fields_need_tracing_(TracingStatus::Unknown()),
16 bases_(0), 16 bases_(0),
17 fields_(0), 17 fields_(0),
18 is_stack_allocated_(kNotComputed), 18 is_stack_allocated_(kNotComputed),
19 is_non_newable_(kNotComputed), 19 is_non_newable_(kNotComputed),
20 is_only_placement_newable_(kNotComputed), 20 is_only_placement_newable_(kNotComputed),
21 does_need_finalization_(kNotComputed), 21 does_need_finalization_(kNotComputed),
22 determined_trace_methods_(false), 22 determined_trace_methods_(false),
23 trace_method_(0), 23 trace_method_(0),
24 trace_dispatch_method_(0), 24 trace_dispatch_method_(0),
25 finalize_dispatch_method_(0), 25 finalize_dispatch_method_(0),
26 is_gc_derived_(false), 26 is_gc_derived_(false) {}
27 base_paths_(0) {}
28 27
29 RecordInfo::~RecordInfo() { 28 RecordInfo::~RecordInfo() {
30 delete fields_; 29 delete fields_;
31 delete bases_; 30 delete bases_;
32 delete base_paths_;
33 } 31 }
34 32
35 // Get |count| number of template arguments. Returns false if there 33 // Get |count| number of template arguments. Returns false if there
36 // are fewer than |count| arguments or any of the arguments are not 34 // are fewer than |count| arguments or any of the arguments are not
37 // of a valid Type structure. If |count| is non-positive, all 35 // of a valid Type structure. If |count| is non-positive, all
38 // arguments are collected. 36 // arguments are collected.
39 bool RecordInfo::GetTemplateArgs(size_t count, TemplateArgs* output_args) { 37 bool RecordInfo::GetTemplateArgs(size_t count, TemplateArgs* output_args) {
40 ClassTemplateSpecializationDecl* tmpl = 38 ClassTemplateSpecializationDecl* tmpl =
41 dyn_cast<ClassTemplateSpecializationDecl>(record_); 39 dyn_cast<ClassTemplateSpecializationDecl>(record_);
42 if (!tmpl) 40 if (!tmpl)
(...skipping 24 matching lines...) Expand all
67 for (TemplateArgs::iterator it = args.begin(); it != args.end(); ++it) { 65 for (TemplateArgs::iterator it = args.begin(); it != args.end(); ++it) {
68 if (CXXRecordDecl* decl = (*it)->getAsCXXRecordDecl()) 66 if (CXXRecordDecl* decl = (*it)->getAsCXXRecordDecl())
69 if (decl->getName() == kHeapAllocatorName) 67 if (decl->getName() == kHeapAllocatorName)
70 return true; 68 return true;
71 } 69 }
72 } 70 }
73 71
74 return Config::IsGCCollection(name_); 72 return Config::IsGCCollection(name_);
75 } 73 }
76 74
77 static bool IsGCBaseCallback(const CXXBaseSpecifier* specifier,
78 CXXBasePath& path,
79 void* data) {
80 if (CXXRecordDecl* record = specifier->getType()->getAsCXXRecordDecl())
81 return Config::IsGCBase(record->getName());
82 return false;
83 }
84
85 // Test if a record is derived from a garbage collected base. 75 // Test if a record is derived from a garbage collected base.
86 bool RecordInfo::IsGCDerived() { 76 bool RecordInfo::IsGCDerived() {
87 // If already computed, return the known result. 77 // If already computed, return the known result.
88 if (base_paths_) 78 if (gc_base_names_.size())
89 return is_gc_derived_; 79 return is_gc_derived_;
90 80
91 base_paths_ = new CXXBasePaths(true, true, false);
92
93 if (!record_->hasDefinition()) 81 if (!record_->hasDefinition())
94 return false; 82 return false;
95 83
96 // The base classes are not themselves considered garbage collected objects. 84 // The base classes are not themselves considered garbage collected objects.
97 if (Config::IsGCBase(name_)) 85 if (Config::IsGCBase(name_))
98 return false; 86 return false;
99 87
100 // Walk the inheritance tree to find GC base classes. 88 // Walk the inheritance tree to find GC base classes.
101 is_gc_derived_ = record_->lookupInBases(IsGCBaseCallback, 0, *base_paths_); 89 walkBases();
102 return is_gc_derived_; 90 return is_gc_derived_;
103 } 91 }
104 92
93 CXXRecordDecl* RecordInfo::GetDependentTemplatedDecl(const Type& type) {
94 const TemplateSpecializationType* tmpl_type =
95 type.getAs<TemplateSpecializationType>();
96 if (!tmpl_type)
97 return 0;
98
99 TemplateDecl* tmpl_decl = tmpl_type->getTemplateName().getAsTemplateDecl();
100 if (!tmpl_decl)
101 return 0;
102
103 return dyn_cast_or_null<CXXRecordDecl>(tmpl_decl->getTemplatedDecl());
104 }
105
106 void RecordInfo::walkBases() {
107 // This traversal is akin to CXXRecordDecl::forallBases()'s,
108 // but without stepping over dependent bases -- these might also
109 // have a "GC base name", so are to be included and considered.
110 SmallVector<const CXXRecordDecl*, 8> queue;
111
112 const CXXRecordDecl *base_record = record();
113 while (true) {
114 for (const auto& it : base_record->bases()) {
115 const RecordType *type = it.getType()->getAs<RecordType>();
116 CXXRecordDecl* base;
117 if (!type)
118 base = GetDependentTemplatedDecl(*it.getType());
119 else {
120 base = cast_or_null<CXXRecordDecl>(type->getDecl()->getDefinition());
121 if (base)
122 queue.push_back(base);
123 }
124 if (!base)
125 continue;
126
127 const std::string& name = base->getName();
128 if (Config::IsGCBase(name)) {
129 gc_base_names_.push_back(name);
130 is_gc_derived_ = true;
131 }
132 }
133
134 if (queue.empty())
135 break;
136 base_record = queue.pop_back_val(); // not actually a queue.
137 }
138 }
139
105 bool RecordInfo::IsGCFinalized() { 140 bool RecordInfo::IsGCFinalized() {
106 if (!IsGCDerived()) 141 if (!IsGCDerived())
107 return false; 142 return false;
108 for (CXXBasePaths::paths_iterator it = base_paths_->begin(); 143 for (const auto& gc_base : gc_base_names_) {
109 it != base_paths_->end(); 144 if (Config::IsGCFinalizedBase(gc_base))
110 ++it) {
111 const CXXBasePathElement& elem = (*it)[it->size() - 1];
112 CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl();
113 if (Config::IsGCFinalizedBase(base->getName()))
114 return true; 145 return true;
115 } 146 }
116 return false; 147 return false;
117 } 148 }
118 149
119 // A GC mixin is a class that inherits from a GC mixin base and has 150 // A GC mixin is a class that inherits from a GC mixin base and has
120 // not yet been "mixed in" with another GC base class. 151 // not yet been "mixed in" with another GC base class.
121 bool RecordInfo::IsGCMixin() { 152 bool RecordInfo::IsGCMixin() {
122 if (!IsGCDerived() || base_paths_->begin() == base_paths_->end()) 153 if (!IsGCDerived() || !gc_base_names_.size())
123 return false; 154 return false;
124 for (CXXBasePaths::paths_iterator it = base_paths_->begin(); 155 for (const auto& gc_base : gc_base_names_) {
125 it != base_paths_->end();
126 ++it) {
127 // Get the last element of the path.
128 const CXXBasePathElement& elem = (*it)[it->size() - 1];
129 CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl();
130 // If it is not a mixin base we are done. 156 // If it is not a mixin base we are done.
131 if (!Config::IsGCMixinBase(base->getName())) 157 if (!Config::IsGCMixinBase(gc_base))
132 return false; 158 return false;
133 } 159 }
134 // This is a mixin if all GC bases are mixins. 160 // This is a mixin if all GC bases are mixins.
135 return true; 161 return true;
136 } 162 }
137 163
138 // Test if a record is allocated on the managed heap. 164 // Test if a record is allocated on the managed heap.
139 bool RecordInfo::IsGCAllocated() { 165 bool RecordInfo::IsGCAllocated() {
140 return IsGCDerived() || IsHeapAllocatedCollection(); 166 return IsGCDerived() || IsHeapAllocatedCollection();
141 } 167 }
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 edge->members().push_back(member); 572 edge->members().push_back(member);
547 } 573 }
548 // TODO: Handle the case where we fail to create an edge (eg, if the 574 // TODO: Handle the case where we fail to create an edge (eg, if the
549 // argument is a primitive type or just not fully known yet). 575 // argument is a primitive type or just not fully known yet).
550 } 576 }
551 return edge; 577 return edge;
552 } 578 }
553 579
554 return new Value(info); 580 return new Value(info);
555 } 581 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698