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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 kOwnPtrToGCManagedClassNote[] = | 71 const char kOwnPtrToGCManagedClassNote[] = |
72 "[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:"; |
73 | 73 |
| 74 const char kMemberToGCUnmanagedClassNote[] = |
| 75 "[blink-gc] Member field %0 to non-GC managed class declared here:"; |
| 76 |
74 const char kStackAllocatedFieldNote[] = | 77 const char kStackAllocatedFieldNote[] = |
75 "[blink-gc] Stack-allocated field %0 declared here:"; | 78 "[blink-gc] Stack-allocated field %0 declared here:"; |
76 | 79 |
77 const char kMemberInUnmanagedClassNote[] = | 80 const char kMemberInUnmanagedClassNote[] = |
78 "[blink-gc] Member field %0 in unmanaged class declared here:"; | 81 "[blink-gc] Member field %0 in unmanaged class declared here:"; |
79 | 82 |
80 const char kPartObjectToGCDerivedClassNote[] = | 83 const char kPartObjectToGCDerivedClassNote[] = |
81 "[blink-gc] Part-object field %0 to a GC derived class declared here:"; | 84 "[blink-gc] Part-object field %0 to a GC derived class declared here:"; |
82 | 85 |
83 const char kPartObjectContainsGCRootNote[] = | 86 const char kPartObjectContainsGCRootNote[] = |
(...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
844 // - An on-heap class must never contain GC roots. | 847 // - An on-heap class must never contain GC roots. |
845 // - Only stack-allocated types may point to stack-allocated types. | 848 // - Only stack-allocated types may point to stack-allocated types. |
846 class CheckFieldsVisitor : public RecursiveEdgeVisitor { | 849 class CheckFieldsVisitor : public RecursiveEdgeVisitor { |
847 public: | 850 public: |
848 | 851 |
849 enum Error { | 852 enum Error { |
850 kRawPtrToGCManaged, | 853 kRawPtrToGCManaged, |
851 kRawPtrToGCManagedWarning, | 854 kRawPtrToGCManagedWarning, |
852 kRefPtrToGCManaged, | 855 kRefPtrToGCManaged, |
853 kOwnPtrToGCManaged, | 856 kOwnPtrToGCManaged, |
| 857 kMemberToGCUnmanaged, |
854 kMemberInUnmanaged, | 858 kMemberInUnmanaged, |
855 kPtrFromHeapToStack, | 859 kPtrFromHeapToStack, |
856 kGCDerivedPartObject | 860 kGCDerivedPartObject |
857 }; | 861 }; |
858 | 862 |
859 typedef std::vector<std::pair<FieldPoint*, Error> > Errors; | 863 typedef std::vector<std::pair<FieldPoint*, Error> > Errors; |
860 | 864 |
861 CheckFieldsVisitor(const BlinkGCPluginOptions& options) | 865 CheckFieldsVisitor(const BlinkGCPluginOptions& options) |
862 : options_(options), current_(0), stack_allocated_host_(false) {} | 866 : options_(options), current_(0), stack_allocated_host_(false) {} |
863 | 867 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
902 return; | 906 return; |
903 } | 907 } |
904 | 908 |
905 if (!Parent() && | 909 if (!Parent() && |
906 edge->value()->IsGCDerived() && | 910 edge->value()->IsGCDerived() && |
907 !edge->value()->IsGCMixin()) { | 911 !edge->value()->IsGCMixin()) { |
908 invalid_fields_.push_back(std::make_pair(current_, kGCDerivedPartObject)); | 912 invalid_fields_.push_back(std::make_pair(current_, kGCDerivedPartObject)); |
909 return; | 913 return; |
910 } | 914 } |
911 | 915 |
| 916 // If in a stack allocated context, be fairly insistent that T in Member<T> |
| 917 // is GC allocated, as stack allocated objects do not have a trace() |
| 918 // that separately verifies the validity of Member<T>. |
| 919 // |
| 920 // Notice that an error is only reported if T's definition is in scope; |
| 921 // we do not require that it must be brought into scope as that would |
| 922 // prevent declarations of mutually dependent class types. |
| 923 // |
| 924 // (Note: Member<>'s constructor will at run-time verify that the |
| 925 // pointer it wraps is indeed heap allocated.) |
| 926 if (stack_allocated_host_ && Parent() && Parent()->IsMember() && |
| 927 edge->value()->HasDefinition() && !edge->value()->IsGCAllocated()) { |
| 928 invalid_fields_.push_back(std::make_pair(current_, |
| 929 kMemberToGCUnmanaged)); |
| 930 return; |
| 931 } |
| 932 |
912 if (!Parent() || !edge->value()->IsGCAllocated()) | 933 if (!Parent() || !edge->value()->IsGCAllocated()) |
913 return; | 934 return; |
914 | 935 |
915 // In transition mode, disallow OwnPtr<T>, RawPtr<T> to GC allocated T's, | 936 // In transition mode, disallow OwnPtr<T>, RawPtr<T> to GC allocated T's, |
916 // also disallow T* in stack-allocated types. | 937 // also disallow T* in stack-allocated types. |
917 if (options_.enable_oilpan) { | 938 if (options_.enable_oilpan) { |
918 if (Parent()->IsOwnPtr() || | 939 if (Parent()->IsOwnPtr() || |
919 Parent()->IsRawPtrClass() || | 940 Parent()->IsRawPtrClass() || |
920 (stack_allocated_host_ && Parent()->IsRawPtr())) { | 941 (stack_allocated_host_ && Parent()->IsRawPtr())) { |
921 invalid_fields_.push_back(std::make_pair( | 942 invalid_fields_.push_back(std::make_pair( |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1052 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 1073 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
1053 DiagnosticsEngine::Note, kBaseRequiresTracingNote); | 1074 DiagnosticsEngine::Note, kBaseRequiresTracingNote); |
1054 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 1075 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
1055 DiagnosticsEngine::Note, kFieldRequiresTracingNote); | 1076 DiagnosticsEngine::Note, kFieldRequiresTracingNote); |
1056 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1077 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
1057 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); | 1078 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); |
1058 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1079 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
1059 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); | 1080 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); |
1060 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1081 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
1061 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); | 1082 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); |
| 1083 diag_member_to_gc_unmanaged_class_note_ = diagnostic_.getCustomDiagID( |
| 1084 DiagnosticsEngine::Note, kMemberToGCUnmanagedClassNote); |
1062 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID( | 1085 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID( |
1063 DiagnosticsEngine::Note, kStackAllocatedFieldNote); | 1086 DiagnosticsEngine::Note, kStackAllocatedFieldNote); |
1064 diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID( | 1087 diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID( |
1065 DiagnosticsEngine::Note, kMemberInUnmanagedClassNote); | 1088 DiagnosticsEngine::Note, kMemberInUnmanagedClassNote); |
1066 diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID( | 1089 diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID( |
1067 DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote); | 1090 DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote); |
1068 diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID( | 1091 diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID( |
1069 DiagnosticsEngine::Note, kPartObjectContainsGCRootNote); | 1092 DiagnosticsEngine::Note, kPartObjectContainsGCRootNote); |
1070 diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID( | 1093 diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID( |
1071 DiagnosticsEngine::Note, kFieldContainsGCRootNote); | 1094 DiagnosticsEngine::Note, kFieldContainsGCRootNote); |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1825 it != errors->end(); | 1848 it != errors->end(); |
1826 ++it) { | 1849 ++it) { |
1827 unsigned error; | 1850 unsigned error; |
1828 if (it->second == CheckFieldsVisitor::kRawPtrToGCManaged || | 1851 if (it->second == CheckFieldsVisitor::kRawPtrToGCManaged || |
1829 it->second == CheckFieldsVisitor::kRawPtrToGCManagedWarning) { | 1852 it->second == CheckFieldsVisitor::kRawPtrToGCManagedWarning) { |
1830 error = diag_raw_ptr_to_gc_managed_class_note_; | 1853 error = diag_raw_ptr_to_gc_managed_class_note_; |
1831 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) { | 1854 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) { |
1832 error = diag_ref_ptr_to_gc_managed_class_note_; | 1855 error = diag_ref_ptr_to_gc_managed_class_note_; |
1833 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) { | 1856 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) { |
1834 error = diag_own_ptr_to_gc_managed_class_note_; | 1857 error = diag_own_ptr_to_gc_managed_class_note_; |
| 1858 } else if (it->second == CheckFieldsVisitor::kMemberToGCUnmanaged) { |
| 1859 error = diag_member_to_gc_unmanaged_class_note_; |
1835 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) { | 1860 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) { |
1836 error = diag_member_in_unmanaged_class_note_; | 1861 error = diag_member_in_unmanaged_class_note_; |
1837 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) { | 1862 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) { |
1838 error = diag_stack_allocated_field_note_; | 1863 error = diag_stack_allocated_field_note_; |
1839 } else if (it->second == CheckFieldsVisitor::kGCDerivedPartObject) { | 1864 } else if (it->second == CheckFieldsVisitor::kGCDerivedPartObject) { |
1840 error = diag_part_object_to_gc_derived_class_note_; | 1865 error = diag_part_object_to_gc_derived_class_note_; |
1841 } else { | 1866 } else { |
1842 assert(false && "Unknown field error"); | 1867 assert(false && "Unknown field error"); |
1843 } | 1868 } |
1844 NoteField(it->first, error); | 1869 NoteField(it->first, error); |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2101 unsigned diag_missing_finalize_dispatch_; | 2126 unsigned diag_missing_finalize_dispatch_; |
2102 unsigned diag_derives_non_stack_allocated_; | 2127 unsigned diag_derives_non_stack_allocated_; |
2103 unsigned diag_class_overrides_new_; | 2128 unsigned diag_class_overrides_new_; |
2104 unsigned diag_class_declares_pure_virtual_trace_; | 2129 unsigned diag_class_declares_pure_virtual_trace_; |
2105 unsigned diag_left_most_base_must_be_polymorphic_; | 2130 unsigned diag_left_most_base_must_be_polymorphic_; |
2106 unsigned diag_base_class_must_declare_virtual_trace_; | 2131 unsigned diag_base_class_must_declare_virtual_trace_; |
2107 unsigned diag_class_must_declare_gc_mixin_trace_method_; | 2132 unsigned diag_class_must_declare_gc_mixin_trace_method_; |
2108 | 2133 |
2109 unsigned diag_base_requires_tracing_note_; | 2134 unsigned diag_base_requires_tracing_note_; |
2110 unsigned diag_field_requires_tracing_note_; | 2135 unsigned diag_field_requires_tracing_note_; |
2111 unsigned diag_field_illegally_traced_note_; | |
2112 unsigned diag_raw_ptr_to_gc_managed_class_note_; | 2136 unsigned diag_raw_ptr_to_gc_managed_class_note_; |
2113 unsigned diag_ref_ptr_to_gc_managed_class_note_; | 2137 unsigned diag_ref_ptr_to_gc_managed_class_note_; |
2114 unsigned diag_own_ptr_to_gc_managed_class_note_; | 2138 unsigned diag_own_ptr_to_gc_managed_class_note_; |
| 2139 unsigned diag_member_to_gc_unmanaged_class_note_; |
2115 unsigned diag_stack_allocated_field_note_; | 2140 unsigned diag_stack_allocated_field_note_; |
2116 unsigned diag_member_in_unmanaged_class_note_; | 2141 unsigned diag_member_in_unmanaged_class_note_; |
2117 unsigned diag_part_object_to_gc_derived_class_note_; | 2142 unsigned diag_part_object_to_gc_derived_class_note_; |
2118 unsigned diag_part_object_contains_gc_root_note_; | 2143 unsigned diag_part_object_contains_gc_root_note_; |
2119 unsigned diag_field_contains_gc_root_note_; | 2144 unsigned diag_field_contains_gc_root_note_; |
2120 unsigned diag_finalized_field_note_; | 2145 unsigned diag_finalized_field_note_; |
2121 unsigned diag_eagerly_finalized_field_note_; | 2146 unsigned diag_eagerly_finalized_field_note_; |
2122 unsigned diag_user_declared_destructor_note_; | 2147 unsigned diag_user_declared_destructor_note_; |
2123 unsigned diag_user_declared_finalizer_note_; | 2148 unsigned diag_user_declared_finalizer_note_; |
2124 unsigned diag_base_requires_finalization_note_; | 2149 unsigned diag_base_requires_finalization_note_; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2169 | 2194 |
2170 private: | 2195 private: |
2171 BlinkGCPluginOptions options_; | 2196 BlinkGCPluginOptions options_; |
2172 }; | 2197 }; |
2173 | 2198 |
2174 } // namespace | 2199 } // namespace |
2175 | 2200 |
2176 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 2201 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
2177 "blink-gc-plugin", | 2202 "blink-gc-plugin", |
2178 "Check Blink GC invariants"); | 2203 "Check Blink GC invariants"); |
OLD | NEW |