Index: runtime/vm/class_finalizer.cc |
=================================================================== |
--- runtime/vm/class_finalizer.cc (revision 41810) |
+++ runtime/vm/class_finalizer.cc (working copy) |
@@ -2346,9 +2346,50 @@ |
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(); |
+ if (!ordinal_value.IsSmi()) continue; |
srdjan
2014/11/18 21:19:18
Maybe add comment how it can be non-smi.
hausner
2014/11/18 23:14:07
Done.
|
+ 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()); |