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) { const CXXBaseSpecifier& spec = *it; RecordInfo* info = cache_->Lookup(spec.getType()); if (!info) continue; CXXRecordDecl* base = info->record(); TracingStatus status = info->InheritsTrace() ? TracingStatus::Needed() : TracingStatus::Unneeded(); bases->insert(std::make_pair(base, BasePoint(spec, info, status))); } return bases; }
void BlinkGCPluginConsumer::CheckTracingMethod(CXXMethodDecl* method) { RecordInfo* parent = cache_.Lookup(method->getParent()); if (IsIgnored(parent)) return; // Check templated tracing methods by checking the template instantiations. // Specialized templates are handled as ordinary classes. if (ClassTemplateDecl* tmpl = parent->record()->getDescribedClassTemplate()) { for (ClassTemplateDecl::spec_iterator it = tmpl->spec_begin(); it != tmpl->spec_end(); ++it) { // Check trace using each template instantiation as the holder. if (Config::IsTemplateInstantiation(*it)) CheckTraceOrDispatchMethod(cache_.Lookup(*it), method); } return; } CheckTraceOrDispatchMethod(parent, method); }
Edge* RecordInfo::CreateEdge(const Type* type) { if (!type) { return 0; } if (type->isPointerType() || type->isReferenceType()) { if (Edge* ptr = CreateEdge(type->getPointeeType().getTypePtrOrNull())) return new RawPtr(ptr, false, type->isReferenceType()); return 0; } RecordInfo* info = cache_->Lookup(type); // If the type is neither a pointer or a C++ record we ignore it. if (!info) { return 0; } TemplateArgs args; if (Config::IsRawPtr(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new RawPtr(ptr, true, false); return 0; } if (Config::IsRefPtr(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new RefPtr(ptr); return 0; } if (Config::IsOwnPtr(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new OwnPtr(ptr); return 0; } if (Config::IsMember(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new Member(ptr); return 0; } if (Config::IsWeakMember(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new WeakMember(ptr); return 0; } if (Config::IsPersistent(info->name())) { // Persistent might refer to v8::Persistent, so check the name space. // TODO: Consider using a more canonical identification than names. NamespaceDecl* ns = dyn_cast<NamespaceDecl>(info->record()->getDeclContext()); if (!ns || ns->getName() != "blink") return 0; if (!info->GetTemplateArgs(1, &args)) return 0; if (Edge* ptr = CreateEdge(args[0])) return new Persistent(ptr); return 0; } if (Config::IsGCCollection(info->name()) || Config::IsWTFCollection(info->name())) { bool is_root = Config::IsPersistentGCCollection(info->name()); bool on_heap = is_root || info->IsHeapAllocatedCollection(); size_t count = Config::CollectionDimension(info->name()); if (!info->GetTemplateArgs(count, &args)) return 0; 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); } // TODO: Handle the case where we fail to create an edge (eg, if the // argument is a primitive type or just not fully known yet). } return edge; } return new Value(info); }
Edge* RecordInfo::CreateEdge(const Type* type) { if (!type) { return 0; } if (type->isPointerType()) { if (Edge* ptr = CreateEdge(type->getPointeeType().getTypePtrOrNull())) return new RawPtr(ptr); return 0; } RecordInfo* info = cache_->Lookup(type); // If the type is neither a pointer or a C++ record we ignore it. if (!info) { return 0; } TemplateArgs args; if (Config::IsRawPtr(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new RawPtr(ptr); return 0; } if (Config::IsRefPtr(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new RefPtr(ptr); return 0; } if (Config::IsOwnPtr(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new OwnPtr(ptr); return 0; } if (Config::IsMember(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new Member(ptr); return 0; } if (Config::IsWeakMember(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new WeakMember(ptr); return 0; } if (Config::IsPersistent(info->name())) { // Persistent might refer to v8::Persistent, so check the name space. // TODO: Consider using a more canonical identification than names. NamespaceDecl* ns = dyn_cast<NamespaceDecl>(info->record()->getDeclContext()); if (!ns || ns->getName() != "WebCore") return 0; if (!info->GetTemplateArgs(1, &args)) return 0; if (Edge* ptr = CreateEdge(args[0])) return new Persistent(ptr); return 0; } if (Config::IsGCCollection(info->name()) || Config::IsWTFCollection(info->name())) { bool is_root = Config::IsPersistentGCCollection(info->name()); bool on_heap = is_root || info->IsHeapAllocatedCollection(); size_t count = Config::CollectionDimension(info->name()); if (!info->GetTemplateArgs(count, &args)) return 0; 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); } else { // We failed to create an edge so abort the entire edge construction. delete edge; // Will delete the already allocated members. return 0; } } return edge; } return new Value(info); }