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