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 |