| 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) | |
| 192 void ClassFinalizer::VerifyBootstrapClasses() { | 197 void ClassFinalizer::VerifyBootstrapClasses() { |
| 193 if (FLAG_trace_class_finalization) { | 198 if (FLAG_trace_class_finalization) { |
| 194 OS::Print("VerifyBootstrapClasses START.\n"); | 199 OS::Print("VerifyBootstrapClasses START.\n"); |
| 195 } | 200 } |
| 196 ObjectStore* object_store = Isolate::Current()->object_store(); | 201 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 197 | 202 |
| 198 Class& cls = Class::Handle(); | 203 Class& cls = Class::Handle(); |
| 199 #if defined(DEBUG) | 204 #if defined(DEBUG) |
| 200 // Basic checking. | 205 // Basic checking. |
| 201 cls = object_store->object_class(); | 206 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()); | 252 const Error& err = Error::Handle(Thread::Current()->sticky_error()); |
| 248 OS::PrintErr("Could not verify bootstrap classes : %s\n", | 253 OS::PrintErr("Could not verify bootstrap classes : %s\n", |
| 249 err.ToErrorCString()); | 254 err.ToErrorCString()); |
| 250 OS::Exit(255); | 255 OS::Exit(255); |
| 251 } | 256 } |
| 252 if (FLAG_trace_class_finalization) { | 257 if (FLAG_trace_class_finalization) { |
| 253 OS::Print("VerifyBootstrapClasses END.\n"); | 258 OS::Print("VerifyBootstrapClasses END.\n"); |
| 254 } | 259 } |
| 255 Isolate::Current()->heap()->Verify(); | 260 Isolate::Current()->heap()->Verify(); |
| 256 } | 261 } |
| 257 #endif // defined(DART_NO_SNAPSHOT). | |
| 258 | 262 |
| 259 | 263 |
| 260 static bool IsLoaded(const Type& type) { | 264 static bool IsLoaded(const Type& type) { |
| 261 if (type.HasResolvedTypeClass()) { | 265 if (type.HasResolvedTypeClass()) { |
| 262 return true; | 266 return true; |
| 263 } | 267 } |
| 264 const UnresolvedClass& unresolved_class = | 268 const UnresolvedClass& unresolved_class = |
| 265 UnresolvedClass::Handle(type.unresolved_class()); | 269 UnresolvedClass::Handle(type.unresolved_class()); |
| 266 const LibraryPrefix& prefix = | 270 const Object& prefix = |
| 267 LibraryPrefix::Handle(unresolved_class.library_prefix()); | 271 Object::Handle(unresolved_class.library_or_library_prefix()); |
| 268 return prefix.IsNull() || prefix.is_loaded(); | 272 if (prefix.IsNull()) { |
| 273 return true; |
| 274 } else if (prefix.IsLibraryPrefix()) { |
| 275 return LibraryPrefix::Cast(prefix).is_loaded(); |
| 276 } else { |
| 277 return true; |
| 278 } |
| 269 } | 279 } |
| 270 | 280 |
| 271 | 281 |
| 272 // Resolve unresolved_class in the library of cls, or return null. | 282 // Resolve unresolved_class in the library of cls, or return null. |
| 273 RawClass* ClassFinalizer::ResolveClass( | 283 RawClass* ClassFinalizer::ResolveClass( |
| 274 const Class& cls, | 284 const Class& cls, |
| 275 const UnresolvedClass& unresolved_class) { | 285 const UnresolvedClass& unresolved_class) { |
| 276 const String& class_name = String::Handle(unresolved_class.ident()); | 286 const String& class_name = String::Handle(unresolved_class.ident()); |
| 277 Library& lib = Library::Handle(); | 287 Library& lib = Library::Handle(); |
| 278 Class& resolved_class = Class::Handle(); | 288 Class& resolved_class = Class::Handle(); |
| 279 if (unresolved_class.library_prefix() == LibraryPrefix::null()) { | 289 if (unresolved_class.library_or_library_prefix() == Object::null()) { |
| 280 lib = cls.library(); | 290 lib = cls.library(); |
| 281 ASSERT(!lib.IsNull()); | 291 ASSERT(!lib.IsNull()); |
| 282 resolved_class = lib.LookupClass(class_name); | 292 resolved_class = lib.LookupClass(class_name); |
| 283 } else { | 293 } else { |
| 284 LibraryPrefix& lib_prefix = LibraryPrefix::Handle(); | 294 const Object& prefix = |
| 285 lib_prefix = unresolved_class.library_prefix(); | 295 Object::Handle(unresolved_class.library_or_library_prefix()); |
| 286 ASSERT(!lib_prefix.IsNull()); | 296 |
| 287 resolved_class = lib_prefix.LookupClass(class_name); | 297 if (prefix.IsLibraryPrefix()) { |
| 298 resolved_class = LibraryPrefix::Cast(prefix).LookupClass(class_name); |
| 299 } else { |
| 300 resolved_class = Library::Cast(prefix).LookupClass(class_name); |
| 301 } |
| 288 } | 302 } |
| 289 return resolved_class.raw(); | 303 return resolved_class.raw(); |
| 290 } | 304 } |
| 291 | 305 |
| 292 | 306 |
| 293 void ClassFinalizer::ResolveRedirectingFactory(const Class& cls, | 307 void ClassFinalizer::ResolveRedirectingFactory(const Class& cls, |
| 294 const Function& factory) { | 308 const Function& factory) { |
| 295 const Function& target = Function::Handle(factory.RedirectionTarget()); | 309 const Function& target = Function::Handle(factory.RedirectionTarget()); |
| 296 if (target.IsNull()) { | 310 if (target.IsNull()) { |
| 297 Type& type = Type::Handle(factory.RedirectionType()); | 311 Type& type = Type::Handle(factory.RedirectionType()); |
| (...skipping 1884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2182 | 2196 |
| 2183 if (FLAG_trace_class_finalization) { | 2197 if (FLAG_trace_class_finalization) { |
| 2184 THR_Print("Applying mixin members of %s to %s at pos %s\n", | 2198 THR_Print("Applying mixin members of %s to %s at pos %s\n", |
| 2185 mixin_cls.ToCString(), cls.ToCString(), | 2199 mixin_cls.ToCString(), cls.ToCString(), |
| 2186 cls.token_pos().ToCString()); | 2200 cls.token_pos().ToCString()); |
| 2187 } | 2201 } |
| 2188 | 2202 |
| 2189 const GrowableObjectArray& cloned_funcs = | 2203 const GrowableObjectArray& cloned_funcs = |
| 2190 GrowableObjectArray::Handle(zone, GrowableObjectArray::New()); | 2204 GrowableObjectArray::Handle(zone, GrowableObjectArray::New()); |
| 2191 | 2205 |
| 2192 CreateForwardingConstructors(cls, mixin_cls, cloned_funcs); | |
| 2193 | |
| 2194 Array& functions = Array::Handle(zone); | 2206 Array& functions = Array::Handle(zone); |
| 2195 Function& func = Function::Handle(zone); | 2207 Function& func = Function::Handle(zone); |
| 2208 |
| 2196 // The parser creates the mixin application class with no functions. | 2209 // The parser creates the mixin application class with no functions. |
| 2197 ASSERT((functions = cls.functions(), functions.Length() == 0)); | 2210 // But the Kernel frontend will generate mixin classes with only |
| 2211 // constructors inside them, which forward to the base class constructors. |
| 2212 // |
| 2213 // => We generate the constructors if they are not already there. |
| 2214 functions = cls.functions(); |
| 2215 if (functions.Length() == 0) { |
| 2216 CreateForwardingConstructors(cls, mixin_cls, cloned_funcs); |
| 2217 } else { |
| 2218 for (intptr_t i = 0; i < functions.Length(); i++) { |
| 2219 func ^= functions.At(i); |
| 2220 ASSERT(func.kernel_function() != 0); |
| 2221 cloned_funcs.Add(func); |
| 2222 } |
| 2223 } |
| 2224 |
| 2198 // Now clone the functions from the mixin class. | 2225 // Now clone the functions from the mixin class. |
| 2199 functions = mixin_cls.functions(); | 2226 functions = mixin_cls.functions(); |
| 2200 const intptr_t num_functions = functions.Length(); | 2227 const intptr_t num_functions = functions.Length(); |
| 2201 for (intptr_t i = 0; i < num_functions; i++) { | 2228 for (intptr_t i = 0; i < num_functions; i++) { |
| 2202 func ^= functions.At(i); | 2229 func ^= functions.At(i); |
| 2203 if (func.IsGenerativeConstructor()) { | 2230 if (func.IsGenerativeConstructor()) { |
| 2204 // A mixin class must not have explicit constructors. | 2231 // A mixin class must not have explicit constructors. |
| 2205 if (!func.IsImplicitConstructor()) { | 2232 if (!func.IsImplicitConstructor()) { |
| 2206 const Script& script = Script::Handle(cls.script()); | 2233 const Script& script = Script::Handle(cls.script()); |
| 2207 const Error& error = Error::Handle(LanguageError::NewFormatted( | 2234 const Error& error = Error::Handle(LanguageError::NewFormatted( |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2377 } else { | 2404 } else { |
| 2378 // This class should not contain any functions or user-defined fields yet, | 2405 // 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 | 2406 // because it has not been compiled yet. There may however be metadata |
| 2380 // fields because type parameters are parsed before the class body. Since | 2407 // fields because type parameters are parsed before the class body. Since |
| 2381 // 'ResolveAndFinalizeMemberTypes(cls)' has not been called yet, unfinalized | 2408 // 'ResolveAndFinalizeMemberTypes(cls)' has not been called yet, unfinalized |
| 2382 // member types could choke the snapshotter. | 2409 // member types could choke the snapshotter. |
| 2383 // Or | 2410 // Or |
| 2384 // if the class is being refinalized because a patch is being applied | 2411 // 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 | 2412 // after the class has been finalized then it is ok for the class to have |
| 2386 // functions. | 2413 // functions. |
| 2387 ASSERT((Array::Handle(cls.functions()).Length() == 0) || | 2414 // |
| 2388 cls.is_refinalize_after_patch()); | 2415 // TODO(kmillikin): This ASSERT will fail when bootstrapping from Kernel |
| 2416 // because classes are first created, methods are added, and then classes |
| 2417 // are finalized. It is not easy to finalize classes earlier because not |
| 2418 // all bootstrap classes have been created yet. It would be possible to |
| 2419 // create all classes, delay adding methods, finalize the classes, and then |
| 2420 // reprocess all classes to add methods, but that seems unnecessary. |
| 2421 // Marking the bootstrap classes as is_refinalize_after_patch seems cute but |
| 2422 // it causes other things to fail by violating their assumptions. Reenable |
| 2423 // this ASSERT if it's important, remove it if it's just a sanity check and |
| 2424 // not required for correctness. |
| 2425 // |
| 2426 // ASSERT((Array::Handle(cls.functions()).Length() == 0) || |
| 2427 // cls.is_refinalize_after_patch()); |
| 2389 } | 2428 } |
| 2390 } | 2429 } |
| 2391 | 2430 |
| 2392 | 2431 |
| 2393 void ClassFinalizer::FinalizeClass(const Class& cls) { | 2432 void ClassFinalizer::FinalizeClass(const Class& cls) { |
| 2394 Thread* thread = Thread::Current(); | 2433 Thread* thread = Thread::Current(); |
| 2395 HANDLESCOPE(thread); | 2434 HANDLESCOPE(thread); |
| 2396 ASSERT(cls.is_type_finalized()); | 2435 ASSERT(cls.is_type_finalized()); |
| 2397 if (cls.is_finalized()) { | 2436 if (cls.is_finalized()) { |
| 2398 return; | 2437 return; |
| (...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3267 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); | 3306 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); |
| 3268 field ^= fields_array.At(0); | 3307 field ^= fields_array.At(0); |
| 3269 ASSERT(field.Offset() == ByteBuffer::data_offset()); | 3308 ASSERT(field.Offset() == ByteBuffer::data_offset()); |
| 3270 name ^= field.name(); | 3309 name ^= field.name(); |
| 3271 expected_name ^= String::New("_data"); | 3310 expected_name ^= String::New("_data"); |
| 3272 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 3311 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
| 3273 #endif | 3312 #endif |
| 3274 } | 3313 } |
| 3275 | 3314 |
| 3276 } // namespace dart | 3315 } // namespace dart |
| OLD | NEW |