15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "Config.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "RecordInfo.h" 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using namespace clang; 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using std::string; 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RecordInfo::RecordInfo(CXXRecordDecl* record, RecordCache* cache) 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : cache_(cache), 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) record_(record), 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) name_(record->getName()), 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) fields_need_tracing_(TracingStatus::Unknown()), 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bases_(0), 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) fields_(0), 1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) is_stack_allocated_(kNotComputed), 19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch is_non_newable_(kNotComputed), 20effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch is_only_placement_newable_(kNotComputed), 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch does_need_finalization_(kNotComputed), 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) determined_trace_methods_(false), 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) trace_method_(0), 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) trace_dispatch_method_(0), 2523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) finalize_dispatch_method_(0), 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) is_gc_derived_(false), 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base_paths_(0) {} 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RecordInfo::~RecordInfo() { 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete fields_; 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete bases_; 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delete base_paths_; 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Get |count| number of template arguments. Returns false if there 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// are fewer than |count| arguments or any of the arguments are not 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// of a valid Type structure. If |count| is non-positive, all 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// arguments are collected. 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool RecordInfo::GetTemplateArgs(size_t count, TemplateArgs* output_args) { 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ClassTemplateSpecializationDecl* tmpl = 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dyn_cast<ClassTemplateSpecializationDecl>(record_); 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!tmpl) 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const TemplateArgumentList& args = tmpl->getTemplateArgs(); 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (args.size() < count) 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (count <= 0) 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) count = args.size(); 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (unsigned i = 0; i < count; ++i) { 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TemplateArgument arg = args[i]; 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (arg.getKind() == TemplateArgument::Type && !arg.getAsType().isNull()) { 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) output_args->push_back(arg.getAsType().getTypePtr()); 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Test if a record is a HeapAllocated collection. 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool RecordInfo::IsHeapAllocatedCollection() { 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!Config::IsGCCollection(name_) && !Config::IsWTFCollection(name_)) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TemplateArgs args; 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (GetTemplateArgs(0, &args)) { 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (TemplateArgs::iterator it = args.begin(); it != args.end(); ++it) { 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (CXXRecordDecl* decl = (*it)->getAsCXXRecordDecl()) 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (decl->getName() == kHeapAllocatorName) 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return Config::IsGCCollection(name_); 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static bool IsGCBaseCallback(const CXXBaseSpecifier* specifier, 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CXXBasePath& path, 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void* data) { 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (CXXRecordDecl* record = specifier->getType()->getAsCXXRecordDecl()) 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return Config::IsGCBase(record->getName()); 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Test if a record is derived from a garbage collected base. 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool RecordInfo::IsGCDerived() { 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If already computed, return the known result. 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (base_paths_) 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return is_gc_derived_; 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base_paths_ = new CXXBasePaths(true, true, false); 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!record_->hasDefinition()) 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The base classes are not themselves considered garbage collected objects. 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (Config::IsGCBase(name_)) 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Walk the inheritance tree to find GC base classes. 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) is_gc_derived_ = record_->lookupInBases(IsGCBaseCallback, 0, *base_paths_); 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return is_gc_derived_; 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool RecordInfo::IsGCFinalized() { 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!IsGCDerived()) 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (CXXBasePaths::paths_iterator it = base_paths_->begin(); 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) it != base_paths_->end(); 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ++it) { 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const CXXBasePathElement& elem = (*it)[it->size() - 1]; 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl(); 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Config::IsGCFinalizedBase(base->getName())) 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// A GC mixin is a class that inherits from a GC mixin base and has 1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// not yet been "mixed in" with another GC base class. 12123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool RecordInfo::IsGCMixin() { 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!IsGCDerived() || base_paths_->begin() == base_paths_->end()) 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (CXXBasePaths::paths_iterator it = base_paths_->begin(); 1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu it != base_paths_->end(); 1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ++it) { 1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Get the last element of the path. 1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const CXXBasePathElement& elem = (*it)[it->size() - 1]; 1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl(); 1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // If it is not a mixin base we are done. 1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!Config::IsGCMixinBase(base->getName())) 1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return false; 1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // This is a mixin if all GC bases are mixins. 1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return true; 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Test if a record is allocated on the managed heap. 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool RecordInfo::IsGCAllocated() { 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return IsGCDerived() || IsHeapAllocatedCollection(); 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)RecordInfo* RecordCache::Lookup(CXXRecordDecl* record) { 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Ignore classes annotated with the GC_PLUGIN_IGNORE macro. 145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!record || Config::IsIgnoreAnnotated(record)) 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Cache::iterator it = cache_.find(record); 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (it != cache_.end()) 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return &it->second; 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return &cache_.insert(std::make_pair(record, RecordInfo(record, this))) 151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch .first->second; 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool RecordInfo::IsStackAllocated() { 15523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (is_stack_allocated_ == kNotComputed) { 15623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) is_stack_allocated_ = kFalse; 15723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) for (Bases::iterator it = GetBases().begin(); 15823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) it != GetBases().end(); 15923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ++it) { 16023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (it->second.info()->IsStackAllocated()) { 16123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) is_stack_allocated_ = kTrue; 162effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return is_stack_allocated_; 163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 165effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (CXXRecordDecl::method_iterator it = record_->method_begin(); 166effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it != record_->method_end(); 167effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++it) { 168effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (it->getNameAsString() == kNewOperatorName && 169effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it->isDeleted() && 170effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Config::IsStackAnnotated(*it)) { 171effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch is_stack_allocated_ = kTrue; 172effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return is_stack_allocated_; 17323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 17423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 175effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return is_stack_allocated_; 177effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 178effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool RecordInfo::IsNonNewable() { 180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (is_non_newable_ == kNotComputed) { 181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bool deleted = false; 182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bool all_deleted = true; 18323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) for (CXXRecordDecl::method_iterator it = record_->method_begin(); 18423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) it != record_->method_end(); 18523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ++it) { 18623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (it->getNameAsString() == kNewOperatorName) { 187effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch deleted = it->isDeleted(); 188effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch all_deleted = all_deleted && deleted; 189effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 190effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 191effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch is_non_newable_ = (deleted && all_deleted) ? kTrue : kFalse; 192effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 193effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return is_non_newable_; 194effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 195effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool RecordInfo::IsOnlyPlacementNewable() { 197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (is_only_placement_newable_ == kNotComputed) { 198effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bool placement = false; 199effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bool new_deleted = false; 200effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (CXXRecordDecl::method_iterator it = record_->method_begin(); 201effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it != record_->method_end(); 202effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++it) { 203effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (it->getNameAsString() == kNewOperatorName) { 204effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (it->getNumParams() == 1) { 205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch new_deleted = it->isDeleted(); 206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else if (it->getNumParams() == 2) { 207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch placement = !it->isDeleted(); 20823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 20923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 21023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch is_only_placement_newable_ = (placement && new_deleted) ? kTrue : kFalse; 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return is_only_placement_newable_; 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 216010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)CXXMethodDecl* RecordInfo::DeclaresNewOperator() { 217010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (CXXRecordDecl::method_iterator it = record_->method_begin(); 218010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) it != record_->method_end(); 219010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ++it) { 220010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (it->getNameAsString() == kNewOperatorName && it->getNumParams() == 1) 221010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return *it; 222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 223010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return 0; 224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// An object requires a tracing method if it has any fields that need tracing 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// or if it inherits from multiple bases that need tracing. 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool RecordInfo::RequiresTraceMethod() { 22923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (IsStackAllocated()) 23023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return false; 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unsigned bases_with_trace = 0; 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) { 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (it->second.NeedsTracing().IsNeeded()) 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ++bases_with_trace; 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (bases_with_trace > 1) 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetFields(); 239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return fields_need_tracing_.IsNeeded(); 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Get the actual tracing method (ie, can be traceAfterDispatch if there is a 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// dispatch method). 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CXXMethodDecl* RecordInfo::GetTraceMethod() { 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DetermineTracingMethods(); 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return trace_method_; 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Get the static trace dispatch method. 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CXXMethodDecl* RecordInfo::GetTraceDispatchMethod() { 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DetermineTracingMethods(); 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return trace_dispatch_method_; 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 25523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)CXXMethodDecl* RecordInfo::GetFinalizeDispatchMethod() { 25623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DetermineTracingMethods(); 25723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return finalize_dispatch_method_; 25823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 25923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RecordInfo::Bases& RecordInfo::GetBases() { 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!bases_) 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bases_ = CollectBases(); 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return *bases_; 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool RecordInfo::InheritsTrace() { 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (GetTraceMethod()) 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) { 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (it->second.info()->InheritsTrace()) 271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 27623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)CXXMethodDecl* RecordInfo::InheritsNonVirtualTrace() { 27723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (CXXMethodDecl* trace = GetTraceMethod()) 27823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return trace->isVirtual() ? 0 : trace; 27923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) { 28023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (CXXMethodDecl* trace = it->second.info()->InheritsNonVirtualTrace()) 28123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return trace; 28223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 28323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return 0; 28423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 28523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 28623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// A (non-virtual) class is considered abstract in Blink if it has 28723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// no public constructors and no create methods. 28823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool RecordInfo::IsConsideredAbstract() { 28923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) for (CXXRecordDecl::ctor_iterator it = record_->ctor_begin(); 29023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) it != record_->ctor_end(); 29123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ++it) { 29223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!it->isCopyOrMoveConstructor() && it->getAccess() == AS_public) 29323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return false; 29423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 29523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) for (CXXRecordDecl::method_iterator it = record_->method_begin(); 29623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) it != record_->method_end(); 29723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ++it) { 29823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (it->getNameAsString() == kCreateName) 29923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return false; 30023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 30123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return true; 30223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 30323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RecordInfo::Bases* RecordInfo::CollectBases() { 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Compute the collection locally to avoid inconsistent states. 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Bases* bases = new Bases; 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!record_->hasDefinition()) 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return bases; 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (CXXRecordDecl::base_class_iterator it = record_->bases_begin(); 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != record_->bases_end(); 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const CXXBaseSpecifier& spec = *it; 313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RecordInfo* info = cache_->Lookup(spec.getType()); 314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!info) 315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) continue; 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CXXRecordDecl* base = info->record(); 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TracingStatus status = info->InheritsTrace() 318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ? TracingStatus::Needed() 319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : TracingStatus::Unneeded(); 320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bases->insert(std::make_pair(base, BasePoint(spec, info, status))); 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return bases; 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RecordInfo::Fields& RecordInfo::GetFields() { 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!fields_) 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) fields_ = CollectFields(); 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return *fields_; 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RecordInfo::Fields* RecordInfo::CollectFields() { 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Compute the collection locally to avoid inconsistent states. 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Fields* fields = new Fields; 334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!record_->hasDefinition()) 335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return fields; 336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TracingStatus fields_status = TracingStatus::Unneeded(); 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (RecordDecl::field_iterator it = record_->field_begin(); 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != record_->field_end(); 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FieldDecl* field = *it; 341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Ignore fields annotated with the GC_PLUGIN_IGNORE macro. 342effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (Config::IsIgnoreAnnotated(field)) 343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) continue; 344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Edge* edge = CreateEdge(field->getType().getTypePtrOrNull())) { 345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) fields_status = fields_status.LUB(edge->NeedsTracing(Edge::kRecursive)); 346effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch fields->insert(std::make_pair(field, FieldPoint(field, edge))); 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) fields_need_tracing_ = fields_status; 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return fields; 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RecordInfo::DetermineTracingMethods() { 354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (determined_trace_methods_) 355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) determined_trace_methods_ = true; 35723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (Config::IsGCBase(name_)) 35823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return; 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CXXMethodDecl* trace = 0; 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CXXMethodDecl* traceAfterDispatch = 0; 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool isTraceAfterDispatch; 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (CXXRecordDecl::method_iterator it = record_->method_begin(); 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != record_->method_end(); 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (Config::IsTraceMethod(*it, &isTraceAfterDispatch)) { 366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (isTraceAfterDispatch) { 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) traceAfterDispatch = *it; 368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) trace = *it; 370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 37123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else if (it->getNameAsString() == kFinalizeName) { 372effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch finalize_dispatch_method_ = *it; 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (traceAfterDispatch) { 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) trace_method_ = traceAfterDispatch; 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) trace_dispatch_method_ = trace; 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO: Can we never have a dispatch method called trace without the same 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // class defining a traceAfterDispatch method? 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) trace_method_ = trace; 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) trace_dispatch_method_ = 0; 3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 38423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (trace_dispatch_method_ && finalize_dispatch_method_) 38523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return; 38623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // If this class does not define dispatching methods inherit them. 38723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) { 38823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // TODO: Does it make sense to inherit multiple dispatch methods? 38923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (CXXMethodDecl* dispatch = it->second.info()->GetTraceDispatchMethod()) { 39023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assert(!trace_dispatch_method_ && "Multiple trace dispatching methods"); 39123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) trace_dispatch_method_ = dispatch; 39223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 39323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (CXXMethodDecl* dispatch = 394effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it->second.info()->GetFinalizeDispatchMethod()) { 39523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assert(!finalize_dispatch_method_ && 39623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) "Multiple finalize dispatching methods"); 39723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) finalize_dispatch_method_ = dispatch; 39823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 39923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// TODO: Add classes with a finalize() method that specialize FinalizerTrait. 403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool RecordInfo::NeedsFinalization() { 404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (does_need_finalization_ == kNotComputed) { 405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Rely on hasNonTrivialDestructor(), but if the only 406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // identifiable reason for it being true is the presence 407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // of a safely ignorable class as a direct base, 408116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // or we're processing such an 'ignorable' class, then it does 409116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // not need finalization. 410116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch does_need_finalization_ = 411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch record_->hasNonTrivialDestructor() ? kTrue : kFalse; 412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!does_need_finalization_) 413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return does_need_finalization_; 414116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Processing a class with a safely-ignorable destructor. 416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NamespaceDecl* ns = 417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch dyn_cast<NamespaceDecl>(record_->getDeclContext()); 418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (ns && Config::HasIgnorableDestructor(ns->getName(), name_)) { 419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch does_need_finalization_ = kFalse; 420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return does_need_finalization_; 421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CXXDestructorDecl* dtor = record_->getDestructor(); 424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (dtor && dtor->isUserProvided()) 425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return does_need_finalization_; 426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (Fields::iterator it = GetFields().begin(); 427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it != GetFields().end(); 428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++it) { 429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (it->second.edge()->NeedsFinalization()) 430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return does_need_finalization_; 431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (Bases::iterator it = GetBases().begin(); 434116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it != GetBases().end(); 435116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++it) { 436116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (it->second.info()->NeedsFinalization()) 437116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return does_need_finalization_; 438116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 439116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Destructor was non-trivial due to bases with destructors that 440116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // can be safely ignored. Hence, no need for finalization. 441116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch does_need_finalization_ = kFalse; 442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return does_need_finalization_; 444a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 445a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// A class needs tracing if: 447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// - it is allocated on the managed heap, 448a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// - it is derived from a class that needs tracing, or 449a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// - it contains fields that need tracing. 450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// TODO: Defining NeedsTracing based on whether a class defines a trace method 451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// (of the proper signature) over approximates too much. The use of transition 452a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// types causes some classes to have trace methods without them needing to be 453a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// traced. 454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TracingStatus RecordInfo::NeedsTracing(Edge::NeedsTracingOption option) { 455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsGCAllocated()) 456a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return TracingStatus::Needed(); 457a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 458effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (IsStackAllocated()) 459effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return TracingStatus::Unneeded(); 460effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 461a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) { 462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (it->second.info()->NeedsTracing(option).IsNeeded()) 463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return TracingStatus::Needed(); 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (option == Edge::kRecursive) 467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetFields(); 468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 469a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return fields_need_tracing_; 470a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 472a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)Edge* RecordInfo::CreateEdge(const Type* type) { 473a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!type) { 474a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (type->isPointerType()) { 478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Edge* ptr = CreateEdge(type->getPointeeType().getTypePtrOrNull())) 479c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return new RawPtr(ptr, false); 480a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 483a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RecordInfo* info = cache_->Lookup(type); 484a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If the type is neither a pointer or a C++ record we ignore it. 486a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!info) { 487a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 490a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TemplateArgs args; 491a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Config::IsRawPtr(info->name()) && info->GetTemplateArgs(1, &args)) { 493a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Edge* ptr = CreateEdge(args[0])) 494c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return new RawPtr(ptr, true); 495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 498a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Config::IsRefPtr(info->name()) && info->GetTemplateArgs(1, &args)) { 499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Edge* ptr = CreateEdge(args[0])) 500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return new RefPtr(ptr); 501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Config::IsOwnPtr(info->name()) && info->GetTemplateArgs(1, &args)) { 505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Edge* ptr = CreateEdge(args[0])) 506a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return new OwnPtr(ptr); 507a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 508a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 510a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Config::IsMember(info->name()) && info->GetTemplateArgs(1, &args)) { 511a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Edge* ptr = CreateEdge(args[0])) 512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return new Member(ptr); 513a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 516a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Config::IsWeakMember(info->name()) && info->GetTemplateArgs(1, &args)) { 517a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Edge* ptr = CreateEdge(args[0])) 518a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return new WeakMember(ptr); 519a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 520a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 521a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 522a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Config::IsPersistent(info->name())) { 523a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Persistent might refer to v8::Persistent, so check the name space. 524a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO: Consider using a more canonical identification than names. 525a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NamespaceDecl* ns = 526a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dyn_cast<NamespaceDecl>(info->record()->getDeclContext()); 527116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!ns || ns->getName() != "blink") 528a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 529a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!info->GetTemplateArgs(1, &args)) 530a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 531a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Edge* ptr = CreateEdge(args[0])) 532a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return new Persistent(ptr); 533a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 534a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 536a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Config::IsGCCollection(info->name()) || 537a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Config::IsWTFCollection(info->name())) { 538a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool is_root = Config::IsPersistentGCCollection(info->name()); 539a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool on_heap = is_root || info->IsHeapAllocatedCollection(); 540a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t count = Config::CollectionDimension(info->name()); 541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!info->GetTemplateArgs(count, &args)) 542a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 543a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Collection* edge = new Collection(info, on_heap, is_root); 544a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (TemplateArgs::iterator it = args.begin(); it != args.end(); ++it) { 545a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Edge* member = CreateEdge(*it)) { 546a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) edge->members().push_back(member); 547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 548010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // TODO: Handle the case where we fail to create an edge (eg, if the 549010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // argument is a primitive type or just not fully known yet). 550a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 551a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return edge; 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 554a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return new Value(info); 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 556