| 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 // This clang plugin checks various invariants of the Blink garbage | 5 // This clang plugin checks various invariants of the Blink garbage |
| 6 // collection infrastructure. | 6 // collection infrastructure. |
| 7 // | 7 // |
| 8 // Errors are described at: | 8 // Errors are described at: |
| 9 // http://www.chromium.org/developers/blink-gc-plugin-errors | 9 // http://www.chromium.org/developers/blink-gc-plugin-errors |
| 10 | 10 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 | 61 |
| 62 const char kFinalizerAccessesEagerlyFinalizedField[] = | 62 const char kFinalizerAccessesEagerlyFinalizedField[] = |
| 63 "[blink-gc] Finalizer %0 accesses eagerly finalized field %1."; | 63 "[blink-gc] Finalizer %0 accesses eagerly finalized field %1."; |
| 64 | 64 |
| 65 const char kRawPtrToGCManagedClassNote[] = | 65 const char kRawPtrToGCManagedClassNote[] = |
| 66 "[blink-gc] Raw pointer field %0 to a GC managed class declared here:"; | 66 "[blink-gc] Raw pointer field %0 to a GC managed class declared here:"; |
| 67 | 67 |
| 68 const char kRefPtrToGCManagedClassNote[] = | 68 const char kRefPtrToGCManagedClassNote[] = |
| 69 "[blink-gc] RefPtr field %0 to a GC managed class declared here:"; | 69 "[blink-gc] RefPtr field %0 to a GC managed class declared here:"; |
| 70 | 70 |
| 71 const char kReferencePtrToGCManagedClassNote[] = |
| 72 "[blink-gc] Reference pointer field %0 to a GC managed class" |
| 73 " declared here:"; |
| 74 |
| 71 const char kOwnPtrToGCManagedClassNote[] = | 75 const char kOwnPtrToGCManagedClassNote[] = |
| 72 "[blink-gc] OwnPtr field %0 to a GC managed class declared here:"; | 76 "[blink-gc] OwnPtr field %0 to a GC managed class declared here:"; |
| 73 | 77 |
| 74 const char kMemberToGCUnmanagedClassNote[] = | 78 const char kMemberToGCUnmanagedClassNote[] = |
| 75 "[blink-gc] Member field %0 to non-GC managed class declared here:"; | 79 "[blink-gc] Member field %0 to non-GC managed class declared here:"; |
| 76 | 80 |
| 77 const char kStackAllocatedFieldNote[] = | 81 const char kStackAllocatedFieldNote[] = |
| 78 "[blink-gc] Stack-allocated field %0 declared here:"; | 82 "[blink-gc] Stack-allocated field %0 declared here:"; |
| 79 | 83 |
| 80 const char kMemberInUnmanagedClassNote[] = | 84 const char kMemberInUnmanagedClassNote[] = |
| (...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 // - Part objects must not be GC derived types. | 850 // - Part objects must not be GC derived types. |
| 847 // - An on-heap class must never contain GC roots. | 851 // - An on-heap class must never contain GC roots. |
| 848 // - Only stack-allocated types may point to stack-allocated types. | 852 // - Only stack-allocated types may point to stack-allocated types. |
| 849 class CheckFieldsVisitor : public RecursiveEdgeVisitor { | 853 class CheckFieldsVisitor : public RecursiveEdgeVisitor { |
| 850 public: | 854 public: |
| 851 | 855 |
| 852 enum Error { | 856 enum Error { |
| 853 kRawPtrToGCManaged, | 857 kRawPtrToGCManaged, |
| 854 kRawPtrToGCManagedWarning, | 858 kRawPtrToGCManagedWarning, |
| 855 kRefPtrToGCManaged, | 859 kRefPtrToGCManaged, |
| 860 kReferencePtrToGCManaged, |
| 861 kReferencePtrToGCManagedWarning, |
| 856 kOwnPtrToGCManaged, | 862 kOwnPtrToGCManaged, |
| 857 kMemberToGCUnmanaged, | 863 kMemberToGCUnmanaged, |
| 858 kMemberInUnmanaged, | 864 kMemberInUnmanaged, |
| 859 kPtrFromHeapToStack, | 865 kPtrFromHeapToStack, |
| 860 kGCDerivedPartObject | 866 kGCDerivedPartObject |
| 861 }; | 867 }; |
| 862 | 868 |
| 863 typedef std::vector<std::pair<FieldPoint*, Error> > Errors; | 869 typedef std::vector<std::pair<FieldPoint*, Error> > Errors; |
| 864 | 870 |
| 865 CheckFieldsVisitor(const BlinkGCPluginOptions& options) | 871 CheckFieldsVisitor(const BlinkGCPluginOptions& options) |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 937 // also disallow T* in stack-allocated types. | 943 // also disallow T* in stack-allocated types. |
| 938 if (options_.enable_oilpan) { | 944 if (options_.enable_oilpan) { |
| 939 if (Parent()->IsOwnPtr() || | 945 if (Parent()->IsOwnPtr() || |
| 940 Parent()->IsRawPtrClass() || | 946 Parent()->IsRawPtrClass() || |
| 941 (stack_allocated_host_ && Parent()->IsRawPtr())) { | 947 (stack_allocated_host_ && Parent()->IsRawPtr())) { |
| 942 invalid_fields_.push_back(std::make_pair( | 948 invalid_fields_.push_back(std::make_pair( |
| 943 current_, InvalidSmartPtr(Parent()))); | 949 current_, InvalidSmartPtr(Parent()))); |
| 944 return; | 950 return; |
| 945 } | 951 } |
| 946 if (options_.warn_raw_ptr && Parent()->IsRawPtr()) { | 952 if (options_.warn_raw_ptr && Parent()->IsRawPtr()) { |
| 947 invalid_fields_.push_back(std::make_pair( | 953 if (static_cast<RawPtr*>(Parent())->HasReferenceType()) { |
| 948 current_, kRawPtrToGCManagedWarning)); | 954 invalid_fields_.push_back(std::make_pair( |
| 955 current_, kReferencePtrToGCManagedWarning)); |
| 956 } else { |
| 957 invalid_fields_.push_back(std::make_pair( |
| 958 current_, kRawPtrToGCManagedWarning)); |
| 959 } |
| 949 } | 960 } |
| 950 return; | 961 return; |
| 951 } | 962 } |
| 952 | 963 |
| 953 if (Parent()->IsRawPtr() || Parent()->IsRefPtr() || Parent()->IsOwnPtr()) { | 964 if (Parent()->IsRawPtr() || Parent()->IsRefPtr() || Parent()->IsOwnPtr()) { |
| 954 invalid_fields_.push_back(std::make_pair( | 965 invalid_fields_.push_back(std::make_pair( |
| 955 current_, InvalidSmartPtr(Parent()))); | 966 current_, InvalidSmartPtr(Parent()))); |
| 956 return; | 967 return; |
| 957 } | 968 } |
| 958 } | 969 } |
| 959 | 970 |
| 960 void AtCollection(Collection* edge) override { | 971 void AtCollection(Collection* edge) override { |
| 961 if (edge->on_heap() && Parent() && Parent()->IsOwnPtr()) | 972 if (edge->on_heap() && Parent() && Parent()->IsOwnPtr()) |
| 962 invalid_fields_.push_back(std::make_pair(current_, kOwnPtrToGCManaged)); | 973 invalid_fields_.push_back(std::make_pair(current_, kOwnPtrToGCManaged)); |
| 963 } | 974 } |
| 964 | 975 |
| 976 static bool IsWarning(Error error) { |
| 977 if (error == kRawPtrToGCManagedWarning) |
| 978 return true; |
| 979 if (error == kReferencePtrToGCManagedWarning) |
| 980 return true; |
| 981 return false; |
| 982 } |
| 983 |
| 984 static bool IsRawPtrError(Error error) { |
| 985 return error == kRawPtrToGCManaged || |
| 986 error == kRawPtrToGCManagedWarning; |
| 987 } |
| 988 |
| 989 static bool IsReferencePtrError(Error error) { |
| 990 return error == kReferencePtrToGCManaged || |
| 991 error == kReferencePtrToGCManagedWarning; |
| 992 } |
| 993 |
| 965 private: | 994 private: |
| 966 Error InvalidSmartPtr(Edge* ptr) { | 995 Error InvalidSmartPtr(Edge* ptr) { |
| 967 if (ptr->IsRawPtr()) | 996 if (ptr->IsRawPtr()) { |
| 968 return kRawPtrToGCManaged; | 997 if (static_cast<RawPtr*>(ptr)->HasReferenceType()) |
| 998 return kReferencePtrToGCManaged; |
| 999 else |
| 1000 return kRawPtrToGCManaged; |
| 1001 } |
| 969 if (ptr->IsRefPtr()) | 1002 if (ptr->IsRefPtr()) |
| 970 return kRefPtrToGCManaged; | 1003 return kRefPtrToGCManaged; |
| 971 if (ptr->IsOwnPtr()) | 1004 if (ptr->IsOwnPtr()) |
| 972 return kOwnPtrToGCManaged; | 1005 return kOwnPtrToGCManaged; |
| 973 assert(false && "Unknown smart pointer kind"); | 1006 assert(false && "Unknown smart pointer kind"); |
| 974 } | 1007 } |
| 975 | 1008 |
| 976 const BlinkGCPluginOptions& options_; | 1009 const BlinkGCPluginOptions& options_; |
| 977 FieldPoint* current_; | 1010 FieldPoint* current_; |
| 978 bool stack_allocated_host_; | 1011 bool stack_allocated_host_; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1070 | 1103 |
| 1071 // Register note messages. | 1104 // Register note messages. |
| 1072 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 1105 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
| 1073 DiagnosticsEngine::Note, kBaseRequiresTracingNote); | 1106 DiagnosticsEngine::Note, kBaseRequiresTracingNote); |
| 1074 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 1107 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
| 1075 DiagnosticsEngine::Note, kFieldRequiresTracingNote); | 1108 DiagnosticsEngine::Note, kFieldRequiresTracingNote); |
| 1076 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1109 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 1077 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); | 1110 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); |
| 1078 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1111 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 1079 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); | 1112 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); |
| 1113 diag_reference_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 1114 DiagnosticsEngine::Note, kReferencePtrToGCManagedClassNote); |
| 1080 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1115 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 1081 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); | 1116 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); |
| 1082 diag_member_to_gc_unmanaged_class_note_ = diagnostic_.getCustomDiagID( | 1117 diag_member_to_gc_unmanaged_class_note_ = diagnostic_.getCustomDiagID( |
| 1083 DiagnosticsEngine::Note, kMemberToGCUnmanagedClassNote); | 1118 DiagnosticsEngine::Note, kMemberToGCUnmanagedClassNote); |
| 1084 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID( | 1119 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID( |
| 1085 DiagnosticsEngine::Note, kStackAllocatedFieldNote); | 1120 DiagnosticsEngine::Note, kStackAllocatedFieldNote); |
| 1086 diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID( | 1121 diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID( |
| 1087 DiagnosticsEngine::Note, kMemberInUnmanagedClassNote); | 1122 DiagnosticsEngine::Note, kMemberInUnmanagedClassNote); |
| 1088 diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID( | 1123 diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID( |
| 1089 DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote); | 1124 DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote); |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1620 const Edge::LivenessKind& kind, | 1655 const Edge::LivenessKind& kind, |
| 1621 const string& loc) { | 1656 const string& loc) { |
| 1622 json_->OpenObject(); | 1657 json_->OpenObject(); |
| 1623 json_->Write("src", src->record()->getQualifiedNameAsString()); | 1658 json_->Write("src", src->record()->getQualifiedNameAsString()); |
| 1624 json_->Write("dst", dst->record()->getQualifiedNameAsString()); | 1659 json_->Write("dst", dst->record()->getQualifiedNameAsString()); |
| 1625 json_->Write("lbl", lbl); | 1660 json_->Write("lbl", lbl); |
| 1626 json_->Write("kind", kind); | 1661 json_->Write("kind", kind); |
| 1627 json_->Write("loc", loc); | 1662 json_->Write("loc", loc); |
| 1628 json_->Write("ptr", | 1663 json_->Write("ptr", |
| 1629 !Parent() ? "val" : | 1664 !Parent() ? "val" : |
| 1630 Parent()->IsRawPtr() ? "raw" : | 1665 Parent()->IsRawPtr() ? |
| 1666 (static_cast<RawPtr*>(Parent())->HasReferenceType() ? |
| 1667 "reference" : "raw") : |
| 1631 Parent()->IsRefPtr() ? "ref" : | 1668 Parent()->IsRefPtr() ? "ref" : |
| 1632 Parent()->IsOwnPtr() ? "own" : | 1669 Parent()->IsOwnPtr() ? "own" : |
| 1633 (Parent()->IsMember() || | 1670 (Parent()->IsMember() || |
| 1634 Parent()->IsWeakMember()) ? "mem" : | 1671 Parent()->IsWeakMember()) ? "mem" : |
| 1635 "val"); | 1672 "val"); |
| 1636 json_->CloseObject(); | 1673 json_->CloseObject(); |
| 1637 } | 1674 } |
| 1638 | 1675 |
| 1639 void DumpField(RecordInfo* src, FieldPoint* point, const string& loc) { | 1676 void DumpField(RecordInfo* src, FieldPoint* point, const string& loc) { |
| 1640 src_ = src; | 1677 src_ = src; |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1831 | 1868 |
| 1832 void ReportClassContainsInvalidFields(RecordInfo* info, | 1869 void ReportClassContainsInvalidFields(RecordInfo* info, |
| 1833 CheckFieldsVisitor::Errors* errors) { | 1870 CheckFieldsVisitor::Errors* errors) { |
| 1834 SourceLocation loc = info->record()->getLocStart(); | 1871 SourceLocation loc = info->record()->getLocStart(); |
| 1835 SourceManager& manager = instance_.getSourceManager(); | 1872 SourceManager& manager = instance_.getSourceManager(); |
| 1836 FullSourceLoc full_loc(loc, manager); | 1873 FullSourceLoc full_loc(loc, manager); |
| 1837 bool only_warnings = options_.warn_raw_ptr; | 1874 bool only_warnings = options_.warn_raw_ptr; |
| 1838 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); | 1875 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); |
| 1839 only_warnings && it != errors->end(); | 1876 only_warnings && it != errors->end(); |
| 1840 ++it) { | 1877 ++it) { |
| 1841 if (it->second != CheckFieldsVisitor::kRawPtrToGCManagedWarning) | 1878 if (!CheckFieldsVisitor::IsWarning(it->second)) |
| 1842 only_warnings = false; | 1879 only_warnings = false; |
| 1843 } | 1880 } |
| 1844 diagnostic_.Report(full_loc, only_warnings ? | 1881 diagnostic_.Report(full_loc, only_warnings ? |
| 1845 diag_class_contains_invalid_fields_warning_ : | 1882 diag_class_contains_invalid_fields_warning_ : |
| 1846 diag_class_contains_invalid_fields_) | 1883 diag_class_contains_invalid_fields_) |
| 1847 << info->record(); | 1884 << info->record(); |
| 1848 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); | 1885 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); |
| 1849 it != errors->end(); | 1886 it != errors->end(); |
| 1850 ++it) { | 1887 ++it) { |
| 1851 unsigned error; | 1888 unsigned error; |
| 1852 if (it->second == CheckFieldsVisitor::kRawPtrToGCManaged || | 1889 if (CheckFieldsVisitor::IsRawPtrError(it->second)) { |
| 1853 it->second == CheckFieldsVisitor::kRawPtrToGCManagedWarning) { | |
| 1854 error = diag_raw_ptr_to_gc_managed_class_note_; | 1890 error = diag_raw_ptr_to_gc_managed_class_note_; |
| 1891 } else if (CheckFieldsVisitor::IsReferencePtrError(it->second)) { |
| 1892 error = diag_reference_ptr_to_gc_managed_class_note_; |
| 1855 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) { | 1893 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) { |
| 1856 error = diag_ref_ptr_to_gc_managed_class_note_; | 1894 error = diag_ref_ptr_to_gc_managed_class_note_; |
| 1857 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) { | 1895 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) { |
| 1858 error = diag_own_ptr_to_gc_managed_class_note_; | 1896 error = diag_own_ptr_to_gc_managed_class_note_; |
| 1859 } else if (it->second == CheckFieldsVisitor::kMemberToGCUnmanaged) { | 1897 } else if (it->second == CheckFieldsVisitor::kMemberToGCUnmanaged) { |
| 1860 error = diag_member_to_gc_unmanaged_class_note_; | 1898 error = diag_member_to_gc_unmanaged_class_note_; |
| 1861 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) { | 1899 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) { |
| 1862 error = diag_member_in_unmanaged_class_note_; | 1900 error = diag_member_in_unmanaged_class_note_; |
| 1863 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) { | 1901 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) { |
| 1864 error = diag_stack_allocated_field_note_; | 1902 error = diag_stack_allocated_field_note_; |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2129 unsigned diag_class_overrides_new_; | 2167 unsigned diag_class_overrides_new_; |
| 2130 unsigned diag_class_declares_pure_virtual_trace_; | 2168 unsigned diag_class_declares_pure_virtual_trace_; |
| 2131 unsigned diag_left_most_base_must_be_polymorphic_; | 2169 unsigned diag_left_most_base_must_be_polymorphic_; |
| 2132 unsigned diag_base_class_must_declare_virtual_trace_; | 2170 unsigned diag_base_class_must_declare_virtual_trace_; |
| 2133 unsigned diag_class_must_declare_gc_mixin_trace_method_; | 2171 unsigned diag_class_must_declare_gc_mixin_trace_method_; |
| 2134 | 2172 |
| 2135 unsigned diag_base_requires_tracing_note_; | 2173 unsigned diag_base_requires_tracing_note_; |
| 2136 unsigned diag_field_requires_tracing_note_; | 2174 unsigned diag_field_requires_tracing_note_; |
| 2137 unsigned diag_raw_ptr_to_gc_managed_class_note_; | 2175 unsigned diag_raw_ptr_to_gc_managed_class_note_; |
| 2138 unsigned diag_ref_ptr_to_gc_managed_class_note_; | 2176 unsigned diag_ref_ptr_to_gc_managed_class_note_; |
| 2177 unsigned diag_reference_ptr_to_gc_managed_class_note_; |
| 2139 unsigned diag_own_ptr_to_gc_managed_class_note_; | 2178 unsigned diag_own_ptr_to_gc_managed_class_note_; |
| 2140 unsigned diag_member_to_gc_unmanaged_class_note_; | 2179 unsigned diag_member_to_gc_unmanaged_class_note_; |
| 2141 unsigned diag_stack_allocated_field_note_; | 2180 unsigned diag_stack_allocated_field_note_; |
| 2142 unsigned diag_member_in_unmanaged_class_note_; | 2181 unsigned diag_member_in_unmanaged_class_note_; |
| 2143 unsigned diag_part_object_to_gc_derived_class_note_; | 2182 unsigned diag_part_object_to_gc_derived_class_note_; |
| 2144 unsigned diag_part_object_contains_gc_root_note_; | 2183 unsigned diag_part_object_contains_gc_root_note_; |
| 2145 unsigned diag_field_contains_gc_root_note_; | 2184 unsigned diag_field_contains_gc_root_note_; |
| 2146 unsigned diag_finalized_field_note_; | 2185 unsigned diag_finalized_field_note_; |
| 2147 unsigned diag_eagerly_finalized_field_note_; | 2186 unsigned diag_eagerly_finalized_field_note_; |
| 2148 unsigned diag_user_declared_destructor_note_; | 2187 unsigned diag_user_declared_destructor_note_; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2195 | 2234 |
| 2196 private: | 2235 private: |
| 2197 BlinkGCPluginOptions options_; | 2236 BlinkGCPluginOptions options_; |
| 2198 }; | 2237 }; |
| 2199 | 2238 |
| 2200 } // namespace | 2239 } // namespace |
| 2201 | 2240 |
| 2202 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 2241 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
| 2203 "blink-gc-plugin", | 2242 "blink-gc-plugin", |
| 2204 "Check Blink GC invariants"); | 2243 "Check Blink GC invariants"); |
| OLD | NEW |