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