Chromium Code Reviews| Index: runtime/vm/object.cc |
| diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
| index f674cd4b80669a4b9a64444e12601acb5135aed4..7320872b0c6e7de052919eff36d745e7e4096386 100644 |
| --- a/runtime/vm/object.cc |
| +++ b/runtime/vm/object.cc |
| @@ -7387,6 +7387,115 @@ void Field::PrintJSONImpl(JSONStream* stream, bool ref) const { |
| } |
| +// Build a closure object that gets the contents of a static field f |
| +// and cache the closure in a newly created static field named #f. |
| +RawInstance* Field::GetterClosure() const { |
| + ASSERT(is_static()); |
| + const Class& field_owner = Class::Handle(owner()); |
| + |
| + String& closure_name = String::Handle(); |
|
Florian Schneider
2015/07/22 08:25:53
String& closure_name = String::Handle(this->name()
hausner
2015/07/22 18:41:09
vertigo prevented :)
|
| + closure_name = this->name(); |
| + closure_name = Symbols::FromConcat(Symbols::HashMark(), closure_name); |
| + |
| + Field& closure_field = Field::Handle(); |
| + closure_field = field_owner.LookupStaticField(closure_name); |
| + if (!closure_field.IsNull()) { |
| + ASSERT(closure_field.is_static()); |
| + const Instance& closure = Instance::Handle(closure_field.value()); |
| + ASSERT(!closure.IsNull()); |
| + ASSERT(closure.IsClosure()); |
| + return closure.raw(); |
| + } |
| + |
| + // This is the first time a getter closure for this field is requested. |
| + // Create the closure and a new static field in which the closure is |
| + // stored. |
| + const char* field_name = String::Handle(name()).ToCString(); |
| + String& expr_src = String::Handle( |
| + String::NewFormatted("() { return %s; }", field_name)); |
| + Object& result = |
| + Object::Handle(field_owner.Evaluate(expr_src, |
| + Object::empty_array(), |
| + Object::empty_array())); |
| + ASSERT(result.IsInstance()); |
| + // The caller may expect the closure to be allocated in old space. Copy |
| + // the result here, since Object::Clone() is a private method. |
| + result = Object::Clone(result, Heap::kOld); |
| + |
| + closure_field = Field::New(closure_name, |
| + true, // is_static |
| + true, // is_final |
| + true, // is_const |
| + true, // is_synthetic |
| + field_owner, |
| + this->token_pos()); |
| + closure_field.set_value(Instance::Cast(result)); |
| + closure_field.set_type(Type::Handle(Type::DynamicType())); |
| + field_owner.AddField(closure_field); |
| + |
| + return Instance::RawCast(result.raw()); |
| +} |
| + |
| + |
| +// Build a closure object that sets the contents of a static field f |
| +// and cache the closure in a newly created static field named #f=. |
| +RawInstance* Field::SetterClosure() const { |
| + ASSERT(is_static()); |
| + const Class& field_owner = Class::Handle(owner()); |
| + |
| + String& closure_name = String::Handle(); |
|
Florian Schneider
2015/07/22 08:25:53
String& closure_name = String::Handle(this->name()
hausner
2015/07/22 18:41:09
Done.
|
| + closure_name = this->name(); |
| + closure_name = String::Concat(closure_name, Symbols::Equals()); |
| + closure_name = Symbols::FromConcat(Symbols::HashMark(), closure_name); |
| + |
| + Field& closure_field = Field::Handle(); |
| + closure_field = field_owner.LookupStaticField(closure_name); |
| + if (!closure_field.IsNull()) { |
| + ASSERT(closure_field.is_static()); |
| + const Instance& closure = Instance::Handle(closure_field.value()); |
| + ASSERT(!closure.IsNull()); |
| + ASSERT(closure.IsClosure()); |
| + return closure.raw(); |
| + } |
| + |
| + // This is the first time a getter closure for this field is requested. |
|
Florian Schneider
2015/07/22 08:25:53
Update comment for setter closure.
hausner
2015/07/22 18:41:09
Done.
|
| + // Create the closure and a new static field in which the closure is |
| + // stored. |
| + const String& field_name = String::Handle(name()); |
| + String& expr_src = String::Handle(); |
| + if (field_owner.IsTopLevel()) { |
|
Florian Schneider
2015/07/22 08:25:54
Why is the top-level case needed here, and not for
hausner
2015/07/22 18:41:09
The class name is added to avoid name conflicts wh
|
| + expr_src = String::NewFormatted("(value) { return %s = value; }", |
| + field_name.ToCString()); |
| + } else { |
| + const String& owner_name = String::Handle(field_owner.Name()); |
| + expr_src = String::NewFormatted("(value) { return %s.%s = value; }", |
| + owner_name.ToCString(), |
| + field_name.ToCString()); |
| + } |
| + Object& result = |
| + Object::Handle(field_owner.Evaluate(expr_src, |
| + Object::empty_array(), |
| + Object::empty_array())); |
| + ASSERT(result.IsInstance()); |
| + // The caller may expect the closure to be allocated in old space. Copy |
| + // the result here, since Object::Clone() is a private method. |
| + result = Object::Clone(result, Heap::kOld); |
| + |
| + closure_field = Field::New(closure_name, |
| + true, // is_static |
| + true, // is_final |
| + true, // is_const |
| + true, // is_synthetic |
| + field_owner, |
| + this->token_pos()); |
| + closure_field.set_value(Instance::Cast(result)); |
| + closure_field.set_type(Type::Handle(Type::DynamicType())); |
| + field_owner.AddField(closure_field); |
|
Florian Schneider
2015/07/22 08:25:54
Maybe factor the creation of the field into a file
hausner
2015/07/22 18:41:09
Factoring out 4 lines of code that would require 3
|
| + |
| + return Instance::RawCast(result.raw()); |
| +} |
| + |
| + |
| RawArray* Field::dependent_code() const { |
| return raw_ptr()->dependent_code_; |
| } |