OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/class_finalizer.h" | 5 #include "vm/class_finalizer.h" |
6 | 6 |
7 #include "vm/code_generator.h" | 7 #include "vm/code_generator.h" |
8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
9 #include "vm/heap.h" | 9 #include "vm/heap.h" |
10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 } | 82 } |
83 finalized_super_classes->Add(cid); | 83 finalized_super_classes->Add(cid); |
84 const AbstractType& super_type = AbstractType::Handle(cls.super_type()); | 84 const AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
85 AddSuperType(super_type, finalized_super_classes); | 85 AddSuperType(super_type, finalized_super_classes); |
86 } | 86 } |
87 | 87 |
88 | 88 |
89 // Use array instead of set since we expect very few subclassed classes | 89 // Use array instead of set since we expect very few subclassed classes |
90 // to occur. | 90 // to occur. |
91 static void CollectFinalizedSuperClasses( | 91 static void CollectFinalizedSuperClasses( |
92 const GrowableObjectArray& pending_classes, | 92 const Class& cls_, GrowableArray<intptr_t>* finalized_super_classes) { |
93 GrowableArray<intptr_t>* finalized_super_classes) { | 93 Class& cls = Class::Handle(cls_.raw()); |
94 Class& cls = Class::Handle(); | |
95 AbstractType& super_type = Type::Handle(); | 94 AbstractType& super_type = Type::Handle(); |
96 for (intptr_t i = 0; i < pending_classes.Length(); i++) { | 95 super_type = cls.super_type(); |
97 cls ^= pending_classes.At(i); | 96 if (!super_type.IsNull()) { |
98 ASSERT(!cls.is_finalized()); | 97 if (!super_type.IsMalformed() && super_type.HasResolvedTypeClass()) { |
99 super_type = cls.super_type(); | 98 cls ^= super_type.type_class(); |
100 if (!super_type.IsNull()) { | 99 if (cls.is_finalized()) { |
101 if (!super_type.IsMalformed() && super_type.HasResolvedTypeClass()) { | 100 AddSuperType(super_type, finalized_super_classes); |
102 cls ^= super_type.type_class(); | |
103 if (cls.is_finalized()) { | |
104 AddSuperType(super_type, finalized_super_classes); | |
105 } | |
106 } | 101 } |
107 } | 102 } |
108 } | 103 } |
109 } | 104 } |
110 | 105 |
111 | 106 |
112 // Class finalization occurs: | 107 // Class finalization occurs: |
113 // a) when bootstrap process completes (VerifyBootstrapClasses). | 108 // a) when bootstrap process completes (VerifyBootstrapClasses). |
114 // b) after the user classes are loaded (dart_api). | 109 // b) after the user classes are loaded (dart_api). |
115 bool ClassFinalizer::FinalizePendingClasses() { | 110 bool ClassFinalizer::FinalizePendingClassInterfaces() { |
Ivan Posva
2013/11/21 23:04:09
This is not finalizing the class's interface. Actu
srdjan
2013/11/22 00:08:14
Renaming to FinalizeTypeHierarchy
| |
116 bool retval = true; | 111 bool retval = true; |
117 Isolate* isolate = Isolate::Current(); | 112 Isolate* isolate = Isolate::Current(); |
118 ASSERT(isolate != NULL); | 113 ASSERT(isolate != NULL); |
119 HANDLESCOPE(isolate); | 114 HANDLESCOPE(isolate); |
120 ObjectStore* object_store = isolate->object_store(); | 115 ObjectStore* object_store = isolate->object_store(); |
121 const Error& error = Error::Handle(isolate, object_store->sticky_error()); | 116 const Error& error = Error::Handle(isolate, object_store->sticky_error()); |
122 if (!error.IsNull()) { | 117 if (!error.IsNull()) { |
123 return false; | 118 return false; |
124 } | 119 } |
125 if (AllClassesFinalized()) { | 120 if (AllClassesFinalized()) { |
126 return true; | 121 return true; |
127 } | 122 } |
128 | 123 |
129 GrowableArray<intptr_t> added_subclasses_to_cids; | |
130 LongJump* base = isolate->long_jump_base(); | 124 LongJump* base = isolate->long_jump_base(); |
131 LongJump jump; | 125 LongJump jump; |
132 isolate->set_long_jump_base(&jump); | 126 isolate->set_long_jump_base(&jump); |
133 if (setjmp(*jump.Set()) == 0) { | 127 if (setjmp(*jump.Set()) == 0) { |
134 GrowableObjectArray& class_array = GrowableObjectArray::Handle(); | 128 GrowableObjectArray& class_array = GrowableObjectArray::Handle(); |
135 class_array = object_store->pending_classes(); | 129 class_array = object_store->pending_classes(); |
136 ASSERT(!class_array.IsNull()); | 130 ASSERT(!class_array.IsNull()); |
137 // Collect superclasses that were already finalized before this run of | |
138 // finalization. | |
139 CollectFinalizedSuperClasses(class_array, &added_subclasses_to_cids); | |
140 Class& cls = Class::Handle(); | 131 Class& cls = Class::Handle(); |
141 // First resolve all superclasses. | 132 // First resolve all superclasses. |
142 for (intptr_t i = 0; i < class_array.Length(); i++) { | 133 for (intptr_t i = 0; i < class_array.Length(); i++) { |
143 cls ^= class_array.At(i); | 134 cls ^= class_array.At(i); |
144 GrowableArray<intptr_t> visited_interfaces; | 135 GrowableArray<intptr_t> visited_interfaces; |
145 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); | 136 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); |
146 } | 137 } |
147 // Finalize all classes. | 138 // Finalize all classes. |
148 for (intptr_t i = 0; i < class_array.Length(); i++) { | 139 for (intptr_t i = 0; i < class_array.Length(); i++) { |
149 cls ^= class_array.At(i); | 140 cls ^= class_array.At(i); |
150 FinalizeTypesInClass(cls); | 141 FinalizeTypesInClass(cls); |
151 } | 142 } |
152 if (FLAG_print_classes) { | 143 if (FLAG_print_classes) { |
153 for (intptr_t i = 0; i < class_array.Length(); i++) { | 144 for (intptr_t i = 0; i < class_array.Length(); i++) { |
154 cls ^= class_array.At(i); | 145 cls ^= class_array.At(i); |
155 PrintClassInformation(cls); | 146 PrintClassInformation(cls); |
156 } | 147 } |
157 } | 148 } |
158 // Clear pending classes array. | 149 // Clear pending classes array. |
159 class_array = GrowableObjectArray::New(); | 150 class_array = GrowableObjectArray::New(); |
160 object_store->set_pending_classes(class_array); | 151 object_store->set_pending_classes(class_array); |
161 VerifyImplicitFieldOffsets(); // Verification after an error may fail. | 152 VerifyImplicitFieldOffsets(); // Verification after an error may fail. |
162 } else { | 153 } else { |
163 retval = false; | 154 retval = false; |
164 } | 155 } |
165 isolate->set_long_jump_base(base); | 156 isolate->set_long_jump_base(base); |
166 if (FLAG_use_cha) { | |
167 RemoveOptimizedCode(added_subclasses_to_cids); | |
168 } | |
169 return retval; | 157 return retval; |
170 } | 158 } |
171 | 159 |
172 | 160 |
173 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur. | 161 // Adds all interfaces of cls into 'collected'. Duplicate entries may occur. |
174 // No cycles are allowed. | 162 // No cycles are allowed. |
175 void ClassFinalizer::CollectInterfaces(const Class& cls, | 163 void ClassFinalizer::CollectInterfaces(const Class& cls, |
176 const GrowableObjectArray& collected) { | 164 const GrowableObjectArray& collected) { |
177 const Array& interface_array = Array::Handle(cls.interfaces()); | 165 const Array& interface_array = Array::Handle(cls.interfaces()); |
178 AbstractType& interface = AbstractType::Handle(); | 166 AbstractType& interface = AbstractType::Handle(); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
231 for (intptr_t i = 0; i < class_array.Length(); i++) { | 219 for (intptr_t i = 0; i < class_array.Length(); i++) { |
232 // TODO(iposva): Add real checks. | 220 // TODO(iposva): Add real checks. |
233 cls ^= class_array.At(i); | 221 cls ^= class_array.At(i); |
234 if (cls.is_finalized() || cls.is_prefinalized()) { | 222 if (cls.is_finalized() || cls.is_prefinalized()) { |
235 // Pre-finalized bootstrap classes must not define any fields. | 223 // Pre-finalized bootstrap classes must not define any fields. |
236 ASSERT(!cls.HasInstanceFields()); | 224 ASSERT(!cls.HasInstanceFields()); |
237 } | 225 } |
238 } | 226 } |
239 | 227 |
240 // Finalize classes that aren't pre-finalized by Object::Init(). | 228 // Finalize classes that aren't pre-finalized by Object::Init(). |
241 if (!FinalizePendingClasses()) { | 229 if (!FinalizePendingClassInterfaces()) { |
242 // TODO(srdjan): Exit like a real VM instead. | 230 // TODO(srdjan): Exit like a real VM instead. |
243 const Error& err = Error::Handle(object_store->sticky_error()); | 231 const Error& err = Error::Handle(object_store->sticky_error()); |
244 OS::PrintErr("Could not verify bootstrap classes : %s\n", | 232 OS::PrintErr("Could not verify bootstrap classes : %s\n", |
245 err.ToErrorCString()); | 233 err.ToErrorCString()); |
246 OS::Exit(255); | 234 OS::Exit(255); |
247 } | 235 } |
248 if (FLAG_trace_class_finalization) { | 236 if (FLAG_trace_class_finalization) { |
249 OS::Print("VerifyBootstrapClasses END.\n"); | 237 OS::Print("VerifyBootstrapClasses END.\n"); |
250 } | 238 } |
251 Isolate::Current()->heap()->Verify(); | 239 Isolate::Current()->heap()->Verify(); |
(...skipping 1795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2047 } | 2035 } |
2048 if (FLAG_trace_class_finalization) { | 2036 if (FLAG_trace_class_finalization) { |
2049 OS::Print("Finalize %s\n", cls.ToCString()); | 2037 OS::Print("Finalize %s\n", cls.ToCString()); |
2050 } | 2038 } |
2051 if (cls.IsMixinApplication()) { | 2039 if (cls.IsMixinApplication()) { |
2052 // Copy instance methods and fields from the mixin class. | 2040 // Copy instance methods and fields from the mixin class. |
2053 // This has to happen before the check whether the methods of | 2041 // This has to happen before the check whether the methods of |
2054 // the class conflict with inherited methods. | 2042 // the class conflict with inherited methods. |
2055 ApplyMixinMembers(cls); | 2043 ApplyMixinMembers(cls); |
2056 } | 2044 } |
2045 GrowableArray<intptr_t> added_subclasses_to_cids; | |
2046 CollectFinalizedSuperClasses(cls, &added_subclasses_to_cids); | |
2057 // Ensure super class is finalized. | 2047 // Ensure super class is finalized. |
2058 const Class& super = Class::Handle(cls.SuperClass()); | 2048 const Class& super = Class::Handle(cls.SuperClass()); |
2059 if (!super.IsNull()) { | 2049 if (!super.IsNull()) { |
2060 FinalizeClass(super); | 2050 FinalizeClass(super); |
2061 } | 2051 } |
2062 // Mark as parsed and finalized. | 2052 // Mark as parsed and finalized. |
2063 cls.Finalize(); | 2053 cls.Finalize(); |
2064 // Mixin app alias classes may still lack their forwarding constructor. | 2054 // Mixin app alias classes may still lack their forwarding constructor. |
2065 if (cls.is_mixin_app_alias() && | 2055 if (cls.is_mixin_app_alias() && |
2066 (cls.functions() == Object::empty_array().raw())) { | 2056 (cls.functions() == Object::empty_array().raw())) { |
2067 const GrowableObjectArray& cloned_funcs = | 2057 const GrowableObjectArray& cloned_funcs = |
2068 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 2058 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
2069 CreateForwardingConstructors(cls, cloned_funcs); | 2059 CreateForwardingConstructors(cls, cloned_funcs); |
2070 const Array& functions = Array::Handle(Array::MakeArray(cloned_funcs)); | 2060 const Array& functions = Array::Handle(Array::MakeArray(cloned_funcs)); |
2071 cls.SetFunctions(functions); | 2061 cls.SetFunctions(functions); |
2072 } | 2062 } |
2073 // Every class should have at least a constructor, unless it is a top level | 2063 // Every class should have at least a constructor, unless it is a top level |
2074 // class or a signature class. | 2064 // class or a signature class. |
2075 ASSERT(cls.IsTopLevel() || | 2065 ASSERT(cls.IsTopLevel() || |
2076 cls.IsSignatureClass() || | 2066 cls.IsSignatureClass() || |
2077 (Array::Handle(cls.functions()).Length() > 0)); | 2067 (Array::Handle(cls.functions()).Length() > 0)); |
2078 // Resolve and finalize all member types. | 2068 // Resolve and finalize all member types. |
2079 ResolveAndFinalizeMemberTypes(cls); | 2069 ResolveAndFinalizeMemberTypes(cls); |
2080 // Run additional checks after all types are finalized. | 2070 // Run additional checks after all types are finalized. |
2081 if (cls.is_const()) { | 2071 if (cls.is_const()) { |
2082 CheckForLegalConstClass(cls); | 2072 CheckForLegalConstClass(cls); |
2083 } | 2073 } |
2074 if (FLAG_use_cha) { | |
2075 RemoveOptimizedCode(added_subclasses_to_cids); | |
Ivan Posva
2013/11/21 23:04:09
This will add Object to the list, but Object never
srdjan
2013/11/22 00:08:14
Modified CollectFinalizedSuperClasses to exclude o
| |
2076 } | |
2084 } | 2077 } |
2085 | 2078 |
2086 | 2079 |
2087 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { | 2080 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { |
2088 Class& test1 = Class::Handle(cls.raw()); | 2081 Class& test1 = Class::Handle(cls.raw()); |
2089 Class& test2 = Class::Handle(cls.SuperClass()); | 2082 Class& test2 = Class::Handle(cls.SuperClass()); |
2090 // A finalized class has been checked for cycles. | 2083 // A finalized class has been checked for cycles. |
2091 // Using the hare and tortoise algorithm for locating cycles. | 2084 // Using the hare and tortoise algorithm for locating cycles. |
2092 while (!test1.is_type_finalized() && | 2085 while (!test1.is_type_finalized() && |
2093 !test2.IsNull() && !test2.is_type_finalized()) { | 2086 !test2.IsNull() && !test2.is_type_finalized()) { |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2761 expected_name ^= String::New("_offset"); | 2754 expected_name ^= String::New("_offset"); |
2762 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2755 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
2763 field ^= fields_array.At(2); | 2756 field ^= fields_array.At(2); |
2764 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2757 ASSERT(field.Offset() == TypedDataView::length_offset()); |
2765 name ^= field.name(); | 2758 name ^= field.name(); |
2766 ASSERT(name.Equals("length")); | 2759 ASSERT(name.Equals("length")); |
2767 #endif | 2760 #endif |
2768 } | 2761 } |
2769 | 2762 |
2770 } // namespace dart | 2763 } // namespace dart |
OLD | NEW |