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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 } | 111 } |
112 } | 112 } |
113 cids->Add(ifc.id()); | 113 cids->Add(ifc.id()); |
114 } | 114 } |
115 } | 115 } |
116 | 116 |
117 | 117 |
118 // Processing ObjectStore::pending_classes_ occurs: | 118 // Processing ObjectStore::pending_classes_ occurs: |
119 // a) when bootstrap process completes (VerifyBootstrapClasses). | 119 // a) when bootstrap process completes (VerifyBootstrapClasses). |
120 // b) after the user classes are loaded (dart_api). | 120 // b) after the user classes are loaded (dart_api). |
121 bool ClassFinalizer::ProcessPendingClasses() { | 121 bool ClassFinalizer::ProcessPendingClasses(bool from_kernel) { |
122 Thread* thread = Thread::Current(); | 122 Thread* thread = Thread::Current(); |
123 NOT_IN_PRODUCT(TimelineDurationScope tds(thread, Timeline::GetIsolateStream(), | 123 NOT_IN_PRODUCT(TimelineDurationScope tds(thread, Timeline::GetIsolateStream(), |
124 "ProcessPendingClasses")); | 124 "ProcessPendingClasses")); |
125 Isolate* isolate = thread->isolate(); | 125 Isolate* isolate = thread->isolate(); |
126 ASSERT(isolate != NULL); | 126 ASSERT(isolate != NULL); |
127 HANDLESCOPE(thread); | 127 HANDLESCOPE(thread); |
128 ObjectStore* object_store = isolate->object_store(); | 128 ObjectStore* object_store = isolate->object_store(); |
129 const Error& error = Error::Handle(thread->zone(), thread->sticky_error()); | 129 const Error& error = Error::Handle(thread->zone(), thread->sticky_error()); |
130 if (!error.IsNull()) { | 130 if (!error.IsNull()) { |
131 return false; | 131 return false; |
(...skipping 11 matching lines...) Expand all Loading... |
143 // First resolve all superclasses. | 143 // First resolve all superclasses. |
144 for (intptr_t i = 0; i < class_array.Length(); i++) { | 144 for (intptr_t i = 0; i < class_array.Length(); i++) { |
145 cls ^= class_array.At(i); | 145 cls ^= class_array.At(i); |
146 GrowableArray<intptr_t> visited_interfaces; | 146 GrowableArray<intptr_t> visited_interfaces; |
147 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); | 147 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); |
148 } | 148 } |
149 // Finalize all classes. | 149 // Finalize all classes. |
150 for (intptr_t i = 0; i < class_array.Length(); i++) { | 150 for (intptr_t i = 0; i < class_array.Length(); i++) { |
151 cls ^= class_array.At(i); | 151 cls ^= class_array.At(i); |
152 FinalizeTypesInClass(cls); | 152 FinalizeTypesInClass(cls); |
| 153 // Classes compiled from Dart sources are finalized more lazily, classes |
| 154 // compiled from Kernel binaries can be finalized now (and should be, |
| 155 // since we will not revisit them). |
| 156 if (from_kernel) { |
| 157 FinalizeClass(cls); |
| 158 } |
153 } | 159 } |
154 if (FLAG_print_classes) { | 160 if (FLAG_print_classes) { |
155 for (intptr_t i = 0; i < class_array.Length(); i++) { | 161 for (intptr_t i = 0; i < class_array.Length(); i++) { |
156 cls ^= class_array.At(i); | 162 cls ^= class_array.At(i); |
157 PrintClassInformation(cls); | 163 PrintClassInformation(cls); |
158 } | 164 } |
159 } | 165 } |
160 // Clear pending classes array. | 166 // Clear pending classes array. |
161 class_array = GrowableObjectArray::New(); | 167 class_array = GrowableObjectArray::New(); |
162 object_store->set_pending_classes(class_array); | 168 object_store->set_pending_classes(class_array); |
(...skipping 18 matching lines...) Expand all Loading... |
181 Class& interface_class = Class::Handle(zone); | 187 Class& interface_class = Class::Handle(zone); |
182 for (intptr_t i = 0; i < interface_array.Length(); i++) { | 188 for (intptr_t i = 0; i < interface_array.Length(); i++) { |
183 interface ^= interface_array.At(i); | 189 interface ^= interface_array.At(i); |
184 interface_class = interface.type_class(); | 190 interface_class = interface.type_class(); |
185 collected->Add(&Class::ZoneHandle(zone, interface_class.raw())); | 191 collected->Add(&Class::ZoneHandle(zone, interface_class.raw())); |
186 CollectInterfaces(interface_class, collected); | 192 CollectInterfaces(interface_class, collected); |
187 } | 193 } |
188 } | 194 } |
189 | 195 |
190 | 196 |
191 #if defined(DART_NO_SNAPSHOT) | 197 #if !defined(DART_PRECOMPILED_RUNTIME) |
192 void ClassFinalizer::VerifyBootstrapClasses() { | 198 void ClassFinalizer::VerifyBootstrapClasses() { |
193 if (FLAG_trace_class_finalization) { | 199 if (FLAG_trace_class_finalization) { |
194 OS::Print("VerifyBootstrapClasses START.\n"); | 200 OS::Print("VerifyBootstrapClasses START.\n"); |
195 } | 201 } |
196 ObjectStore* object_store = Isolate::Current()->object_store(); | 202 ObjectStore* object_store = Isolate::Current()->object_store(); |
197 | 203 |
198 Class& cls = Class::Handle(); | 204 Class& cls = Class::Handle(); |
199 #if defined(DEBUG) | 205 #if defined(DEBUG) |
200 // Basic checking. | 206 // Basic checking. |
201 cls = object_store->object_class(); | 207 cls = object_store->object_class(); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 const Error& err = Error::Handle(Thread::Current()->sticky_error()); | 253 const Error& err = Error::Handle(Thread::Current()->sticky_error()); |
248 OS::PrintErr("Could not verify bootstrap classes : %s\n", | 254 OS::PrintErr("Could not verify bootstrap classes : %s\n", |
249 err.ToErrorCString()); | 255 err.ToErrorCString()); |
250 OS::Exit(255); | 256 OS::Exit(255); |
251 } | 257 } |
252 if (FLAG_trace_class_finalization) { | 258 if (FLAG_trace_class_finalization) { |
253 OS::Print("VerifyBootstrapClasses END.\n"); | 259 OS::Print("VerifyBootstrapClasses END.\n"); |
254 } | 260 } |
255 Isolate::Current()->heap()->Verify(); | 261 Isolate::Current()->heap()->Verify(); |
256 } | 262 } |
257 #endif // defined(DART_NO_SNAPSHOT). | 263 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
258 | 264 |
259 | 265 |
260 static bool IsLoaded(const Type& type) { | 266 static bool IsLoaded(const Type& type) { |
261 if (type.HasResolvedTypeClass()) { | 267 if (type.HasResolvedTypeClass()) { |
262 return true; | 268 return true; |
263 } | 269 } |
264 const UnresolvedClass& unresolved_class = | 270 const UnresolvedClass& unresolved_class = |
265 UnresolvedClass::Handle(type.unresolved_class()); | 271 UnresolvedClass::Handle(type.unresolved_class()); |
266 const LibraryPrefix& prefix = | 272 const Object& prefix = |
267 LibraryPrefix::Handle(unresolved_class.library_prefix()); | 273 Object::Handle(unresolved_class.library_or_library_prefix()); |
268 return prefix.IsNull() || prefix.is_loaded(); | 274 if (prefix.IsNull()) { |
| 275 return true; |
| 276 } else if (prefix.IsLibraryPrefix()) { |
| 277 return LibraryPrefix::Cast(prefix).is_loaded(); |
| 278 } else { |
| 279 return true; |
| 280 } |
269 } | 281 } |
270 | 282 |
271 | 283 |
272 // Resolve unresolved_class in the library of cls, or return null. | 284 // Resolve unresolved_class in the library of cls, or return null. |
273 RawClass* ClassFinalizer::ResolveClass( | 285 RawClass* ClassFinalizer::ResolveClass( |
274 const Class& cls, | 286 const Class& cls, |
275 const UnresolvedClass& unresolved_class) { | 287 const UnresolvedClass& unresolved_class) { |
276 const String& class_name = String::Handle(unresolved_class.ident()); | 288 const String& class_name = String::Handle(unresolved_class.ident()); |
277 Library& lib = Library::Handle(); | 289 Library& lib = Library::Handle(); |
278 Class& resolved_class = Class::Handle(); | 290 Class& resolved_class = Class::Handle(); |
279 if (unresolved_class.library_prefix() == LibraryPrefix::null()) { | 291 if (unresolved_class.library_or_library_prefix() == Object::null()) { |
280 lib = cls.library(); | 292 lib = cls.library(); |
281 ASSERT(!lib.IsNull()); | 293 ASSERT(!lib.IsNull()); |
282 resolved_class = lib.LookupClass(class_name); | 294 resolved_class = lib.LookupClass(class_name); |
283 } else { | 295 } else { |
284 LibraryPrefix& lib_prefix = LibraryPrefix::Handle(); | 296 const Object& prefix = |
285 lib_prefix = unresolved_class.library_prefix(); | 297 Object::Handle(unresolved_class.library_or_library_prefix()); |
286 ASSERT(!lib_prefix.IsNull()); | 298 |
287 resolved_class = lib_prefix.LookupClass(class_name); | 299 if (prefix.IsLibraryPrefix()) { |
| 300 resolved_class = LibraryPrefix::Cast(prefix).LookupClass(class_name); |
| 301 } else { |
| 302 resolved_class = Library::Cast(prefix).LookupClass(class_name); |
| 303 } |
288 } | 304 } |
289 return resolved_class.raw(); | 305 return resolved_class.raw(); |
290 } | 306 } |
291 | 307 |
292 | 308 |
293 void ClassFinalizer::ResolveRedirectingFactory(const Class& cls, | 309 void ClassFinalizer::ResolveRedirectingFactory(const Class& cls, |
294 const Function& factory) { | 310 const Function& factory) { |
295 const Function& target = Function::Handle(factory.RedirectionTarget()); | 311 const Function& target = Function::Handle(factory.RedirectionTarget()); |
296 if (target.IsNull()) { | 312 if (target.IsNull()) { |
297 Type& type = Type::Handle(factory.RedirectionType()); | 313 Type& type = Type::Handle(factory.RedirectionType()); |
(...skipping 1884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2182 | 2198 |
2183 if (FLAG_trace_class_finalization) { | 2199 if (FLAG_trace_class_finalization) { |
2184 THR_Print("Applying mixin members of %s to %s at pos %s\n", | 2200 THR_Print("Applying mixin members of %s to %s at pos %s\n", |
2185 mixin_cls.ToCString(), cls.ToCString(), | 2201 mixin_cls.ToCString(), cls.ToCString(), |
2186 cls.token_pos().ToCString()); | 2202 cls.token_pos().ToCString()); |
2187 } | 2203 } |
2188 | 2204 |
2189 const GrowableObjectArray& cloned_funcs = | 2205 const GrowableObjectArray& cloned_funcs = |
2190 GrowableObjectArray::Handle(zone, GrowableObjectArray::New()); | 2206 GrowableObjectArray::Handle(zone, GrowableObjectArray::New()); |
2191 | 2207 |
2192 CreateForwardingConstructors(cls, mixin_cls, cloned_funcs); | |
2193 | |
2194 Array& functions = Array::Handle(zone); | 2208 Array& functions = Array::Handle(zone); |
2195 Function& func = Function::Handle(zone); | 2209 Function& func = Function::Handle(zone); |
| 2210 |
2196 // The parser creates the mixin application class with no functions. | 2211 // The parser creates the mixin application class with no functions. |
2197 ASSERT((functions = cls.functions(), functions.Length() == 0)); | 2212 // But the Kernel frontend will generate mixin classes with only |
| 2213 // constructors inside them, which forward to the base class constructors. |
| 2214 // |
| 2215 // => We generate the constructors if they are not already there. |
| 2216 functions = cls.functions(); |
| 2217 if (functions.Length() == 0) { |
| 2218 CreateForwardingConstructors(cls, mixin_cls, cloned_funcs); |
| 2219 } else { |
| 2220 for (intptr_t i = 0; i < functions.Length(); i++) { |
| 2221 func ^= functions.At(i); |
| 2222 ASSERT(func.kernel_function() != 0); |
| 2223 cloned_funcs.Add(func); |
| 2224 } |
| 2225 } |
| 2226 |
2198 // Now clone the functions from the mixin class. | 2227 // Now clone the functions from the mixin class. |
2199 functions = mixin_cls.functions(); | 2228 functions = mixin_cls.functions(); |
2200 const intptr_t num_functions = functions.Length(); | 2229 const intptr_t num_functions = functions.Length(); |
2201 for (intptr_t i = 0; i < num_functions; i++) { | 2230 for (intptr_t i = 0; i < num_functions; i++) { |
2202 func ^= functions.At(i); | 2231 func ^= functions.At(i); |
2203 if (func.IsGenerativeConstructor()) { | 2232 if (func.IsGenerativeConstructor()) { |
2204 // A mixin class must not have explicit constructors. | 2233 // A mixin class must not have explicit constructors. |
2205 if (!func.IsImplicitConstructor()) { | 2234 if (!func.IsImplicitConstructor()) { |
2206 const Script& script = Script::Handle(cls.script()); | 2235 const Script& script = Script::Handle(cls.script()); |
2207 const Error& error = Error::Handle(LanguageError::NewFormatted( | 2236 const Error& error = Error::Handle(LanguageError::NewFormatted( |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2377 } else { | 2406 } else { |
2378 // This class should not contain any functions or user-defined fields yet, | 2407 // This class should not contain any functions or user-defined fields yet, |
2379 // because it has not been compiled yet. There may however be metadata | 2408 // because it has not been compiled yet. There may however be metadata |
2380 // fields because type parameters are parsed before the class body. Since | 2409 // fields because type parameters are parsed before the class body. Since |
2381 // 'ResolveAndFinalizeMemberTypes(cls)' has not been called yet, unfinalized | 2410 // 'ResolveAndFinalizeMemberTypes(cls)' has not been called yet, unfinalized |
2382 // member types could choke the snapshotter. | 2411 // member types could choke the snapshotter. |
2383 // Or | 2412 // Or |
2384 // if the class is being refinalized because a patch is being applied | 2413 // if the class is being refinalized because a patch is being applied |
2385 // after the class has been finalized then it is ok for the class to have | 2414 // after the class has been finalized then it is ok for the class to have |
2386 // functions. | 2415 // functions. |
2387 ASSERT((Array::Handle(cls.functions()).Length() == 0) || | 2416 // |
2388 cls.is_refinalize_after_patch()); | 2417 // TODO(kmillikin): This ASSERT will fail when bootstrapping from Kernel |
| 2418 // because classes are first created, methods are added, and then classes |
| 2419 // are finalized. It is not easy to finalize classes earlier because not |
| 2420 // all bootstrap classes have been created yet. It would be possible to |
| 2421 // create all classes, delay adding methods, finalize the classes, and then |
| 2422 // reprocess all classes to add methods, but that seems unnecessary. |
| 2423 // Marking the bootstrap classes as is_refinalize_after_patch seems cute but |
| 2424 // it causes other things to fail by violating their assumptions. Reenable |
| 2425 // this ASSERT if it's important, remove it if it's just a sanity check and |
| 2426 // not required for correctness. |
| 2427 // |
| 2428 // ASSERT((Array::Handle(cls.functions()).Length() == 0) || |
| 2429 // cls.is_refinalize_after_patch()); |
2389 } | 2430 } |
2390 } | 2431 } |
2391 | 2432 |
2392 | 2433 |
2393 void ClassFinalizer::FinalizeClass(const Class& cls) { | 2434 void ClassFinalizer::FinalizeClass(const Class& cls) { |
2394 Thread* thread = Thread::Current(); | 2435 Thread* thread = Thread::Current(); |
2395 HANDLESCOPE(thread); | 2436 HANDLESCOPE(thread); |
2396 ASSERT(cls.is_type_finalized()); | 2437 ASSERT(cls.is_type_finalized()); |
2397 if (cls.is_finalized()) { | 2438 if (cls.is_finalized()) { |
2398 return; | 2439 return; |
(...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3267 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); | 3308 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); |
3268 field ^= fields_array.At(0); | 3309 field ^= fields_array.At(0); |
3269 ASSERT(field.Offset() == ByteBuffer::data_offset()); | 3310 ASSERT(field.Offset() == ByteBuffer::data_offset()); |
3270 name ^= field.name(); | 3311 name ^= field.name(); |
3271 expected_name ^= String::New("_data"); | 3312 expected_name ^= String::New("_data"); |
3272 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 3313 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
3273 #endif | 3314 #endif |
3274 } | 3315 } |
3275 | 3316 |
3276 } // namespace dart | 3317 } // namespace dart |
OLD | NEW |