| Index: tools/clang/blink_gc_plugin/RecordInfo.cpp
|
| diff --git a/tools/clang/blink_gc_plugin/RecordInfo.cpp b/tools/clang/blink_gc_plugin/RecordInfo.cpp
|
| index 2fa8d5363b92a3ebb30f301121e186615ca209fb..1878f1ecdd58ec8ef3e25d4c71b34409ddf192fa 100644
|
| --- a/tools/clang/blink_gc_plugin/RecordInfo.cpp
|
| +++ b/tools/clang/blink_gc_plugin/RecordInfo.cpp
|
| @@ -113,6 +113,21 @@ bool RecordInfo::IsGCFinalized() {
|
| return false;
|
| }
|
|
|
| +// A mixin has not yet been "mixed in" if its only GC base is the mixin base.
|
| +bool RecordInfo::IsUnmixedGCMixin() {
|
| + if (!IsGCDerived() || base_paths_->begin() == base_paths_->end())
|
| + return false;
|
| + // Get the last element of the first path.
|
| + CXXBasePaths::paths_iterator it = base_paths_->begin();
|
| + const CXXBasePathElement& elem = (*it)[it->size() - 1];
|
| + CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl();
|
| + // If it is not a mixin base we are done.
|
| + if (!Config::IsGCMixinBase(base->getName()))
|
| + return false;
|
| + // Otherwise, this is unmixed if there are no other paths to GC bases.
|
| + return ++it == base_paths_->end();
|
| +}
|
| +
|
| // Test if a record is allocated on the managed heap.
|
| bool RecordInfo::IsGCAllocated() {
|
| return IsGCDerived() || IsHeapAllocatedCollection();
|
| @@ -171,16 +186,20 @@ bool RecordInfo::InheritsNonPureTrace() {
|
| RecordInfo::Bases* RecordInfo::CollectBases() {
|
| // Compute the collection locally to avoid inconsistent states.
|
| Bases* bases = new Bases;
|
| + if (!record_->hasDefinition())
|
| + return bases;
|
| for (CXXRecordDecl::base_class_iterator it = record_->bases_begin();
|
| it != record_->bases_end();
|
| ++it) {
|
| - if (CXXRecordDecl* base = it->getType()->getAsCXXRecordDecl()) {
|
| - RecordInfo* info = cache_->Lookup(base);
|
| - TracingStatus status = info->InheritsNonPureTrace()
|
| - ? TracingStatus::Needed()
|
| - : TracingStatus::Unneeded();
|
| - bases->insert(std::make_pair(base, BasePoint(info, status)));
|
| - }
|
| + const CXXBaseSpecifier& spec = *it;
|
| + RecordInfo* info = cache_->Lookup(spec.getType());
|
| + if (!info)
|
| + continue;
|
| + CXXRecordDecl* base = info->record();
|
| + TracingStatus status = info->InheritsNonPureTrace()
|
| + ? TracingStatus::Needed()
|
| + : TracingStatus::Unneeded();
|
| + bases->insert(std::make_pair(base, BasePoint(spec, info, status)));
|
| }
|
| return bases;
|
| }
|
| @@ -194,6 +213,8 @@ RecordInfo::Fields& RecordInfo::GetFields() {
|
| RecordInfo::Fields* RecordInfo::CollectFields() {
|
| // Compute the collection locally to avoid inconsistent states.
|
| Fields* fields = new Fields;
|
| + if (!record_->hasDefinition())
|
| + return fields;
|
| TracingStatus fields_status = TracingStatus::Unneeded();
|
| for (RecordDecl::field_iterator it = record_->field_begin();
|
| it != record_->field_end();
|
| @@ -241,14 +262,28 @@ void RecordInfo::DetermineTracingMethods() {
|
| }
|
| }
|
|
|
| +// TODO: Add classes with a finalize() method that specialize FinalizerTrait.
|
| +bool RecordInfo::NeedsFinalization() {
|
| + return record_->hasNonTrivialDestructor();
|
| +}
|
| +
|
| // A class needs tracing if:
|
| // - it is allocated on the managed heap,
|
| -// - it defines a trace method (of the proper signature), or
|
| +// - it is derived from a class that needs tracing, or
|
| // - it contains fields that need tracing.
|
| +// TODO: Defining NeedsTracing based on whether a class defines a trace method
|
| +// (of the proper signature) over approximates too much. The use of transition
|
| +// types causes some classes to have trace methods without them needing to be
|
| +// traced.
|
| TracingStatus RecordInfo::NeedsTracing(Edge::NeedsTracingOption option) {
|
| - if (IsGCAllocated() || GetTraceMethod())
|
| + if (IsGCAllocated())
|
| return TracingStatus::Needed();
|
|
|
| + for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) {
|
| + if (it->second.info()->NeedsTracing(option).IsNeeded())
|
| + return TracingStatus::Needed();
|
| + }
|
| +
|
| if (option == Edge::kRecursive)
|
| GetFields();
|
|
|
| @@ -266,15 +301,13 @@ Edge* RecordInfo::CreateEdge(const Type* type) {
|
| return 0;
|
| }
|
|
|
| - CXXRecordDecl* record = type->getAsCXXRecordDecl();
|
| + RecordInfo* info = cache_->Lookup(type);
|
|
|
| // If the type is neither a pointer or a C++ record we ignore it.
|
| - if (!record) {
|
| + if (!info) {
|
| return 0;
|
| }
|
|
|
| - RecordInfo* info = cache_->Lookup(record);
|
| -
|
| TemplateArgs args;
|
|
|
| if (Config::IsRawPtr(info->name()) && info->GetTemplateArgs(1, &args)) {
|
| @@ -328,7 +361,7 @@ Edge* RecordInfo::CreateEdge(const Type* type) {
|
| size_t count = Config::CollectionDimension(info->name());
|
| if (!info->GetTemplateArgs(count, &args))
|
| return 0;
|
| - Collection* edge = new Collection(on_heap, is_root);
|
| + Collection* edge = new Collection(info, on_heap, is_root);
|
| for (TemplateArgs::iterator it = args.begin(); it != args.end(); ++it) {
|
| if (Edge* member = CreateEdge(*it)) {
|
| edge->members().push_back(member);
|
|
|