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 |