Skip to content

Commit

Permalink
Reland "heap: Fix clang plugin handling of cppgc library types"
Browse files Browse the repository at this point in the history
This is a reland of 3d3cb2f

Original change's description:
> heap: Fix clang plugin handling of cppgc library types
>
> Bug: 1056170
> Change-Id: I8a056a9a44e6b482e6d96df8c486b6d134fed46e
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2976400
> Commit-Queue: Omer Katz <omerkatz@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#894876}

Bug: 1056170
Change-Id: Ibcfe9064edaa739badebffc3701b863f5cc359d2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2982560
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#896116}
  • Loading branch information
omerktz authored and Chromium LUCI CQ committed Jun 25, 2021
1 parent 193ef7d commit 91fb9e9
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 70 deletions.
87 changes: 71 additions & 16 deletions tools/clang/blink_gc_plugin/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include <cassert>

#include "RecordInfo.h"
#include "clang/AST/AST.h"
#include "clang/AST/Attr.h"

Expand All @@ -35,28 +36,78 @@ extern const char kConstReverseIteratorName[];
extern const char kReverseIteratorName[];

class Config {
public:
static bool IsMember(llvm::StringRef name) {
return name == "Member";
private:
// Checks that the namespace matches the expected namespace and that the type
// takes at least |expected_minimum_arg_count| template arguments. If both
// requirements are fulfilled, populates |args| with the first
// |expected_minimum_arg_count| template arguments. Verifying only the minimum
// expected argument keeps the plugin resistant to changes in the type
// definitions (to some extent)
static bool VerifyNamespaceAndArgCount(std::string expected_ns_name,
int expected_minimum_arg_count,
llvm::StringRef ns_name,
RecordInfo* info,
RecordInfo::TemplateArgs* args) {
return (ns_name == expected_ns_name) &&
info->GetTemplateArgs(expected_minimum_arg_count, args);
}

static bool IsWeakMember(llvm::StringRef name) {
return name == "WeakMember";
public:
static bool IsMember(llvm::StringRef name,
llvm::StringRef ns_name,
RecordInfo* info,
RecordInfo::TemplateArgs* args) {
if (name == "Member") {
return VerifyNamespaceAndArgCount("blink", 1, ns_name, info, args);
}
if (name == "BasicMember") {
if (!VerifyNamespaceAndArgCount("cppgc", 2, ns_name, info, args))
return false;
return (*args)[1]->getAsRecordDecl()->getName() == "StrongMemberTag";
}
return false;
}

static bool IsMemberHandle(llvm::StringRef name) {
return IsMember(name) ||
IsWeakMember(name);
static bool IsWeakMember(llvm::StringRef name,
llvm::StringRef ns_name,
RecordInfo* info,
RecordInfo::TemplateArgs* args) {
if (name == "WeakMember") {
return VerifyNamespaceAndArgCount("blink", 1, ns_name, info, args);
}
if (name == "BasicMember") {
if (!VerifyNamespaceAndArgCount("cppgc", 2, ns_name, info, args))
return false;
return (*args)[1]->getAsRecordDecl()->getName() == "WeakMemberTag";
}
return false;
}

static bool IsPersistent(llvm::StringRef name) {
return name == "Persistent" ||
name == "WeakPersistent" ;
static bool IsPersistent(llvm::StringRef name,
llvm::StringRef ns_name,
RecordInfo* info,
RecordInfo::TemplateArgs* args) {
if ((name == "Persistent") || (name == "WeakPersistent")) {
return VerifyNamespaceAndArgCount("blink", 1, ns_name, info, args);
}
if (name == "BasicPersistent") {
return VerifyNamespaceAndArgCount("cppgc", 1, ns_name, info, args);
}
return false;
}

static bool IsCrossThreadPersistent(llvm::StringRef name) {
return name == "CrossThreadPersistent" ||
name == "CrossThreadWeakPersistent" ;
static bool IsCrossThreadPersistent(llvm::StringRef name,
llvm::StringRef ns_name,
RecordInfo* info,
RecordInfo::TemplateArgs* args) {
if ((name == "CrossThreadPersistent") ||
(name == "CrossThreadWeakPersistent")) {
return VerifyNamespaceAndArgCount("blink", 1, ns_name, info, args);
}
if (name == "BasicCrossThreadPersistent") {
return VerifyNamespaceAndArgCount("cppgc", 1, ns_name, info, args);
}
return false;
}

static bool IsRefPtr(llvm::StringRef name) { return name == "scoped_refptr"; }
Expand All @@ -71,8 +122,12 @@ class Config {
return name == "unique_ptr";
}

static bool IsTraceWrapperV8Reference(llvm::StringRef name) {
return name == "TraceWrapperV8Reference";
static bool IsTraceWrapperV8Reference(llvm::StringRef name,
llvm::StringRef ns_name,
RecordInfo* info,
RecordInfo::TemplateArgs* args) {
return name == "TraceWrapperV8Reference" &&
VerifyNamespaceAndArgCount("blink", 1, ns_name, info, args);
}

static bool IsWTFCollection(llvm::StringRef name) {
Expand Down
38 changes: 18 additions & 20 deletions tools/clang/blink_gc_plugin/RecordInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,33 +686,32 @@ Edge* RecordInfo::CreateEdge(const Type* type) {
return 0;
}

if (Config::IsMember(info->name()) && info->GetTemplateArgs(1, &args)) {
if (Edge* ptr = CreateEdge(args[0]))
// Find top-level namespace.
NamespaceDecl* ns = dyn_cast<NamespaceDecl>(info->record()->getDeclContext());
if (ns) {
while (NamespaceDecl* outer_ns =
dyn_cast<NamespaceDecl>(ns->getDeclContext())) {
ns = outer_ns;
}
}
auto ns_name = ns ? ns->getName() : "";

if (Config::IsMember(info->name(), ns_name, info, &args)) {
if (Edge* ptr = CreateEdge(args[0])) {
return new Member(ptr);
}
return 0;
}

if (Config::IsWeakMember(info->name()) && info->GetTemplateArgs(1, &args)) {
if (Config::IsWeakMember(info->name(), ns_name, info, &args)) {
if (Edge* ptr = CreateEdge(args[0]))
return new WeakMember(ptr);
return 0;
}

bool is_persistent = Config::IsPersistent(info->name());
if (is_persistent || Config::IsCrossThreadPersistent(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());
// Find outer-most namespace.
while (NamespaceDecl* outer_ns =
dyn_cast<NamespaceDecl>(ns->getDeclContext())) {
ns = outer_ns;
}
if (!ns || (ns->getName() != "blink") && (ns->getName() != "cppgc"))
return 0;
if (!info->GetTemplateArgs(1, &args))
return 0;
bool is_persistent = Config::IsPersistent(info->name(), ns_name, info, &args);
if (is_persistent ||
Config::IsCrossThreadPersistent(info->name(), ns_name, info, &args)) {
if (Edge* ptr = CreateEdge(args[0])) {
if (is_persistent)
return new Persistent(ptr);
Expand All @@ -739,8 +738,7 @@ Edge* RecordInfo::CreateEdge(const Type* type) {
return edge;
}

if (Config::IsTraceWrapperV8Reference(info->name()) &&
info->GetTemplateArgs(1, &args)) {
if (Config::IsTraceWrapperV8Reference(info->name(), ns_name, info, &args)) {
if (Edge* ptr = CreateEdge(args[0]))
return new TraceWrapperV8Reference(ptr);
return 0;
Expand Down
73 changes: 41 additions & 32 deletions tools/clang/blink_gc_plugin/tests/heap/stubs.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,67 +196,76 @@ class Visitor {

namespace internal {
class GarbageCollectedBase {};
} // namespace internal

template <typename T>
class GarbageCollected : public internal::GarbageCollectedBase {};
class StrongMemberTag;
class WeakMemberTag;

class GarbageCollectedMixin : public internal::GarbageCollectedBase {
public:
virtual void AdjustAndMark(Visitor*) const = 0;
virtual bool IsHeapObjectAlive(Visitor*) const = 0;
virtual void Trace(Visitor*) const {}
};
class MemberBase {};

template <typename T>
class Member {
template <typename T, typename Tag>
class BasicMember : public MemberBase {
public:
operator T*() const { return 0; }
T* operator->() const { return 0; }
bool operator!() const { return false; }
};

template <typename T>
class WeakMember {
class StrongPersistentPolicy;
class WeakPersistentPolicy;

class PersistentBase {};

template <typename T, typename Tag>
class BasicPersistent : public PersistentBase {
public:
operator T*() const { return 0; }
T* operator->() const { return 0; }
bool operator!() const { return false; }
};

template <typename T>
class Persistent {
class StrongCrossThreadPersistentPolicy;
class WeakCrossThreadPersistentPolicy;

template <typename T, typename Tag>
class BasicCrossThreadPersistent : public PersistentBase {
public:
operator T*() const { return 0; }
T* operator->() const { return 0; }
bool operator!() const { return false; }
};

} // namespace internal

template <typename T>
class WeakPersistent {
class GarbageCollected : public internal::GarbageCollectedBase {};

class GarbageCollectedMixin : public internal::GarbageCollectedBase {
public:
operator T*() const { return 0; }
T* operator->() const { return 0; }
bool operator!() const { return false; }
virtual void AdjustAndMark(Visitor*) const = 0;
virtual bool IsHeapObjectAlive(Visitor*) const = 0;
virtual void Trace(Visitor*) const {}
};

namespace subtle {
template <typename T>
using Member = internal::BasicMember<T, internal::StrongMemberTag>;
template <typename T>
using WeakMember = internal::BasicMember<T, internal::WeakMemberTag>;

template <typename T>
class CrossThreadPersistent {
public:
operator T*() const { return 0; }
T* operator->() const { return 0; }
bool operator!() const { return false; }
};
using Persistent =
internal::BasicPersistent<T, internal::StrongPersistentPolicy>;
template <typename T>
using WeakPersistent =
internal::BasicPersistent<T, internal::WeakPersistentPolicy>;

namespace subtle {

template <typename T>
class CrossThreadWeakPersistent {
public:
operator T*() const { return 0; }
T* operator->() const { return 0; }
bool operator!() const { return false; }
};
using CrossThreadPersistent = internal::
BasicCrossThreadPersistent<T, internal::StrongCrossThreadPersistentPolicy>;
template <typename T>
using CrossThreadWeakPersistent = internal::
BasicCrossThreadPersistent<T, internal::WeakCrossThreadPersistentPolicy>;

} // namespace subtle

Expand Down
2 changes: 1 addition & 1 deletion tools/clang/blink_gc_plugin/tests/stack_allocated.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class DerivedHeapObject2 : public HeapObject {
./stack_allocated.h:44:3: warning: [blink-gc] Garbage collected class 'DerivedHeapObject2' is not permitted to override its new operator.
STACK_ALLOCATED();
^
./heap/stubs.h:362:3: note: expanded from macro 'STACK_ALLOCATED'
./heap/stubs.h:371:3: note: expanded from macro 'STACK_ALLOCATED'
__attribute__((annotate("blink_stack_allocated"))) \
^
In file included from stack_allocated.cpp:5:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
trace_if_needed.cpp:9:1: warning: [blink-gc] Class 'TemplatedObject<cppgc::Member<blink::HeapObject>>' has untraced fields that require tracing.
trace_if_needed.cpp:9:1: warning: [blink-gc] Class 'TemplatedObject<cppgc::internal::BasicMember<blink::HeapObject, cppgc::internal::StrongMemberTag>>' has untraced fields that require tracing.
template <typename T>
^
./trace_if_needed.h:21:5: note: [blink-gc] Untraced field 'm_two' declared here:
Expand Down

0 comments on commit 91fb9e9

Please sign in to comment.