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

Side by Side Diff: runtime/vm/isolate_reload.cc

Issue 2489723003: Run field initializers for new instance fields after a reload (Closed)
Patch Set: 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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/isolate_reload.h" 5 #include "vm/isolate_reload.h"
6 6
7 #include "vm/become.h" 7 #include "vm/become.h"
8 #include "vm/bit_vector.h" 8 #include "vm/bit_vector.h"
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 #define TIMELINE_SCOPE(name) \ 44 #define TIMELINE_SCOPE(name) \
45 TimelineDurationScope tds##name(Thread::Current(), \ 45 TimelineDurationScope tds##name(Thread::Current(), \
46 Timeline::GetIsolateStream(), \ 46 Timeline::GetIsolateStream(), \
47 #name) 47 #name)
48 48
49 49
50 InstanceMorpher::InstanceMorpher(Zone* zone, const Class& from, const Class& to) 50 InstanceMorpher::InstanceMorpher(Zone* zone, const Class& from, const Class& to)
51 : from_(Class::Handle(zone, from.raw())), 51 : from_(Class::Handle(zone, from.raw())),
52 to_(Class::Handle(zone, to.raw())), 52 to_(Class::Handle(zone, to.raw())),
53 mapping_(zone, 0) { 53 mapping_(zone, 0) {
54 ComputeMapping();
55 before_ = new(zone) ZoneGrowableArray<const Instance*>(zone, 0); 54 before_ = new(zone) ZoneGrowableArray<const Instance*>(zone, 0);
56 after_ = new(zone) ZoneGrowableArray<const Instance*>(zone, 0); 55 after_ = new(zone) ZoneGrowableArray<const Instance*>(zone, 0);
56 new_fields_ = new(zone) ZoneGrowableArray<const Field*>(zone, 0);
57 ASSERT(from_.id() == to_.id()); 57 ASSERT(from_.id() == to_.id());
58 cid_ = from_.id(); 58 cid_ = from_.id();
59 ComputeMapping();
59 } 60 }
60 61
61 62
62 void InstanceMorpher::AddObject(RawObject* object) const { 63 void InstanceMorpher::AddObject(RawObject* object) const {
63 ASSERT(object->GetClassId() == cid()); 64 ASSERT(object->GetClassId() == cid());
64 const Instance& instance = Instance::Cast(Object::Handle(object)); 65 const Instance& instance = Instance::Cast(Object::Handle(object));
65 before_->Add(&instance); 66 before_->Add(&instance);
66 } 67 }
67 68
68 69
69 void InstanceMorpher::ComputeMapping() { 70 void InstanceMorpher::ComputeMapping() {
70 if (from_.NumTypeArguments()) { 71 if (from_.NumTypeArguments()) {
71 // Add copying of the optional type argument field. 72 // Add copying of the optional type argument field.
72 intptr_t from_offset = from_.type_arguments_field_offset(); 73 intptr_t from_offset = from_.type_arguments_field_offset();
73 ASSERT(from_offset != Class::kNoTypeArguments); 74 ASSERT(from_offset != Class::kNoTypeArguments);
74 intptr_t to_offset = to_.type_arguments_field_offset(); 75 intptr_t to_offset = to_.type_arguments_field_offset();
75 ASSERT(to_offset != Class::kNoTypeArguments); 76 ASSERT(to_offset != Class::kNoTypeArguments);
76 mapping_.Add(from_offset); 77 mapping_.Add(from_offset);
77 mapping_.Add(to_offset); 78 mapping_.Add(to_offset);
78 } 79 }
79 80
80 // Add copying of the instance fields if matching by name. 81 // Add copying of the instance fields if matching by name.
81 // Note: currently the type of the fields are ignored. 82 // Note: currently the type of the fields are ignored.
82 const Array& from_fields = Array::Handle(from_.OffsetToFieldMap()); 83 const Array& from_fields = Array::Handle(from_.OffsetToFieldMap());
83 const Array& to_fields = Array::Handle(to_.OffsetToFieldMap()); 84 const Array& to_fields = Array::Handle(to_.OffsetToFieldMap());
84 Field& from_field = Field::Handle(); 85 Field& from_field = Field::Handle();
85 Field& to_field = Field::Handle(); 86 Field& to_field = Field::Handle();
86 String& from_name = String::Handle(); 87 String& from_name = String::Handle();
87 String& to_name = String::Handle(); 88 String& to_name = String::Handle();
88 for (intptr_t i = 0; i < from_fields.Length(); i++) { 89
89 if (from_fields.At(i) == Field::null()) continue; // Ignore non-fields. 90 // Scan across all the fields in the new class definition.
90 from_field = Field::RawCast(from_fields.At(i)); 91 for (intptr_t i = 0; i < to_fields.Length(); i++) {
91 ASSERT(from_field.is_instance()); 92 if (to_fields.At(i) == Field::null()) {
92 from_name = from_field.name(); 93 continue; // Ignore non-fields.
93 // We now have to find where this field is in the to class. 94 }
94 for (intptr_t j = 0; j < to_fields.Length(); j++) { 95
95 if (to_fields.At(j) == Field::null()) continue; // Ignore non-fields. 96 // Grab the field's name.
96 to_field = Field::RawCast(to_fields.At(j)); 97 to_field = Field::RawCast(to_fields.At(i));
97 ASSERT(to_field.is_instance()); 98 ASSERT(to_field.is_instance());
98 to_name = to_field.name(); 99 to_name = to_field.name();
100
101 // Did this field not exist in the old class definition?
102 bool new_field = true;
103
104 // Find this field in the old class.
105 for (intptr_t j = 0; j < from_fields.Length(); j++) {
106 if (from_fields.At(j) == Field::null()) {
107 continue; // Ignore non-fields.
108 }
109 from_field = Field::RawCast(from_fields.At(j));
110 ASSERT(from_field.is_instance());
111 from_name = from_field.name();
99 if (from_name.Equals(to_name)) { 112 if (from_name.Equals(to_name)) {
100 // Success 113 // Success
101 mapping_.Add(from_field.Offset()); 114 mapping_.Add(from_field.Offset());
102 mapping_.Add(to_field.Offset()); 115 mapping_.Add(to_field.Offset());
116 // Field did exist in old class deifnition.
117 new_field = false;
118 }
119 }
120
121 if (new_field) {
122 if (to_field.has_initializer()) {
123 // This is a new field with an initializer.
124 const Field& field = Field::Handle(to_field.raw());
125 new_fields_->Add(&field);
103 } 126 }
104 } 127 }
105 } 128 }
106 } 129 }
107 130
108 131
109 RawInstance* InstanceMorpher::Morph(const Instance& instance) const { 132 RawInstance* InstanceMorpher::Morph(const Instance& instance) const {
110 const Instance& result = Instance::Handle(Instance::New(to_)); 133 const Instance& result = Instance::Handle(Instance::New(to_));
111 // Morph the context from instance to result using mapping_. 134 // Morph the context from instance to result using mapping_.
112 for (intptr_t i = 0; i < mapping_.length(); i +=2) { 135 for (intptr_t i = 0; i < mapping_.length(); i +=2) {
113 intptr_t from_offset = mapping_.At(i); 136 intptr_t from_offset = mapping_.At(i);
114 intptr_t to_offset = mapping_.At(i+1); 137 intptr_t to_offset = mapping_.At(i+1);
115 const Object& value = 138 const Object& value =
116 Object::Handle(instance.RawGetFieldAtOffset(from_offset)); 139 Object::Handle(instance.RawGetFieldAtOffset(from_offset));
117 result.RawSetFieldAtOffset(to_offset, value); 140 result.RawSetFieldAtOffset(to_offset, value);
118 } 141 }
119 // Convert the instance into a filler object. 142 // Convert the instance into a filler object.
120 Become::MakeDummyObject(instance); 143 Become::MakeDummyObject(instance);
121 return result.raw(); 144 return result.raw();
122 } 145 }
123 146
124 147
148 void InstanceMorpher::RunNewFieldInitializers() const {
149 if ((new_fields_->length() == 0) || (after_->length() == 0)) {
150 return;
151 }
152
153 TIR_Print("Running new field initializers for class: %s\n", to_.ToCString());
154 String& initializing_expression = String::Handle();
155 Function& eval_func = Function::Handle();
156 Object& result = Object::Handle();
157 // For each new field.
158 for (intptr_t i = 0; i < new_fields_->length(); i++) {
159 // Create a function that returns the expression.
160 const Field* field = new_fields_->At(i);
161 // Extract the initializing expression.
162 initializing_expression = field->InitializingExpression();
163 TIR_Print("New `%s` has initializing expression `%s`\n",
164 field->ToCString(),
165 initializing_expression.ToCString());
166 eval_func ^= Function::EvaluateHelper(to_,
rmacnak 2016/11/09 00:36:32 to_ -> field.owner to get the right scope Check f
Cutch 2016/11/09 23:20:58 Done.
167 initializing_expression,
168 Array::empty_array(),
169 true);
170 for (intptr_t j = 0; j < after_->length(); j++) {
171 const Instance* instance = after_->At(j);
172 TIR_Print("Initializing instance %" Pd " / %" Pd "\n",
173 j + 1, after_->length());
174 /// Run the function and assign the field.
175 result = DartEntry::InvokeFunction(eval_func, Array::empty_array());
rmacnak 2016/11/09 00:36:32 fail stop if (result.IsError()) return result.raw
Cutch 2016/11/09 23:20:58 going with: log error to standard error leave fie
176 instance->RawSetFieldAtOffset(field->Offset(), result);
177 }
178 }
179 }
180
181
125 void InstanceMorpher::CreateMorphedCopies() const { 182 void InstanceMorpher::CreateMorphedCopies() const {
126 for (intptr_t i = 0; i < before()->length(); i++) { 183 for (intptr_t i = 0; i < before()->length(); i++) {
127 const Instance& copy = Instance::Handle(Morph(*before()->At(i))); 184 const Instance& copy = Instance::Handle(Morph(*before()->At(i)));
128 after()->Add(&copy); 185 after()->Add(&copy);
129 } 186 }
130 } 187 }
131 188
132 189
133 void InstanceMorpher::DumpFormatFor(const Class& cls) const { 190 void InstanceMorpher::DumpFormatFor(const Class& cls) const {
134 THR_Print("%s\n", cls.ToCString()); 191 THR_Print("%s\n", cls.ToCString());
(...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1277 } 1334 }
1278 ASSERT(index == count); 1335 ASSERT(index == count);
1279 } 1336 }
1280 1337
1281 // This is important: The saved class table (describing before objects) 1338 // This is important: The saved class table (describing before objects)
1282 // must be zapped to prevent the forwarding in GetClassForHeapWalkAt. 1339 // must be zapped to prevent the forwarding in GetClassForHeapWalkAt.
1283 // Instance will from now be described by the isolate's class table. 1340 // Instance will from now be described by the isolate's class table.
1284 free(saved_class_table_); 1341 free(saved_class_table_);
1285 saved_class_table_ = NULL; 1342 saved_class_table_ = NULL;
1286 Become::ElementsForwardIdentity(before, after); 1343 Become::ElementsForwardIdentity(before, after);
1344
1345 // Run new field initializers on all instances.
1346 for (intptr_t i = 0; i < instance_morphers_.length(); i++) {
1347 instance_morphers_.At(i)->RunNewFieldInitializers();
rmacnak 2016/11/09 00:36:32 fail stop
Cutch 2016/11/09 23:20:58 Acknowledged.
1348 }
1287 } 1349 }
1288 1350
1289 1351
1290 bool IsolateReloadContext::ValidateReload() { 1352 bool IsolateReloadContext::ValidateReload() {
1291 TIMELINE_SCOPE(ValidateReload); 1353 TIMELINE_SCOPE(ValidateReload);
1292 if (reload_aborted()) return false; 1354 if (reload_aborted()) return false;
1293 1355
1294 TIR_Print("---- VALIDATING RELOAD\n"); 1356 TIR_Print("---- VALIDATING RELOAD\n");
1295 1357
1296 // Validate libraries. 1358 // Validate libraries.
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after
1681 ASSERT(!super_cls.IsNull()); 1743 ASSERT(!super_cls.IsNull());
1682 super_cls.AddDirectSubclass(cls); 1744 super_cls.AddDirectSubclass(cls);
1683 } 1745 }
1684 } 1746 }
1685 } 1747 }
1686 } 1748 }
1687 1749
1688 #endif // !PRODUCT 1750 #endif // !PRODUCT
1689 1751
1690 } // namespace dart 1752 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698