| Index: runtime/vm/class_finalizer.cc
|
| ===================================================================
|
| --- runtime/vm/class_finalizer.cc (revision 41810)
|
| +++ runtime/vm/class_finalizer.cc (working copy)
|
| @@ -2346,9 +2346,53 @@
|
| CollectImmediateSuperInterfaces(cls, &cids);
|
| RemoveCHAOptimizedCode(cids);
|
| }
|
| + if (cls.is_enum_class()) {
|
| + AllocateEnumValues(cls);
|
| + }
|
| }
|
|
|
|
|
| +// Allocate instances for each enumeration value, and populate the
|
| +// static field 'values'.
|
| +// By allocating the instances programmatically, we save an implicit final
|
| +// getter function object for each enumeration value and for the
|
| +// values field. We also don't have to generate the code for these getters
|
| +// from thin air (no source code is available).
|
| +void ClassFinalizer::AllocateEnumValues(const Class &enum_cls) {
|
| + const Field& index_field =
|
| + Field::Handle(enum_cls.LookupInstanceField(Symbols::Index()));
|
| + ASSERT(!index_field.IsNull());
|
| + const Field& values_field =
|
| + Field::Handle(enum_cls.LookupStaticField(Symbols::Values()));
|
| + ASSERT(!values_field.IsNull());
|
| + ASSERT(Instance::Handle(values_field.value()).IsArray());
|
| + Array& values_list = Array::Handle(Array::RawCast(values_field.value()));
|
| +
|
| + const Array& fields = Array::Handle(enum_cls.fields());
|
| + Field& field = Field::Handle();
|
| + Instance& ordinal_value = Instance::Handle();
|
| + Instance& enum_value = Instance::Handle();
|
| +
|
| + for (intptr_t i = 0; i < fields.Length(); i++) {
|
| + field = Field::RawCast(fields.At(i));
|
| + if (!field.is_static()) continue;
|
| + ordinal_value = field.value();
|
| + // The static fields that need to be initialized with enum instances
|
| + // contain the smi value of the ordinal number, which was stored in
|
| + // the field by the parser. Other fields contain non-smi values.
|
| + if (!ordinal_value.IsSmi()) continue;
|
| + enum_value = Instance::New(enum_cls, Heap::kOld);
|
| + enum_value.SetField(index_field, ordinal_value);
|
| + field.set_value(enum_value);
|
| + field.RecordStore(enum_value);
|
| + intptr_t ord = Smi::Cast(ordinal_value).Value();
|
| + ASSERT(ord < values_list.Length());
|
| + values_list.SetAt(ord, enum_value);
|
| + }
|
| + values_list.MakeImmutable();
|
| +}
|
| +
|
| +
|
| bool ClassFinalizer::IsSuperCycleFree(const Class& cls) {
|
| Class& test1 = Class::Handle(cls.raw());
|
| Class& test2 = Class::Handle(cls.SuperClass());
|
| @@ -2726,8 +2770,14 @@
|
| "class '%s' may not extend function type alias '%s'",
|
| String::Handle(isolate, cls.Name()).ToCString(),
|
| String::Handle(isolate,
|
| - super_type.UserVisibleName()).ToCString());
|
| + super_type.UserVisibleName()).ToCString());
|
| }
|
| + if (interface_class.is_enum_class()) {
|
| + ReportError(cls, cls.token_pos(),
|
| + "class '%s' may not extend enum '%s'",
|
| + String::Handle(isolate, cls.Name()).ToCString(),
|
| + String::Handle(isolate, interface_class.Name()).ToCString());
|
| + }
|
|
|
| // If cls belongs to core lib or to core lib's implementation, restrictions
|
| // about allowed interfaces are lifted.
|
| @@ -2803,6 +2853,13 @@
|
| "function type alias '%s' may not be used as interface",
|
| interface_name.ToCString());
|
| }
|
| + if (interface_class.is_enum_class()) {
|
| + const String& interface_name = String::Handle(isolate,
|
| + interface_class.Name());
|
| + ReportError(cls, cls.token_pos(),
|
| + "enum '%s' may not be used as interface",
|
| + interface_name.ToCString());
|
| + }
|
| // Verify that unless cls belongs to core lib, it cannot extend, implement,
|
| // or mixin any of Null, bool, num, int, double, String, dynamic.
|
| if (!cls_belongs_to_core_lib) {
|
|
|