Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(247)

Unified Diff: runtime/vm/object_reload.cc

Issue 2498863002: Map deleted enum values to a sentinel value. (Closed)
Patch Set: asiva review Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/isolate_reload_test.cc ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object_reload.cc
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index b48c46e4f3becb3694bad160029d3a1e0e303b93..b41ff6c03d77b3fafe4bc3088882dfd47eac2141 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -204,18 +204,10 @@ class EnumMapTraits {
// the ordering is always correct (i.e. enum indicies match slots in values
// array)
// 3) An existing enum value is removed.
-// We leave old enum values that have no mapping to the reloaded class
-// in the heap. This means that if a programmer does the following:
-// enum Foo { A, B }; var x = Foo.A;
-// *reload*
-// enum Foo { B };
-// *reload*
-// enum Foo { A, B }; expect(identical(x, Foo.A));
-// The program will fail because we were not able to pair Foo.A on the second
-// reload.
+// Each enum class has a canonical 'deleted' enum sentinel instance.
+// When an enum value is deleted, we 'become' all references to the 'deleted'
+// sentinel value. The index value is -1.
//
-// Deleted enum values still in the heap continue to function but their
-// index field will not be valid.
void Class::ReplaceEnum(const Class& old_enum) const {
// We only do this for finalized enum classes.
ASSERT(is_enum_class());
@@ -237,6 +229,10 @@ void Class::ReplaceEnum(const Class& old_enum) const {
Instance& old_enum_values = Instance::Handle(zone);
// The E.values array.
Instance& enum_values = Instance::Handle(zone);
+ // The E._deleted_enum_sentinel instance.
+ Instance& old_deleted_enum_sentinel = Instance::Handle(zone);
+ // The E._deleted_enum_sentinel instance.
+ Instance& deleted_enum_sentinel = Instance::Handle(zone);
Array& enum_map_storage =
Array::Handle(zone, HashTables::New<UnorderedHashMap<EnumMapTraits> >(4));
ASSERT(!enum_map_storage.IsNull());
@@ -259,6 +255,11 @@ void Class::ReplaceEnum(const Class& old_enum) const {
// Non-enum instance.
continue;
}
+ if (enum_ident.Equals(Symbols::_DeletedEnumSentinel())) {
+ old_deleted_enum_sentinel = field.StaticValue();
+ // Non-enum instance.
+ continue;
+ }
old_enum_value = field.StaticValue();
ASSERT(!old_enum_value.IsNull());
VTIR_Print("Element %s being added to mapping\n", enum_ident.ToCString());
@@ -288,6 +289,11 @@ void Class::ReplaceEnum(const Class& old_enum) const {
// Non-enum instance.
continue;
}
+ if (enum_ident.Equals(Symbols::_DeletedEnumSentinel())) {
+ deleted_enum_sentinel = field.StaticValue();
+ // Non-enum instance.
+ continue;
+ }
enum_value = field.StaticValue();
ASSERT(!enum_value.IsNull());
old_enum_value ^= enum_map.GetOrNull(enum_ident);
@@ -313,17 +319,29 @@ void Class::ReplaceEnum(const Class& old_enum) const {
ASSERT(!enum_values.IsNull());
reload_context->AddEnumBecomeMapping(old_enum_values, enum_values);
- if (enums_deleted && FLAG_trace_reload_verbose) {
+ // Map the old E._deleted_enum_sentinel to the new E._deleted_enum_sentinel.
+ ASSERT(!old_deleted_enum_sentinel.IsNull());
+ ASSERT(!deleted_enum_sentinel.IsNull());
+ reload_context->AddEnumBecomeMapping(old_deleted_enum_sentinel,
+ deleted_enum_sentinel);
+
+ if (enums_deleted) {
+ // Map all deleted enums to the deleted enum senintel value.
// TODO(johnmccutchan): Add this to the reload 'notices' list.
VTIR_Print(
- "The following enum values were deleted and are forever lost in "
- "the heap:\n");
+ "The following enum values were deleted from %s and will become the "
+ "deleted enum sentinel:\n",
+ old_enum.ToCString());
UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.raw());
UnorderedHashMap<EnumMapTraits>::Iterator it(&enum_map);
while (it.MoveNext()) {
const intptr_t entry = it.Current();
enum_ident = String::RawCast(enum_map.GetKey(entry));
ASSERT(!enum_ident.IsNull());
+ old_enum_value ^= enum_map.GetOrNull(enum_ident);
+ VTIR_Print("Element `%s` was deleted\n", enum_ident.ToCString());
+ reload_context->AddEnumBecomeMapping(old_enum_value,
+ deleted_enum_sentinel);
}
enum_map.Release();
}
« no previous file with comments | « runtime/vm/isolate_reload_test.cc ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698