diff options
Diffstat (limited to 'chromium/tools/clang/blink_gc_plugin/RecordInfo.h')
-rw-r--r-- | chromium/tools/clang/blink_gc_plugin/RecordInfo.h | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/chromium/tools/clang/blink_gc_plugin/RecordInfo.h b/chromium/tools/clang/blink_gc_plugin/RecordInfo.h new file mode 100644 index 00000000000..a2fa10e7a7a --- /dev/null +++ b/chromium/tools/clang/blink_gc_plugin/RecordInfo.h @@ -0,0 +1,173 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file provides a wrapper for CXXRecordDecl that accumulates GC related +// information about a class. Accumulated information is memoized and the info +// objects are stored in a RecordCache. + +#ifndef TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_ +#define TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_ + +#include <map> +#include <vector> + +#include "Edge.h" + +#include "clang/AST/AST.h" +#include "clang/AST/CXXInheritance.h" + +class RecordCache; + +// A potentially tracable and/or lifetime affecting point in the object graph. +class GraphPoint { + public: + GraphPoint() : traced_(false) {} + void MarkTraced() { traced_ = true; } + bool IsProperlyTraced() { return traced_ || !NeedsTracing().IsNeeded(); } + virtual const TracingStatus NeedsTracing() = 0; + + private: + bool traced_; +}; + +class BasePoint : public GraphPoint { + public: + BasePoint(const clang::CXXBaseSpecifier& spec, + RecordInfo* info, + const TracingStatus& status) + : spec_(spec), info_(info), status_(status) {} + const TracingStatus NeedsTracing() { return status_; } + const clang::CXXBaseSpecifier& spec() { return spec_; } + RecordInfo* info() { return info_; } + + private: + const clang::CXXBaseSpecifier& spec_; + RecordInfo* info_; + TracingStatus status_; +}; + +class FieldPoint : public GraphPoint { + public: + FieldPoint(clang::FieldDecl* field, Edge* edge) + : field_(field), edge_(edge) {} + const TracingStatus NeedsTracing() { + return edge_->NeedsTracing(Edge::kRecursive); + } + clang::FieldDecl* field() { return field_; } + Edge* edge() { return edge_; } + + private: + clang::FieldDecl* field_; + Edge* edge_; + + friend class RecordCache; + void deleteEdge() { delete edge_; } +}; + +// Wrapper class to lazily collect information about a C++ record. +class RecordInfo { + public: + typedef std::map<clang::CXXRecordDecl*, BasePoint> Bases; + typedef std::map<clang::FieldDecl*, FieldPoint> Fields; + typedef std::vector<const clang::Type*> TemplateArgs; + + ~RecordInfo(); + + clang::CXXRecordDecl* record() const { return record_; } + const std::string& name() const { return name_; } + Fields& GetFields(); + Bases& GetBases(); + clang::CXXMethodDecl* GetTraceMethod(); + clang::CXXMethodDecl* GetTraceDispatchMethod(); + clang::CXXMethodDecl* GetFinalizeDispatchMethod(); + + bool GetTemplateArgs(size_t count, TemplateArgs* output_args); + + bool IsHeapAllocatedCollection(); + bool IsGCDerived(); + bool IsGCAllocated(); + bool IsGCFinalized(); + bool IsGCMixin(); + bool IsStackAllocated(); + bool IsNonNewable(); + bool IsOnlyPlacementNewable(); + clang::CXXMethodDecl* DeclaresNewOperator(); + + bool RequiresTraceMethod(); + bool NeedsFinalization(); + TracingStatus NeedsTracing(Edge::NeedsTracingOption); + clang::CXXMethodDecl* InheritsNonVirtualTrace(); + bool IsConsideredAbstract(); + + private: + RecordInfo(clang::CXXRecordDecl* record, RecordCache* cache); + + Fields* CollectFields(); + Bases* CollectBases(); + void DetermineTracingMethods(); + bool InheritsTrace(); + + Edge* CreateEdge(const clang::Type* type); + + RecordCache* cache_; + clang::CXXRecordDecl* record_; + const std::string name_; + TracingStatus fields_need_tracing_; + Bases* bases_; + Fields* fields_; + + enum CachedBool { kFalse = 0, kTrue = 1, kNotComputed = 2 }; + CachedBool is_stack_allocated_; + CachedBool is_non_newable_; + CachedBool is_only_placement_newable_; + + bool determined_trace_methods_; + clang::CXXMethodDecl* trace_method_; + clang::CXXMethodDecl* trace_dispatch_method_; + clang::CXXMethodDecl* finalize_dispatch_method_; + + bool is_gc_derived_; + clang::CXXBasePaths* base_paths_; + + friend class RecordCache; +}; + +class RecordCache { + public: + RecordInfo* Lookup(clang::CXXRecordDecl* record); + + RecordInfo* Lookup(const clang::CXXRecordDecl* record) { + return Lookup(const_cast<clang::CXXRecordDecl*>(record)); + } + + RecordInfo* Lookup(clang::DeclContext* decl) { + return Lookup(clang::dyn_cast<clang::CXXRecordDecl>(decl)); + } + + RecordInfo* Lookup(const clang::Type* type) { + return Lookup(type->getAsCXXRecordDecl()); + } + + RecordInfo* Lookup(const clang::QualType& type) { + return Lookup(type.getTypePtr()); + } + + ~RecordCache() { + for (Cache::iterator it = cache_.begin(); it != cache_.end(); ++it) { + if (!it->second.fields_) + continue; + for (RecordInfo::Fields::iterator fit = it->second.fields_->begin(); + fit != it->second.fields_->end(); + ++fit) { + fit->second.deleteEdge(); + } + } + } + + private: + typedef std::map<clang::CXXRecordDecl*, RecordInfo> Cache; + Cache cache_; +}; + +#endif // TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_ |