Commit fa20d4c4 authored by kouhei's avatar kouhei Committed by Commit bot

[BlinkGCPlugin] Allow tracing member in traceImpl.

Blink r187605 https://crrev.com/804873004 introduced DEFINE_TRACE macros,
which dedupes trace(Visitor*) and trace(InlinedGlobalMarkingVisitor) by
using template method:
template<typename VisitorDispatcher> void traceImpl(VisitorDispatcher);

This CL updates the GC plugin, so that it:
- recognizes traceImpl method, and mark trace(field) calls made inside.
- recognizes trace method that just delegate to traceImpl, and skip its processing.
  - e.g.) void trace(Visitor* visitor) { traceImpl(visitor); }

BUG=420515

Review URL: https://codereview.chromium.org/824853003

Cr-Commit-Position: refs/heads/master@{#309627}
parent 5adbb0a9
......@@ -322,7 +322,9 @@ class CheckDispatchVisitor : public RecursiveASTVisitor<CheckDispatchVisitor> {
class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
public:
CheckTraceVisitor(CXXMethodDecl* trace, RecordInfo* info)
: trace_(trace), info_(info) {}
: trace_(trace), info_(info), delegates_to_traceimpl_(false) {}
bool delegates_to_traceimpl() const { return delegates_to_traceimpl_; }
bool VisitMemberExpr(MemberExpr* member) {
// In weak callbacks, consider any occurrence as a correct usage.
......@@ -383,6 +385,11 @@ class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
if (CXXMemberCallExpr* expr = dyn_cast<CXXMemberCallExpr>(call)) {
if (CheckTraceFieldCall(expr) || CheckRegisterWeakMembers(expr))
return true;
if (expr->getMethodDecl()->getNameAsString() == kTraceImplName) {
delegates_to_traceimpl_ = true;
return true;
}
}
CheckTraceBaseCall(call);
......@@ -415,6 +422,23 @@ class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
void CheckCXXDependentScopeMemberExpr(CallExpr* call,
CXXDependentScopeMemberExpr* expr) {
string fn_name = expr->getMember().getAsString();
// Check for VisitorDispatcher::trace(field)
if (!expr->isImplicitAccess()) {
if (clang::DeclRefExpr* base_decl =
clang::dyn_cast<clang::DeclRefExpr>(expr->getBase())) {
if (Config::IsVisitorDispatcherType(base_decl->getType()) &&
call->getNumArgs() == 1 && fn_name == kTraceName) {
FindFieldVisitor finder;
finder.TraverseStmt(call->getArg(0));
if (finder.field())
FoundField(finder.field());
return;
}
}
}
CXXRecordDecl* tmpl = GetDependentTemplatedDecl(expr);
if (!tmpl)
return;
......@@ -565,6 +589,7 @@ class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
CXXMethodDecl* trace_;
RecordInfo* info_;
bool delegates_to_traceimpl_;
};
// This visitor checks that the fields of a class and the fields of
......@@ -1303,6 +1328,11 @@ class BlinkGCPluginConsumer : public ASTConsumer {
CheckTraceVisitor visitor(trace, parent);
visitor.TraverseCXXMethodDecl(trace);
// Skip reporting if this trace method is a just delegate to
// traceImpl method. We will report on CheckTraceMethod on traceImpl method.
if (visitor.delegates_to_traceimpl())
return;
for (RecordInfo::Bases::iterator it = parent->GetBases().begin();
it != parent->GetBases().end();
++it) {
......
......@@ -18,11 +18,13 @@
const char kNewOperatorName[] = "operator new";
const char kCreateName[] = "create";
const char kTraceName[] = "trace";
const char kTraceImplName[] = "traceImpl";
const char kFinalizeName[] = "finalizeGarbageCollectedObject";
const char kTraceAfterDispatchName[] = "traceAfterDispatch";
const char kRegisterWeakMembersName[] = "registerWeakMembers";
const char kHeapAllocatorName[] = "HeapAllocator";
const char kTraceIfNeededName[] = "TraceIfNeeded";
const char kVisitorDispatcherName[] = "VisitorDispatcher";
class Config {
public:
......@@ -163,16 +165,7 @@ class Config {
return name == "Visitor" || name == "VisitorHelper";
}
static bool IsTraceMethod(clang::FunctionDecl* method,
bool* isTraceAfterDispatch = 0) {
if (method->getNumParams() != 1)
return false;
const std::string& name = method->getNameAsString();
if (name != kTraceName && name != kTraceAfterDispatchName)
return false;
const clang::QualType& formal_type = method->getParamDecl(0)->getType();
static bool IsVisitorPtrType(const clang::QualType& formal_type) {
if (!formal_type->isPointerType())
return false;
......@@ -184,8 +177,50 @@ class Config {
if (!IsVisitor(pointee_type->getName()))
return false;
return true;
}
static bool IsVisitorDispatcherType(const clang::QualType& formal_type) {
if (const clang::SubstTemplateTypeParmType* subst_type =
clang::dyn_cast<clang::SubstTemplateTypeParmType>(
formal_type.getTypePtr())) {
if (IsVisitorPtrType(subst_type->getReplacementType())) {
// VisitorDispatcher template parameter substituted to Visitor*.
return true;
}
} else if (const clang::TemplateTypeParmType* parm_type =
clang::dyn_cast<clang::TemplateTypeParmType>(
formal_type.getTypePtr())) {
if (parm_type->getDecl()->getName() == kVisitorDispatcherName) {
// Unresolved, but its parameter name is VisitorDispatcher.
return false;
}
}
return IsVisitorPtrType(formal_type);
}
static bool IsTraceMethod(clang::FunctionDecl* method,
bool* isTraceAfterDispatch = 0) {
if (method->getNumParams() != 1)
return false;
const std::string& name = method->getNameAsString();
if (name != kTraceName && name != kTraceAfterDispatchName &&
name != kTraceImplName)
return false;
const clang::QualType& formal_type = method->getParamDecl(0)->getType();
if (name == kTraceImplName) {
if (!IsVisitorDispatcherType(formal_type))
return false;
} else if (!IsVisitorPtrType(formal_type)) {
return false;
}
if (isTraceAfterDispatch)
*isTraceAfterDispatch = (name == kTraceAfterDispatchName);
return true;
}
......
// 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.
#include "traceimpl.h"
namespace blink {
void TraceImplExtern::trace(Visitor* visitor) {
traceImpl(visitor);
}
template <typename VisitorDispatcher>
inline void TraceImplExtern::traceImpl(VisitorDispatcher visitor) {
visitor->trace(m_x);
}
}
// 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.
#ifndef TRACEIMPL_H_
#define TRACEIMPL_H_
#include "heap/stubs.h"
namespace blink {
class X : public GarbageCollected<X> {
public:
virtual void trace(Visitor*) {}
};
class TraceImplInlined : public GarbageCollected<TraceImplInlined> {
public:
void trace(Visitor* visitor) { traceImpl(visitor); }
template <typename VisitorDispatcher>
void traceImpl(VisitorDispatcher visitor) {
visitor->trace(m_x);
}
private:
Member<X> m_x;
};
class TraceImplExtern : public GarbageCollected<TraceImplExtern> {
public:
void trace(Visitor* visitor);
template <typename VisitorDispatcher>
inline void traceImpl(VisitorDispatcher);
private:
Member<X> m_x;
};
}
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment