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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/isolate_reload.cc
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 139c6d4dbe38863c7a0dd8085390a88eadc1d2f5..34f75102dc139e9b0ac407a8e7781e09168b94ee 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -51,11 +51,12 @@ InstanceMorpher::InstanceMorpher(Zone* zone, const Class& from, const Class& to)
: from_(Class::Handle(zone, from.raw())),
to_(Class::Handle(zone, to.raw())),
mapping_(zone, 0) {
- ComputeMapping();
before_ = new(zone) ZoneGrowableArray<const Instance*>(zone, 0);
after_ = new(zone) ZoneGrowableArray<const Instance*>(zone, 0);
+ new_fields_ = new(zone) ZoneGrowableArray<const Field*>(zone, 0);
ASSERT(from_.id() == to_.id());
cid_ = from_.id();
+ ComputeMapping();
}
@@ -85,21 +86,43 @@ void InstanceMorpher::ComputeMapping() {
Field& to_field = Field::Handle();
String& from_name = String::Handle();
String& to_name = String::Handle();
- for (intptr_t i = 0; i < from_fields.Length(); i++) {
- if (from_fields.At(i) == Field::null()) continue; // Ignore non-fields.
- from_field = Field::RawCast(from_fields.At(i));
- ASSERT(from_field.is_instance());
- from_name = from_field.name();
- // We now have to find where this field is in the to class.
- for (intptr_t j = 0; j < to_fields.Length(); j++) {
- if (to_fields.At(j) == Field::null()) continue; // Ignore non-fields.
- to_field = Field::RawCast(to_fields.At(j));
- ASSERT(to_field.is_instance());
- to_name = to_field.name();
+
+ // Scan across all the fields in the new class definition.
+ for (intptr_t i = 0; i < to_fields.Length(); i++) {
+ if (to_fields.At(i) == Field::null()) {
+ continue; // Ignore non-fields.
+ }
+
+ // Grab the field's name.
+ to_field = Field::RawCast(to_fields.At(i));
+ ASSERT(to_field.is_instance());
+ to_name = to_field.name();
+
+ // Did this field not exist in the old class definition?
+ bool new_field = true;
+
+ // Find this field in the old class.
+ for (intptr_t j = 0; j < from_fields.Length(); j++) {
+ if (from_fields.At(j) == Field::null()) {
+ continue; // Ignore non-fields.
+ }
+ from_field = Field::RawCast(from_fields.At(j));
+ ASSERT(from_field.is_instance());
+ from_name = from_field.name();
if (from_name.Equals(to_name)) {
// Success
mapping_.Add(from_field.Offset());
mapping_.Add(to_field.Offset());
+ // Field did exist in old class deifnition.
+ new_field = false;
+ }
+ }
+
+ if (new_field) {
+ if (to_field.has_initializer()) {
+ // This is a new field with an initializer.
+ const Field& field = Field::Handle(to_field.raw());
+ new_fields_->Add(&field);
}
}
}
@@ -122,6 +145,40 @@ RawInstance* InstanceMorpher::Morph(const Instance& instance) const {
}
+void InstanceMorpher::RunNewFieldInitializers() const {
+ if ((new_fields_->length() == 0) || (after_->length() == 0)) {
+ return;
+ }
+
+ TIR_Print("Running new field initializers for class: %s\n", to_.ToCString());
+ String& initializing_expression = String::Handle();
+ Function& eval_func = Function::Handle();
+ Object& result = Object::Handle();
+ // For each new field.
+ for (intptr_t i = 0; i < new_fields_->length(); i++) {
+ // Create a function that returns the expression.
+ const Field* field = new_fields_->At(i);
+ // Extract the initializing expression.
+ initializing_expression = field->InitializingExpression();
+ TIR_Print("New `%s` has initializing expression `%s`\n",
+ field->ToCString(),
+ initializing_expression.ToCString());
+ 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.
+ initializing_expression,
+ Array::empty_array(),
+ true);
+ for (intptr_t j = 0; j < after_->length(); j++) {
+ const Instance* instance = after_->At(j);
+ TIR_Print("Initializing instance %" Pd " / %" Pd "\n",
+ j + 1, after_->length());
+ /// Run the function and assign the field.
+ 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
+ instance->RawSetFieldAtOffset(field->Offset(), result);
+ }
+ }
+}
+
+
void InstanceMorpher::CreateMorphedCopies() const {
for (intptr_t i = 0; i < before()->length(); i++) {
const Instance& copy = Instance::Handle(Morph(*before()->At(i)));
@@ -1284,6 +1341,11 @@ void IsolateReloadContext::MorphInstances() {
free(saved_class_table_);
saved_class_table_ = NULL;
Become::ElementsForwardIdentity(before, after);
+
+ // Run new field initializers on all instances.
+ for (intptr_t i = 0; i < instance_morphers_.length(); i++) {
+ instance_morphers_.At(i)->RunNewFieldInitializers();
rmacnak 2016/11/09 00:36:32 fail stop
Cutch 2016/11/09 23:20:58 Acknowledged.
+ }
}

Powered by Google App Engine
This is Rietveld 408576698