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

Unified Diff: tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp

Issue 207913002: Global cycle detection analysis. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review comments Created 6 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tools/clang/blink_gc_plugin/Config.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
diff --git a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
index 89f0bd419bb94037deb240e7fb10e41ca09637a4..075dc7069d0300c163e4757e1b55dd3ff0fa5afd 100644
--- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
+++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
@@ -9,6 +9,7 @@
// http://www.chromium.org/developers/blink-gc-plugin-errors
#include "Config.h"
+#include "JsonWriter.h"
#include "RecordInfo.h"
#include "clang/AST/AST.h"
@@ -110,8 +111,9 @@ const char kDerivesNonStackAllocated[] =
" which is not stack allocated.";
struct BlinkGCPluginOptions {
- BlinkGCPluginOptions() : enable_oilpan(false) {}
+ BlinkGCPluginOptions() : enable_oilpan(false), detect_cycles(false) {}
bool enable_oilpan;
+ bool detect_cycles;
std::set<std::string> ignored_classes;
std::set<std::string> checked_namespaces;
std::vector<std::string> ignored_directories;
@@ -485,7 +487,8 @@ class BlinkGCPluginConsumer : public ASTConsumer {
const BlinkGCPluginOptions& options)
: instance_(instance),
diagnostic_(instance.getDiagnostics()),
- options_(options) {
+ options_(options),
+ json_(0) {
// Only check structures in the blink, WebCore and WebKit namespaces.
options_.checked_namespaces.insert("blink");
@@ -561,6 +564,30 @@ class BlinkGCPluginConsumer : public ASTConsumer {
CollectVisitor visitor;
visitor.TraverseDecl(context.getTranslationUnitDecl());
+ if (options_.detect_cycles) {
+ string err;
+ // TODO: Make createDefaultOutputFile or a shorter createOutputFile work.
+ json_ = JsonWriter::from(instance_.createOutputFile(
+ "", // OutputPath
+ err, // Errors
+ true, // Binary
+ true, // RemoveFileOnSignal
+ instance_.getFrontendOpts().OutputFile, // BaseInput
+ "graph.json", // Extension
+ false, // UseTemporary
+ false, // CreateMissingDirectories
+ 0, // ResultPathName
+ 0)); // TempPathName
+ if (err.empty() && json_) {
+ json_->OpenList();
+ } else {
+ json_ = 0;
+ llvm::errs()
+ << "[blink-gc] "
+ << "Failed to create an output file for the object graph.\n";
+ }
+ }
+
for (RecordVector::iterator it = visitor.record_decls().begin();
it != visitor.record_decls().end();
++it) {
@@ -572,6 +599,12 @@ class BlinkGCPluginConsumer : public ASTConsumer {
++it) {
CheckTracingMethod(*it);
}
+
+ if (json_) {
+ json_->CloseList();
+ delete json_;
+ json_ = 0;
+ }
}
// Main entry for checking a record declaration.
@@ -634,6 +667,8 @@ class BlinkGCPluginConsumer : public ASTConsumer {
if (info->NeedsFinalization())
CheckFinalization(info);
}
+
+ DumpClass(info);
}
void CheckDispatch(RecordInfo* info) {
@@ -804,12 +839,111 @@ class BlinkGCPluginConsumer : public ASTConsumer {
}
}
+ void DumpClass(RecordInfo* info) {
+ if (!json_) return;
+
+ json_->OpenObject();
+ json_->Write("name", info->record()->getQualifiedNameAsString());
+ json_->Write("loc", GetLocString(info->record()->getLocStart()));
+ json_->CloseObject();
+
+ class DumpEdgeVisitor : public RecursiveEdgeVisitor {
+ public:
+ DumpEdgeVisitor(JsonWriter* json) : json_(json) { }
+ void DumpEdge(RecordInfo* src,
+ RecordInfo* dst,
+ const string& lbl,
+ const Edge::LivenessKind& kind,
+ const string& loc) {
+ json_->OpenObject();
+ json_->Write("src", src->record()->getQualifiedNameAsString());
+ json_->Write("dst", dst->record()->getQualifiedNameAsString());
+ json_->Write("lbl", lbl);
+ json_->Write("kind", kind);
+ json_->Write("loc", loc);
+ json_->CloseObject();
+ }
+
+ void DumpField(RecordInfo* src, FieldPoint* point, const string& loc) {
+ src_ = src;
+ point_ = point;
+ loc_ = loc;
+ point_->edge()->Accept(this);
+ }
+
+ void AtValue(Value* e) {
+ // The liveness kind of a path from the point to this value
+ // is given by the innermost place that is non-strong.
+ Edge::LivenessKind kind = Edge::kStrong;
+ if (Config::IsIgnoreCycleAnnotated(point_->field())) {
+ kind = Edge::kWeak;
+ } else {
+ for (Context::iterator it = context().begin();
+ it != context().end();
+ ++it) {
+ Edge::LivenessKind pointer_kind = (*it)->Kind();
+ if (pointer_kind != Edge::kStrong) {
+ kind = pointer_kind;
+ break;
+ }
+ }
+ }
+ DumpEdge(src_,
+ e->value(),
+ point_->field()->getNameAsString(),
+ kind,
+ loc_);
+ }
+
+ private:
+ JsonWriter* json_;
+ RecordInfo* src_;
+ FieldPoint* point_;
+ string loc_;
+ };
+
+ DumpEdgeVisitor visitor(json_);
+
+ RecordInfo::Bases& bases = info->GetBases();
+ for (RecordInfo::Bases::iterator it = bases.begin();
+ it != bases.end();
+ ++it) {
+ visitor.DumpEdge(info,
+ it->second.info(),
+ "<super>",
+ Edge::kStrong,
+ GetLocString(it->second.spec().getLocStart()));
+ }
+
+ RecordInfo::Fields& fields = info->GetFields();
+ for (RecordInfo::Fields::iterator it = fields.begin();
+ it != fields.end();
+ ++it) {
+ visitor.DumpField(info,
+ &it->second,
+ GetLocString(it->second.field()->getLocStart()));
+ }
+ }
+
// Adds either a warning or error, based on the current handling of -Werror.
DiagnosticsEngine::Level getErrorLevel() {
return diagnostic_.getWarningsAsErrors() ? DiagnosticsEngine::Error
: DiagnosticsEngine::Warning;
}
+ const string GetLocString(SourceLocation loc) {
+ const SourceManager& source_manager = instance_.getSourceManager();
+ PresumedLoc ploc = source_manager.getPresumedLoc(loc);
+ if (ploc.isInvalid())
+ return "";
+ string loc_str;
+ llvm::raw_string_ostream OS(loc_str);
+ OS << ploc.getFilename()
+ << ":" << ploc.getLine()
+ << ":" << ploc.getColumn();
+ return OS.str();
+ }
+
bool IsIgnored(RecordInfo* record) {
return !record ||
!InCheckedNamespace(record) ||
@@ -1132,6 +1266,7 @@ class BlinkGCPluginConsumer : public ASTConsumer {
DiagnosticsEngine& diagnostic_;
BlinkGCPluginOptions options_;
RecordCache cache_;
+ JsonWriter* json_;
};
class BlinkGCPluginAction : public PluginASTAction {
@@ -1152,6 +1287,8 @@ class BlinkGCPluginAction : public PluginASTAction {
for (size_t i = 0; i < args.size() && parsed; ++i) {
if (args[i] == "enable-oilpan") {
options_.enable_oilpan = true;
+ } else if (args[i] == "detect-cycles") {
+ options_.detect_cycles = true;
} else {
parsed = false;
llvm::errs() << "Unknown blink-gc-plugin argument: " << args[i] << "\n";
« no previous file with comments | « no previous file | tools/clang/blink_gc_plugin/Config.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698