1f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// found in the LICENSE file.
4f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// This file provides a wrapper for CXXRecordDecl that accumulates GC related
6f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// information about a class. Accumulated information is memoized and the info
7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// objects are stored in a RecordCache.
8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
9f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#ifndef TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_
10f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_
11f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
12f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include <map>
13f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include <vector>
14f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
15f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "Edge.h"
16f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
17f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "clang/AST/AST.h"
18f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "clang/AST/CXXInheritance.h"
19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "clang/Frontend/CompilerInstance.h"
20f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
21f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochclass RecordCache;
22f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
23f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// A potentially tracable and/or lifetime affecting point in the object graph.
24f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochclass GraphPoint {
25f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch public:
26f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  GraphPoint() : traced_(false) {}
27f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  virtual ~GraphPoint() {}
28f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void MarkTraced() { traced_ = true; }
29f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool IsProperlyTraced() { return traced_ || !NeedsTracing().IsNeeded(); }
30f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool IsInproperlyTraced() { return traced_ && NeedsTracing().IsIllegal(); }
31f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  virtual const TracingStatus NeedsTracing() = 0;
32f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
33f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch private:
34f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool traced_;
35f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch};
36f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
37f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochclass BasePoint : public GraphPoint {
38f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch public:
39f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  BasePoint(const clang::CXXBaseSpecifier& spec,
40f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            RecordInfo* info,
41f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            const TracingStatus& status)
42f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      : spec_(spec), info_(info), status_(status) {}
43f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const TracingStatus NeedsTracing() { return status_; }
44f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const clang::CXXBaseSpecifier& spec() { return spec_; }
45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RecordInfo* info() { return info_; }
46f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
47f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch private:
48f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const clang::CXXBaseSpecifier& spec_;
49f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RecordInfo* info_;
50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  TracingStatus status_;
51f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch};
52f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochclass FieldPoint : public GraphPoint {
54f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch public:
55f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  FieldPoint(clang::FieldDecl* field, Edge* edge)
56f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      : field_(field), edge_(edge) {}
57f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const TracingStatus NeedsTracing() {
58f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return edge_->NeedsTracing(Edge::kRecursive);
59f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
60f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::FieldDecl* field() { return field_; }
61f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Edge* edge() { return edge_; }
62f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
63f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch private:
64f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::FieldDecl* field_;
65f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Edge* edge_;
66f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
67f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  friend class RecordCache;
68f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void deleteEdge() { delete edge_; }
69f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch};
70f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
71f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Wrapper class to lazily collect information about a C++ record.
72f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochclass RecordInfo {
73f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch public:
74f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  typedef std::vector<std::pair<clang::CXXRecordDecl*, BasePoint>> Bases;
75f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
76f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  struct FieldDeclCmp {
77f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    bool operator()(clang::FieldDecl* a, clang::FieldDecl *b) const {
78f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return a->getLocStart() < b->getLocStart();
79f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
80f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  };
81f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  typedef std::map<clang::FieldDecl*, FieldPoint, FieldDeclCmp> Fields;
82f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
83f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  typedef std::vector<const clang::Type*> TemplateArgs;
84f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
85f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ~RecordInfo();
86f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
87f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::CXXRecordDecl* record() const { return record_; }
88f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const std::string& name() const { return name_; }
89f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Fields& GetFields();
90f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Bases& GetBases();
91f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::CXXMethodDecl* GetTraceMethod();
92f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::CXXMethodDecl* GetTraceDispatchMethod();
93f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::CXXMethodDecl* GetFinalizeDispatchMethod();
94f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
95f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool GetTemplateArgs(size_t count, TemplateArgs* output_args);
96f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
97f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool IsHeapAllocatedCollection();
98f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool IsGCDerived();
99f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool IsGCAllocated();
100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool IsGCFinalized();
101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool IsGCMixin();
102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool IsStackAllocated();
103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool IsNonNewable();
104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool IsOnlyPlacementNewable();
105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool IsEagerlyFinalized();
106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool HasDefinition();
108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::CXXMethodDecl* DeclaresNewOperator();
110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool RequiresTraceMethod();
112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool NeedsFinalization();
113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool DeclaresGCMixinMethods();
114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool DeclaresLocalTraceMethod();
115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  TracingStatus NeedsTracing(Edge::NeedsTracingOption);
116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::CXXMethodDecl* InheritsNonVirtualTrace();
117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool IsConsideredAbstract();
118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static clang::CXXRecordDecl* GetDependentTemplatedDecl(const clang::Type&);
120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch private:
122f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RecordInfo(clang::CXXRecordDecl* record, RecordCache* cache);
123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void walkBases();
125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Fields* CollectFields();
127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Bases* CollectBases();
128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void DetermineTracingMethods();
129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool InheritsTrace();
130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Edge* CreateEdge(const clang::Type* type);
132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RecordCache* cache_;
134f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::CXXRecordDecl* record_;
135f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const std::string name_;
136f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  TracingStatus fields_need_tracing_;
137f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Bases* bases_;
138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Fields* fields_;
139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
140f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  enum CachedBool { kFalse = 0, kTrue = 1, kNotComputed = 2 };
141f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CachedBool is_stack_allocated_;
142f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CachedBool is_non_newable_;
143f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CachedBool is_only_placement_newable_;
144f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CachedBool does_need_finalization_;
145f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CachedBool has_gc_mixin_methods_;
146f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CachedBool is_declaring_local_trace_;
147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CachedBool is_eagerly_finalized_;
148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
149f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool determined_trace_methods_;
150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::CXXMethodDecl* trace_method_;
151f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::CXXMethodDecl* trace_dispatch_method_;
152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::CXXMethodDecl* finalize_dispatch_method_;
153f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
154f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool is_gc_derived_;
155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
156f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  std::vector<std::string> gc_base_names_;
157f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  friend class RecordCache;
159f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch};
160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochclass RecordCache {
162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch public:
163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RecordCache(clang::CompilerInstance& instance)
164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    : instance_(instance)
165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RecordInfo* Lookup(clang::CXXRecordDecl* record);
169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RecordInfo* Lookup(const clang::CXXRecordDecl* record) {
171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return Lookup(const_cast<clang::CXXRecordDecl*>(record));
172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RecordInfo* Lookup(clang::DeclContext* decl) {
175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return Lookup(clang::dyn_cast<clang::CXXRecordDecl>(decl));
176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RecordInfo* Lookup(const clang::Type* type) {
179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return Lookup(type->getAsCXXRecordDecl());
180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RecordInfo* Lookup(const clang::QualType& type) {
183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return Lookup(type.getTypePtr());
184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
186f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ~RecordCache() {
187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    for (Cache::iterator it = cache_.begin(); it != cache_.end(); ++it) {
188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (!it->second.fields_)
189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        continue;
190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      for (RecordInfo::Fields::iterator fit = it->second.fields_->begin();
191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        fit != it->second.fields_->end();
192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        ++fit) {
193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        fit->second.deleteEdge();
194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::CompilerInstance& instance() const { return instance_; }
199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch private:
201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  clang::CompilerInstance& instance_;
202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  typedef std::map<clang::CXXRecordDecl*, RecordInfo> Cache;
204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Cache cache_;
205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch};
206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
207f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#endif  // TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_
208