Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / tools / clang / blink_gc_plugin / Edge.h
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef TOOLS_BLINK_GC_PLUGIN_EDGE_H_
6 #define TOOLS_BLINK_GC_PLUGIN_EDGE_H_
7
8 #include <deque>
9
10 #include "TracingStatus.h"
11
12 class RecordInfo;
13
14 class Edge;
15 class Value;
16 class RawPtr;
17 class RefPtr;
18 class OwnPtr;
19 class Member;
20 class WeakMember;
21 class Persistent;
22 class Collection;
23
24 // Bare-bones visitor.
25 class EdgeVisitor {
26  public:
27   virtual void VisitValue(Value*) {}
28   virtual void VisitRawPtr(RawPtr*) {}
29   virtual void VisitRefPtr(RefPtr*) {}
30   virtual void VisitOwnPtr(OwnPtr*) {}
31   virtual void VisitMember(Member*) {}
32   virtual void VisitWeakMember(WeakMember*) {}
33   virtual void VisitPersistent(Persistent*) {}
34   virtual void VisitCollection(Collection*) {}
35 };
36
37 // Recursive edge visitor. The traversed path is accessible in context.
38 class RecursiveEdgeVisitor : public EdgeVisitor {
39  public:
40   // Overrides that recursively walk the edges and record the path.
41   virtual void VisitValue(Value*) override;
42   virtual void VisitRawPtr(RawPtr*) override;
43   virtual void VisitRefPtr(RefPtr*) override;
44   virtual void VisitOwnPtr(OwnPtr*) override;
45   virtual void VisitMember(Member*) override;
46   virtual void VisitWeakMember(WeakMember*) override;
47   virtual void VisitPersistent(Persistent*) override;
48   virtual void VisitCollection(Collection*) override;
49
50  protected:
51   typedef std::deque<Edge*> Context;
52   Context& context() { return context_; }
53   Edge* Parent() { return context_.empty() ? 0 : context_.front(); }
54   void Enter(Edge* e) { return context_.push_front(e); }
55   void Leave() { context_.pop_front(); }
56
57   // Default callback to overwrite in visitor subclass.
58   virtual void AtValue(Value*);
59   virtual void AtRawPtr(RawPtr*);
60   virtual void AtRefPtr(RefPtr*);
61   virtual void AtOwnPtr(OwnPtr*);
62   virtual void AtMember(Member*);
63   virtual void AtWeakMember(WeakMember*);
64   virtual void AtPersistent(Persistent*);
65   virtual void AtCollection(Collection*);
66
67  private:
68   Context context_;
69 };
70
71 // Base class for all edges.
72 class Edge {
73  public:
74   enum NeedsTracingOption { kRecursive, kNonRecursive };
75   enum LivenessKind { kWeak, kStrong, kRoot };
76
77   virtual ~Edge() {}
78   virtual LivenessKind Kind() = 0;
79   virtual void Accept(EdgeVisitor*) = 0;
80   virtual bool NeedsFinalization() = 0;
81   virtual TracingStatus NeedsTracing(NeedsTracingOption) {
82     return TracingStatus::Unknown();
83   }
84
85   virtual bool IsValue() { return false; }
86   virtual bool IsRawPtr() { return false; }
87   virtual bool IsRawPtrClass() { return false; }
88   virtual bool IsRefPtr() { return false; }
89   virtual bool IsOwnPtr() { return false; }
90   virtual bool IsMember() { return false; }
91   virtual bool IsWeakMember() { return false; }
92   virtual bool IsPersistent() { return false; }
93   virtual bool IsCollection() { return false; }
94 };
95
96 // A value edge is a direct edge to some type, eg, part-object edges.
97 class Value : public Edge {
98  public:
99   explicit Value(RecordInfo* value) : value_(value) {};
100   bool IsValue() override { return true; }
101   LivenessKind Kind() override { return kStrong; }
102   bool NeedsFinalization() override;
103   TracingStatus NeedsTracing(NeedsTracingOption) override;
104   void Accept(EdgeVisitor* visitor) override { visitor->VisitValue(this); }
105   RecordInfo* value() { return value_; }
106
107  private:
108   RecordInfo* value_;
109 };
110
111 // Shared base for smart-pointer edges.
112 class PtrEdge : public Edge {
113  public:
114   ~PtrEdge() { delete ptr_; }
115   Edge* ptr() { return ptr_; }
116  protected:
117   PtrEdge(Edge* ptr) : ptr_(ptr) {
118     assert(ptr && "EdgePtr pointer must be non-null");
119   }
120  private:
121   Edge* ptr_;
122 };
123
124 class RawPtr : public PtrEdge {
125  public:
126   explicit RawPtr(Edge* ptr, bool is_ptr_class)
127       : PtrEdge(ptr), is_ptr_class_(is_ptr_class) { }
128   bool IsRawPtr() { return true; }
129   bool IsRawPtrClass() { return is_ptr_class_; }
130   LivenessKind Kind() { return kWeak; }
131   bool NeedsFinalization() { return false; }
132   TracingStatus NeedsTracing(NeedsTracingOption) {
133     return TracingStatus::Unneeded();
134   }
135   void Accept(EdgeVisitor* visitor) { visitor->VisitRawPtr(this); }
136  private:
137   bool is_ptr_class_;
138 };
139
140 class RefPtr : public PtrEdge {
141  public:
142   explicit RefPtr(Edge* ptr) : PtrEdge(ptr) { }
143   bool IsRefPtr() { return true; }
144   LivenessKind Kind() { return kStrong; }
145   bool NeedsFinalization() { return true; }
146   TracingStatus NeedsTracing(NeedsTracingOption) {
147     return TracingStatus::Unneeded();
148   }
149   void Accept(EdgeVisitor* visitor) { visitor->VisitRefPtr(this); }
150 };
151
152 class OwnPtr : public PtrEdge {
153  public:
154   explicit OwnPtr(Edge* ptr) : PtrEdge(ptr) { }
155   bool IsOwnPtr() { return true; }
156   LivenessKind Kind() { return kStrong; }
157   bool NeedsFinalization() { return true; }
158   TracingStatus NeedsTracing(NeedsTracingOption) {
159     return TracingStatus::Unneeded();
160   }
161   void Accept(EdgeVisitor* visitor) { visitor->VisitOwnPtr(this); }
162 };
163
164 class Member : public PtrEdge {
165  public:
166   explicit Member(Edge* ptr) : PtrEdge(ptr) { }
167   bool IsMember() { return true; }
168   LivenessKind Kind() { return kStrong; }
169   bool NeedsFinalization() { return false; }
170   TracingStatus NeedsTracing(NeedsTracingOption) {
171     return TracingStatus::Needed();
172   }
173   void Accept(EdgeVisitor* visitor) { visitor->VisitMember(this); }
174 };
175
176 class WeakMember : public PtrEdge {
177  public:
178   explicit WeakMember(Edge* ptr) : PtrEdge(ptr) { }
179   bool IsWeakMember() { return true; }
180   LivenessKind Kind() { return kWeak; }
181   bool NeedsFinalization() { return false; }
182   TracingStatus NeedsTracing(NeedsTracingOption) {
183     return TracingStatus::Needed();
184   }
185   void Accept(EdgeVisitor* visitor) { visitor->VisitWeakMember(this); }
186 };
187
188 class Persistent : public PtrEdge {
189  public:
190   explicit Persistent(Edge* ptr) : PtrEdge(ptr) { }
191   bool IsPersistent() { return true; }
192   LivenessKind Kind() { return kRoot; }
193   bool NeedsFinalization() { return true; }
194   TracingStatus NeedsTracing(NeedsTracingOption) {
195     return TracingStatus::Unneeded();
196   }
197   void Accept(EdgeVisitor* visitor) { visitor->VisitPersistent(this); }
198 };
199
200 class Collection : public Edge {
201  public:
202   typedef std::vector<Edge*> Members;
203   Collection(RecordInfo* info, bool on_heap, bool is_root)
204       : info_(info),
205         on_heap_(on_heap),
206         is_root_(is_root) {}
207   ~Collection() {
208     for (Members::iterator it = members_.begin(); it != members_.end(); ++it) {
209       assert(*it && "Collection-edge members must be non-null");
210       delete *it;
211     }
212   }
213   bool IsCollection() { return true; }
214   LivenessKind Kind() { return is_root_ ? kRoot : kStrong; }
215   bool on_heap() { return on_heap_; }
216   bool is_root() { return is_root_; }
217   Members& members() { return members_; }
218   void Accept(EdgeVisitor* visitor) { visitor->VisitCollection(this); }
219   void AcceptMembers(EdgeVisitor* visitor) {
220     for (Members::iterator it = members_.begin(); it != members_.end(); ++it)
221       (*it)->Accept(visitor);
222   }
223   bool NeedsFinalization();
224   TracingStatus NeedsTracing(NeedsTracingOption) {
225     if (is_root_)
226       return TracingStatus::Unneeded();
227     if (on_heap_)
228       return TracingStatus::Needed();
229     // For off-heap collections, determine tracing status of members.
230     TracingStatus status = TracingStatus::Unneeded();
231     for (Members::iterator it = members_.begin(); it != members_.end(); ++it) {
232       // Do a non-recursive test here since members could equal the holder.
233       status = status.LUB((*it)->NeedsTracing(kNonRecursive));
234     }
235     return status;
236   }
237
238  private:
239   RecordInfo* info_;
240   Members members_;
241   bool on_heap_;
242   bool is_root_;
243 };
244
245 #endif  // TOOLS_BLINK_GC_PLUGIN_EDGE_H_