| 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/flags.h" | 7 #include "vm/flags.h" |
| 8 #include "vm/hash_table.h" | 8 #include "vm/hash_table.h" |
| 9 #include "vm/heap.h" | 9 #include "vm/heap.h" |
| 10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 } | 314 } |
| 315 | 315 |
| 316 | 316 |
| 317 void ClassFinalizer::ResolveRedirectingFactory(const Class& cls, | 317 void ClassFinalizer::ResolveRedirectingFactory(const Class& cls, |
| 318 const Function& factory) { | 318 const Function& factory) { |
| 319 const Function& target = Function::Handle(factory.RedirectionTarget()); | 319 const Function& target = Function::Handle(factory.RedirectionTarget()); |
| 320 if (target.IsNull()) { | 320 if (target.IsNull()) { |
| 321 Type& type = Type::Handle(factory.RedirectionType()); | 321 Type& type = Type::Handle(factory.RedirectionType()); |
| 322 if (!type.IsMalformed() && IsLoaded(type)) { | 322 if (!type.IsMalformed() && IsLoaded(type)) { |
| 323 const GrowableObjectArray& visited_factories = | 323 const GrowableObjectArray& visited_factories = |
| 324 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 324 GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld)); |
| 325 ResolveRedirectingFactoryTarget(cls, factory, visited_factories); | 325 ResolveRedirectingFactoryTarget(cls, factory, visited_factories); |
| 326 } | 326 } |
| 327 if (factory.is_const()) { | 327 if (factory.is_const()) { |
| 328 type = factory.RedirectionType(); | 328 type = factory.RedirectionType(); |
| 329 if (type.IsMalformedOrMalbounded()) { | 329 if (type.IsMalformedOrMalbounded()) { |
| 330 ReportError(Error::Handle(type.error())); | 330 ReportError(Error::Handle(type.error())); |
| 331 } | 331 } |
| 332 } | 332 } |
| 333 } | 333 } |
| 334 } | 334 } |
| 335 | 335 |
| 336 | 336 |
| 337 void ClassFinalizer::ResolveRedirectingFactoryTarget( | 337 void ClassFinalizer::ResolveRedirectingFactoryTarget( |
| 338 const Class& cls, | 338 const Class& cls, |
| 339 const Function& factory, | 339 const Function& factory, |
| 340 const GrowableObjectArray& visited_factories) { | 340 const GrowableObjectArray& visited_factories) { |
| 341 ASSERT(factory.IsRedirectingFactory()); | 341 ASSERT(factory.IsRedirectingFactory()); |
| 342 | 342 |
| 343 // Check for redirection cycle. | 343 // Check for redirection cycle. |
| 344 for (intptr_t i = 0; i < visited_factories.Length(); i++) { | 344 for (intptr_t i = 0; i < visited_factories.Length(); i++) { |
| 345 if (visited_factories.At(i) == factory.raw()) { | 345 if (visited_factories.At(i) == factory.raw()) { |
| 346 // A redirection cycle is reported as a compile-time error. | 346 // A redirection cycle is reported as a compile-time error. |
| 347 ReportError(cls, factory.token_pos(), | 347 ReportError(cls, factory.token_pos(), |
| 348 "factory '%s' illegally redirects to itself", | 348 "factory '%s' illegally redirects to itself", |
| 349 String::Handle(factory.name()).ToCString()); | 349 String::Handle(factory.name()).ToCString()); |
| 350 } | 350 } |
| 351 } | 351 } |
| 352 visited_factories.Add(factory); | 352 visited_factories.Add(factory, Heap::kOld); |
| 353 | 353 |
| 354 // Check if target is already resolved. | 354 // Check if target is already resolved. |
| 355 Type& type = Type::Handle(factory.RedirectionType()); | 355 Type& type = Type::Handle(factory.RedirectionType()); |
| 356 Function& target = Function::Handle(factory.RedirectionTarget()); | 356 Function& target = Function::Handle(factory.RedirectionTarget()); |
| 357 if (type.IsMalformedOrMalbounded()) { | 357 if (type.IsMalformedOrMalbounded()) { |
| 358 // Already resolved to a malformed or malbounded type. Will throw on usage. | 358 // Already resolved to a malformed or malbounded type. Will throw on usage. |
| 359 ASSERT(target.IsNull()); | 359 ASSERT(target.IsNull()); |
| 360 return; | 360 return; |
| 361 } | 361 } |
| 362 if (!target.IsNull()) { | 362 if (!target.IsNull()) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 381 type = NewFinalizedMalformedType(Error::Handle(), // No previous error. | 381 type = NewFinalizedMalformedType(Error::Handle(), // No previous error. |
| 382 Script::Handle(cls.script()), | 382 Script::Handle(cls.script()), |
| 383 factory.token_pos(), | 383 factory.token_pos(), |
| 384 "factory may not redirect to 'dynamic'"); | 384 "factory may not redirect to 'dynamic'"); |
| 385 factory.SetRedirectionType(type); | 385 factory.SetRedirectionType(type); |
| 386 ASSERT(factory.RedirectionTarget() == Function::null()); | 386 ASSERT(factory.RedirectionTarget() == Function::null()); |
| 387 return; | 387 return; |
| 388 } | 388 } |
| 389 const Class& target_class = Class::Handle(type.type_class()); | 389 const Class& target_class = Class::Handle(type.type_class()); |
| 390 String& target_class_name = String::Handle(target_class.Name()); | 390 String& target_class_name = String::Handle(target_class.Name()); |
| 391 String& target_name = | 391 String& target_name = String::Handle( |
| 392 String::Handle(String::Concat(target_class_name, Symbols::Dot())); | 392 String::Concat(target_class_name, Symbols::Dot(), Heap::kOld)); |
| 393 const String& identifier = String::Handle(factory.RedirectionIdentifier()); | 393 const String& identifier = String::Handle(factory.RedirectionIdentifier()); |
| 394 if (!identifier.IsNull()) { | 394 if (!identifier.IsNull()) { |
| 395 target_name = String::Concat(target_name, identifier); | 395 target_name = String::Concat(target_name, identifier, Heap::kOld); |
| 396 } | 396 } |
| 397 | 397 |
| 398 // Verify that the target constructor of the redirection exists. | 398 // Verify that the target constructor of the redirection exists. |
| 399 target = target_class.LookupConstructor(target_name); | 399 target = target_class.LookupConstructor(target_name); |
| 400 if (target.IsNull()) { | 400 if (target.IsNull()) { |
| 401 target = target_class.LookupFactory(target_name); | 401 target = target_class.LookupFactory(target_name); |
| 402 } | 402 } |
| 403 if (target.IsNull()) { | 403 if (target.IsNull()) { |
| 404 const String& user_visible_target_name = | 404 const String& user_visible_target_name = |
| 405 identifier.IsNull() ? target_class_name : target_name; | 405 identifier.IsNull() ? target_class_name : target_name; |
| (...skipping 1892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2298 const String& super_name = String::Handle(Z, super_class.Name()); | 2298 const String& super_name = String::Handle(Z, super_class.Name()); |
| 2299 const Array& functions = Array::Handle(Z, super_class.functions()); | 2299 const Array& functions = Array::Handle(Z, super_class.functions()); |
| 2300 const intptr_t num_functions = functions.Length(); | 2300 const intptr_t num_functions = functions.Length(); |
| 2301 Function& func = Function::Handle(Z); | 2301 Function& func = Function::Handle(Z); |
| 2302 for (intptr_t i = 0; i < num_functions; i++) { | 2302 for (intptr_t i = 0; i < num_functions; i++) { |
| 2303 func ^= functions.At(i); | 2303 func ^= functions.At(i); |
| 2304 if (func.IsGenerativeConstructor()) { | 2304 if (func.IsGenerativeConstructor()) { |
| 2305 // Build constructor name from mixin application class name | 2305 // Build constructor name from mixin application class name |
| 2306 // and name of cloned super class constructor. | 2306 // and name of cloned super class constructor. |
| 2307 const String& ctor_name = String::Handle(Z, func.name()); | 2307 const String& ctor_name = String::Handle(Z, func.name()); |
| 2308 String& clone_name = | 2308 String& clone_name = String::Handle( |
| 2309 String::Handle(Z, String::SubString(ctor_name, super_name.Length())); | 2309 Z, String::SubString(ctor_name, super_name.Length(), Heap::kOld)); |
| 2310 clone_name = Symbols::FromConcat(T, mixin_name, clone_name); | 2310 clone_name = Symbols::FromConcat(T, mixin_name, clone_name); |
| 2311 | 2311 |
| 2312 if (FLAG_trace_class_finalization) { | 2312 if (FLAG_trace_class_finalization) { |
| 2313 THR_Print("Cloning constructor '%s' as '%s'\n", ctor_name.ToCString(), | 2313 THR_Print("Cloning constructor '%s' as '%s'\n", ctor_name.ToCString(), |
| 2314 clone_name.ToCString()); | 2314 clone_name.ToCString()); |
| 2315 } | 2315 } |
| 2316 | 2316 |
| 2317 // The owner of the forwarding constructor is the mixin application | 2317 // The owner of the forwarding constructor is the mixin application |
| 2318 // class. The source is the mixin class. The source may be needed | 2318 // class. The source is the mixin class. The source may be needed |
| 2319 // to parse field initializer expressions in the mixin class. | 2319 // to parse field initializer expressions in the mixin class. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2333 clone.set_result_type(Object::dynamic_type()); | 2333 clone.set_result_type(Object::dynamic_type()); |
| 2334 clone.set_is_debuggable(false); | 2334 clone.set_is_debuggable(false); |
| 2335 | 2335 |
| 2336 const intptr_t num_parameters = func.NumParameters(); | 2336 const intptr_t num_parameters = func.NumParameters(); |
| 2337 // The cloned ctor shares the parameter names array with the | 2337 // The cloned ctor shares the parameter names array with the |
| 2338 // original. | 2338 // original. |
| 2339 const Array& parameter_names = Array::Handle(Z, func.parameter_names()); | 2339 const Array& parameter_names = Array::Handle(Z, func.parameter_names()); |
| 2340 ASSERT(parameter_names.Length() == num_parameters); | 2340 ASSERT(parameter_names.Length() == num_parameters); |
| 2341 clone.set_parameter_names(parameter_names); | 2341 clone.set_parameter_names(parameter_names); |
| 2342 // The parameter types of the cloned constructor are 'dynamic'. | 2342 // The parameter types of the cloned constructor are 'dynamic'. |
| 2343 clone.set_parameter_types(Array::Handle(Z, Array::New(num_parameters))); | 2343 clone.set_parameter_types( |
| 2344 Array::Handle(Z, Array::New(num_parameters, Heap::kOld))); |
| 2344 for (intptr_t n = 0; n < num_parameters; n++) { | 2345 for (intptr_t n = 0; n < num_parameters; n++) { |
| 2345 clone.SetParameterTypeAt(n, Object::dynamic_type()); | 2346 clone.SetParameterTypeAt(n, Object::dynamic_type()); |
| 2346 } | 2347 } |
| 2347 cloned_funcs.Add(clone); | 2348 cloned_funcs.Add(clone); |
| 2348 } | 2349 } |
| 2349 } | 2350 } |
| 2350 } | 2351 } |
| 2351 | 2352 |
| 2352 | 2353 |
| 2353 void ClassFinalizer::ApplyMixinMembers(const Class& cls) { | 2354 void ClassFinalizer::ApplyMixinMembers(const Class& cls) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2366 Class::Handle(zone, cls.SuperClass()).IsMixinApplication()); | 2367 Class::Handle(zone, cls.SuperClass()).IsMixinApplication()); |
| 2367 // A default constructor will be created for the mixin app alias class. | 2368 // A default constructor will be created for the mixin app alias class. |
| 2368 | 2369 |
| 2369 if (FLAG_trace_class_finalization) { | 2370 if (FLAG_trace_class_finalization) { |
| 2370 THR_Print("Applying mixin members of %s to %s at pos %s\n", | 2371 THR_Print("Applying mixin members of %s to %s at pos %s\n", |
| 2371 mixin_cls.ToCString(), cls.ToCString(), | 2372 mixin_cls.ToCString(), cls.ToCString(), |
| 2372 cls.token_pos().ToCString()); | 2373 cls.token_pos().ToCString()); |
| 2373 } | 2374 } |
| 2374 | 2375 |
| 2375 const GrowableObjectArray& cloned_funcs = | 2376 const GrowableObjectArray& cloned_funcs = |
| 2376 GrowableObjectArray::Handle(zone, GrowableObjectArray::New()); | 2377 GrowableObjectArray::Handle(zone, GrowableObjectArray::New(Heap::kOld)); |
| 2377 | 2378 |
| 2378 Array& functions = Array::Handle(zone); | 2379 Array& functions = Array::Handle(zone); |
| 2379 Function& func = Function::Handle(zone); | 2380 Function& func = Function::Handle(zone); |
| 2380 | 2381 |
| 2381 // The parser creates the mixin application class with no functions. | 2382 // The parser creates the mixin application class with no functions. |
| 2382 // But the Kernel frontend will generate mixin classes with only | 2383 // But the Kernel frontend will generate mixin classes with only |
| 2383 // constructors inside them, which forward to the base class constructors. | 2384 // constructors inside them, which forward to the base class constructors. |
| 2384 // | 2385 // |
| 2385 // => We generate the constructors if they are not already there. | 2386 // => We generate the constructors if they are not already there. |
| 2386 functions = cls.functions(); | 2387 functions = cls.functions(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2398 functions = mixin_cls.functions(); | 2399 functions = mixin_cls.functions(); |
| 2399 const intptr_t num_functions = functions.Length(); | 2400 const intptr_t num_functions = functions.Length(); |
| 2400 for (intptr_t i = 0; i < num_functions; i++) { | 2401 for (intptr_t i = 0; i < num_functions; i++) { |
| 2401 func ^= functions.At(i); | 2402 func ^= functions.At(i); |
| 2402 if (func.IsGenerativeConstructor()) { | 2403 if (func.IsGenerativeConstructor()) { |
| 2403 // A mixin class must not have explicit constructors. | 2404 // A mixin class must not have explicit constructors. |
| 2404 if (!func.IsImplicitConstructor()) { | 2405 if (!func.IsImplicitConstructor()) { |
| 2405 const Script& script = Script::Handle(cls.script()); | 2406 const Script& script = Script::Handle(cls.script()); |
| 2406 const Error& error = Error::Handle(LanguageError::NewFormatted( | 2407 const Error& error = Error::Handle(LanguageError::NewFormatted( |
| 2407 Error::Handle(), script, func.token_pos(), Report::AtLocation, | 2408 Error::Handle(), script, func.token_pos(), Report::AtLocation, |
| 2408 Report::kError, Heap::kNew, | 2409 Report::kError, Heap::kOld, |
| 2409 "constructor '%s' is illegal in mixin class %s", | 2410 "constructor '%s' is illegal in mixin class %s", |
| 2410 String::Handle(func.UserVisibleName()).ToCString(), | 2411 String::Handle(func.UserVisibleName()).ToCString(), |
| 2411 String::Handle(zone, mixin_cls.Name()).ToCString())); | 2412 String::Handle(zone, mixin_cls.Name()).ToCString())); |
| 2412 | 2413 |
| 2413 ReportErrors(error, cls, cls.token_pos(), | 2414 ReportErrors(error, cls, cls.token_pos(), |
| 2414 "mixin class '%s' must not have constructors", | 2415 "mixin class '%s' must not have constructors", |
| 2415 String::Handle(zone, mixin_cls.Name()).ToCString()); | 2416 String::Handle(zone, mixin_cls.Name()).ToCString()); |
| 2416 } | 2417 } |
| 2417 continue; // Skip the implicit constructor. | 2418 continue; // Skip the implicit constructor. |
| 2418 } | 2419 } |
| 2419 if (!func.is_static() && !func.IsMethodExtractor() && | 2420 if (!func.is_static() && !func.IsMethodExtractor() && |
| 2420 !func.IsNoSuchMethodDispatcher() && !func.IsInvokeFieldDispatcher()) { | 2421 !func.IsNoSuchMethodDispatcher() && !func.IsInvokeFieldDispatcher()) { |
| 2421 func = func.Clone(cls); | 2422 func = func.Clone(cls); |
| 2422 cloned_funcs.Add(func); | 2423 cloned_funcs.Add(func, Heap::kOld); |
| 2423 } | 2424 } |
| 2424 } | 2425 } |
| 2425 functions = Array::MakeArray(cloned_funcs); | 2426 functions = Array::MakeArray(cloned_funcs); |
| 2426 cls.SetFunctions(functions); | 2427 cls.SetFunctions(functions); |
| 2427 | 2428 |
| 2428 // Now clone the fields from the mixin class. There should be no | 2429 // Now clone the fields from the mixin class. There should be no |
| 2429 // existing fields in the mixin application class. | 2430 // existing fields in the mixin application class. |
| 2430 ASSERT(Array::Handle(cls.fields()).Length() == 0); | 2431 ASSERT(Array::Handle(cls.fields()).Length() == 0); |
| 2431 const Array& fields = Array::Handle(zone, mixin_cls.fields()); | 2432 const Array& fields = Array::Handle(zone, mixin_cls.fields()); |
| 2432 const intptr_t num_fields = fields.Length(); | 2433 const intptr_t num_fields = fields.Length(); |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2643 // This has to happen before the check whether the methods of | 2644 // This has to happen before the check whether the methods of |
| 2644 // the class conflict with inherited methods. | 2645 // the class conflict with inherited methods. |
| 2645 ApplyMixinMembers(cls); | 2646 ApplyMixinMembers(cls); |
| 2646 } | 2647 } |
| 2647 // Mark as parsed and finalized. | 2648 // Mark as parsed and finalized. |
| 2648 cls.Finalize(); | 2649 cls.Finalize(); |
| 2649 // Mixin app alias classes may still lack their forwarding constructor. | 2650 // Mixin app alias classes may still lack their forwarding constructor. |
| 2650 if (cls.is_mixin_app_alias() && | 2651 if (cls.is_mixin_app_alias() && |
| 2651 (cls.functions() == Object::empty_array().raw())) { | 2652 (cls.functions() == Object::empty_array().raw())) { |
| 2652 const GrowableObjectArray& cloned_funcs = | 2653 const GrowableObjectArray& cloned_funcs = |
| 2653 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 2654 GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld)); |
| 2654 | 2655 |
| 2655 const Class& mixin_app_class = Class::Handle(cls.SuperClass()); | 2656 const Class& mixin_app_class = Class::Handle(cls.SuperClass()); |
| 2656 const Type& mixin_type = Type::Handle(mixin_app_class.mixin()); | 2657 const Type& mixin_type = Type::Handle(mixin_app_class.mixin()); |
| 2657 const Class& mixin_cls = Class::Handle(mixin_type.type_class()); | 2658 const Class& mixin_cls = Class::Handle(mixin_type.type_class()); |
| 2658 | 2659 |
| 2659 CreateForwardingConstructors(cls, mixin_cls, cloned_funcs); | 2660 CreateForwardingConstructors(cls, mixin_cls, cloned_funcs); |
| 2660 const Array& functions = Array::Handle(Array::MakeArray(cloned_funcs)); | 2661 const Array& functions = Array::Handle(Array::MakeArray(cloned_funcs)); |
| 2661 cls.SetFunctions(functions); | 2662 cls.SetFunctions(functions); |
| 2662 } | 2663 } |
| 2663 // Every class should have at least a constructor, unless it is a top level | 2664 // Every class should have at least a constructor, unless it is a top level |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2699 zone, enum_cls.LookupInstanceFieldAllowPrivate(Symbols::_name())); | 2700 zone, enum_cls.LookupInstanceFieldAllowPrivate(Symbols::_name())); |
| 2700 ASSERT(!name_field.IsNull()); | 2701 ASSERT(!name_field.IsNull()); |
| 2701 const Field& values_field = | 2702 const Field& values_field = |
| 2702 Field::Handle(zone, enum_cls.LookupStaticField(Symbols::Values())); | 2703 Field::Handle(zone, enum_cls.LookupStaticField(Symbols::Values())); |
| 2703 ASSERT(!values_field.IsNull()); | 2704 ASSERT(!values_field.IsNull()); |
| 2704 ASSERT(Instance::Handle(zone, values_field.StaticValue()).IsArray()); | 2705 ASSERT(Instance::Handle(zone, values_field.StaticValue()).IsArray()); |
| 2705 Array& values_list = | 2706 Array& values_list = |
| 2706 Array::Handle(zone, Array::RawCast(values_field.StaticValue())); | 2707 Array::Handle(zone, Array::RawCast(values_field.StaticValue())); |
| 2707 const String& enum_name = String::Handle(enum_cls.ScrubbedName()); | 2708 const String& enum_name = String::Handle(enum_cls.ScrubbedName()); |
| 2708 const String& name_prefix = | 2709 const String& name_prefix = |
| 2709 String::Handle(String::Concat(enum_name, Symbols::Dot())); | 2710 String::Handle(String::Concat(enum_name, Symbols::Dot(), Heap::kOld)); |
| 2710 | 2711 |
| 2711 Field& field = Field::Handle(zone); | 2712 Field& field = Field::Handle(zone); |
| 2712 Instance& ordinal_value = Instance::Handle(zone); | 2713 Instance& ordinal_value = Instance::Handle(zone); |
| 2713 Instance& enum_value = Instance::Handle(zone); | 2714 Instance& enum_value = Instance::Handle(zone); |
| 2714 | 2715 |
| 2715 String& enum_ident = String::Handle(); | 2716 String& enum_ident = String::Handle(); |
| 2716 | 2717 |
| 2717 enum_ident = | 2718 enum_ident = |
| 2718 Symbols::FromConcat(thread, Symbols::_DeletedEnumPrefix(), enum_name); | 2719 Symbols::FromConcat(thread, Symbols::_DeletedEnumPrefix(), enum_name); |
| 2719 enum_value = Instance::New(enum_cls, Heap::kOld); | 2720 enum_value = Instance::New(enum_cls, Heap::kOld); |
| (...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3800 ProgramVisitor::VisitFunctions(&function_visitor); | 3801 ProgramVisitor::VisitFunctions(&function_visitor); |
| 3801 | 3802 |
| 3802 class ClearCodeClassVisitor : public ClassVisitor { | 3803 class ClearCodeClassVisitor : public ClassVisitor { |
| 3803 void Visit(const Class& cls) { cls.DisableAllocationStub(); } | 3804 void Visit(const Class& cls) { cls.DisableAllocationStub(); } |
| 3804 }; | 3805 }; |
| 3805 ClearCodeClassVisitor class_visitor; | 3806 ClearCodeClassVisitor class_visitor; |
| 3806 ProgramVisitor::VisitClasses(&class_visitor); | 3807 ProgramVisitor::VisitClasses(&class_visitor); |
| 3807 } | 3808 } |
| 3808 | 3809 |
| 3809 } // namespace dart | 3810 } // namespace dart |
| OLD | NEW |