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 2328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2339 // Run additional checks after all types are finalized. | 2339 // Run additional checks after all types are finalized. |
2340 if (cls.is_const()) { | 2340 if (cls.is_const()) { |
2341 CheckForLegalConstClass(cls); | 2341 CheckForLegalConstClass(cls); |
2342 } | 2342 } |
2343 if (FLAG_use_cha) { | 2343 if (FLAG_use_cha) { |
2344 GrowableArray<intptr_t> cids; | 2344 GrowableArray<intptr_t> cids; |
2345 CollectFinalizedSuperClasses(cls, &cids); | 2345 CollectFinalizedSuperClasses(cls, &cids); |
2346 CollectImmediateSuperInterfaces(cls, &cids); | 2346 CollectImmediateSuperInterfaces(cls, &cids); |
2347 RemoveCHAOptimizedCode(cids); | 2347 RemoveCHAOptimizedCode(cids); |
2348 } | 2348 } |
| 2349 if (cls.is_enum_class()) { |
| 2350 AllocateEnumValues(cls); |
| 2351 } |
| 2352 } |
| 2353 |
| 2354 |
| 2355 // Allocate instances for each enumeration value, and populate the |
| 2356 // static field 'values'. |
| 2357 // By allocating the instances programmatically, we save an implicit final |
| 2358 // getter function object for each enumeration value and for the |
| 2359 // values field. We also don't have to generate the code for these getters |
| 2360 // from thin air (no source code is available). |
| 2361 void ClassFinalizer::AllocateEnumValues(const Class &enum_cls) { |
| 2362 const Field& index_field = |
| 2363 Field::Handle(enum_cls.LookupInstanceField(Symbols::Index())); |
| 2364 ASSERT(!index_field.IsNull()); |
| 2365 const Field& values_field = |
| 2366 Field::Handle(enum_cls.LookupStaticField(Symbols::Values())); |
| 2367 ASSERT(!values_field.IsNull()); |
| 2368 ASSERT(Instance::Handle(values_field.value()).IsArray()); |
| 2369 Array& values_list = Array::Handle(Array::RawCast(values_field.value())); |
| 2370 |
| 2371 const Array& fields = Array::Handle(enum_cls.fields()); |
| 2372 Field& field = Field::Handle(); |
| 2373 Instance& ordinal_value = Instance::Handle(); |
| 2374 Instance& enum_value = Instance::Handle(); |
| 2375 |
| 2376 for (intptr_t i = 0; i < fields.Length(); i++) { |
| 2377 field = Field::RawCast(fields.At(i)); |
| 2378 if (!field.is_static()) continue; |
| 2379 ordinal_value = field.value(); |
| 2380 // The static fields that need to be initialized with enum instances |
| 2381 // contain the smi value of the ordinal number, which was stored in |
| 2382 // the field by the parser. Other fields contain non-smi values. |
| 2383 if (!ordinal_value.IsSmi()) continue; |
| 2384 enum_value = Instance::New(enum_cls, Heap::kOld); |
| 2385 enum_value.SetField(index_field, ordinal_value); |
| 2386 field.set_value(enum_value); |
| 2387 field.RecordStore(enum_value); |
| 2388 intptr_t ord = Smi::Cast(ordinal_value).Value(); |
| 2389 ASSERT(ord < values_list.Length()); |
| 2390 values_list.SetAt(ord, enum_value); |
| 2391 } |
| 2392 values_list.MakeImmutable(); |
2349 } | 2393 } |
2350 | 2394 |
2351 | 2395 |
2352 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { | 2396 bool ClassFinalizer::IsSuperCycleFree(const Class& cls) { |
2353 Class& test1 = Class::Handle(cls.raw()); | 2397 Class& test1 = Class::Handle(cls.raw()); |
2354 Class& test2 = Class::Handle(cls.SuperClass()); | 2398 Class& test2 = Class::Handle(cls.SuperClass()); |
2355 // A finalized class has been checked for cycles. | 2399 // A finalized class has been checked for cycles. |
2356 // Using the hare and tortoise algorithm for locating cycles. | 2400 // Using the hare and tortoise algorithm for locating cycles. |
2357 while (!test1.is_type_finalized() && | 2401 while (!test1.is_type_finalized() && |
2358 !test2.IsNull() && !test2.is_type_finalized()) { | 2402 !test2.IsNull() && !test2.is_type_finalized()) { |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2719 ReportError(cls, cls.token_pos(), | 2763 ReportError(cls, cls.token_pos(), |
2720 "class '%s' may not extend 'dynamic'", | 2764 "class '%s' may not extend 'dynamic'", |
2721 String::Handle(isolate, cls.Name()).ToCString()); | 2765 String::Handle(isolate, cls.Name()).ToCString()); |
2722 } | 2766 } |
2723 interface_class = super_type.type_class(); | 2767 interface_class = super_type.type_class(); |
2724 if (interface_class.IsSignatureClass()) { | 2768 if (interface_class.IsSignatureClass()) { |
2725 ReportError(cls, cls.token_pos(), | 2769 ReportError(cls, cls.token_pos(), |
2726 "class '%s' may not extend function type alias '%s'", | 2770 "class '%s' may not extend function type alias '%s'", |
2727 String::Handle(isolate, cls.Name()).ToCString(), | 2771 String::Handle(isolate, cls.Name()).ToCString(), |
2728 String::Handle(isolate, | 2772 String::Handle(isolate, |
2729 super_type.UserVisibleName()).ToCString()); | 2773 super_type.UserVisibleName()).ToCString()); |
| 2774 } |
| 2775 if (interface_class.is_enum_class()) { |
| 2776 ReportError(cls, cls.token_pos(), |
| 2777 "class '%s' may not extend enum '%s'", |
| 2778 String::Handle(isolate, cls.Name()).ToCString(), |
| 2779 String::Handle(isolate, interface_class.Name()).ToCString()); |
2730 } | 2780 } |
2731 | 2781 |
2732 // If cls belongs to core lib or to core lib's implementation, restrictions | 2782 // If cls belongs to core lib or to core lib's implementation, restrictions |
2733 // about allowed interfaces are lifted. | 2783 // about allowed interfaces are lifted. |
2734 if (!cls_belongs_to_core_lib) { | 2784 if (!cls_belongs_to_core_lib) { |
2735 // Prevent extending core implementation classes. | 2785 // Prevent extending core implementation classes. |
2736 bool is_error = false; | 2786 bool is_error = false; |
2737 switch (interface_class.id()) { | 2787 switch (interface_class.id()) { |
2738 case kNumberCid: | 2788 case kNumberCid: |
2739 case kIntegerCid: // Class Integer, not int. | 2789 case kIntegerCid: // Class Integer, not int. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2796 "'dynamic' may not be used as interface"); | 2846 "'dynamic' may not be used as interface"); |
2797 } | 2847 } |
2798 interface_class = interface.type_class(); | 2848 interface_class = interface.type_class(); |
2799 if (interface_class.IsSignatureClass()) { | 2849 if (interface_class.IsSignatureClass()) { |
2800 const String& interface_name = String::Handle(isolate, | 2850 const String& interface_name = String::Handle(isolate, |
2801 interface_class.Name()); | 2851 interface_class.Name()); |
2802 ReportError(cls, cls.token_pos(), | 2852 ReportError(cls, cls.token_pos(), |
2803 "function type alias '%s' may not be used as interface", | 2853 "function type alias '%s' may not be used as interface", |
2804 interface_name.ToCString()); | 2854 interface_name.ToCString()); |
2805 } | 2855 } |
| 2856 if (interface_class.is_enum_class()) { |
| 2857 const String& interface_name = String::Handle(isolate, |
| 2858 interface_class.Name()); |
| 2859 ReportError(cls, cls.token_pos(), |
| 2860 "enum '%s' may not be used as interface", |
| 2861 interface_name.ToCString()); |
| 2862 } |
2806 // Verify that unless cls belongs to core lib, it cannot extend, implement, | 2863 // Verify that unless cls belongs to core lib, it cannot extend, implement, |
2807 // or mixin any of Null, bool, num, int, double, String, dynamic. | 2864 // or mixin any of Null, bool, num, int, double, String, dynamic. |
2808 if (!cls_belongs_to_core_lib) { | 2865 if (!cls_belongs_to_core_lib) { |
2809 if (interface.IsBoolType() || | 2866 if (interface.IsBoolType() || |
2810 interface.IsNullType() || | 2867 interface.IsNullType() || |
2811 interface.IsNumberType() || | 2868 interface.IsNumberType() || |
2812 interface.IsIntType() || | 2869 interface.IsIntType() || |
2813 interface.IsDoubleType() || | 2870 interface.IsDoubleType() || |
2814 interface.IsStringType() || | 2871 interface.IsStringType() || |
2815 interface.IsDynamicType()) { | 2872 interface.IsDynamicType()) { |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3083 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); | 3140 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); |
3084 field ^= fields_array.At(0); | 3141 field ^= fields_array.At(0); |
3085 ASSERT(field.Offset() == ByteBuffer::data_offset()); | 3142 ASSERT(field.Offset() == ByteBuffer::data_offset()); |
3086 name ^= field.name(); | 3143 name ^= field.name(); |
3087 expected_name ^= String::New("_data"); | 3144 expected_name ^= String::New("_data"); |
3088 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 3145 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
3089 #endif | 3146 #endif |
3090 } | 3147 } |
3091 | 3148 |
3092 } // namespace dart | 3149 } // namespace dart |
OLD | NEW |