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 is_stack_allocated_(kNotComputed), | 18 is_stack_allocated_(kNotComputed), |
19 is_non_newable_(kNotComputed), | 19 is_non_newable_(kNotComputed), |
20 is_only_placement_newable_(kNotComputed), | 20 is_only_placement_newable_(kNotComputed), |
| 21 does_need_finalization_(kNotComputed), |
21 determined_trace_methods_(false), | 22 determined_trace_methods_(false), |
22 trace_method_(0), | 23 trace_method_(0), |
23 trace_dispatch_method_(0), | 24 trace_dispatch_method_(0), |
24 finalize_dispatch_method_(0), | 25 finalize_dispatch_method_(0), |
25 is_gc_derived_(false), | 26 is_gc_derived_(false), |
26 base_paths_(0) {} | 27 base_paths_(0) {} |
27 | 28 |
28 RecordInfo::~RecordInfo() { | 29 RecordInfo::~RecordInfo() { |
29 delete fields_; | 30 delete fields_; |
30 delete bases_; | 31 delete bases_; |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 it->second.info()->GetFinalizeDispatchMethod()) { | 394 it->second.info()->GetFinalizeDispatchMethod()) { |
394 assert(!finalize_dispatch_method_ && | 395 assert(!finalize_dispatch_method_ && |
395 "Multiple finalize dispatching methods"); | 396 "Multiple finalize dispatching methods"); |
396 finalize_dispatch_method_ = dispatch; | 397 finalize_dispatch_method_ = dispatch; |
397 } | 398 } |
398 } | 399 } |
399 } | 400 } |
400 | 401 |
401 // TODO: Add classes with a finalize() method that specialize FinalizerTrait. | 402 // TODO: Add classes with a finalize() method that specialize FinalizerTrait. |
402 bool RecordInfo::NeedsFinalization() { | 403 bool RecordInfo::NeedsFinalization() { |
403 return record_->hasNonTrivialDestructor(); | 404 if (does_need_finalization_ == kNotComputed) { |
| 405 // Rely on hasNonTrivialDestructor(), but if the only |
| 406 // identifiable reason for it being true is the presence |
| 407 // of a safely ignorable class as a direct base, |
| 408 // or we're processing such an 'ignorable' class, then it does |
| 409 // not need finalization. |
| 410 does_need_finalization_ = |
| 411 record_->hasNonTrivialDestructor() ? kTrue : kFalse; |
| 412 if (!does_need_finalization_) |
| 413 return does_need_finalization_; |
| 414 |
| 415 // Processing a class with a safely-ignorable destructor. |
| 416 NamespaceDecl* ns = |
| 417 dyn_cast<NamespaceDecl>(record_->getDeclContext()); |
| 418 if (ns && Config::HasIgnorableDestructor(ns->getName(), name_)) { |
| 419 does_need_finalization_ = kFalse; |
| 420 return does_need_finalization_; |
| 421 } |
| 422 |
| 423 CXXDestructorDecl* dtor = record_->getDestructor(); |
| 424 if (dtor && dtor->isUserProvided()) |
| 425 return does_need_finalization_; |
| 426 for (Fields::iterator it = GetFields().begin(); |
| 427 it != GetFields().end(); |
| 428 ++it) { |
| 429 if (it->second.edge()->NeedsFinalization()) |
| 430 return does_need_finalization_; |
| 431 } |
| 432 |
| 433 for (Bases::iterator it = GetBases().begin(); |
| 434 it != GetBases().end(); |
| 435 ++it) { |
| 436 if (it->second.info()->NeedsFinalization()) |
| 437 return does_need_finalization_; |
| 438 } |
| 439 // Destructor was non-trivial due to bases with destructors that |
| 440 // can be safely ignored. Hence, no need for finalization. |
| 441 does_need_finalization_ = kFalse; |
| 442 } |
| 443 return does_need_finalization_; |
404 } | 444 } |
405 | 445 |
406 // A class needs tracing if: | 446 // A class needs tracing if: |
407 // - it is allocated on the managed heap, | 447 // - it is allocated on the managed heap, |
408 // - it is derived from a class that needs tracing, or | 448 // - it is derived from a class that needs tracing, or |
409 // - it contains fields that need tracing. | 449 // - it contains fields that need tracing. |
410 // TODO: Defining NeedsTracing based on whether a class defines a trace method | 450 // TODO: Defining NeedsTracing based on whether a class defines a trace method |
411 // (of the proper signature) over approximates too much. The use of transition | 451 // (of the proper signature) over approximates too much. The use of transition |
412 // types causes some classes to have trace methods without them needing to be | 452 // types causes some classes to have trace methods without them needing to be |
413 // traced. | 453 // traced. |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 edge->members().push_back(member); | 546 edge->members().push_back(member); |
507 } | 547 } |
508 // TODO: Handle the case where we fail to create an edge (eg, if the | 548 // TODO: Handle the case where we fail to create an edge (eg, if the |
509 // argument is a primitive type or just not fully known yet). | 549 // argument is a primitive type or just not fully known yet). |
510 } | 550 } |
511 return edge; | 551 return edge; |
512 } | 552 } |
513 | 553 |
514 return new Value(info); | 554 return new Value(info); |
515 } | 555 } |
OLD | NEW |