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 does_need_finalization_(kNotComputed), |
| 22 has_gc_mixin_methods_(kNotComputed), |
| 23 is_declaring_local_trace_(kNotComputed), |
22 determined_trace_methods_(false), | 24 determined_trace_methods_(false), |
23 trace_method_(0), | 25 trace_method_(0), |
24 trace_dispatch_method_(0), | 26 trace_dispatch_method_(0), |
25 finalize_dispatch_method_(0), | 27 finalize_dispatch_method_(0), |
26 is_gc_derived_(false) {} | 28 is_gc_derived_(false) {} |
27 | 29 |
28 RecordInfo::~RecordInfo() { | 30 RecordInfo::~RecordInfo() { |
29 delete fields_; | 31 delete fields_; |
30 delete bases_; | 32 delete bases_; |
31 } | 33 } |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 CXXMethodDecl* RecordInfo::InheritsNonVirtualTrace() { | 304 CXXMethodDecl* RecordInfo::InheritsNonVirtualTrace() { |
303 if (CXXMethodDecl* trace = GetTraceMethod()) | 305 if (CXXMethodDecl* trace = GetTraceMethod()) |
304 return trace->isVirtual() ? 0 : trace; | 306 return trace->isVirtual() ? 0 : trace; |
305 for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) { | 307 for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) { |
306 if (CXXMethodDecl* trace = it->second.info()->InheritsNonVirtualTrace()) | 308 if (CXXMethodDecl* trace = it->second.info()->InheritsNonVirtualTrace()) |
307 return trace; | 309 return trace; |
308 } | 310 } |
309 return 0; | 311 return 0; |
310 } | 312 } |
311 | 313 |
| 314 bool RecordInfo::DeclaresGCMixinMethods() { |
| 315 DetermineTracingMethods(); |
| 316 return has_gc_mixin_methods_; |
| 317 } |
| 318 |
| 319 bool RecordInfo::DeclaresLocalTraceMethod() { |
| 320 if (is_declaring_local_trace_ != kNotComputed) |
| 321 return is_declaring_local_trace_; |
| 322 DetermineTracingMethods(); |
| 323 is_declaring_local_trace_ = trace_method_ ? kTrue : kFalse; |
| 324 if (is_declaring_local_trace_) { |
| 325 for (auto it = record_->method_begin(); |
| 326 it != record_->method_end(); ++it) { |
| 327 if (*it == trace_method_) { |
| 328 is_declaring_local_trace_ = kTrue; |
| 329 break; |
| 330 } |
| 331 } |
| 332 } |
| 333 return is_declaring_local_trace_; |
| 334 } |
| 335 |
| 336 bool RecordInfo::IsGCMixinInstance() { |
| 337 assert(IsGCDerived()); |
| 338 if (record_->isAbstract()) |
| 339 return false; |
| 340 |
| 341 assert(!IsGCMixin()); |
| 342 |
| 343 // true iff the class derives from GCMixin and |
| 344 // one or more other GC base classes. |
| 345 bool seen_gc_mixin = false; |
| 346 bool seen_gc_derived = false; |
| 347 for (const auto& gc_base : gc_base_names_) { |
| 348 if (Config::IsGCMixinBase(gc_base)) |
| 349 seen_gc_mixin = true; |
| 350 else if (Config::IsGCBase(gc_base)) |
| 351 seen_gc_derived = true; |
| 352 } |
| 353 return seen_gc_derived && seen_gc_mixin; |
| 354 } |
| 355 |
312 // A (non-virtual) class is considered abstract in Blink if it has | 356 // A (non-virtual) class is considered abstract in Blink if it has |
313 // no public constructors and no create methods. | 357 // no public constructors and no create methods. |
314 bool RecordInfo::IsConsideredAbstract() { | 358 bool RecordInfo::IsConsideredAbstract() { |
315 for (CXXRecordDecl::ctor_iterator it = record_->ctor_begin(); | 359 for (CXXRecordDecl::ctor_iterator it = record_->ctor_begin(); |
316 it != record_->ctor_end(); | 360 it != record_->ctor_end(); |
317 ++it) { | 361 ++it) { |
318 if (!it->isCopyOrMoveConstructor() && it->getAccess() == AS_public) | 362 if (!it->isCopyOrMoveConstructor() && it->getAccess() == AS_public) |
319 return false; | 363 return false; |
320 } | 364 } |
321 for (CXXRecordDecl::method_iterator it = record_->method_begin(); | 365 for (CXXRecordDecl::method_iterator it = record_->method_begin(); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 | 422 |
379 void RecordInfo::DetermineTracingMethods() { | 423 void RecordInfo::DetermineTracingMethods() { |
380 if (determined_trace_methods_) | 424 if (determined_trace_methods_) |
381 return; | 425 return; |
382 determined_trace_methods_ = true; | 426 determined_trace_methods_ = true; |
383 if (Config::IsGCBase(name_)) | 427 if (Config::IsGCBase(name_)) |
384 return; | 428 return; |
385 CXXMethodDecl* trace = 0; | 429 CXXMethodDecl* trace = 0; |
386 CXXMethodDecl* traceAfterDispatch = 0; | 430 CXXMethodDecl* traceAfterDispatch = 0; |
387 bool isTraceAfterDispatch; | 431 bool isTraceAfterDispatch; |
| 432 bool hasAdjustAndMark = false; |
| 433 bool hasIsHeapObjectAlive = false; |
388 for (CXXRecordDecl::method_iterator it = record_->method_begin(); | 434 for (CXXRecordDecl::method_iterator it = record_->method_begin(); |
389 it != record_->method_end(); | 435 it != record_->method_end(); |
390 ++it) { | 436 ++it) { |
391 if (Config::IsTraceMethod(*it, &isTraceAfterDispatch)) { | 437 if (Config::IsTraceMethod(*it, &isTraceAfterDispatch)) { |
392 if (isTraceAfterDispatch) { | 438 if (isTraceAfterDispatch) { |
393 traceAfterDispatch = *it; | 439 traceAfterDispatch = *it; |
394 } else { | 440 } else { |
395 trace = *it; | 441 trace = *it; |
396 } | 442 } |
397 } else if (it->getNameAsString() == kFinalizeName) { | 443 } else if (it->getNameAsString() == kFinalizeName) { |
398 finalize_dispatch_method_ = *it; | 444 finalize_dispatch_method_ = *it; |
| 445 } else if (it->getNameAsString() == kAdjustAndMarkName) { |
| 446 hasAdjustAndMark = true; |
| 447 } else if (it->getNameAsString() == kIsHeapObjectAliveName) { |
| 448 hasIsHeapObjectAlive = true; |
399 } | 449 } |
400 } | 450 } |
| 451 // Record if class defines the two GCMixin methods. |
| 452 has_gc_mixin_methods_ = |
| 453 hasAdjustAndMark && hasIsHeapObjectAlive ? kTrue : kFalse; |
401 if (traceAfterDispatch) { | 454 if (traceAfterDispatch) { |
402 trace_method_ = traceAfterDispatch; | 455 trace_method_ = traceAfterDispatch; |
403 trace_dispatch_method_ = trace; | 456 trace_dispatch_method_ = trace; |
404 } else { | 457 } else { |
405 // TODO: Can we never have a dispatch method called trace without the same | 458 // TODO: Can we never have a dispatch method called trace without the same |
406 // class defining a traceAfterDispatch method? | 459 // class defining a traceAfterDispatch method? |
407 trace_method_ = trace; | 460 trace_method_ = trace; |
408 trace_dispatch_method_ = 0; | 461 trace_dispatch_method_ = 0; |
409 } | 462 } |
410 if (trace_dispatch_method_ && finalize_dispatch_method_) | 463 if (trace_dispatch_method_ && finalize_dispatch_method_) |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 edge->members().push_back(member); | 625 edge->members().push_back(member); |
573 } | 626 } |
574 // TODO: Handle the case where we fail to create an edge (eg, if the | 627 // TODO: Handle the case where we fail to create an edge (eg, if the |
575 // argument is a primitive type or just not fully known yet). | 628 // argument is a primitive type or just not fully known yet). |
576 } | 629 } |
577 return edge; | 630 return edge; |
578 } | 631 } |
579 | 632 |
580 return new Value(info); | 633 return new Value(info); |
581 } | 634 } |
OLD | NEW |