OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "Config.h" | 5 #include "Config.h" |
6 #include "RecordInfo.h" | 6 #include "RecordInfo.h" |
7 | 7 |
8 using namespace clang; | 8 using namespace clang; |
9 using std::string; | 9 using std::string; |
10 | 10 |
11 RecordInfo::RecordInfo(CXXRecordDecl* record, RecordCache* cache) | 11 RecordInfo::RecordInfo(CXXRecordDecl* record, RecordCache* cache) |
12 : cache_(cache), | 12 : cache_(cache), |
13 record_(record), | 13 record_(record), |
14 name_(record->getName()), | 14 name_(record->getName()), |
15 fields_need_tracing_(TracingStatus::Unknown()), | 15 fields_need_tracing_(TracingStatus::Unknown()), |
16 bases_(0), | 16 bases_(0), |
17 fields_(0), | 17 fields_(0), |
| 18 field_map_(0), |
18 is_stack_allocated_(kNotComputed), | 19 is_stack_allocated_(kNotComputed), |
19 is_non_newable_(kNotComputed), | 20 is_non_newable_(kNotComputed), |
20 is_only_placement_newable_(kNotComputed), | 21 is_only_placement_newable_(kNotComputed), |
21 does_need_finalization_(kNotComputed), | 22 does_need_finalization_(kNotComputed), |
22 has_gc_mixin_methods_(kNotComputed), | 23 has_gc_mixin_methods_(kNotComputed), |
23 is_declaring_local_trace_(kNotComputed), | 24 is_declaring_local_trace_(kNotComputed), |
24 is_eagerly_finalized_(kNotComputed), | 25 is_eagerly_finalized_(kNotComputed), |
25 determined_trace_methods_(false), | 26 determined_trace_methods_(false), |
26 trace_method_(0), | 27 trace_method_(0), |
27 trace_dispatch_method_(0), | 28 trace_dispatch_method_(0), |
28 finalize_dispatch_method_(0), | 29 finalize_dispatch_method_(0), |
29 is_gc_derived_(false) {} | 30 is_gc_derived_(false) {} |
30 | 31 |
31 RecordInfo::~RecordInfo() { | 32 RecordInfo::~RecordInfo() { |
32 delete fields_; | 33 delete fields_; |
| 34 delete field_map_; |
33 delete bases_; | 35 delete bases_; |
34 } | 36 } |
35 | 37 |
36 // Get |count| number of template arguments. Returns false if there | 38 // Get |count| number of template arguments. Returns false if there |
37 // are fewer than |count| arguments or any of the arguments are not | 39 // are fewer than |count| arguments or any of the arguments are not |
38 // of a valid Type structure. If |count| is non-positive, all | 40 // of a valid Type structure. If |count| is non-positive, all |
39 // arguments are collected. | 41 // arguments are collected. |
40 bool RecordInfo::GetTemplateArgs(size_t count, TemplateArgs* output_args) { | 42 bool RecordInfo::GetTemplateArgs(size_t count, TemplateArgs* output_args) { |
41 ClassTemplateSpecializationDecl* tmpl = | 43 ClassTemplateSpecializationDecl* tmpl = |
42 dyn_cast<ClassTemplateSpecializationDecl>(record_); | 44 dyn_cast<ClassTemplateSpecializationDecl>(record_); |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 return trace_dispatch_method_; | 314 return trace_dispatch_method_; |
313 } | 315 } |
314 | 316 |
315 CXXMethodDecl* RecordInfo::GetFinalizeDispatchMethod() { | 317 CXXMethodDecl* RecordInfo::GetFinalizeDispatchMethod() { |
316 DetermineTracingMethods(); | 318 DetermineTracingMethods(); |
317 return finalize_dispatch_method_; | 319 return finalize_dispatch_method_; |
318 } | 320 } |
319 | 321 |
320 RecordInfo::Bases& RecordInfo::GetBases() { | 322 RecordInfo::Bases& RecordInfo::GetBases() { |
321 if (!bases_) | 323 if (!bases_) |
322 bases_ = CollectBases(); | 324 CollectBases(); |
323 return *bases_; | 325 return *bases_; |
324 } | 326 } |
325 | 327 |
326 bool RecordInfo::InheritsTrace() { | 328 bool RecordInfo::InheritsTrace() { |
327 if (GetTraceMethod()) | 329 if (GetTraceMethod()) |
328 return true; | 330 return true; |
329 for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) { | 331 for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) { |
330 if (it->second.info()->InheritsTrace()) | 332 if (it->second.info()->InheritsTrace()) |
331 return true; | 333 return true; |
332 } | 334 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 } | 378 } |
377 for (CXXRecordDecl::method_iterator it = record_->method_begin(); | 379 for (CXXRecordDecl::method_iterator it = record_->method_begin(); |
378 it != record_->method_end(); | 380 it != record_->method_end(); |
379 ++it) { | 381 ++it) { |
380 if (it->getNameAsString() == kCreateName) | 382 if (it->getNameAsString() == kCreateName) |
381 return false; | 383 return false; |
382 } | 384 } |
383 return true; | 385 return true; |
384 } | 386 } |
385 | 387 |
386 RecordInfo::Bases* RecordInfo::CollectBases() { | 388 void RecordInfo::CollectBases() { |
387 // Compute the collection locally to avoid inconsistent states. | 389 // Compute the collection locally to avoid inconsistent states. |
388 Bases* bases = new Bases; | 390 assert(!bases_); |
| 391 bases_ = new Bases; |
389 if (!record_->hasDefinition()) | 392 if (!record_->hasDefinition()) |
390 return bases; | 393 return; |
391 for (CXXRecordDecl::base_class_iterator it = record_->bases_begin(); | 394 for (CXXRecordDecl::base_class_iterator it = record_->bases_begin(); |
392 it != record_->bases_end(); | 395 it != record_->bases_end(); |
393 ++it) { | 396 ++it) { |
394 const CXXBaseSpecifier& spec = *it; | 397 const CXXBaseSpecifier& spec = *it; |
395 RecordInfo* info = cache_->Lookup(spec.getType()); | 398 RecordInfo* info = cache_->Lookup(spec.getType()); |
396 if (!info) | 399 if (!info) |
397 continue; | 400 continue; |
398 CXXRecordDecl* base = info->record(); | 401 CXXRecordDecl* base = info->record(); |
399 TracingStatus status = info->InheritsTrace() | 402 TracingStatus status = info->InheritsTrace() |
400 ? TracingStatus::Needed() | 403 ? TracingStatus::Needed() |
401 : TracingStatus::Unneeded(); | 404 : TracingStatus::Unneeded(); |
402 bases->insert(std::make_pair(base, BasePoint(spec, info, status))); | 405 bases_->push_back(std::make_pair(base, BasePoint(spec, info, status))); |
403 } | 406 } |
404 return bases; | |
405 } | 407 } |
406 | 408 |
407 RecordInfo::Fields& RecordInfo::GetFields() { | 409 RecordInfo::Fields& RecordInfo::GetFields() { |
408 if (!fields_) | 410 if (!fields_) { |
409 fields_ = CollectFields(); | 411 assert(!field_map_); |
| 412 CollectFields(); |
| 413 } |
410 return *fields_; | 414 return *fields_; |
411 } | 415 } |
412 | 416 |
413 RecordInfo::Fields* RecordInfo::CollectFields() { | 417 bool RecordInfo::HasField(clang::FieldDecl* field) { |
| 418 GetFields(); |
| 419 assert(field_map_); |
| 420 return field_map_->count(field); |
| 421 } |
| 422 |
| 423 RecordInfo::Field& RecordInfo::GetField(clang::FieldDecl* field) { |
| 424 assert(HasField(field)); |
| 425 return fields_->at((*field_map_)[field]); |
| 426 } |
| 427 |
| 428 void RecordInfo::CollectFields() { |
414 // Compute the collection locally to avoid inconsistent states. | 429 // Compute the collection locally to avoid inconsistent states. |
415 Fields* fields = new Fields; | 430 assert(!fields_); |
| 431 fields_ = new Fields; |
| 432 field_map_ = new std::map<clang::FieldDecl*, size_t>; |
| 433 |
416 if (!record_->hasDefinition()) | 434 if (!record_->hasDefinition()) |
417 return fields; | 435 return; |
| 436 |
418 TracingStatus fields_status = TracingStatus::Unneeded(); | 437 TracingStatus fields_status = TracingStatus::Unneeded(); |
419 for (RecordDecl::field_iterator it = record_->field_begin(); | 438 for (RecordDecl::field_iterator it = record_->field_begin(); |
420 it != record_->field_end(); | 439 it != record_->field_end(); |
421 ++it) { | 440 ++it) { |
422 FieldDecl* field = *it; | 441 FieldDecl* field = *it; |
423 // Ignore fields annotated with the GC_PLUGIN_IGNORE macro. | 442 // Ignore fields annotated with the GC_PLUGIN_IGNORE macro. |
424 if (Config::IsIgnoreAnnotated(field)) | 443 if (Config::IsIgnoreAnnotated(field)) |
425 continue; | 444 continue; |
426 if (Edge* edge = CreateEdge(field->getType().getTypePtrOrNull())) { | 445 if (Edge* edge = CreateEdge(field->getType().getTypePtrOrNull())) { |
427 fields_status = fields_status.LUB(edge->NeedsTracing(Edge::kRecursive)); | 446 fields_status = fields_status.LUB(edge->NeedsTracing(Edge::kRecursive)); |
428 fields->insert(std::make_pair(field, FieldPoint(field, edge))); | 447 (*field_map_)[field] = fields_->size(); |
| 448 fields_->push_back(std::make_pair(field, FieldPoint(field, edge))); |
429 } | 449 } |
430 } | 450 } |
431 fields_need_tracing_ = fields_status; | 451 fields_need_tracing_ = fields_status; |
432 return fields; | |
433 } | 452 } |
434 | 453 |
435 void RecordInfo::DetermineTracingMethods() { | 454 void RecordInfo::DetermineTracingMethods() { |
436 if (determined_trace_methods_) | 455 if (determined_trace_methods_) |
437 return; | 456 return; |
438 determined_trace_methods_ = true; | 457 determined_trace_methods_ = true; |
439 if (Config::IsGCBase(name_)) | 458 if (Config::IsGCBase(name_)) |
440 return; | 459 return; |
441 CXXMethodDecl* trace = nullptr; | 460 CXXMethodDecl* trace = nullptr; |
442 CXXMethodDecl* trace_impl = nullptr; | 461 CXXMethodDecl* trace_impl = nullptr; |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 edge->members().push_back(member); | 673 edge->members().push_back(member); |
655 } | 674 } |
656 // TODO: Handle the case where we fail to create an edge (eg, if the | 675 // TODO: Handle the case where we fail to create an edge (eg, if the |
657 // argument is a primitive type or just not fully known yet). | 676 // argument is a primitive type or just not fully known yet). |
658 } | 677 } |
659 return edge; | 678 return edge; |
660 } | 679 } |
661 | 680 |
662 return new Value(info); | 681 return new Value(info); |
663 } | 682 } |
OLD | NEW |