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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
110 } | 110 } |
111 } | 111 } |
112 cids->Add(ifc.id()); | 112 cids->Add(ifc.id()); |
113 } | 113 } |
114 } | 114 } |
115 | 115 |
116 | 116 |
117 // Processing ObjectStore::pending_classes_ occurs: | 117 // Processing ObjectStore::pending_classes_ occurs: |
118 // a) when bootstrap process completes (VerifyBootstrapClasses). | 118 // a) when bootstrap process completes (VerifyBootstrapClasses). |
119 // b) after the user classes are loaded (dart_api). | 119 // b) after the user classes are loaded (dart_api). |
120 bool ClassFinalizer::ProcessPendingClasses() { | 120 bool ClassFinalizer::ProcessPendingClasses(bool from_kernel) { |
121 Thread* thread = Thread::Current(); | 121 Thread* thread = Thread::Current(); |
122 NOT_IN_PRODUCT(TimelineDurationScope tds(thread, Timeline::GetIsolateStream(), | 122 NOT_IN_PRODUCT(TimelineDurationScope tds(thread, Timeline::GetIsolateStream(), |
123 "ProcessPendingClasses")); | 123 "ProcessPendingClasses")); |
124 Isolate* isolate = thread->isolate(); | 124 Isolate* isolate = thread->isolate(); |
125 ASSERT(isolate != NULL); | 125 ASSERT(isolate != NULL); |
126 HANDLESCOPE(thread); | 126 HANDLESCOPE(thread); |
127 ObjectStore* object_store = isolate->object_store(); | 127 ObjectStore* object_store = isolate->object_store(); |
128 const Error& error = Error::Handle(thread->zone(), thread->sticky_error()); | 128 const Error& error = Error::Handle(thread->zone(), thread->sticky_error()); |
129 if (!error.IsNull()) { | 129 if (!error.IsNull()) { |
130 return false; | 130 return false; |
(...skipping 11 matching lines...) Expand all Loading... | |
142 // First resolve all superclasses. | 142 // First resolve all superclasses. |
143 for (intptr_t i = 0; i < class_array.Length(); i++) { | 143 for (intptr_t i = 0; i < class_array.Length(); i++) { |
144 cls ^= class_array.At(i); | 144 cls ^= class_array.At(i); |
145 GrowableArray<intptr_t> visited_interfaces; | 145 GrowableArray<intptr_t> visited_interfaces; |
146 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); | 146 ResolveSuperTypeAndInterfaces(cls, &visited_interfaces); |
147 } | 147 } |
148 // Finalize all classes. | 148 // Finalize all classes. |
149 for (intptr_t i = 0; i < class_array.Length(); i++) { | 149 for (intptr_t i = 0; i < class_array.Length(); i++) { |
150 cls ^= class_array.At(i); | 150 cls ^= class_array.At(i); |
151 FinalizeTypesInClass(cls); | 151 FinalizeTypesInClass(cls); |
152 // Classes compiled from Dart sources are finalized more lazily, classes | |
153 // compiled from Kernel binaries can be finalized now (and should be, | |
154 // since we will not revisit them). | |
hausner
2016/11/09 00:42:49
Why? Would be nice to have a brief explanation.
Vyacheslav Egorov (Google)
2016/11/09 14:43:16
The original idea behind Kernel was to be an AOT r
| |
155 if (from_kernel) { | |
156 FinalizeClass(cls); | |
157 } | |
152 } | 158 } |
153 if (FLAG_print_classes) { | 159 if (FLAG_print_classes) { |
154 for (intptr_t i = 0; i < class_array.Length(); i++) { | 160 for (intptr_t i = 0; i < class_array.Length(); i++) { |
155 cls ^= class_array.At(i); | 161 cls ^= class_array.At(i); |
156 PrintClassInformation(cls); | 162 PrintClassInformation(cls); |
157 } | 163 } |
158 } | 164 } |
159 // Clear pending classes array. | 165 // Clear pending classes array. |
160 class_array = GrowableObjectArray::New(); | 166 class_array = GrowableObjectArray::New(); |
161 object_store->set_pending_classes(class_array); | 167 object_store->set_pending_classes(class_array); |
(...skipping 18 matching lines...) Expand all Loading... | |
180 Class& interface_class = Class::Handle(zone); | 186 Class& interface_class = Class::Handle(zone); |
181 for (intptr_t i = 0; i < interface_array.Length(); i++) { | 187 for (intptr_t i = 0; i < interface_array.Length(); i++) { |
182 interface ^= interface_array.At(i); | 188 interface ^= interface_array.At(i); |
183 interface_class = interface.type_class(); | 189 interface_class = interface.type_class(); |
184 collected->Add(&Class::ZoneHandle(zone, interface_class.raw())); | 190 collected->Add(&Class::ZoneHandle(zone, interface_class.raw())); |
185 CollectInterfaces(interface_class, collected); | 191 CollectInterfaces(interface_class, collected); |
186 } | 192 } |
187 } | 193 } |
188 | 194 |
189 | 195 |
190 #if defined(DART_NO_SNAPSHOT) | |
191 void ClassFinalizer::VerifyBootstrapClasses() { | 196 void ClassFinalizer::VerifyBootstrapClasses() { |
192 if (FLAG_trace_class_finalization) { | 197 if (FLAG_trace_class_finalization) { |
193 OS::Print("VerifyBootstrapClasses START.\n"); | 198 OS::Print("VerifyBootstrapClasses START.\n"); |
194 } | 199 } |
195 ObjectStore* object_store = Isolate::Current()->object_store(); | 200 ObjectStore* object_store = Isolate::Current()->object_store(); |
196 | 201 |
197 Class& cls = Class::Handle(); | 202 Class& cls = Class::Handle(); |
198 #if defined(DEBUG) | 203 #if defined(DEBUG) |
199 // Basic checking. | 204 // Basic checking. |
200 cls = object_store->object_class(); | 205 cls = object_store->object_class(); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
246 const Error& err = Error::Handle(Thread::Current()->sticky_error()); | 251 const Error& err = Error::Handle(Thread::Current()->sticky_error()); |
247 OS::PrintErr("Could not verify bootstrap classes : %s\n", | 252 OS::PrintErr("Could not verify bootstrap classes : %s\n", |
248 err.ToErrorCString()); | 253 err.ToErrorCString()); |
249 OS::Exit(255); | 254 OS::Exit(255); |
250 } | 255 } |
251 if (FLAG_trace_class_finalization) { | 256 if (FLAG_trace_class_finalization) { |
252 OS::Print("VerifyBootstrapClasses END.\n"); | 257 OS::Print("VerifyBootstrapClasses END.\n"); |
253 } | 258 } |
254 Isolate::Current()->heap()->Verify(); | 259 Isolate::Current()->heap()->Verify(); |
255 } | 260 } |
256 #endif // defined(DART_NO_SNAPSHOT). | |
257 | 261 |
258 | 262 |
259 static bool IsLoaded(const Type& type) { | 263 static bool IsLoaded(const Type& type) { |
260 if (type.HasResolvedTypeClass()) { | 264 if (type.HasResolvedTypeClass()) { |
261 return true; | 265 return true; |
262 } | 266 } |
263 const UnresolvedClass& unresolved_class = | 267 const UnresolvedClass& unresolved_class = |
264 UnresolvedClass::Handle(type.unresolved_class()); | 268 UnresolvedClass::Handle(type.unresolved_class()); |
265 const LibraryPrefix& prefix = | 269 const Object& prefix = |
266 LibraryPrefix::Handle(unresolved_class.library_prefix()); | 270 Object::Handle(unresolved_class.library_or_library_prefix()); |
267 return prefix.IsNull() || prefix.is_loaded(); | 271 if (prefix.IsNull()) { |
272 return true; | |
273 } else if (prefix.IsLibraryPrefix()) { | |
274 return LibraryPrefix::Cast(prefix).is_loaded(); | |
275 } else { | |
276 return true; | |
277 } | |
268 } | 278 } |
269 | 279 |
270 | 280 |
271 // Resolve unresolved_class in the library of cls, or return null. | 281 // Resolve unresolved_class in the library of cls, or return null. |
272 RawClass* ClassFinalizer::ResolveClass( | 282 RawClass* ClassFinalizer::ResolveClass( |
273 const Class& cls, | 283 const Class& cls, |
274 const UnresolvedClass& unresolved_class) { | 284 const UnresolvedClass& unresolved_class) { |
275 const String& class_name = String::Handle(unresolved_class.ident()); | 285 const String& class_name = String::Handle(unresolved_class.ident()); |
276 Library& lib = Library::Handle(); | 286 Library& lib = Library::Handle(); |
277 Class& resolved_class = Class::Handle(); | 287 Class& resolved_class = Class::Handle(); |
278 if (unresolved_class.library_prefix() == LibraryPrefix::null()) { | 288 if (unresolved_class.library_or_library_prefix() == Object::null()) { |
279 lib = cls.library(); | 289 lib = cls.library(); |
280 ASSERT(!lib.IsNull()); | 290 ASSERT(!lib.IsNull()); |
281 resolved_class = lib.LookupClass(class_name); | 291 resolved_class = lib.LookupClass(class_name); |
282 } else { | 292 } else { |
283 LibraryPrefix& lib_prefix = LibraryPrefix::Handle(); | 293 const Object& prefix = |
284 lib_prefix = unresolved_class.library_prefix(); | 294 Object::Handle(unresolved_class.library_or_library_prefix()); |
285 ASSERT(!lib_prefix.IsNull()); | 295 |
286 resolved_class = lib_prefix.LookupClass(class_name); | 296 if (prefix.IsLibraryPrefix()) { |
297 resolved_class = LibraryPrefix::Cast(prefix).LookupClass(class_name); | |
298 } else { | |
299 resolved_class = Library::Cast(prefix).LookupClass(class_name); | |
300 } | |
287 } | 301 } |
288 return resolved_class.raw(); | 302 return resolved_class.raw(); |
289 } | 303 } |
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()) { |
(...skipping 1940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2237 if (FLAG_trace_class_finalization) { | 2251 if (FLAG_trace_class_finalization) { |
2238 THR_Print("Applying mixin members of %s to %s at pos %s\n", | 2252 THR_Print("Applying mixin members of %s to %s at pos %s\n", |
2239 mixin_cls.ToCString(), | 2253 mixin_cls.ToCString(), |
2240 cls.ToCString(), | 2254 cls.ToCString(), |
2241 cls.token_pos().ToCString()); | 2255 cls.token_pos().ToCString()); |
2242 } | 2256 } |
2243 | 2257 |
2244 const GrowableObjectArray& cloned_funcs = | 2258 const GrowableObjectArray& cloned_funcs = |
2245 GrowableObjectArray::Handle(zone, GrowableObjectArray::New()); | 2259 GrowableObjectArray::Handle(zone, GrowableObjectArray::New()); |
2246 | 2260 |
2247 CreateForwardingConstructors(cls, mixin_cls, cloned_funcs); | |
2248 | |
2249 Array& functions = Array::Handle(zone); | 2261 Array& functions = Array::Handle(zone); |
2250 Function& func = Function::Handle(zone); | 2262 Function& func = Function::Handle(zone); |
2263 | |
2251 // The parser creates the mixin application class with no functions. | 2264 // The parser creates the mixin application class with no functions. |
2252 ASSERT((functions = cls.functions(), functions.Length() == 0)); | 2265 // But the Kernel frontend will generate mixin classes with only |
2266 // constructors inside them, which forward to the base class constructors. | |
2267 // | |
2268 // => We generate the constructors if they are not already there. | |
2269 functions = cls.functions(); | |
2270 if (functions.Length() == 0) { | |
2271 CreateForwardingConstructors(cls, mixin_cls, cloned_funcs); | |
2272 } else { | |
2273 for (intptr_t i = 0; i < functions.Length(); i++) { | |
2274 func ^= functions.At(i); | |
2275 ASSERT(func.kernel_function() != 0); | |
2276 cloned_funcs.Add(func); | |
2277 } | |
2278 } | |
2279 | |
2253 // Now clone the functions from the mixin class. | 2280 // Now clone the functions from the mixin class. |
2254 functions = mixin_cls.functions(); | 2281 functions = mixin_cls.functions(); |
2255 const intptr_t num_functions = functions.Length(); | 2282 const intptr_t num_functions = functions.Length(); |
2256 for (intptr_t i = 0; i < num_functions; i++) { | 2283 for (intptr_t i = 0; i < num_functions; i++) { |
2257 func ^= functions.At(i); | 2284 func ^= functions.At(i); |
2258 if (func.IsGenerativeConstructor()) { | 2285 if (func.IsGenerativeConstructor()) { |
2259 // A mixin class must not have explicit constructors. | 2286 // A mixin class must not have explicit constructors. |
2260 if (!func.IsImplicitConstructor()) { | 2287 if (!func.IsImplicitConstructor()) { |
2261 const Script& script = Script::Handle(cls.script()); | 2288 const Script& script = Script::Handle(cls.script()); |
2262 const Error& error = Error::Handle( | 2289 const Error& error = Error::Handle( |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2437 } else { | 2464 } else { |
2438 // This class should not contain any functions or user-defined fields yet, | 2465 // This class should not contain any functions or user-defined fields yet, |
2439 // because it has not been compiled yet. There may however be metadata | 2466 // because it has not been compiled yet. There may however be metadata |
2440 // fields because type parameters are parsed before the class body. Since | 2467 // fields because type parameters are parsed before the class body. Since |
2441 // 'ResolveAndFinalizeMemberTypes(cls)' has not been called yet, unfinalized | 2468 // 'ResolveAndFinalizeMemberTypes(cls)' has not been called yet, unfinalized |
2442 // member types could choke the snapshotter. | 2469 // member types could choke the snapshotter. |
2443 // Or | 2470 // Or |
2444 // if the class is being refinalized because a patch is being applied | 2471 // if the class is being refinalized because a patch is being applied |
2445 // after the class has been finalized then it is ok for the class to have | 2472 // after the class has been finalized then it is ok for the class to have |
2446 // functions. | 2473 // functions. |
2447 ASSERT((Array::Handle(cls.functions()).Length() == 0) || | 2474 // |
2448 cls.is_refinalize_after_patch()); | 2475 // TODO(kmillikin): This ASSERT will fail when bootstrapping from Kernel |
2476 // because classes are first created, methods are added, and then classes | |
2477 // are finalized. It is not easy to finalize classes earlier because not | |
2478 // all bootstrap classes have been created yet. It would be possible to | |
2479 // create all classes, delay adding methods, finalize the classes, and then | |
2480 // reprocess all classes to add methods, but that seems unnecessary. | |
2481 // Marking the bootstrap classes as is_refinalize_after_patch seems cute but | |
2482 // it causes other things to fail by violating their assumptions. Reenable | |
2483 // this ASSERT if it's important, remove it if it's just a sanity check and | |
2484 // not required for correctness. | |
2485 // | |
2486 // ASSERT((Array::Handle(cls.functions()).Length() == 0) || | |
2487 // cls.is_refinalize_after_patch()); | |
2449 } | 2488 } |
2450 } | 2489 } |
2451 | 2490 |
2452 | 2491 |
2453 void ClassFinalizer::FinalizeClass(const Class& cls) { | 2492 void ClassFinalizer::FinalizeClass(const Class& cls) { |
2454 Thread* thread = Thread::Current(); | 2493 Thread* thread = Thread::Current(); |
2455 HANDLESCOPE(thread); | 2494 HANDLESCOPE(thread); |
2456 ASSERT(cls.is_type_finalized()); | 2495 ASSERT(cls.is_type_finalized()); |
2457 if (cls.is_finalized()) { | 2496 if (cls.is_finalized()) { |
2458 return; | 2497 return; |
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3345 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); | 3384 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); |
3346 field ^= fields_array.At(0); | 3385 field ^= fields_array.At(0); |
3347 ASSERT(field.Offset() == ByteBuffer::data_offset()); | 3386 ASSERT(field.Offset() == ByteBuffer::data_offset()); |
3348 name ^= field.name(); | 3387 name ^= field.name(); |
3349 expected_name ^= String::New("_data"); | 3388 expected_name ^= String::New("_data"); |
3350 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 3389 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
3351 #endif | 3390 #endif |
3352 } | 3391 } |
3353 | 3392 |
3354 } // namespace dart | 3393 } // namespace dart |
OLD | NEW |