Chromium Code Reviews| 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.
|
| + } |
| } |